Skip to main content
ZBD sends a signed POST to each URL you subscribe with Create a Webhook. Payout events cover payouts your backend sends and cash outs from the widget, in both products. Transaction events cover value moving inside ZBD, for programs where ZBD holds balances.

Payout events

Transaction events

The payload carries transaction_id, type, reference_id, project_id, and the transaction’s movements, in the same shape as Get a Transaction. It’s signed the same way as payout events.

Payout payload

string
Unique ID for the event. Deduplicate on it, since a retry can deliver the same event twice.
string
Which event this is, from the table above.
string
When it happened, as an ISO 8601 timestamp.
string
The payout the event is about.
string
api for payouts your backend sent and widget for cash outs.
string
The user being paid.
string | null
The payout’s project, if it has one.
string | null
Your own ID for the payout, if you sent one. Use it to match the event to your records.
integer
The payout amount, in the currency’s smallest unit.
string
Currency code for the amounts.
integer
The fee for the payment method, in the smallest unit. By default it comes out of amount.
integer
What the user receives, in the smallest unit. By default this is amount minus fee_amount.
string
Why the payout failed or came back. Only on FAILED and RETURNED.
string
A readable version of reason_code. Only on FAILED and RETURNED.
boolean
true once the amount is back in your funding account. Only on FAILED and RETURNED.

Verifying a webhook

Every webhook is signed. The X-ZBD-Signature header carries the signature, and X-ZBD-Signature-Key-Id names the key that signed it.
  1. Fetch ZBD’s public keys from GET /api/v1/webhooks/jwks.json and cache them.
  2. Pick the key that matches X-ZBD-Signature-Key-Id.
  3. Check the signature over the raw request body before you act on the event.

Handling deliveries

  • Respond quickly with a 2xx. Do the work after you respond. ZBD retries deliveries that fail or time out.
  • Deduplicate on event_id. A retry can deliver the same event more than once.
  • Don’t rely on order. Use occurred_at, and the payout’s current status from Get a Payout if you need to be sure.