Skip to content
Linq Copy agent prompt
Webhooks

Webhooks

Register endpoints, verify deliveries, rotate secrets, and replay safely.

Register a destination with POST /v1/webhook_endpoints. The created response returns signing-secret material once; store it immediately in a secret manager. Endpoint reads expose configuration and health, never the secret value.

Verify every request against the exact raw body before parsing JSON. Respond quickly after durable acceptance in your system, and process asynchronously. Use the event ID as the deduplication key.

Deliveries to one endpoint and chat are sent in the order their events were recorded. A message.received for a message with attachments can be recorded once its attachments are captured or have failed, or ten minutes after the message arrived, so it can follow deliveries for later messages of the same chat with a lower data.seq_from. Never discard it as stale: deduplicate by event ID and order the chat by data.seq_from. See Events and recovery → Messages with attachments.

GET /v1/webhook_deliveries exposes delivery attempts and outcomes. If a bounded historical range needs redelivery, create a replay under the endpoint and poll that replay’s status. Replay creation has its own idempotency key; use a stable key when retrying the same replay request.

Adding a signing secret starts a rotation window. Deploy verification for both active secrets before retiring the old one. Disabling an endpoint is a cutoff, not a pause: events produced while disabled are not silently queued for later.

By default an endpoint receives events for every number the account has now and adds later; endpoint reads report phone_number_ids as null. To narrow it, pass phone_number_ids on POST /v1/webhook_endpoints or PATCH /v1/webhook_endpoints/{endpoint}: up to 100 exact ids from GET /v1/phone_numbers (see the phone numbers guide). The endpoint then receives only the chat events of those numbers. Account-wide events that carry no phone number reach only unscoped endpoints, so keep one unscoped endpoint if you need them.

An id the account cannot use — unknown, another account’s, the other mode’s, or not an active number of this account — is refused with HTTP 422 and error.code 1041. The pointer is the list, /phone_number_ids, never the id, so a refusal does not say whose number it is; only a malformed id (empty, or over 128 bytes) is pointered at its own index, /phone_number_ids/{i}. Either way nothing is created or changed.

An update replaces the list outright; an empty array restores every current and future number. The change affects only events fanned out after the update: deliveries already queued keep their destination, and a replay accepted earlier keeps the scope it was accepted under. Field details are on the create and update reference pages.