Skip to main content

Deliveries fail with HTTP 401 on my side

95% of the time: signature mismatch from framework body re-parse. Your framework (Express, FastAPI, Rails, etc.) is probably parsing the JSON body before your handler sees it, then re-serializing when you compute the HMAC. Re-serialization drifts whitespace or key order → signature mismatch. Fix: verify against the raw bytes. In Express, use express.raw({ type: "application/json" }). In FastAPI, use await request.body() before any JSON parsing. See signature verification for code. Second most common: clock skew. Your server’s clock is off by more than 5 minutes. Run timedatectl status (Linux) or check Windows Time service. Sync with NTP.

Every delivery fails with 404

Your webhook URL is wrong. Check the dashboard → Webhooks → the subscription → URL field. A typo in the path or a missing route in your app returns 404 on our side, which we dead-letter without retry (see retries).

Deliveries were working, now they’re all failing

1

Check the delivery log

Dashboard → Webhooks → Delivery log. Click a failed row to see the HTTP status and response snippet. Often your handler logs the error body there.
2

Check if auto-disable fired

If the subscription shows disabled_at set, you crossed the consecutive-failures threshold. Re-enable from the dashboard after fixing the root cause.
3

Check your endpoint's TLS certificate

We do proper certificate validation. An expired or self-signed cert will fail with a TLS handshake error (visible as a connection error in the delivery log).

I got duplicate events

Expected. Retries reuse the same event_id. Also:
  • At-least-once delivery — we don’t guarantee exactly-once. If your 200 response was lost in the network, we’ll retry.
  • Parallel subscriptions — each subscription receives its own delivery. Two subs to the same URL will POST twice for the same event.
Fix: key on event_id in your handler. Store processed IDs in Redis or DB with a TTL >= 7.5 hours (our total retry window).

I’m missing events I should have received

Dashboard → Webhooks → subscription → Event types. The full list is in the event catalog.
Look for disabled_at or is_active: false. Re-enable if appropriate.
Some events have preconditions — e.g. call.ended only fires on calls that reached CHANNEL_HANGUP. A call that never answered fires call.started and nothing else.
Delivery log will show status: pending or status: failed with a next_retry_at. The retry sweep fires every 30s.
See above.

Force a test delivery

Dashboard → Webhooks → your subscription → Test fire. We POST a synthetic event (event_id prefixed with test_) to your endpoint and show you the outcome right in the dashboard — HTTP status, response body, duration. Lets you debug without waiting for real events.

My signing_secret is leaked or lost

Lost: we can’t recover it — only a hash lives on our side. Delete and recreate the subscription. Leaked: delete the subscription immediately. Recreate with a new URL if you can (so attackers who captured the old URL also need to rediscover the new one). Signing-secret rotation without downtime is a v1.1 feature.

Still stuck?

Email support@yotel.in with:
  • The X-Zetta-Delivery header value from a failing delivery
  • Your subscription ID (from the dashboard URL)
  • Timestamp range of the failures
We’ll look at the delivery log on our side and reply with what we see.