Choose the scope
UsePOST /v1/project-webhooks for whatsapp.phone_number.created and whatsapp.phone_number.disconnected.
Use POST /v1/phones/{phoneNumberId}/webhooks for whatsapp.message.received, whatsapp.message.sent, whatsapp.message.delivered, whatsapp.message.read and whatsapp.message.failed.
Both accept public HTTPS url, secret (32–512 characters), events and optional active. Store the secret securely. The reference includes list, update and delete operations.
Verify each delivery
Headers areX-Webhook-Event, X-Webhook-Signature and X-Idempotency-Key. The signature is the hex HMAC-SHA256 of the exact raw body using your webhook secret, without a sha256= prefix.
Read raw bytes before JSON parsing. Compute the HMAC, compare in constant time and reject invalid signatures. Reserializing JSON can change bytes and invalidate the signature.
Handle retries
Delivery is at least once. PersistX-Idempotency-Key to avoid repeating business actions. Acknowledge with 2xx after safely accepting the event, then process expensive work asynchronously. Do not assume fixed retry timing or guaranteed event order.
The older administrative subscriber destination uses different headers. Do not use its x-watahub-delivery-id in your developer webhook handler.