WhatsApp in Dify on the official API, with ZapClaw

In short: ZapClaw posts each WhatsApp message to a Webhook Trigger in a Dify workflow. The workflow reads it, asks your model in an LLM node and replies with one HTTP Request. Messages go through Meta's official Cloud API, and the number keeps working in the WhatsApp Business app on your phone. No relay server and no Meta app of your own.

Connect your number in minutes and give your Dify app a WhatsApp number, on Dify Cloud or on your own install.

Business plan: US$ 29 per month, with unlimited numbers

Start for free See the steps

What you need to connect

You do not need a company tax ID or a verified business to connect. The full checklist.

Why the official API for a Dify app

Why a Webhook Trigger, and not Dify's API

Dify can also run a workflow through its app API (POST /v1/workflows/run), but that call needs an Authorization: Bearer header with the app's API key. A ZapClaw webhook sends only its own headers, so it cannot call that API directly. The Webhook Trigger accepts a plain HTTP request, which is exactly what ZapClaw sends. If you already run a server between ZapClaw and Dify, that server can call the app API instead.

Triggers run only in Workflow apps, not in Chatflow or Agent apps. A self-hosted Dify has had them since version 1.10.0, released in November 2025; on an older install, upgrade first.

Set it up in six steps

  1. In Dify, create a Workflow app. On the canvas, right-click and choose Add Node > Start > Webhook Trigger. Set the method to POST and the content type to application/json.
  2. Add three request body parameters and leave them optional: event as String, data as Object and account as Object. The names must match ZapClaw's keys. A required parameter that is missing keeps the workflow from starting, and the dashboard's test event has no account.
  3. After the trigger, add in this order: a Code node that reads the message, an If-Else that goes on only when text is not empty, an LLM node that writes the answer, a second Code node that builds the reply and an HTTP Request that sends it. The settings of each are below.
  4. In ZapClaw, connect your number, create an API key and paste the trigger's test URL under Webhook. Under Events to receive, leave only Inbound messages checked: every delivery status would otherwise start a run, and on Dify Cloud each run counts against the trigger quota. In Dify, click Run this step on the trigger, then send a WhatsApp message to your number from another phone. The trigger's Last Run tab shows what arrived.
  5. Publish the workflow, and in ZapClaw replace the test URL with the trigger's webhook URL.
  6. Send another WhatsApp message from the other phone: the workflow answers it.

The two Code nodes

Both run Python. In the first, map the input variables event, data and account to the trigger's outputs, and declare three String outputs: sender, customer and text. Anything that is not an incoming text leaves text empty, so status updates and the test event end at the If-Else and your own replies never loop.

def main(event: str, data: dict, account: dict) -> dict:
    data = data or {}
    account = account or {}
    text = ""
    if event == "message.received" and data.get("type") == "text":
        text = (data.get("text") or {}).get("body") or ""
    return {
        "sender": str(account.get("display_phone_number") or account.get("phone_number_id") or ""),
        "customer": str(data.get("from") or data.get("user_id") or ""),
        "text": text,
    }

In the LLM node, pick your model, write your instructions in the system prompt and put the first Code node's text in the user prompt. In the second Code node, map sender and customer from the first one and reply from the LLM node's text output, and declare one Object output, body. Built in code, the body stays valid JSON whatever quotes or line breaks the model writes.

def main(sender: str, customer: str, reply: str) -> dict:
    return {
        "body": {"from": sender, "to": customer, "text": reply},
    }

To prove the round trip before you set up a model, map reply to the first Code node's text instead: the workflow answers with the text it received.

The HTTP Request node

Free text works within 24 hours of the customer's last message. Outside that window Meta accepts only an approved template: call POST /api/v1/send/template instead.

To try your key before you build the workflow, send the same call from a terminal. A sent message answers 201.

curl -X POST https://api.zapclaw.app/api/v1/send/text \
  -H "X-API-Key: zc_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "from": "15551617409", "to": "15555550100", "text": "Hello from Dify" }'

What reaches the Webhook Trigger

Each message comes as a message.received event, and the trigger hands the workflow its three top-level keys: event, data with the message (the text in data.text.body, the sender in data.from, the contact's name in data.contact_name) and account with your number. A media message carries a media_url you download with your API key.

{
  "event": "message.received",
  "sequence": 1042,
  "timestamp": "2026-05-21T14:00:00.000Z",
  "data": {
    "from": "15555550100",
    "user_id": "US.1A2B3C4D5E6F7G8H9I0J",
    "contact_name": "Maria Silva",
    "contact_username": "maria_lima",
    "message_id": "wamid.HBg...",
    "type": "text",
    "timestamp": "1747836000",
    "text": { "body": "Hello" }
  },
  "account": {
    "phone_number_id": "964283400112599",
    "display_name": "My Business",
    "display_phone_number": "+1 555 161-7409"
  }
}

Every request carries an X-ZapClaw-Signature header, an HMAC-SHA256 of the raw body keyed with your signing secret: how to verify it. Dify's Webhook Trigger extracts fields and headers but does not document a way to read the raw body the signature covers, so keep the trigger's URL to yourself, like a password.

Good to know

What it costs

Meta bills its WhatsApp message fees to you directly, with no ZapClaw markup. Every plan and price.

Who it is for

Teams that build their AI in Dify and want it on WhatsApp: answers from a knowledge base, lead qualification, first-line support. Agencies connect their clients' numbers on the Agency plan, each client isolated from the others. It does not fit bulk broadcasting.

Go further

Sources

Checked on 15 October 2026. Dify changes quickly, so if a setting looks different, check the source.

Put your Dify app on WhatsApp today

Start on the free plan: one number, no card. Move to the Business plan when you need more numbers or more messages.

Start for free Read the webhook docs