Webhook Payloads
This document describes the payload structure for payment, refund, and payout webhooks sent by the OrchestraPay system.
Payment Webhook
Sent when a payment's status changes. Payments can have three main statuses: pending, success, or canceled. Only the pending status is mutable - once a payment gets the success or canceled status, it is guaranteed that it will not change again.
Payment Webhook Parameters
idempotency_keystringUnique key to prevent duplicate webhook processing
uuidstringUnique identifier for the payment
idnumberInternal payment ID
gatewaystringPayment gateway used for the payment
statusstringMain status of the payment (pending, success, or canceled)
sub_statusstringDetailed status of the payment
preflight_idnumberID of the preflight object used to generate this payment
payloadobjectAdditional payment data
amountnumberPayment amount in cents
currencystringThree-letter ISO currency code
step_numbernumberCurrent step in payment flow
last_reasonstringLast status reason or message
webhook_typestringType of webhook (always "payment" for payment webhooks)
{
"idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"id": 123,
"gateway": "paystack",
"status": "success",
"sub_status": "success",
"preflight_id": 456,
"payload": {},
"amount": 1000,
"currency": "EGP",
"step_number": 3,
"last_reason": null,
"webhook_type": "payment"
}Refund Webhook
Sent when a refund's status changes. Refunds can have three main statuses: pending, success, or canceled. Only the pending status is mutable - once a refund gets the success or canceled status, it is guaranteed that it will not change again.
Refund Webhook Parameters
idempotency_keystringUnique key to prevent duplicate webhook processing
idnumberInternal refund ID
statusstringMain status of the refund (pending, success, or canceled)
sub_statusstringDetailed status of the refund
transaction_idnumberID of the original payment being refunded
amountnumberRefund amount in cents
currencystringThree-letter ISO currency code
webhook_typestringType of webhook (always "refund" for refund webhooks)
{
"idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
"id": 123,
"status": "success",
"sub_status": "success",
"transaction_id": 456,
"amount": 1000,
"currency": "EGP",
"webhook_type": "refund"
}Payout Webhook
Sent when a payout's status changes. Configure webhook_urls and an optional webhook_secret on POST /payouts. Orchestrapay POSTs the JSON body to each URL and sends Orchestrapay-Webhook-Secret when a secret was provided.
Payouts use the same promise model as refunds: main status is pending, success, or canceled (derived from sub_status), and sub_status carries the detailed value.
When webhooks are sent
| Event | Typical sub_status | Notes |
|---|---|---|
| Payout row saved, before gateway initiation | pending_created | First notification after create. |
| Gateway reports in-flight / retry | pending_promise | After initiation when the transfer is still processing. |
| Transfer completed | success | Funds sent successfully. |
| Gateway rejected the transfer | canceled_rejected | e.g. invalid account, insufficient balance. |
| Technical or unexpected failure | canceled_failure | Non-rejection failure path. |
A single POST /payouts may produce multiple webhooks (for example pending_created, then pending_promise or success, depending on the gateway response).
Payout Webhook Parameters
webhook_typestringAlways `"payout"` for payout webhooks.
idempotency_keyoptional, stringIdempotency key from the create request, if provided.
uuidstringPublic payout identifier (same as `payout_uuid` in create responses).
idnumberInternal payout ID.
statusstringMain status: `pending`, `success`, or `canceled` (first segment of `sub_status`).
sub_statusstringDetailed payout status.
tenant_idnumberOwning tenant ID.
gatewaystringPayout gateway identifier.
recipient_idnumberInternal ID of the linked payout recipient (not `recipient_uuid`).
amountnumberPayout amount in cents.
currencystringThree-letter ISO currency code.
narrationoptional, stringTransfer description from the create request.
gateway_payout_idoptional, stringGateway reference for the transfer, when known.
gateway_auxiliary_idoptional, stringSecondary gateway reference, when provided by the gateway.
failure_reasonoptional, stringHuman-readable rejection or failure message on canceled payouts.
{
"webhook_type": "payout",
"idempotency_key": "settlement-seller-1042-week-15",
"uuid": "4c56e5c2-7ef0-4db0-8d2e-5e980f3f3bc7",
"id": 301,
"status": "pending",
"sub_status": "pending_promise",
"tenant_id": 1,
"gateway": "mygateway",
"recipient_id": 88,
"amount": 250000,
"currency": "NGN",
"narration": "Weekly seller settlement",
"gateway_payout_id": "mock-transfer-301",
"gateway_auxiliary_id": null,
"failure_reason": null
}