Navigation

Webhooks

Receive real-time notifications when events occur in your BillerAPI integration.

Overview

Webhooks allow BillerAPI to push event notifications to your server in real time. Instead of polling for changes, register a webhook URL and we'll send HTTP POST requests when events occur.

Registering a Webhook

cURL
curl -X POST https://sandbox.api.billerapi.com/iam/clients/{clientId}/webhooks \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <jwt_token>" \
  -d '{
    "environment": "sandbox",
    "url": "https://your-server.com/webhooks/billerapi",
    "events": ["bill.created", "bill.updated", "account-link.created"],
    "secret": "whsec_your_signing_secret"
  }'

Payload Format

Every webhook delivery sends a JSON payload with a consistent envelope structure. The data field contains minimal resource IDs — fetch full details from the API.

Payload Envelope
{
  "event_type": "bill.created",
  "event_id": "evt_abc123",
  "timestamp": "2026-03-27T10:00:00Z",
  "client_id": "client_xyz",
  "data": {
    "bill_id": "bill_456",
    "account_link_id": "link_789",
    "client_user_id": "user_123"
  }
}

HTTP Headers

HeaderDescription
X-Webhook-Event-TypeEvent type (e.g., bill.created)
X-Webhook-IdUnique event ID for deduplication
X-Webhook-TimestampISO 8601 timestamp of the event
X-Webhook-Client-IdYour client ID
X-Webhook-SourceAlways billerapi
X-Webhook-SignatureHMAC-SHA256 signature (if secret provided)

Event Reference

Click an event to see its full payload example and recommended handling.

EventDescriptionKey Data
request-to-link.createdA new link request was created
request_to_link_idclient_user_id+2
request-to-link.updatedA link request status changed
request_to_link_idclient_user_id
account-link.createdAn account was successfully linked
account_link_idclient_user_id+1
account-link.updatedA linked account status changed
account_link_idclient_user_id
link.createdA link session was initiated
link_idlink_session_id
link.updatedA link session state changed
link_idlink_session_id
bill.createdA new bill was discovered
bill_idaccount_link_id+1
bill.updatedA bill was updated
bill_idaccount_link_id
link-session.createdA Connect session started
link_session_id
link-session.updatedA Connect session progressed
link_session_id

Event Details

Webhook Security

If you provide a secret when registering your webhook, every delivery includes an HMAC-SHA256 signature in theX-Webhook-Signature header. Always verify this signature before processing events.

Verify webhook signature
import crypto from 'crypto';

function verifyWebhookSignature(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body, 'utf8')
    .digest('base64');

  const received = signature.replace('sha256=', '');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(received),
  );
}

// In your webhook handler:
app.post('/webhooks/billerapi', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    process.env.WEBHOOK_SECRET,
  );

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the event...
  res.status(200).json({ received: true });
});

Always verify signatures

Without signature verification, an attacker could forge webhook payloads to your endpoint. Use a timing-safe comparison to prevent timing attacks.

Retry Policy

If your endpoint returns a non-2xx status code or doesn't respond within 10 seconds, we retry with exponential backoff.

  • Your endpoint must respond within 10 seconds
  • Return any 2xx status to acknowledge receipt
  • Failed deliveries are retried with exponential backoff
  • Use the X-Webhook-Id header for deduplication

Tip

Process webhooks asynchronously. Acknowledge receipt immediately with a 200 response, then process the event in a background job to avoid timeout issues.

Testing with Sandbox

Use the sandbox trigger endpoint to simulate webhook events and test your handler.

Trigger a test webhook event
cURL
curl -X POST https://sandbox.api.billerapi.com/sandbox/trigger-event \
  -H "Content-Type: application/json" \
  -H "X-Client-ID: your_client_id" \
  -H "X-Client-Secret: your_client_secret" \
  -d '{
    "event_type": "bill.created",
    "client_id": "your_client_id",
    "webhook_url": "https://your-server.com/webhooks/billerapi",
    "webhook_secret": "whsec_your_signing_secret"
  }'

Note

Sandbox webhook delivery includes all the same headers as production, including HMAC-SHA256 signatures when you provide a secret.

Related