{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "0a9264be-bff1-46a8-969a-c18b2530a947",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -752,
        -3504
      ],
      "parameters": {
        "width": 400,
        "height": 944,
        "content": "## How It Works\nThe workflow automatically monitors WooCommerce for failed payments, processes each failed order, and instantly notifies your team in Slack. It begins on a fixed schedule and retrieves recent failed orders from your WooCommerce store. The data is then cleaned, standardized, and transformed into a simple finance-friendly structure. This ensures every failed order is consistent, easy to read, and ready for storage.\nNext, the workflow saves each processed record into Airtable, creating a reliable database of failed payments for tracking and reporting. Once stored, the workflow uses AI to generate a short summary message containing the essential order details and payment failure information. Finally, this message is sent to Slack so your team can review the issue and take action immediately.\n\n## Setup Steps\n\nWooCommerce Domain:\nSet your store domain in the \u201cSet WooCommerce Domain\u201d node so API requests point to the correct site.\n\nWooCommerce API Access:\nAdd your WooCommerce Consumer Key and Consumer Secret to the \u201cFetch Failed Orders\u201d HTTP Request node using Basic Auth.\n\nAirtable Connection:\nConnect your Airtable account in the \u201cSave to Airtable\u201d node and select the correct Base and Table.\n\nOpenAI Configuration:\nAdd your OpenAI API key to the \u201cGenerate Slack Message\u201d node.\n\nSlack Integration:\nConnect your Slack account in the \u201cSend Slack Alert\u201d node and choose the channel where alerts should be posted.\n\nActivate Workflow:\nEnable the workflow so it runs on your schedule and automatically processes failed WooCommerce orders."
      },
      "typeVersion": 1
    },
    {
      "id": "4286a4ff-1ba2-436c-a442-6a513c7e6a46",
      "name": "Format Order Data1",
      "type": "n8n-nodes-base.code",
      "position": [
        1632,
        -2416
      ],
      "parameters": {
        "jsCode": "const order = items[0].json;\n\n// Map failure reason (right now you have no gateway message)\nlet failure_reason_raw = order.payment_method_title || \"Unknown\";\nlet failure_reason_canonical = \"unknown\";\n\n// Canonical reason mapper (expand later)\nif (failure_reason_raw.toLowerCase().includes(\"expire\")) {\n  failure_reason_canonical = \"card_expired\";\n} else if (failure_reason_raw.toLowerCase().includes(\"declin\")) {\n  failure_reason_canonical = \"card_declined\";\n}\n\nreturn [{\n  order_id: order.id,\n  invoice_amount: order.total,\n  currency: order.currency,\n  customer_name: `${order.billing.first_name} ${order.billing.last_name}`,\n  customer_email: order.billing.email,\n  payment_method: order.payment_method,\n  failure_reason_raw,\n  failure_reason_canonical,\n  attempts_count: 1,\n\n  order_items_summary: order.line_items?.length\n    ? order.line_items.map(i => `${i.name} x ${i.quantity}`).join(\", \")\n    : \"No items found\",\n\n  links: {\n    order_admin_url: `https://{{YOUR_DOMAIN}}/wp-admin/post.php?post=${order.id}&action=edit`,\n    customer_profile_url: \"\",\n    retry_payment_url: order.payment_url\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e6f3b034-77d5-4a7b-bad6-4fe38ac61601",
      "name": "Save Failed Order to Airtable1",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1824,
        -2416
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appipUxLpxPEKRXrJ",
          "cachedResultUrl": "https://airtable.com/appipUxLpxPEKRXrJ",
          "cachedResultName": "Fake Review Detector"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblP4nfLbKZdHcGFt",
          "cachedResultUrl": "https://airtable.com/appipUxLpxPEKRXrJ/tblP4nfLbKZdHcGFt",
          "cachedResultName": "OrderFailedData"
        },
        "columns": {
          "value": {
            "currency": "={{ $json.currency }}",
            "order_id": "={{ $json.order_id }}",
            "customer_name": "={{ $json.customer_name }}",
            "attempts_count": "={{ $json.attempts_count }}",
            "customer_email": "={{ $json.customer_email }}",
            "invoice_amount": "={{ $json.invoice_amount }}",
            "payment_method": "={{ $json.payment_method }}",
            "order_admin_url": "={{ $json.links.order_admin_url }}",
            "retry_payment_url": "={{ $json.links.retry_payment_url }}",
            "failure_reason_raw": "={{ $json.failure_reason_raw }}",
            "order_items_summary": "={{ $json.links.order_admin_url }}",
            "customer_profile_url": "={{ $json.links.customer_profile_url }}",
            "failure_reason_canonical": "={{ $json.failure_reason_canonical }}"
          },
          "schema": [
            {
              "id": "order_id",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "order_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "invoice_amount",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "invoice_amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "currency",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "currency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_name",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "customer_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_email",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "customer_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "payment_method",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "payment_method",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "failure_reason_raw",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "failure_reason_raw",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "failure_reason_canonical",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "failure_reason_canonical",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "attempts_count",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "attempts_count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "order_items_summary",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "order_items_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "order_admin_url",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "order_admin_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_profile_url",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "customer_profile_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "retry_payment_url",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "retry_payment_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a34e289e-1d4a-4d71-ad0e-63b361b98dad",
      "name": "Generate Slack Summary Message 1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2160,
        -2432
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=You are an assistant that writes short, clear summaries for Slack messages.\n\nCreate a concise and readable message about a WooCommerce failed order, using the following details:\n\nOrder ID: {{$json.fields.order_id}}\nInvoice Amount: {{$json.fields.invoice_amount}} {{$json.fields.currency}}\nCustomer Name: {{$json.fields.customer_name}}\nCustomer Email: {{$json.fields.customer_email}}\nFailure Reason (Raw): {{$json.fields.failure_reason_raw}}\nFailure Reason (Canonical): {{$json.fields.failure_reason_canonical}}\nAttempts Count: {{$json.fields.attempts_count}}\nOrder Admin URL: {{$json.fields.order_admin_url}}\nRetry Payment URL: {{$json.fields.retry_payment_url}}\n\nWrite a short, professional summary message that includes all important details and tells the support team what action to take.\n"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "bd426bce-a45a-4cad-b750-06097ea2af91",
      "name": "Send Failed Order Alert to Slack1",
      "type": "n8n-nodes-base.slack",
      "position": [
        2480,
        -2432
      ],
      "parameters": {
        "text": "={{ $json.output[0].content[0].text }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09S57E2JQ2",
          "cachedResultName": "n8n"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "23c78a95-3933-4907-8d81-ebe64044b10c",
      "name": "Search records",
      "type": "n8n-nodes-base.airtable",
      "position": [
        800,
        -2432
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appipUxLpxPEKRXrJ",
          "cachedResultUrl": "https://airtable.com/appipUxLpxPEKRXrJ",
          "cachedResultName": "Fake Review Detector"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblP4nfLbKZdHcGFt",
          "cachedResultUrl": "https://airtable.com/appipUxLpxPEKRXrJ/tblP4nfLbKZdHcGFt",
          "cachedResultName": "OrderFailedData"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "=order_id = {{ $json.id }}"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "00ce6b80-a7b5-4678-aa84-9d1e9392a10b",
      "name": "Check Failed Orders (Scheduler)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -272,
        -2528
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "beaeed54-b5c2-44dc-be64-297ad27addb5",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1616,
        -2784
      ],
      "parameters": {
        "text": "=Duplicate failed order detected (no action needed)  Order ID: {{ $json.id }}\nCustomer id: {{ $json.customer_id || 'N/A' }} \nAmount: {{ $json.total }} {{ $json.currency }}  \nThis failed order was already logged in Airtable earlier. No new record was created and no further action is required. \n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09S57E2JQ2",
          "cachedResultName": "n8n"
        },
        "otherOptions": {
          "includeLinkToWorkflow": true
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "673d19ea-3c0c-4bac-8d55-48ed370d677d",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        -2720
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 384,
        "content": "## Workflow Start & Domain Setup\nThis section starts the workflow on a schedule and defines the WooCommerce domain dynamically. It ensures the automation runs consistently and allows easy switching between test, staging, or production domains without modifying the API request settings."
      },
      "typeVersion": 1
    },
    {
      "id": "6fe9b56a-a0cc-4f1a-8458-3ea4533e735d",
      "name": "Set WooCommerce Domain2",
      "type": "n8n-nodes-base.set",
      "position": [
        -80,
        -2528
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3430ea5f-30bf-46ee-9c2f-3ce12af176ca",
              "name": "wc_domain",
              "type": "string",
              "value": "{{YOUR_DOMAIN}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "312c6e2e-b3c3-4884-ba8c-62ad53ca8550",
      "name": "Fetch Failed Orders From WooCommerce2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        240,
        -2528
      ],
      "parameters": {
        "url": "=https://{{$json.wc_domain}}/wp-json/wc/v3/orders?status=failed",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "failed"
            }
          ]
        }
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "67026269-08d3-4988-b3f0-9fede8df3006",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        -2576
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 320,
        "content": "## Create Summary & Send Team Notification\nThis section uses AI to create a concise summary of the failed order and sends it to Slack. It ensures your team receives a clear, actionable alert so they can quickly follow up, retry payments, or contact the customer when needed."
      },
      "typeVersion": 1
    },
    {
      "id": "c677ac86-ac73-4a64-859e-bdf507f1bb77",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1568,
        -2576
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 320,
        "content": "## Prepare & Save Failed Orders\nThis section formats the raw data into a clean finance-friendly structure, and stores the final result in Airtable. It ensures every failed order is captured, standardized, and logged for tracking, reporting, and follow-up actions."
      },
      "typeVersion": 1
    },
    {
      "id": "2b1027da-7ef2-4293-ad1b-51b3b8fdf7c8",
      "name": "Process Each Failed Order",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        480,
        -2528
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "b4249d93-b08c-4003-bd5c-fc3b6885c4ad",
      "name": "Attach Search Result to Order",
      "type": "n8n-nodes-base.merge",
      "position": [
        1072,
        -2496
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "ca1544f7-de19-4a71-8319-b2e258f2e184",
      "name": "Is Order Already Logged?",
      "type": "n8n-nodes-base.if",
      "position": [
        1264,
        -2496
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "d0e614a6-d0e9-4ed4-811f-84aa07ca003e",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $items(\"Search records\")[0]?.json?.id }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9ffdf6ce-d0c9-4858-a937-937a1f498b24",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1568,
        -2848
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 224,
        "content": "This odres are already log in table"
      },
      "typeVersion": 1
    },
    {
      "id": "3d14681e-c0fc-4f3a-bdbc-7adf4c5d0e40",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        -2720
      ],
      "parameters": {
        "color": 7,
        "width": 1392,
        "height": 432,
        "content": "## Failed Order Handling & Duplicate Check\nThis block gets all FAILED orders from WooCommerce and handles them one by one. For each order, it checks Airtable using the order_id to see if the order is already saved. The WooCommerce order data and the Airtable search result are combined so the check works safely. Based on this check, the workflow decides what to do next. If the order already exists, it stops to avoid duplicates. If the order is new, it saves the failed order and sends a notification. This helps keep the data clean and prevents duplicate records."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Search records": {
      "main": [
        [
          {
            "node": "Attach Search Result to Order",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Format Order Data1": {
      "main": [
        [
          {
            "node": "Save Failed Order to Airtable1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set WooCommerce Domain2": {
      "main": [
        [
          {
            "node": "Fetch Failed Orders From WooCommerce2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Order Already Logged?": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format Order Data1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Each Failed Order": {
      "main": [
        [],
        [
          {
            "node": "Search records",
            "type": "main",
            "index": 0
          },
          {
            "node": "Attach Search Result to Order",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Attach Search Result to Order": {
      "main": [
        [
          {
            "node": "Is Order Already Logged?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Failed Order to Airtable1": {
      "main": [
        [
          {
            "node": "Generate Slack Summary Message 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Failed Orders (Scheduler)": {
      "main": [
        [
          {
            "node": "Set WooCommerce Domain2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Slack Summary Message 1": {
      "main": [
        [
          {
            "node": "Send Failed Order Alert to Slack1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Failed Orders From WooCommerce2": {
      "main": [
        [
          {
            "node": "Process Each Failed Order",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}