Looking for the inbound side — Meta’s Cloud API webhook that delivers
WhatsApp messages to iZap? That’s internal to iZap’s own WhatsApp connection.
What’s on this page is iZap’s own outbound delivery to your endpoint.
Register an endpoint
url must be https:// on the standard port (443) — a custom port (e.g.
https://example.com:8443/hook) is rejected, as is a private or loopback
address, with 422. subscribed_events can be left as []
to receive every event in the catalog, including ones added later.
The response is the only place the signing secret is ever shown in full:
signing_secret right away — there is no endpoint to read it back later.
If you lose it, rotate it for a new one.
Registering an endpoint requires a plan with event webhooks included. Without
one, the call returns
403 with code: "plan_limit_event_webhooks".Event catalog
The catalog is versioned by addition only — existing event payloads don’t change
shape once shipped, so parsing today’s
message.received stays safe as new event
types are added.
Payload
Headers
A retried or manually resent delivery carries the same
izap-webhook-id and
payload bytes, but a fresh izap-webhook-timestamp and both signatures
recomputed at send time. Once you’ve verified izap-webhook-signature-v2,
izap-webhook-id is safe to use as your idempotency key — v2 signs the id
itself, so a delivery replayed under a different id fails verification.
Dedupe on the id only after that check passes, never on the timestamp or the
signature alone: both change on every retry and resend of the same event.
Verify the signature
izap-webhook-signature-v2 is the recommended check — it’s the only one of
the two that covers izap-webhook-id, which closes a real gap: an attacker
who captures one delivery can replay it inside your timestamp tolerance under
a new izap-webhook-id, and a v1-only check still verifies because v1 never
signed the id. There’s also no other generic signed identifier on the body to
fall back on, and deduping on timestamp + signature doesn’t help either — both
are freshly computed on every retry and resend of the same event.
Legacy: v1 signature
izap-webhook-signature (v1=<hex-hmac>) is still sent on every delivery and
there’s no plan to stop — existing integrations keep working unchanged. It
does not cover izap-webhook-id, so on its own it can’t tell a replayed
delivery under a new id from a genuine new one; prefer
izap-webhook-signature-v2 for new integrations, and
migrate existing ones when convenient.
Delivery and retries
- Your endpoint gets 10 seconds to respond. Anything in
2xxcounts as delivered. 5xxand429responses are retried; any other4xxis treated as a permanent rejection and isn’t retried — return2xxonly once you’ve durably accepted the event.- After 20 consecutive failures an endpoint is automatically disabled
(
enabled: false, withlast_errorset). Re-enable it once your receiver is healthy again — it doesn’t recover on its own.
Manage an endpoint
Rotating invalidates the previous secret immediately — there’s no overlap
window, so update your verification code with the new secret before rotating
in production. A resend replays the original stored bytes, so it verifies
against the same payload the first attempt did.
Scaffold a receiver
izap-wizard webhook receiver writes a starting point that implements this
contract for you.