Webhook types
All available webhook types are included in the WebhookType enum. Example payloads for each can be found in our Event Types guide.
Creating webhooks
To create a webhook via the API:
mutation WebhookCreate($input: WebhookCreateInput!) { webhookCreate(input: $input) { id url type status secret headers { key } }}Important: Save the
secretvalue when you create the webhook — it's only returned here, and you'll need it to verify webhook signatures. See Verifying webhook signatures below.
Edit webhook details
To edit an existing webhook via the API:
mutation WebhookUpdate($input: WebhookUpdateInput!) { webhookUpdate(input: $input) { id url type status }}Verifying webhook signatures
Every webhook request Zonos sends includes a zonos-signature header so you can confirm the request actually came from Zonos and that the payload wasn't altered in transit.
The header value has the format:
timestamp=<unix-timestamp-ms>,hmac=<base64-encoded-signature>
timestamp— the time, in Unix epoch milliseconds, the request was signed.hmac— an HMAC-SHA256 signature of the raw JSON request body, computed using your webhook's secret as the key and Base64-encoded.
To verify a request:
- Parse the
timestampandhmacvalues out of thezonos-signatureheader. - Compute your own HMAC-SHA256 signature over the raw, unparsed request body, using the secret you received when you created the webhook.
- Compare your computed signature to the
hmacvalue using a constant-time comparison, and reject the request if they don't match. - Optionally reject requests where
timestampis older than a few minutes to guard against replay of a captured request. Zonos doesn't enforce a delivery window itself, so this check is up to you.
const crypto = require("crypto"); function verifyZonosWebhook(rawBody, signatureHeader, secret) { const [timestampPart, hmacPart] = signatureHeader.split(","); const receivedHmac = hmacPart.split("=")[1]; const expectedHmac = crypto .createHmac("sha256", secret) .update(rawBody) .digest("base64"); const receivedBuffer = Buffer.from(receivedHmac); const expectedBuffer = Buffer.from(expectedHmac); if (receivedBuffer.length !== expectedBuffer.length) { return false; } return crypto.timingSafeEqual(receivedBuffer, expectedBuffer);}Note: If you configured custom headers on your webhook, those are also included verbatim on every request alongside
zonos-signature.
View webhook logs
To view webhook logs via the API:
query WebhookLogs($first: Int$after: String$filter: WebhookLogsFilterInput) { webhookLogs(first: $first, after: $after, filter: $filter) { edges { node { id type url createdAt responseStatus } } }}
Listen to events with webhooks
Get real-time event notifications for your Zonos integration.
Webhooks provide a way for Zonos to proactively notify your external systems whenever certain events take place. When the subscribed event occurs, Zonos will send an HTTP POST request to the webhook URL you specify. The request body will contain the event details, allowing your system to handle the event programmatically.
Webhooks are useful for integrating Zonos with other platforms, triggering automated workflows, and keeping data in sync across systems in real-time. For example, you could use webhooks to: