Skip to main content

Webhook event types

Event types are named <resource>.<action>. This page documents the events Orchestr currently emits and the data payload each one carries. (Additional event families are planned; only the events below are emitted today.)

All data fields are snake_case. status values are lowercase. Fields marked nullable may be absent or null.

Payment events​

These events report the lifecycle of a payment transaction. They all share the payment payload below.

Event typeWhen it fires
payment.succeededThe payment completed successfully. On a manual-capture payment this is also the settlement event - it fires once per payment, when the capture that closes the authorization settles, and carries captured_amount and the closing capture's identifiers.
payment.failedThe payment failed.
payment.canceledThe payment was canceled.
payment.requires_actionThe payment needs customer action (e.g. a 3-DS challenge).
payment.authorizedManual capture only: the card was authorized and funds are held, but nothing has moved.
payment.partially_capturedA capture settled but left the authorization open (a non-final partial capture). The closing capture emits payment.succeeded instead.
payment.capture_failedA capture did not settle - refused inline, a transport failure, or a pending capture the provider later reported failed. No money moved and the authorization stands.
payment.underpaidThe payer sent less than amount and the provider is holding the funds until you accept or decline them. The payment stays processing.
payment.overpaidThe payer sent more than amount and the provider is holding the funds until you accept or decline them. The payment stays processing.
payment.returnedThe provider sent a held under- or overpayment back to the payer after you declined it. The payment ends returned.

Payment payload​

Fields are grouped logically: identifiers, then status, money, the provider/failure details, and finally customer, metadata, and timing.

FieldTypeNullableDescription
transaction_idstringnoThe transaction this event concerns.
parent_transaction_idstringyesOnly on the payment.succeeded of an accepted under- or overpayment: the held payment that transaction_id replaced. Absent otherwise.
order_idstringnoThe owning order.
session_idstringyesThe checkout session, if the payment originated from one.
merchant_referencestringnoYour reference for the order.
processing_profilestringyesThe processing profile code the payment was addressed to; absent at account scope.
provider_referencestringyesThe reference Upprove sent the provider for this attempt.
statusstringnoTransaction status (lowercase), e.g. completed, failed.
amountnumbernoDecimal amount. On a card payment, the authorized amount.
processing_amountnumberyesWhat the provider actually processed, when it reports an amount in a different currency from currency (e.g. the cryptocurrency of a crypto pay-in). Absent otherwise.
processing_currencystringyesThe currency of processing_amount. Absent alongside it.
captured_amountnumberyesCumulative settled captured total on the authorization. Present on payment.partially_captured and on the payment.succeeded a capture closes; absent otherwise. May be less than amount after a partial final capture.
capture_transaction_idstringyesThe capture that closed the payment. Only on a payment.succeeded closed by a capture.
capture_provider_transaction_idstringyesThe provider's reference for that closing capture.
amount_mismatchbooleanyestrue on every event for an order whose payer sent a different amount from the one requested - see Under- and overpayments. Never false; absent otherwise.
received_amountnumberyesWhat the payer actually sent, in currency. Present whenever amount_mismatch is.
returned_amountnumberyesWhat went back to the payer. Only on payment.returned.
return_transaction_idstringyesThe return transaction that carried the funds back. Only on payment.returned.
currencystringnoISO 4217 currency code.
payment_methodstringyesPayment method code used, when known.
providerstringyesThe provider that ran the attempt (lowercase), e.g. stripe, when known.
payment_instrumentobjectyesThe instrument the transaction ran on, when known, e.g. the card brand (lowercase) and last four digits on a card payment.
provider_transaction_idstringyesThe provider's transaction identifier.
provider_error_codestringyesThe provider's own error code, verbatim. null on success and when the provider never answered.
provider_error_reasonstringyesThe provider's own error message, verbatim. Do not parse it.
network_error_codestringyesRaw card-network (scheme) error code, only when the provider relays one.
network_error_reasonstringyesRaw card-network (scheme) error message, only when the provider relays one.
decline_codestringyesCanonical decline code; null on success.
decline_categorystringyesThe kind of failure (funds, instrument, authentication, …); null on success.
decline_sourcestringyesWho originated the decline (issuer, acquirer, network, …); null on success.
retry_advicestringyesNetwork retry verdict for this attempt; null on success or when no advice was given.
retryablebooleanyesWhether the customer can retry on the same session; null on success.
stored_credential_initiatorstringyesWho initiated a charge on a stored card, as declared on the create: customer or merchant. Absent means customer-initiated.
stored_credential_reasonstringyesThe agreement a merchant-initiated charge ran under: recurring, unscheduled, or installment.
customer_idstringyesThe customer, when known.
metadataobject (string→string)yesMetadata you attached to the order.
event_timestring (date-time)noWhen the event occurred (ISO 8601).

