Skip to main content
When a webhook does not arrive, the cause is almost always on the delivery path: the URL is not publicly reachable, a firewall blocks our sender, or your endpoint rejected the event or the retries were spent. Work through these in order.

1. Your endpoint must be publicly reachable

Webhook notifications are only delivered to a publicly accessible URL. While building locally, events cannot reach localhost. Fix: expose your local server with a tunnel such as ngrok or localtunnel, then update the webhook URL setting on your dashboard. Only do this in your test environment to avoid leaking data to the public.

2. Your firewall may be blocking us

If your infrastructure restricts inbound traffic, allow requests from our webhook delivery addresses: These addresses can change; we announce changes ahead of time. An allowlist is not a substitute for verifying the x-bitnob-signature header, which stays correct even if our infrastructure moves.
Don’t allowlist by IP alone. Any host can send a request from an allowlisted address. Always validate the signature on every event, whether or not you filter by IP.

3. Your endpoint rejected the event, or the retries ran out

Any 2xx counts as delivered. A 400, 404, 410, 422, or 451 is treated as a permanent rejection, and the event is never retried. Anything else, including a timeout, is retried with increasing delays (by default about 1, 5, 15, and 60 minutes), up to the retry count set on your webhook: 1 to 5 attempts in total. After that, the event is not sent again. Common ways to lose an event:
  • a route mismatch returned 404, or validation in your handler returned 400 or 422, so the first failure was final,
  • your endpoint was down or redeploying for longer than the retry window,
  • it did heavy processing synchronously before responding, and timed out on every attempt.
Fix: respond with a 2xx immediately and process asynchronously. If processing fails temporarily, return a 5xx so the event is retried. Make handling idempotent, since the same event can be delivered more than once. See Retries and duplicates.

4. Verify the signature while debugging

If events arrive but appear to be dropped by your own handler, check signature verification. Validate the x-bitnob-signature header: an HMAC SHA-512 (hex) of the raw request body, keyed with the webhook secret set in your dashboard. Signing with your API client secret, or over re-serialized JSON, never matches.
A handler that silently skips unverified events looks identical to “no webhook received”. Log verification failures explicitly.

Don’t rely on webhooks entirely

We recommend that you set up a service to always query transactions, in the event that webhooks keep failing.
Polling is your safety net, not a fallback you add later. For payouts specifically, store the payout id and track status via GET /api/payouts/{id}, so a missed webhook never leaves a transaction in an unknown state.