Payout Webhooks
Payout webhook events track single payouts, payout intents, and batch payouts.
Single Payout Events
| Event | Description |
|---|---|
payout.initiated | Payout accepted by ZenPay and moved into processing (funds are reserved but the final outcome is not yet known) |
payout.completed | Payout processing finished successfully and funds have been fully debited from the reserved balance |
payout.failed | Payout processing did not complete successfully and any reserved funds are released or returned according to ZenPay rules |
payout.cancelled | Payout was cancelled before processing completed |
Payload
{
"event_type": "payout.completed",
"payment_data": {
"payoutId": "payout_1774778823937_17298d89",
"transactionId": "po6efbc8502da51774842226226",
"intentId": "poi_mnblh1o5_e8190e32",
"amount": 100,
"currency": "INR",
"status": "completed",
"beneficiary": "Rajesh Kumar",
"payoutType": "BANK_TRANSFER",
"failureReason": null,
"metadata": {
"order_no": "ORD-2026-001",
"customer_ref": "CUST-789"
}
}
}
Payload Fields
| Field | Type | Description |
|---|---|---|
payoutId | string | Internal payout ID |
transactionId | string | External payout transaction reference — matches externalPayoutId from the confirm response |
intentId | string | null | Payout intent ID (if created via the two-step intent flow) |
amount | number | Payout amount |
currency | string | Payout currency |
status | string | initiated, completed, failed, or cancelled |
beneficiary | string | Beneficiary name |
payoutType | string | Payout method (e.g. BANK_TRANSFER, UPI) |
failureReason | string | null | Reason for failure (only on payout.failed) |
metadata | object | null | Custom key-value pairs passed when creating the payout intent — returned as-is in all webhook callbacks |
Linking payouts end-to-end
When using the two-step payout intent flow:
- Create intent → get
intentId - Confirm intent → get
intentId+payoutId+externalPayoutId - Webhook callback → get
intentId+payoutId+transactionId
The transactionId in the webhook equals externalPayoutId from the confirm response. All three IDs are present in both the confirm response and webhook, so you can always link them.
Payout Intent Events
| Event | Description |
|---|---|
payout_intent.created | Payout intent created |
payout_intent.confirmed | Payout intent confirmed and submitted for processing |
payout_intent.succeeded | Payout intent completed successfully |
payout_intent.failed | Payout intent failed |
payout_intent.cancelled | Payout intent cancelled |
payout_intent.expired | Payout intent expired without confirmation |
Payload
Shares the same payload shape as single payout webhooks:
{
"event_type": "payout_intent.succeeded",
"payment_data": {
"intentId": "poi_mnblh1o5_e8190e32",
"payoutId": "payout_1774778823937_17298d89",
"transactionId": "po6efbc8502da51774842226226",
"amount": 500,
"currency": "INR",
"status": "succeeded",
"beneficiary": "Rajesh Kumar",
"payoutType": "BANK_TRANSFER",
"failureReason": null,
"metadata": {
"order_no": "ORD-2026-001"
}
}
}
Batch Payout Events
| Event | Description |
|---|---|
batch_payout.created | Batch payout created |
batch_payout.processing | Batch payout is being processed |
batch_payout.completed | All payouts in the batch completed successfully |
batch_payout.partially_completed | Some payouts in the batch completed, others failed |
batch_payout.failed | Batch payout failed |
batch_payout.cancelled | Batch payout was cancelled |
Payload
{
"event_type": "batch_payout.completed",
"payment_data": {
"batchId": "bp_abc123",
"totalPayouts": 50,
"successCount": 48,
"failedCount": 2,
"totalAmount": 25000,
"currency": "INR",
"status": "completed",
"completedAt": "2026-03-16T14:30:00.000Z"
}
}
Payload Fields
| Field | Type | Description |
|---|---|---|
batchId | string | Batch payout ID |
totalPayouts | number | Total payouts in the batch |
successCount | number | Number of successful payouts |
failedCount | number | Number of failed payouts |
totalAmount | number | Total amount across all payouts |
currency | string | Batch currency |
status | string | created, processing, completed, partially_completed, failed, cancelled |
completedAt | string | null | ISO 8601 completion timestamp |