Example - payment.succeeded​

{
"id": "evt_1a2b3c4d5e6f7081",
"type": "payment.succeeded",
"created": 1719056400,
"data": {
"transaction_id": "txn_9f8e7d6c",
"order_id": "ord_5b4a3c2d",
"session_id": "cs_7e6d5c4b",
"merchant_reference": "order-1001",
"status": "completed",
"amount": 42.00,
"currency": "GBP",
"payment_method": "card",
"provider": "stripe",
"payment_instrument": {
"id": "pi_8a7b6c5d",
"type": "card",
"country_code": "GB",
"holder_name": "Jane Doe",
"card_brand": "visa",
"last4_digits": "4242",
"bin": "42424242",
"card_funding": "credit",
"card_product": "platinum",
"issuer_name": "Commonwealth Bank"
},
"provider_transaction_id": "pi_3PqRsT2eZvKYlo2C1aBcD3eF",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": null,
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T10:00:00Z"
}
}

Example - payment.failed​

{
"id": "evt_2b3c4d5e6f708192",
"type": "payment.failed",
"created": 1719056460,
"data": {
"transaction_id": "txn_9f8e7d6c",
"order_id": "ord_5b4a3c2d",
"session_id": "cs_7e6d5c4b",
"merchant_reference": "order-1001",
"status": "failed",
"amount": 42.00,
"currency": "GBP",
"payment_method": "card",
"provider": "stripe",
"provider_transaction_id": "pi_3PqRsT2eZvKYlo2C1aBcD3eF",
"provider_error_code": "card_declined",
"provider_error_reason": "Your card was declined.",
"network_error_code": "51",
"network_error_reason": "Insufficient funds",
"decline_code": "insufficient_funds",
"decline_category": "funds",
"decline_source": "issuer",
"retry_advice": "do_not_retry",
"retryable": true,
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T10:01:00Z"
}
}

Example - payment.partially_captured​

A £30 capture against a £42 authorization, sent with final: false so the remaining £12 stays capturable. captured_amount is the cumulative settled total, not the amount of this capture:

{
"id": "evt_3c4d5e6f708192a3",
"type": "payment.partially_captured",
"created": 1719060000,
"data": {
"transaction_id": "txn_2c3d4e5f",
"order_id": "ord_5b4a3c2d",
"session_id": null,
"merchant_reference": "order-1001",
"status": "completed",
"amount": 42.00,
"captured_amount": 30.00,
"currency": "GBP",
"payment_method": "card",
"provider": "stripe",
"provider_transaction_id": "pi_3PqRsT2eZvKYlo2C1aBcD3eF",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retryable": null,
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T11:00:00Z"
}
}

The capture that finally closes the authorization emits payment.succeeded, not another payment.partially_captured. See Manual capture.

Example - payment.succeeded after a capture​

The event is anchored on the authorization (transaction_id, amount) and names what settled: captured_amount and the closing capture. Here a final £30 capture closed the £42 hold above, so amount stays 42.00:

{
"id": "evt_4d5e6f708192a3b4",
"type": "payment.succeeded",
"created": 1719063600,
"data": {
"transaction_id": "txn_9f8e7d6c",
"order_id": "ord_5b4a3c2d",
"session_id": null,
"merchant_reference": "order-1001",
"status": "completed",
"amount": 42.00,
"captured_amount": 30.00,
"capture_transaction_id": "txn_2c3d4e5f",
"capture_provider_transaction_id": "ch_3PqRsT2eZvKYlo2C1aBcD3eF",
"currency": "GBP",
"payment_method": "card",
"provider": "stripe",
"provider_transaction_id": "pi_3PqRsT2eZvKYlo2C1aBcD3eF",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": null,
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T12:00:00Z"
}
}

