Payment transaction and dispute statuses
An external payment transaction exposes a single PaymentTransactionStatus through PaymentExternalTransaction.status. Only three of its values can be submitted through the API mutations, the PaymentExternalTransactionStatusInput values pended, completed and failed; the other statuses are derived: OMS sets them as a consequence of refunds and disputes.
Transaction statuses
Typical progression:
Status updates (paymentExternalTransactionUpdate) are validated against the current status:
pendedcan move tocompletedorfailed.completedandfailedcan be corrected into each other. Nothing goes back topended.requested(a refund waiting for the gateway, see below) acceptspended,completedorfailed.partially_refundedandtotally_refundedaccept no direct update;charged_backcan only be corrected tocompleted.- Submitting the status the transaction already has is rejected like any invalid transition, with
Invalid status updateand the error codeBAD_REQUEST(see Errors).
Refund transactions: the original and its children
In OMS a refund is never an update of the paid transaction: it is a separate transaction record with a negative amount, linked to the original payment. Money records are append-only — the original transaction from the customer stays untouched, and every refund adds a new child record next to it:
Transaction 1005 — amount: 10.00 (the original payment)
└── Transaction 1006 — amount: -4.00 (a refund: child of 1005)
The two records stay linked in both directions: the original transaction lists its refunds in refundTransactions, and each refund transaction points back to the original through saleTransaction (see the PaymentExternalTransaction reference). Through the original transaction the refund also reaches the order it refunds — see From transactions and disputes to the order.
Refund transactions come into existence in two ways: your integration records one with paymentExternalTransactionRefund, or OMS creates one itself to ask the gateway for a refund (the requested case below). Either way a refund transaction is a transaction in its own right, with its own number, status, timestamps and fees, and its status follows the same rules as any other transaction.
The original transaction reacts to its children: when the completed refunds cover part of its amount, OMS moves it to partially_refunded; when they cover all of it, to totally_refunded. A pended refund does not affect it until it completes, and correcting a completed refund to failed recalculates the original. The refunded total cannot exceed the original amount, and a failed transaction cannot be refunded (both rejected with BAD_REQUEST).
Derived transaction statuses
A derived status is one the API can only read, never write: it is not part of PaymentExternalTransactionStatusInput, OMS sets it as the side effect of another event.
partially_refunded/totally_refunded: the original transaction's reaction to its completed refunds, see above.charged_back: set on the disputed transaction when one of its disputes moves tocharged_backorchargeback_lost. It can be corrected tocompleted(for example after the chargeback is reversed).requested: refund transactions created by OMS to ask the gateway for a refund, notified through therefund_requestedwebhook event. The gateway reports the outcome by moving the refund tocompletedorfailed, optionally throughpended: see the payment gateway use case.
Dispute statuses
A dispute exposes a single PaymentDisputeStatus through PaymentExternalDispute.status. Every value can be submitted through the API mutations, both at creation and — within the transitions below — on update.
Status updates (paymentExternalDisputeUpdate) are validated against the current status:
- A
pendeddispute can move to any other status. closed,charged_backandchargeback_reversedcan still be resolved intochargeback_wonorchargeback_lost;charged_backcan also becomechargeback_reversed.chargeback_wonandchargeback_lostare terminal: no further update is accepted.- No status can move back to
pended, and submitting the status the dispute already has is rejected like any invalid transition, withInvalid status updateand the error codeBAD_REQUEST(see Errors).
Final statuses and defenseEndAt
The merchant defense deadline (defenseEndAt) is cleared automatically when the dispute reaches a final status: closed, chargeback_won, chargeback_lost or chargeback_reversed. charged_back keeps the deadline, since the merchant can still defend the chargeback.
Effect on the disputed transaction
When a dispute moves to charged_back or chargeback_lost, OMS sets the status of the disputed transaction to charged_back — see derived transaction statuses for how it can evolve from there.