Skip to content
Reference/Webhooks/Register Webhook

Register Webhook

POSThttps://public.leadpattern.com/v2/webhook/register
Plan: webhooksapplication/json60 req/min

Register an endpoint to receive real-time event notifications. Use https:// — http:// is accepted, but deliveries (payloads, custom headers, credentials) are then unencrypted and the response includes a warnings array saying so. Private and internal addresses are rejected with 400. Signing is opt-in on the public API (recommended): pass generateSecret: true and the response contains a generated signing secret — shown only once, so store it immediately — or pass your own secret (16–128 chars). Without either, deliveries are unsigned. See the Webhooks Guide for verification. Deliveries are always a JSON POST; optional custom headers and a Bearer/Basic Authorization header are sent with each one. Payloads include waId (phone number) for standard contacts, or bsuid + username (Business-Scoped User ID) for opted-in contacts that have not shared their phone number.

  • Before saving, LeadPattern POSTs a signed test event (event: "test") to the URL with the configured headers, authorization and secret. Any 2xx response within 10 seconds passes; anything else returns 422 and nothing is saved.
  • Signing is opt-in on the public API (recommended). Send generateSecret: true to get a generated secret (returned once as data.secret), or secret to supply your own (16–128 chars, never echoed). With neither, deliveries are unsigned (hasSecret: false) and carry no signature headers.
  • Use the canonical lowercase event names below — they are also the values that arrive as `event` in the delivered payload.
  • Unrecognised names are skipped and returned in invalidWebhooks; if none of them are recognised the request fails with 400.
  • Deliveries are always a JSON POST. method, bodyFormat, retryOnTimeout, body and query are accepted only with harmless values (POST, JSON, true, empty) for compatibility — retryOnTimeout: false returns 400 because timeouts are always retried. wabaNumbers is accepted and ignored.
  • https:// is recommended. http:// URLs are accepted, but deliveries — including custom headers and authorization credentials — are sent unencrypted; the response then includes a warnings array and the webhook has insecure: true.
  • headers is a { "Header-Name": "value" } map (max 20). Reserved names are rejected: Host, Content-Length, Content-Type, User-Agent, Expect, Proxy-Authorization, Connection, Keep-Alive, Transfer-Encoding, Upgrade and any X-Webhook-* header.

Headers

1 field
Authorizationstring
required
Your API key. Sent raw (e.g. 'lp_...'). No Bearer prefix required.

Body Parameters

11 fields
namestring
required
Webhook name.
urlstring
required
Public endpoint URL. https:// is recommended; http:// is accepted but deliveries are unencrypted, so the response includes a warnings entry. Private and internal addresses (localhost, 10.x, 192.168.x, metadata endpoints, …) return 400 "Invalid webhook URL: …". Must be unique within the project — a URL that is already registered returns 409.
webhookEventsarray<enum>
required
Events to subscribe to (non-empty, canonical lowercase names).
generateSecretboolean
optional
true → LeadPattern generates a signing secret and returns it ONCE as data.secret. Mutually exclusive with secret. Omit both for unsigned deliveries.
secretstring
optional
Your own signing secret (16–128 characters). Stored, never echoed back. Mutually exclusive with generateSecret.
headersobject
optionalnullable
Custom HTTP headers sent with every delivery, as a name → value map (max 20), e.g. { "X-Source": "crm" }. Reserved and rejected: Host, Content-Length, Content-Type, User-Agent, Expect, Proxy-Authorization, the hop-by-hop headers Connection / Keep-Alive / Transfer-Encoding / Upgrade, and any X-Webhook-* header.
authorizationobject
optionalnullable
Sent as the Authorization header on every delivery. Over http:// it travels unencrypted — use https://.
typeenum
required
BEARER → `Authorization: Bearer <payload>`. BASIC → `Authorization: Basic base64(<payload>)`. NONE → no Authorization header (clears a saved one).
Allowed values:
BEARERBASICNONE
payloadstring
optional
Required for BEARER / BASIC. BEARER: the token. BASIC: `username:password`.
methodenum
optional
Compatibility only — deliveries are always POST. Any other value returns 400.
Allowed values:
POST
bodyFormatenum
optional
Compatibility only — deliveries are always JSON. Any other value returns 400.
Allowed values:
JSON
retryOnTimeoutboolean
optional
Compatibility only — true is accepted and ignored (timeouts are always retried). false returns 400.
wabaNumbersarray<string>
optional
Compatibility only — accepted and ignored (a workspace has one WhatsApp number). invalidWabaNumbers in the response is always empty.

Responses

JSON Response
{
  "type": "success",
  "data": {
    "webhookId": "664abc123def456789012345",
    "secret": "whsec_3b9f0c…",
    "validWebhooks": [
      {
        "webhookId": "664abc123def456789012345",
        "webhookEventType": "message_received"
      },
      {
        "webhookId": "664abc123def456789012345",
        "webhookEventType": "conversation_closed"
      },
      {
        "webhookId": "664abc123def456789012345",
        "webhookEventType": "chat_assigned"
      }
    ],
    "invalidWebhooks": [],
    "invalidWabaNumbers": [],
    "webhook": {
      "id": "664abc123def456789012345",
      "name": "My Webhook",
      "url": "https://example.com/hook",
      "events": [
        "message_received",
        "conversation_closed",
        "chat_assigned"
      ],
      "isActive": true,
      "disabledReason": null,
      "failureCount": 0,
      "lastFailureAt": null,
      "hasSecret": true,
      "insecure": false,
      "headers": {
        "X-Source": "••••••"
      },
      "authorization": {
        "type": "BEARER",
        "configured": true
      },
      "createdAt": "2026-06-01T09:00:00.000Z",
      "updatedAt": "2026-06-01T09:00:00.000Z"
    }
  }
}

Sample Request Body

{
  "name": "My Webhook",
  "url": "https://example.com/hook",
  "webhookEvents": [
    "message_received",
    "conversation_closed",
    "chat_assigned"
  ],
  "generateSecret": true,
  "headers": {
    "X-Source": "leadpattern"
  },
  "authorization": {
    "type": "BEARER",
    "payload": "your-secret-token"
  }
}