A void behind settled partial captures closes the payment the same way, as payment.succeeded for the captured total. payment.canceled fires only when a void releases a hold with nothing captured.

Example - payment.underpaid​

A €100 crypto payment where the payer's coins were worth €95. amount stays the requested charge and received_amount is what arrived; the provider holds the funds until you accept or decline them:

{
"id": "evt_5e6f708192a3b4c5",
"type": "payment.underpaid",
"created": 1719064800,
"data": {
"transaction_id": "txn_9f8e7d6c",
"order_id": "ord_5b4a3c2d",
"session_id": "cs_7e6d5c4b",
"merchant_reference": "order-1001",
"status": "processing",
"amount": 100.00,
"amount_mismatch": true,
"received_amount": 95.00,
"currency": "EUR",
"payment_method": "crypto",
"provider": "crypto_provider",
"provider_transaction_id": "prv_8821734",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": null,
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T12:20:00Z"
}
}

One event fires per amount the provider reports, so a payer who tops up to another amount that still differs triggers a new payment.underpaid or payment.overpaid.

Example - payment.succeeded after an accepted underpayment​

Accepting settles the received amount on a new transaction. transaction_id and amount describe that new payment; parent_transaction_id names the held one, which ends canceled with no payment.canceled of its own:

{
"id": "evt_6f708192a3b4c5d6",
"type": "payment.succeeded",
"created": 1719065400,
"data": {
"transaction_id": "txn_4b5c6d7e",
"parent_transaction_id": "txn_9f8e7d6c",
"order_id": "ord_5b4a3c2d",
"session_id": "cs_7e6d5c4b",
"merchant_reference": "order-1001",
"status": "completed",
"amount": 95.00,
"amount_mismatch": true,
"received_amount": 95.00,
"currency": "EUR",
"processing_amount": 0.00142,
"processing_currency": "BTC",
"payment_method": "crypto",
"provider": "crypto_provider",
"provider_transaction_id": "prv_8821734",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": null,
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T12:30:00Z"
}
}

Example - payment.returned​

Declining sends the funds back. The event is anchored on the held payment (transaction_id, amount), now returned, and names the return transaction that carried the funds back:

{
"id": "evt_708192a3b4c5d6e7",
"type": "payment.returned",
"created": 1719066000,
"data": {
"transaction_id": "txn_9f8e7d6c",
"order_id": "ord_5b4a3c2d",
"session_id": "cs_7e6d5c4b",
"merchant_reference": "order-1001",
"status": "returned",
"amount": 100.00,
"amount_mismatch": true,
"received_amount": 95.00,
"returned_amount": 95.00,
"return_transaction_id": "txn_6e5f4a3b",
"currency": "EUR",
"processing_amount": 0.00142,
"processing_currency": "BTC",
"payment_method": "crypto",
"provider": "crypto_provider",
"provider_transaction_id": "prv_8821734",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": false,
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T13:00:00Z"
}
}

Checkout session events​

These report the outcome of a hosted checkout session. They share the checkout session payload below.

Event typeWhen it fires
checkout.session.completedThe customer completed payment on the session. On a session created with capture_method: manual this fires at authorization, before any capture - see Manual capture on hosted checkout. It also fires when a declined under- or overpayment is returned to the payer, just before payment.returned - nothing was paid in that case.
checkout.session.expiredThe session expired before completion.
checkout.session.canceledThe session was cancelled.
checkout.session.failedPayment on the session failed terminally.

Checkout session payload​

FieldTypeNullableDescription
session_idstringnoThe checkout session.
order_idstringnoThe associated order.
transaction_idstringyesThe resulting transaction, when one exists.
merchant_referencestringnoYour reference for the order.
processing_profilestringyesThe processing profile code the session was addressed to; absent at account scope.
statusstringnoSession status (lowercase), e.g. completed, expired, canceled, failed.
amountnumbernoDecimal amount.
currencystringnoISO 4217 currency code.
capture_methodstringyesautomatic or manual, present when the session was created with one. On manual, a completed session is a hold you still have to capture.
customer_idstringyesThe customer, when known.
metadataobject (string→string)yesMetadata you attached to the session.
event_timestring (date-time)noWhen the event occurred (ISO 8601).

