Skip to main content

What are Webhooks?

Webhooks let you receive real-time HTTP notifications when funding account, deposit, transfer, withdrawal, or customer verification lifecycle events occur, instead of polling the API for status changes.
Webhooks are the recommended way to track funding account provisioning, deposit settlement, merchant-initiated bank transfers, crypto withdrawal progress, and customer verification changes.

Supported Events

Deposit Events:
EventResourceDescription
deposit.receivedDepositDeposit received (NGN or crypto)
deposit.processingDepositDeposit settlement has started
deposit.requires_reviewDepositDeposit needs review before it can continue
deposit.completedDepositDeposit reached its settlement destination
deposit.failedDepositDeposit failed
deposit.reversedDepositCompleted deposit reversed
Funding Account Events:
EventResourceDescription
funding_account.createdFunding AccountFunding account record created in pending state
funding_account.activeFunding AccountReceive instructions provisioned successfully
funding_account.failedFunding AccountReceive instruction provisioning failed
funding_account.disabledFunding AccountFunding account disabled
Withdrawal Events:
EventResourceDescription
withdrawal.createdWithdrawalWithdrawal request accepted
withdrawal.submittedWithdrawalWithdrawal submitted to chain
withdrawal.completedWithdrawalWithdrawal confirmed on-chain
withdrawal.failedWithdrawalWithdrawal failed
Transfer Events:
EventResourceDescription
transfer.createdTransferTransfer record created
transfer.processingTransferFunds locked and transfer submission queued
transfer.requires_reviewTransferTransfer flagged for manual review
transfer.submittedTransferProvider accepted the transfer submission
transfer.completedTransferTransfer settled after provider success and ledger finalization
transfer.failedTransferTransfer failed terminally
transfer.reversedTransferCompleted transfer reversed
Customer Verification Events:
EventResourceDescription
customer.verification.submittedCustomerVerification submitted for review
customer.verification.approvedCustomerVerification approved
customer.verification.rejectedCustomerVerification rejected
Use transfer.* events for POST /v1/transfers. For deposits, track settlement with deposit.* events; settlement delivery work that Daya performs in the background is not surfaced as a separate payout webhook.

Webhook Configuration

Configure webhook endpoints in your Daya Dashboard:
  1. Navigate to Webhooks
  2. Add your webhook URL
  3. Generate or copy your webhook secret
  4. Subscribe to the events you want to receive
The event_types setting controls which events an endpoint receives. Omit event_types or set it to [] to receive all events. Use a non-empty array, such as ["deposit.received", "deposit.completed"], to receive only those exact event names. Unknown event names are rejected.
Use HTTPS in production. HTTP should be limited to local or sandbox development.

Webhook Payload

All merchant webhooks use the same envelope:
{
  "event": "transfer.completed",
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "id": "650e8400-e29b-41d4-a716-446655440000",
    "status": "SETTLED",
    "rail": "NGN_BANK",
    "reference": "txn_ngn_001"
  },
  "timestamp": "2026-03-10T09:03:00Z"
}

Common Fields

event
string
Event type, such as deposit.completed, transfer.completed, or withdrawal.failed.
id
string
Unique webhook event identifier. Store this value to deduplicate deliveries.
data
object
Resource payload for the event. Funding account events send a funding account object, deposit events send a deposit object, transfer events send a transfer object, withdrawal events send a withdrawal object, and customer verification events send a customer object.
timestamp
string
RFC3339 timestamp for when the event was emitted.
See Webhook Events for the full event list and resource payload mapping.

Delivery Guarantees

Webhooks may be delivered more than once. Your handler must deduplicate repeated deliveries.
Events can arrive out of order. Use the timestamp field to order updates client-side.
If your endpoint returns a non-2xx response or times out, Daya retries with backoff. Build your handler to be safe for repeated delivery.
Respond quickly and offload heavy work asynchronously. Slow handlers increase duplicate deliveries.

Webhook Verification

All webhook requests include an HMAC-SHA256 signature in the X-Daya-Signature header. See Webhook Verification for implementation details.

Implementing a Webhook Endpoint

Your endpoint should:
  1. Verify the signature
  2. Build a stable deduplication key from the payload
  3. Return 2xx quickly
  4. Process the event asynchronously if work is non-trivial
const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

function webhookSubjectId(event) {
  return event.data.id || event.data.deposit_id;
}

function dedupeKey(event) {
  return event.id || `${event.event}:${webhookSubjectId(event)}:${event.timestamp}`;
}

app.post('/webhooks/daya', (req, res) => {
  const signature = req.headers['x-daya-signature'];
  const payload = JSON.stringify(req.body);

  if (!verifySignature(payload, signature, process.env.DAYA_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const key = dedupeKey(req.body);
  if (isProcessed(key)) {
    return res.status(200).send('Already processed');
  }

  queue.add('process-webhook', req.body);
  markAsProcessed(key);

  res.status(200).send('OK');
});

Best Practices

1

Verify signatures

Always verify X-Daya-Signature before trusting the payload.
2

Deduplicate deliveries

Store the webhook event id as your primary deduplication key.
CREATE TABLE processed_webhook_events (
  webhook_event_id VARCHAR(255) PRIMARY KEY,
  processed_at TIMESTAMP
);
3

Return 200 quickly

Acknowledge receipt immediately and queue heavier downstream work.
4

Handle out-of-order events

Use timestamp and the underlying resource state to reconcile event order safely.
5

Monitor webhook health

Track failed deliveries and alert on sustained retries.

Testing Webhooks

For deposit webhook flows:
  1. Create a sandbox receive instruction
  2. Trigger a sandbox deposit with Create a sandbox deposit
  3. Observe the resulting deposit lifecycle webhooks
For withdrawal webhook flows:
  1. Fund merchant balance through a merchant-balance settlement flow
  2. Create a withdrawal
  3. Observe withdrawal.created, withdrawal.submitted, withdrawal.completed, or withdrawal.failed

Troubleshooting

Check endpoint reachability, TLS configuration, and whether your handler is returning non-2xx responses.
Duplicate delivery is expected under at-least-once semantics. Deduplicate using the webhook event id.
Sort or reconcile events using timestamp instead of arrival order.
Verify you are using the correct webhook secret and the raw request body.

Next Steps

Webhook Events

Event inventory and resource payload mapping

Signature Verification

Implement HMAC verification