{
  "name": "Payment reminders on WhatsApp that stop when the customer says \"paid\"",
  "nodes": [
    {
      "parameters": {
        "content": "What you get: a daily reminder to customers with an open invoice, and an automatic stop (plus a CRM note) the moment they reply that they paid.\nWhat it replaces: manual chasing, spreadsheets of \"who did I remind\", and reminders sent to people who already paid.\nSetup time: about 15 minutes.\n\nPolite, persistent, and it never nags someone who has already paid.\n\nWorks with a normal WhatsApp number — no Meta Business account needed.\n\nTwo independent triggers live in this one workflow: a daily Schedule Trigger (left branch) and a Webhook node fed by WASync (right branch), instead of the WASync Trigger. The Bitrix24 fields used here (deal stage ID, and the custom fields for amount/due date) are placeholders -- adjust them to match your own pipeline before activating.\n\nSetup:\n1. Create an API key at https://developers.wasync.app/keys (scopes: whatsapp.send (add whatsapp.events too if you'll use the optional Register Webhook node)).\n2. In n8n, go to Credentials -> New -> Header Auth. Name the credential \"WASync API key\". Set its Name field to `Authorization` and its Value field to `Bearer wsk_live_<your key>`.\n3. Open the \"Settings\" node at the top of this workflow and fill in your own values. Never commit real portal URLs, tokens, connection ids, or phone numbers.\n\nPoint WASync at this workflow's Webhook node: copy its Production URL (Webhook node -> double-click -> \"Production URL\"), then either paste it at developers.wasync.app (Webhooks section) for event `message.received`, or call `PUT https://developers.wasync.app/api/v1/webhook` with `{\"url\": \"<that URL>\"}` using your API key. The disabled \"Register WASync Webhook (one-time)\" HTTP Request node below does the same call -- fill in the URL, enable it, execute it once, then disable it again (PUT is idempotent, so running it again just moves the endpoint).\n\nThis template uses only built-in n8n nodes, so it works on n8n Cloud; if you self-host, you can also use our community node n8n-nodes-wasync.\n\nDocs: https://docs.wasync.app/docs/guides/n8n?utm_source=n8n&utm_medium=template&utm_campaign=t3-http",
        "height": 600,
        "width": 520
      },
      "name": "Read Me First",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -140
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "days",
              "triggerAtHour": 9,
              "triggerAtMinute": 0
            }
          ]
        }
      },
      "name": "Daily 09:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        460
      ]
    },
    {
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "Settings (Reminders)-0",
              "name": "bitrixPortalUrl",
              "value": "https://yourportal.bitrix24.com",
              "type": "string"
            },
            {
              "id": "Settings (Reminders)-1",
              "name": "bitrixWebhookToken",
              "value": "REPLACE_WITH_YOUR_INBOUND_WEBHOOK_TOKEN",
              "type": "string"
            },
            {
              "id": "Settings (Reminders)-2",
              "name": "dealStageIdAwaitingPayment",
              "value": "REPLACE_WITH_YOUR_STAGE_ID",
              "type": "string"
            },
            {
              "id": "Settings (Reminders)-3",
              "name": "wasyncConnectionId",
              "value": "REPLACE_WITH_YOUR_WASYNC_CONNECTION_ID",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "name": "Settings (Reminders)",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        0,
        700
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $('Settings (Reminders)').item.json.bitrixPortalUrl }}/rest/{{ $('Settings (Reminders)').item.json.bitrixWebhookToken }}/crm.deal.list",
        "options": {},
        "sendQuery": true,
        "specifyQuery": "keypair",
        "queryParameters": {
          "parameters": [
            {
              "name": "filter[STAGE_ID]",
              "value": "={{ $('Settings (Reminders)').item.json.dealStageIdAwaitingPayment }}"
            },
            {
              "name": "filter[CLOSED]",
              "value": "N"
            },
            {
              "name": "select[]",
              "value": "ID"
            },
            {
              "name": "select[]",
              "value": "TITLE"
            },
            {
              "name": "select[]",
              "value": "OPPORTUNITY"
            },
            {
              "name": "select[]",
              "value": "CURRENCY_ID"
            },
            {
              "name": "select[]",
              "value": "UF_CRM_DUE_DATE"
            },
            {
              "name": "select[]",
              "value": "UF_CRM_WHATSAPP_PHONE"
            }
          ]
        }
      },
      "name": "List Awaiting-Payment Deals",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        260,
        700
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// crm.deal.list returns one item with a `result` array.\n// Turn each deal into its own item so the WASync send node below sends one reminder per deal.\nconst deals = $input.first().json.result || [];\nreturn deals.map((deal) => ({ json: deal }));"
      },
      "name": "Split Deals",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        520,
        700
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://developers.wasync.app/api/v1/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        },
        "options": {},
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ connectionId: $('Settings (Reminders)').item.json.wasyncConnectionId, to: $json.UF_CRM_WHATSAPP_PHONE, text: 'Hi! This is a friendly reminder that your invoice for \"' + $json.TITLE + '\" (' + $json.OPPORTUNITY + ' ' + $json.CURRENCY_ID + ', due ' + $json.UF_CRM_DUE_DATE + ') is still awaiting payment. Reply *PAID* once you\\'ve sent it, and we\\'ll confirm right away.' }) }}"
      },
      "name": "Send Payment Reminder",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        780,
        700
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "WASync API key"
        }
      }
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "wasync-inbound",
        "responseMode": "onReceived",
        "options": {}
      },
      "name": "WhatsApp Inbound Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        40
      ]
    },
    {
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "Settings (Payment Confirmation)-0",
              "name": "bitrixPortalUrl",
              "value": "https://yourportal.bitrix24.com",
              "type": "string"
            },
            {
              "id": "Settings (Payment Confirmation)-1",
              "name": "bitrixWebhookToken",
              "value": "REPLACE_WITH_YOUR_INBOUND_WEBHOOK_TOKEN",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "name": "Settings (Payment Confirmation)",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        260,
        40
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "Says Paid?-cond0",
              "leftValue": "={{ $('WhatsApp Inbound Webhook').item.json.body.message.text.trim().toUpperCase() }}",
              "rightValue": "PAID",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "Says Paid?-cond1",
              "leftValue": "={{ $('WhatsApp Inbound Webhook').item.json.body.message.text.trim() }}",
              "rightValue": "1",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "name": "Says Paid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        520,
        40
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $('Settings (Payment Confirmation)').item.json.bitrixPortalUrl }}/rest/{{ $('Settings (Payment Confirmation)').item.json.bitrixWebhookToken }}/crm.contact.list",
        "options": {},
        "sendQuery": true,
        "specifyQuery": "keypair",
        "queryParameters": {
          "parameters": [
            {
              "name": "filter[PHONE]",
              "value": "={{ $('WhatsApp Inbound Webhook').item.json.body.message.from }}"
            },
            {
              "name": "select[]",
              "value": "ID"
            }
          ]
        }
      },
      "name": "Find Contact by Phone",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        780,
        40
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $('Settings (Payment Confirmation)').item.json.bitrixPortalUrl }}/rest/{{ $('Settings (Payment Confirmation)').item.json.bitrixWebhookToken }}/crm.deal.list",
        "options": {},
        "sendQuery": true,
        "specifyQuery": "keypair",
        "queryParameters": {
          "parameters": [
            {
              "name": "filter[CONTACT_ID]",
              "value": "={{ $json.result && $json.result[0] ? $json.result[0].ID : '' }}"
            },
            {
              "name": "filter[CLOSED]",
              "value": "N"
            },
            {
              "name": "order[DATE_CREATE]",
              "value": "DESC"
            },
            {
              "name": "select[]",
              "value": "ID"
            }
          ]
        }
      },
      "name": "Find Open Deal",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1040,
        40
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $('Settings (Payment Confirmation)').item.json.bitrixPortalUrl }}/rest/{{ $('Settings (Payment Confirmation)').item.json.bitrixWebhookToken }}/crm.timeline.comment.add",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ fields: { ENTITY_ID: ($json.result && $json.result[0] ? $json.result[0].ID : ''), ENTITY_TYPE: 'deal', COMMENT: 'Customer confirmed payment via WhatsApp (' + $('WhatsApp Inbound Webhook').item.json.body.message.from + ')' } }) }}",
        "options": {}
      },
      "name": "Add Timeline Comment",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1300,
        40
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://developers.wasync.app/api/v1/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        },
        "options": {},
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ connectionId: $('WhatsApp Inbound Webhook').item.json.body.connection_id, to: $('WhatsApp Inbound Webhook').item.json.body.message.from, text: 'Thank you for confirming your payment! We\\'ve noted it on your account.' }) }}"
      },
      "name": "Send Thank You",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1560,
        40
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "WASync API key"
        }
      }
    },
    {
      "parameters": {
        "method": "PUT",
        "url": "https://developers.wasync.app/api/v1/webhook",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        },
        "options": {},
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ url: 'https://YOUR-N8N-INSTANCE/webhook/wasync-inbound' }) }}"
      },
      "name": "Register WASync Webhook (one-time)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        780,
        -140
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "WASync API key"
        }
      },
      "disabled": true
    }
  ],
  "connections": {
    "Daily 09:00": {
      "main": [
        [
          {
            "node": "Settings (Reminders)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Settings (Reminders)": {
      "main": [
        [
          {
            "node": "List Awaiting-Payment Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List Awaiting-Payment Deals": {
      "main": [
        [
          {
            "node": "Split Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Deals": {
      "main": [
        [
          {
            "node": "Send Payment Reminder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WhatsApp Inbound Webhook": {
      "main": [
        [
          {
            "node": "Settings (Payment Confirmation)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Settings (Payment Confirmation)": {
      "main": [
        [
          {
            "node": "Says Paid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Says Paid?": {
      "main": [
        [
          {
            "node": "Find Contact by Phone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Contact by Phone": {
      "main": [
        [
          {
            "node": "Find Open Deal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Open Deal": {
      "main": [
        [
          {
            "node": "Add Timeline Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Timeline Comment": {
      "main": [
        [
          {
            "node": "Send Thank You",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}