Example - checkout.session.completed​

{
"id": "evt_3c4d5e6f70819203",
"type": "checkout.session.completed",
"created": 1719056405,
"data": {
"session_id": "cs_7e6d5c4b",
"order_id": "ord_5b4a3c2d",
"transaction_id": "txn_9f8e7d6c",
"merchant_reference": "order-1001",
"status": "completed",
"amount": 42.00,
"currency": "GBP",
"customer_id": "cus_8a7b6c5d",
"metadata": {
"cart_id": "C-1001"
},
"event_time": "2024-06-22T10:00:05Z"
}
}

Refund events​

These report the lifecycle of a refund. They reuse the payment payload above, with some fields always null on the refund path: session_id (refunds have no checkout session), metadata, and the decline attributes decline_category, decline_source, retry_advice, and retryable. Note decline_code is not always null - a failed refund can carry a canonical decline_code. amount and currency reflect the refund, which may be partial; status is a transaction status that moves from pending to completed, failed or canceled. parent_transaction_id is not set on refund events - use provider_transaction_id and your merchant_reference to reconcile.

Event typeWhen it fires
refund.createdA refund has been created and is pending.
refund.succeededThe refund completed at the provider.
refund.failedThe refund failed.
refund.canceledThe refund was canceled before it completed - the provider canceled it, or its approval request was declined. No money moved.

Example - refund.succeeded​

{
"id": "evt_4d5e6f7081920304",
"type": "refund.succeeded",
"created": 1719060000,
"data": {
"transaction_id": "txn_2d3e4f5a",
"order_id": "ord_5b4a3c2d",
"session_id": null,
"merchant_reference": "refund-1001",
"status": "completed",
"amount": 42.00,
"currency": "GBP",
"payment_method": "card",
"provider": "stripe",
"provider_transaction_id": "re_3PqRsT2eZvKYlo2C1aBcD3eF",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": null,
"customer_id": "cus_8a7b6c5d",
"metadata": null,
"event_time": "2024-06-22T11:00:00Z"
}
}

Payout events​

These report the lifecycle of a payout. They reuse the payment payload above, built from the payout transaction. amount and currency reflect the payout; status is a transaction status that moves from pending through to completed or failed. The session/decline attributes - session_id, payment_method, decline_code, decline_category, decline_source, retry_advice, retryable - and metadata are null on the payout path. Use provider_transaction_id and your merchant_reference to reconcile.

Event typeWhen it fires
payout.createdA payout has been created and is pending.
payout.processingThe payout is being processed by the provider.
payout.paidThe payout completed at the provider.
payout.failedThe payout failed.
payout.canceledThe payout was canceled.

Example - payout.paid​

{
"id": "evt_5e6f708192030415",
"type": "payout.paid",
"created": 1719063600,
"data": {
"transaction_id": "txn_1c2b3a4d",
"order_id": "pou_5b4a3c2d",
"session_id": null,
"merchant_reference": "payout-1001",
"status": "completed",
"amount": 10.00,
"currency": "GBP",
"payment_method": null,
"provider": "stripe",
"provider_transaction_id": "po_3PqRsT2eZvKYlo2C1aBcD3eF",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": null,
"customer_id": "cus_8a7b6c5d",
"metadata": null,
"event_time": "2024-06-22T12:00:00Z"
}
}

Transfer events​

These report the lifecycle of a transfer. Like payout events, they reuse the payment payload built from the transfer transaction, with the same session/decline fields and metadata always null. amount and currency reflect the transfer; status moves from pending to completed or failed.

Event typeWhen it fires
transfer.createdA transfer has been created and is pending.
transfer.processingThe transfer is being processed by the provider.
transfer.paidThe transfer completed at the provider.
transfer.failedThe transfer failed.
transfer.canceledThe transfer was canceled.

Example - transfer.paid​

