Webhooks & Event Handling
Webhooks power the most important parts of your system: receiving Bitcoin, settling fiat, delivering airtime, or triggering a downstream event. They are the bridge between Bitnob and your app when something changes — and they must be handled with care.
This guide teaches you how to build a robust webhook system: one that can handle retries, duplicate messages, bad payloads, delayed delivery, and even downstream service outages.
How Webhooks Work
A webhook is an HTTP request Bitnob sends to your server when something happens. Instead of you polling an endpoint to see “has this payment arrived?”, Bitnob notifies you the moment it’s confirmed.
For example, when a user sends BTC and it clears, Bitnob sends:
Webhook Flow Overview

What You Get from Bitnob
Bitnob supports:
Secure webhook delivery for all asynchronous flows
A dashboard to inspect webhook logs, payloads, and retry attempts
Webhooks for offramps, swaps, airtime, and payment confirmations
Writing a Webhook Handler
Use a backend route that accepts POST requests with a JSON payload.
Example in Node.js:
// ...existing code...
Writing a Webhook Handler
Use a backend route that accepts POST requests with a JSON payload.
Example in Node.js:
Key things to remember:
Respond with 200 OK quickly to prevent retries.
Do not block this handler with long-running DB calls or downstream logic (consider using a queue).
Log every webhook attempt with timestamp and reference.
Bitnob Webhook Retry Behavior
Bitnob retries if:
Your endpoint is offline or times out
Your server returns a 4xx or 5xx
You don't acknowledge the webhook with a 200 OK
idempotency means processing a webhook once and only once, no matter how many times it is received.
Without idempotency, you may:
Send multiple offramps for the same crypto payment
Deliver airtime multiple times (especially dangerous if the amount is large)
Trigger double card funding or duplicate messages to a user
Corrupt internal logs by writing duplicate events with different timestamps
Real-World Failure Example
Before processing any event, check if that reference has already been marked as processed in your database.
Bitnob sends airtime.delivered
Your webhook server receives it but times out before responding
Bitnob retries
Your app processes it again → duplicate airtime top-up sent
How to Fix It
Suggested Database Schema
Every time you create a quote, store it alongside your transaction or UI session.
id | reference | event | status | received_at |
---|---|---|---|---|
a | tx_123abc | airtime.deleivered | processed | 2025-04-08T14:20 |
This makes auditing, debugging, and duplicate suppression easy.

Recommended Webhook Architecture (with Queue)
This decouples fast acknowledgment (step B) from slow logic (step D). Bitnob gets a 200 OK immediately. You process the event asynchronously in the background. Use queues like:
BullMQ or BeeQueue (Node.js)
Sidekiq or Sneakers (Ruby)
Celery (Python)
Redis Streams or Kafka (at scale)
Securing Your Webhooks
Signature Verification
If Bitnob provides webhook signatures (e.g., in a header like X-Bitnob-Signature), verify the payload:
IP Whitelisting
If Bitnob publishes webhook IP ranges, restrict your endpoint to only accept requests from those addresses.
HTTPS Required
Always use https:// URLs for your webhook. Never expose webhooks over HTTP.
Testing and Debugging Webhooks
For local development:
Use ngrok, localtunnel, or cloudflared to expose your local server
Simulate a transaction (e.g., simulate deposit in sandbox)
Use webhook inspection tools to replay and analyze events
You can also log webhook attempts using a simple logger:
For production observability, log:
Event type
Reference
Timestamp
Delivery status (received, retried, failed)
What to Always Do
Handle webhooks in a dedicated endpoint
Respond with 200 OK fast
Always make your logic idempotent
Log everything (reference, type, status)
Use a queue if your processing takes time
Verify signatures to secure the source
Use the Bitnob dashboard to inspect payloads and retry if needed
Webhooks are your single source of truth for offchain confirmations. If you treat them like production infrastructure, your product will feel real-time, even though the underlying rails (blockchain, fiat, telcos) are asynchronous and imperfect.