Webhook

Webhook delivery (bot → your middleware)

When the bot emits a message, Landbot POSTs this payload to the webhook URL configured on the APIchat channel.

Outbound only — bot messages only. Customer messages you push to POST /send/{customer_token}/ advance the flow but do NOT fire a webhook back. No authenticity header: APIchat sends no Authorization header and has no outbound-secret field. Authenticate by other means (hard-to-guess URL suffix, IP allowlist of GCP egress ranges, reverse-proxy gate). User-Agent: landbot/webhooks. Retries (diverges from Platform): any non-2xx, including 4xx, is retried on linear backoff (deltas ~5/10/15/20/25 s, ≥6 attempts). To reject permanently you must still return 2xx and discard internally. Timeout ≥30 s. Dedupe on the sentry-trace header (stable across retries).

Body·
required
application/json

APIchat webhook delivery body. Unlike Platform, customer/channel/agent are TOP-LEVEL, not nested per message. Always exactly one entry in messages (no batching).

  • agent
    Type: object ·
    required

    Who emitted the message — shared across the whole envelope (APIchat has no per-message sender). Conditional shape: bot envelopes carry only { id, type }; human-agent envelopes also carry { name, email } from the agent's Landbot account. Switch on type for attribution.

  • channel
    Type: object ·
    required

    The APIchat channel. Note: there is NO channel.type field — its absence is the reliable discriminator that you're reading an APIchat (not Platform) envelope.

  • customer
    Type: object ·
    required

    The customer this conversation belongs to: Landbot identifiers plus the customer's Field bag. Custom Fields set by a Set-Field block appear as ADDITIONAL top-level keys (only on webhooks emitted after the block runs) and may be type-mangled — treat values as strings unless guaranteed otherwise. No Platform-style metadata (agent_id/is_external/country/url/archived).

  • messages
    Type: array ·
    required
Responses
  • 200

    Acknowledged. Return any 2xx; body ignored. Remember 4xx is also retried.

Request Example for postmessage
{
  "messages": [
    {
      "type": "text",
      "timestamp": 1,
      "message": ""
    }
  ],
  "customer": {
    "id": 1,
    "token": "",
    "register_date": 1,
    "name": null,
    "phone": null,
    "email": null,
    "additionalProperty": "anything"
  },
  "channel": {
    "id": 1,
    "name": ""
  },
  "agent": {
    "id": 1,
    "type": "bot",
    "name": "",
    "email": ""
  }
}
No Body