{
"id": "evt_6f70819203041526",
"type": "transfer.paid",
"created": 1719067200,
"data": {
"transaction_id": "txn_1c2b3a4d",
"order_id": "trf_5b4a3c2d",
"session_id": null,
"merchant_reference": "transfer-1001",
"status": "completed",
"amount": 250.00,
"currency": "GBP",
"payment_method": null,
"provider": "stripe",
"provider_transaction_id": "tr_3PqRsT2eZvKYlo2C1aBcD3eF",
"provider_error_code": null,
"provider_error_reason": null,
"network_error_code": null,
"network_error_reason": null,
"decline_code": null,
"decline_category": null,
"decline_source": null,
"retry_advice": null,
"retryable": null,
"customer_id": null,
"metadata": null,
"event_time": "2024-06-22T13:00:00Z"
}
}

Approval request events​

These are sent only when approval workflows are enabled on your account (configured in the portal). A gated payout, refund or transfer is not sent to the provider until it is approved: its transaction and order stay pending until then. If the request is approved, it continues through its normal payout.*, refund.* or transfer.* events. If it is declined, the transaction is canceled and its own payout.canceled, refund.canceled or transfer.canceled follows. They share the approval request payload below.

Event typeWhen it fires
approval_request.pendingThe transaction matched an approval workflow and is waiting for approval. Carries every step of the workflow in steps, so you know up front what it takes.
approval_request.new_approvalAn approver recorded an approval. Fires once per approval, so a step that needs two approvals fires it twice.
approval_request.approvedThe last required approval was recorded and the transaction is submitted to the provider. It follows the approval_request.new_approval for that last approval.
approval_request.declinedAn approver declined the request, or the person who initiated it withdrew it.

Approval request payload​

FieldTypeNullableDescription
approval_request_idstringnoThe approval request.
statusstringnoRequest status (lowercase): pending_approval, approved or declined.
subject_typestringnoWhat the request gates. Always money_out today.
subject_idstringnoThe gated entity. For money_out, the transaction id.
transaction_idstringyesThe gated payout, refund or transfer transaction. Set for money_out.
operation_typestringyesThe kind of money-out (lowercase): payout, refund or transfer.
amountnumbernoDecimal amount of the gated transaction.
currencystringnoISO 4217 currency code.
merchant_referencestringyesYour reference for the gated transaction.
workflow_namestringnoThe approval workflow that matched.
current_stepintegernoThe step the request is on, counted from 1.
total_stepsintegernoHow many steps the workflow has.
step_namestringyesThe step this event concerns.
approvals_receivedintegeryesApprovals recorded on that step so far. Absent on approval_request.declined.
required_approvalsintegeryesApprovals that step needs. Absent on approval_request.declined.
stepsarraynoEvery step of the workflow, in order, as { "name", "required_approvals" }.
actorobjectyesWho acted: id, type (user, api_key or system), name and email. Absent on approval_request.pending.
notestringyesThe note the actor left, if any.
decline_reasonstringyesWhy the request was declined. Only on approval_request.declined.
event_timestring (date-time)noWhen the event occurred (ISO 8601).

Example - approval_request.new_approval​

The first of two approvals on the first step of a two-step workflow:

{
"id": "evt_708192030415263a",
"type": "approval_request.new_approval",
"created": 1719070800,
"data": {
"approval_request_id": "apr_3e4f5a6b",
"status": "pending_approval",
"subject_type": "money_out",
"subject_id": "txn_1c2b3a4d",
"transaction_id": "txn_1c2b3a4d",
"operation_type": "payout",
"amount": 5000.00,
"currency": "GBP",
"merchant_reference": "payout-1002",
"workflow_name": "Large payouts",
"current_step": 1,
"total_steps": 2,
"step_name": "Finance review",
"approvals_received": 1,
"required_approvals": 2,
"steps": [
{ "name": "Finance review", "required_approvals": 2 },
{ "name": "Director sign-off", "required_approvals": 1 }
],
"actor": {
"id": "usr_9a8b7c6d",
"type": "user",
"name": "Alex Smith",
"email": "alex@example.com"
},
"note": "Matches the supplier invoice.",
"event_time": "2024-06-22T14:00:00Z"
}
}

Choosing what to listen to​

A payment.succeeded and a checkout.session.completed often describe the same successful purchase from different angles. For most hosted-checkout integrations, checkout.session.completed is the event to fulfil orders on; use the payment events for finer-grained transaction tracking and for direct (non-session) payments. If you accept crypto, also handle the under- and overpayment events: a returned payment completes its session too.

See Retries for delivery guarantees and idempotency.