WAPI events
Withdrawal lifecycle events delivered to WAPI webhook endpoints.
WAPI events track every status change on a withdrawal. Every event uses the
shared webhook envelope, headers, signature, and retry model.
The event name maps one-to-one to the withdrawal's numeric status field;
consumers can switch on either event or data.status.
Event catalog
| Event | data.status | Meaning |
|---|---|---|
withdrawal.not_on_ach_file | 0 | Withdrawal created; not yet added to the ACH file. |
withdrawal.being_processed_by_bank | 1 | Submitted to the bank for processing. |
withdrawal.transaction_completed | 2 | Bank confirmed the funds have been paid out. |
withdrawal.held_by_compliance | 3 | Held pending compliance review. |
withdrawal.released_by_compliance | 4 | Compliance released the hold; processing resumes. |
withdrawal.refunded_to_account | 5 | Funds returned to the merchant's WiPay balance. |
withdrawal.taken_for_chargeback | 6 | Funds taken from the withdrawal to cover a chargeback. |
withdrawal.taken_for_refund | 7 | Funds taken from the withdrawal to cover a refund. |
withdrawal.held_for_refund | 8 | Withdrawal held while a refund is processed. |
withdrawal.held_for_chargeback | 9 | Withdrawal held while a chargeback is reviewed. |
data payload
| Field | Type | Notes |
|---|---|---|
amount | string | 2-decimal amount being withdrawn. |
bank_account | string | null | Destination bank account number. |
bank_account_type | string | null | e.g. chequing, savings. May be null for sub-banked or legacy bank-transaction deliveries. |
bank_branch | string | null | Branch name. |
bank_name | string | Destination bank. |
created_at | string | ISO 8601 timestamp the withdrawal was created. |
currency | string | ISO 4217 alpha code. |
deleted_at | string | null | Soft-delete timestamp; populated only for cancelled withdrawals. |
email | string | null | Recipient email (where collected). |
fee_amount | string | null | 2-decimal fee amount. |
id_number | string | null | Recipient government ID number (sub-unbanked flow). |
id_type | string | null | Government ID type, e.g. national_id, drivers_license, passport. |
name_in_bank | string | Account-holder name as registered with the bank. |
phone | string | null | Recipient phone (where collected). |
recipient_name | string | null | Display name of the recipient. |
reference | string | null | Merchant-supplied reference / memo. |
status | int | 0–9, see catalog table above. |
status_description | string | Human-readable status text, e.g. Being Processed By Bank, Transaction Completed. For sub_unbanked withdrawals, statuses 0 and 2 are described as Not Redeemed and Redeemed. |
transaction_id | string | null | Linked WiPay transaction reference, when one exists. |
updated_at | string | ISO 8601 timestamp of the most recent status change. |
withdrawal_type | string | null | One of normal, sub_banked, sub_unbanked. null on legacy bank-transaction deliveries. |
Legacy bank-transaction payloads
Some deliveries originate from a legacy bank-transaction path with no linked
WAPI withdrawal record. In those cases, the same envelope is sent but the
withdrawal-form-only fields are null: email, phone, id_number,
id_type, recipient_name, reference, fee_amount, bank_branch,
bank_account_type, and withdrawal_type. The core columns — amount,
bank_name, bank_account, name_in_bank, currency, status,
status_description, created_at, and updated_at — remain populated.
meta
| Key | Description |
|---|---|
previous_status | Numeric status before the transition, or null for the first transition (typically seen on withdrawal.not_on_ach_file). |
Example — withdrawal.transaction_completed (sub-banked)
{
"id": "a14d3e2f-0b9c-4d1e-9f80-5a6b7c8d9e0f",
"api_family": "wapi",
"event": "withdrawal.transaction_completed",
"occurred_at": "2026-04-17T19:14:25+00:00",
"data": {
"amount": "100.00",
"bank_account": "1234567890",
"bank_account_type": null,
"bank_branch": "Port of Spain",
"bank_name": "Republic Bank",
"created_at": "2026-04-17T19:14:25+00:00",
"currency": "TTD",
"deleted_at": null,
"email": "jane.customer@example.com",
"fee_amount": "0.00",
"id_number": null,
"id_type": null,
"name_in_bank": "Jane Customer",
"phone": "+18680000000",
"recipient_name": "Jane Customer",
"reference": null,
"status": 2,
"status_description": "Transaction Completed",
"transaction_id": null,
"updated_at": "2026-04-17T19:14:25+00:00",
"withdrawal_type": "sub_banked"
},
"meta": {
"previous_status": 1
}
}Example — withdrawal.being_processed_by_bank (legacy bank-transaction path)
{
"id": "b25e4f30-1c0d-4e2f-8091-6b7c8d9e0f12",
"api_family": "wapi",
"event": "withdrawal.being_processed_by_bank",
"occurred_at": "2026-04-17T15:14:25-04:00",
"data": {
"amount": "50.00",
"bank_account": "1234567890",
"bank_account_type": null,
"bank_branch": null,
"bank_name": "Republic Bank",
"created_at": "2026-04-17T15:14:25-04:00",
"currency": "TTD",
"deleted_at": null,
"email": null,
"fee_amount": null,
"id_number": null,
"id_type": null,
"name_in_bank": "John Merchant",
"phone": null,
"recipient_name": null,
"reference": null,
"status": 1,
"status_description": "Being Processed By Bank",
"transaction_id": null,
"updated_at": "2026-04-17T15:14:25-04:00",
"withdrawal_type": null
},
"meta": {
"previous_status": 0
}
}Ordering
Status changes fire in whatever order the underlying systems report them.
Consumers must not assume a fixed sequence — always reconcile using
data.status (authoritative) and meta.previous_status. Because the event
is per endpoint, a given transition is emitted once. If a delivery is retried,
it is a redelivery of the same transition rather than a new status change.