Webhook Payloads
This document describes the payload structure for payment, refund, and payout webhooks sent by the Orchestrapay system.
Event envelope
Every webhook is delivered as an event envelope: a small wrapper that identifies the event, with the resource itself under data. The type field follows the <object>.<event> convention (for example payment.success) and is exactly one of the names you subscribe to in the webhooks[] array.
Envelope Parameters
idstringUnique id of this event (evt_...). Use it to deduplicate deliveries: the same event may be delivered more than once.
typestringThe event type as <object>.<event>, e.g. payment.success, refund.canceled, payout.success. The <object> prefix tells you what data contains.
created_atstringISO 8601 time the event was created.
dataobjectThe resource this event is about. Its shape depends on type, and is documented per object below.
{
"id": "evt_eu1_9f8c2b1a7d6e4f3c8b2a1d0e5f6a7b8c",
"type": "payment.success",
"created_at": "2026-07-01T12:00:00Z",
"data": {
// object-specific fields, see below
}
}Payment Intent Webhook
Sent when a payment intent transitions. A payment intent can be attempted
several times (a customer may retry with another card or method), so these
events describe the intent, not an individual attempt. The type is one of:
payment.success— the intent was paid. It is now immutable.payment.canceled— the intent reached a terminal, immutable canceled state: you canceled it, or it timed out end-to-end. No further attempts can be made against it.payment.attempt_failed— a single payment attempt failed, but the intent is still open and can be retried. Not terminal; do not treat it as canceled.
Once you receive payment.success or payment.canceled, the intent will not
change again.
The fields below are the contents of the envelope's data object.
data Parameters
payment_intentstringThe payment intent this event is about (pi_...). This is the id you pass to POST /refunds to refund the payment.
statusstringThe payment intent status: pending (still open), success, or canceled. On payment.attempt_failed this stays pending.
sub_statusstringThe detailed status of the transaction attempt that triggered this event (e.g. canceled_rejected on payment.attempt_failed, success on payment.success).
amountnumberPayment amount in cents.
currencystringThree-letter ISO currency code.
customeroptional, stringThe attached customer (cus_...), if any.
metadataoptional, objectThe metadata you attached when creating the payment intent, echoed back.
gateway_transaction_idoptional, stringThe gateway's own reference for the underlying transaction, for reconciliation.
failure_reasonoptional, stringHuman-readable reason on canceled payments.
{
"id": "evt_eu1_9f8c2b1a7d6e4f3c8b2a1d0e5f6a7b8c",
"type": "payment.success",
"created_at": "2026-07-01T12:00:00Z",
"data": {
"payment_intent": "pi_eu1_b8b5be0f481f42b4b7f5972118777c5f",
"status": "success",
"sub_status": "success",
"amount": 15000,
"currency": "usd",
"customer": "cus_eu1_2c1d7ef04db08d2e5e980f3f3bc70000",
"metadata": { "order_id": "order_123" },
"gateway_transaction_id": "9f4c2a7e1d8b60352c1a",
"failure_reason": null
}
}Refund Webhook
Sent when a refund's status changes, with type set to refund.pending, refund.success, or refund.canceled. Only refund.pending is mutable - once a refund succeeds or is canceled, it is guaranteed not to change again.
The fields below are the contents of the envelope's data object.
data Parameters
refundstringThe refund this event is about (re_...).
payment_intentstringThe payment intent that was refunded (pi_...).
statusstringMain status of the refund (pending, success, or canceled).
sub_statusstringDetailed status of the refund.
amountnumberRefund amount in cents.
currencystringThree-letter ISO currency code.
gateway_transaction_idoptional, stringThe gateway's own reference for this refund, for reconciliation.
failure_reasonoptional, stringHuman-readable reason on canceled refunds.
{
"id": "evt_eu1_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
"type": "refund.success",
"created_at": "2026-07-01T12:05:00Z",
"data": {
"refund": "re_eu1_582f94c6856c447b9b2cfbbd9a528c9d",
"payment_intent": "pi_eu1_b8b5be0f481f42b4b7f5972118777c5f",
"status": "success",
"sub_status": "success",
"amount": 20000,
"currency": "usd",
"gateway_transaction_id": "a1e8c3f60d2b95743f0e",
"failure_reason": null
}
}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). The event type is payout.pending, payout.success, or payout.canceled.
Payouts are a release candidate. Payout events use the same envelope, but the data object below still carries legacy resource fields (uuid, numeric id, gateway) pending its own 202607 alignment.
data Parameters
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.
{
"id": "evt_eu1_7c3d9e2f1a8b4c5d6e7f8a9b0c1d2e3f",
"type": "payout.pending",
"created_at": "2026-07-01T12:10:00Z",
"data": {
"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": "USD",
"narration": "Weekly seller settlement",
"gateway_payout_id": "mock-transfer-301",
"gateway_auxiliary_id": null,
"failure_reason": null
}
}