Top
Webhooks

Real‑time Webhooks for Modern Integrations

Receive instant, secure callbacks when events occur in your B21 account. Build reactive systems, reduce polling, and ship faster with verified deliveries.

Instant
Realtime delivery
Verified
HMAC signatures
Reliable
Auto retries
curl -X POST https://your-app.example/webhook \\
  -H "Content-Type: application/json" \\
  -H "B21-Signature: $SIGNATURE" \\
  -d '{
    "id": "evt_123",
    "type": "payment.succeeded",
    "data": {"object": {"id": "pay_123", "amount": 10000, "currency": "NGN"}}
  }'
Reduced Polling

Stop wasting API calls; react the moment something happens.

Event Coverage

Payments, transfers, disputes, accounts — all in one stream.

Trust & Security

Signed requests, HTTPS only, and timestamp verification.

Webhook Payload Examples

Click any code to copy
curl -X POST https://your-app.example/webhook \\
  -H "Content-Type: application/json" \\
  -H "B21-Signature: $SIGNATURE" \\
  -d '{
    "id": "evt_123",
    "type": "payment.succeeded",
    "data": {"object": {"id": "pay_123", "amount": 10000, "currency": "NGN"}}
  }'
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.get('B21-Signature');
  const expected = crypto.createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
  if (signature !== expected) return res.status(401).send('Unauthorized');
  const event = JSON.parse(req.body);
  // switch(event.type) { ... }
  res.status(200).send('OK');
});
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_B21_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $payload, $_ENV['WEBHOOK_SECRET']);
if (!hash_equals($expected, $signature)) { http_response_code(401); exit('Unauthorized'); }
$event = json_decode($payload, true);
// handle $event['type']
echo 'OK';
from flask import Flask, request
import os, hmac, hashlib, json
app = Flask(__name__)
@app.post('/webhook')
def webhook():
    payload = request.data
    signature = request.headers.get('B21-Signature', '')
    expected = hmac.new(bytes(os.getenv('WEBHOOK_SECRET'),'utf-8'), payload, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, signature): return ('Unauthorized', 401)
    event = json.loads(payload)
    # handle event['type']
    return ('OK', 200)

Popular Events

payment.created payment.succeeded payment.failed transfer.completed dispute.created account.updated

Setup in 4 steps

1
Create endpoint
Expose a POST URL to receive events
2
Configure in Dashboard
Add URL and select events
3
Verify signature
Compare HMAC using your secret
4
Handle events
Switch on event type and process

Security & Best Practices

HMAC signatures
Sign and verify every request
Timestamp check
Prevent replay attacks
Retries
Automatic exponential backoff
HTTPS only
Enforce TLS for delivery

Start receiving webhooks in minutes

Plug into payments, transfers, disputes and more — instantly.

Webhooks

Real-time notifications for your application when events occur in your B21 account

What are Webhooks?

Webhooks are HTTP callbacks that B21 sends to your application when specific events occur. Instead of polling our API for changes, webhooks allow you to receive real-time notifications, making your integration more efficient and responsive.

Real-time Updates

Get instant notifications when events occur

Reduced API Calls

No need to constantly poll for updates

Automatic Sync

Keep your systems in sync automatically

Secure Delivery

Cryptographically signed for security

Available Event Types

Payment Events

  • payment.created
  • payment.succeeded
  • payment.failed
  • payment.canceled
  • payment.refunded

Transfer Events

  • transfer.created
  • transfer.processing
  • transfer.completed
  • transfer.failed
  • transfer.reversed

Account Events

  • account.updated
  • account.verified
  • account.suspended
  • balance.updated

Dispute Events

  • dispute.created
  • dispute.updated
  • dispute.resolved
  • dispute.closed

Setting Up Webhooks

1

Create Endpoint

Create an HTTP endpoint in your application to receive webhook events

2

Configure Webhook

Add your endpoint URL in the B21 dashboard and select events to receive

3

Verify Signature

Implement signature verification to ensure webhook authenticity

4

Handle Events

Process the webhook events and update your application accordingly

Example Webhook Endpoint

// Node.js/Express example const express = require('express'); const crypto = require('crypto'); const app = express(); app.use(express.raw({type: 'application/json'})); app.post('/webhook', (req, res) => { const signature = req.get('B21-Signature'); const payload = req.body; // Verify webhook signature const expectedSignature = crypto .createHmac('sha256', process.env.WEBHOOK_SECRET) .update(payload) .digest('hex'); if (signature !== expectedSignature) { return res.status(401).send('Unauthorized'); } const event = JSON.parse(payload); // Handle the event switch (event.type) { case 'payment.succeeded': handlePaymentSucceeded(event.data); break; case 'payment.failed': handlePaymentFailed(event.data); break; default: console.log('Unhandled event type:', event.type); } res.status(200).send('OK'); });

Webhook Payload Examples

JSON
{
  "id": "evt_1234567890",
  "type": "payment.succeeded",
  "created": "2025-08-02T23:31:00Z",
  "data": {
    "object": {
      "id": "pay_1234567890",
      "amount": "10000",
      "currency": "NGN",
      "status": "succeeded",
      "customer": {
        "id": "cus_1234567890",
        "email": "customer@example.com",
        "name": "John Doe"
      },
      "created_at": "2025-08-02T23:30:00Z",
      "updated_at": "2025-08-02T23:31:00Z"
    }
  }
}
JSON
{
  "id": "evt_0987654321",
  "type": "transfer.completed",
  "created": "2025-08-02T23:31:00Z",
  "data": {
    "object": {
      "id": "txf_0987654321",
      "amount": "50000",
      "currency": "NGN",
      "status": "completed",
      "recipient": {
        "account_number": "1234567890",
        "bank_code": "044",
        "name": "Jane Smith"
      },
      "created_at": "2025-08-02T23:25:00Z",
      "completed_at": "2025-08-02T23:31:00Z"
    }
  }
}
JSON
{
  "id": "evt_1122334455",
  "type": "dispute.created",
  "created": "2025-08-02T23:31:00Z",
  "data": {
    "object": {
      "id": "dp_1122334455",
      "payment_id": "pay_1234567890",
      "amount": "10000",
      "currency": "NGN",
      "reason": "fraudulent",
      "status": "warning_needs_response",
      "created_at": "2025-08-02T23:31:00Z"
    }
  }
}

Security & Best Practices

B21 webhooks include several security features to ensure the integrity and authenticity of the data you receive.

HMAC Signatures

Every webhook is signed with HMAC-SHA256

Timestamp Verification

Prevent replay attacks with timestamps

Automatic Retries

Failed deliveries are automatically retried

HTTPS Only

All webhooks are delivered over HTTPS