Objects
A transaction is one payment attempt with one provider connection. It carries your
orderId,
the amount and currency you requested, and the processingAmount / processingCurrency actually
sent to the provider. The transaction schema also lists the actions AUTHORIZE, REFUND and
CHARGEBACK; the public create endpoints produce SALE and PAYOUT, and refunds are separate
rf_ objects with their own status model.
orderId is unique per merchant and mode across sales and payouts. The prefix pl_ is reserved
for payment links (422 ORDER_ID_RESERVED).
Transaction statuses
* Completed with a negative result. For a sale, a later
SUCCESS reported by the provider
still replaces it, because the provider reports money that was actually taken. Only SUCCESS is
absorbing.
The diagram shows the common paths; not every provider uses every state. Rules that hold for all:
- Fulfil only on
SUCCESS. TreatDECLINED,CANCELEDandEXPIREDas the current negative result, not as an absorbing state: for a sale, keep accepting verified webhooks and apply a laterSUCCESS(fulfil the order, or refund it if you have already replaced it). PROCESSINGcan last. WitherrorCode: PSP_OUTCOME_UNKNOWNthe provider’s answer was not received; keep the order pending and never resubmit it as a new payment.- An
errorCodealone is not a final state. For example, an Adyen session attempt refused withADYEN_REFUSEDkeeps the transactionPROCESSINGwhile the buyer may retry in the same session. - A sale still
CREATED48 hours after creation becomesEXPIRED(default; your deployment can configure a different period). A provider that reports expiry itself can expire it earlier. - Existing transaction modes never change: a test transaction stays a test transaction.
Where statuses come from
Status changes are written together with an outbox event in one database transaction, so every change that notifies you produces atransaction.updated webhook. You can also
read the stored state at any time with GET /v1/transactions/{id}; reads
never contact the provider.