Skip to main content
Cresora Commerce
Core Concepts

Transaction Lifecycle

The 15 transaction states, how payments move between them, and the webhook fired at each step.

Every payment in Cresora follows a deterministic state machine. State values are UPPERCASE on the wire — state: "CAPTURED", never lower-case.

The happy paths

Card sale:      INITIATED → CAPTURED → SUBMITTED → SETTLED
Card auth-only: INITIATED → AUTHORIZED → (your capture) → CAPTURED → SUBMITTED → SETTLED
ACH debit:      INITIATED → SUBMITTED → SETTLED        (or → RETURNED with an R-code)

All 16 states

StateMeaning
INITIATEDTransaction created; no gateway outcome yet
THREE_DS_PENDINGA 3-D Secure challenge is outstanding — three_ds.challenge_url is populated, 15-minute TTL. Reserved card-authentication flows only; no current POST /transactions create path issues a step-up
THREE_DS_FAILEDThe challenge failed, was abandoned, or timed out — see three_ds_failure_reason
AUTHORIZEDFunds held on the card, not yet captured. Reached via an auth-only hosted-page session (capture_mode: authorize)
CAPTUREDFunds captured; awaiting the settlement batch
SUBMITTEDACH: accepted into the ODFI origination batch — clears 1–3 banking days later
SETTLEDFunds transferred. The gate for refunds
VOIDEDCancelled pre-settlement (ledger-only VOID)
REVERSEDAuthorization released via AUTH_REVERSAL (card), or a merchant-initiated NACHA reversal (ACH)
RETURNEDTerminal: the receiving bank returned the ACH entry with an R-code — reached from SUBMITTED or SETTLED; a transaction.returned webhook fires
REFUNDEDFully refunded (cumulative refunds reached the original amount)
PARTIALLY_REFUNDEDSome but not all of the amount refunded — re-entrant across multiple partial refunds
FAILEDDeclined or failed — discriminate on decline_code
DISPUTEDThe cardholder initiated a dispute
CHARGED_BACKThe dispute resolved against the merchant
VERIFIEDTerminal state of a CARD_VERIFICATION ($0 verification)

Two states you may see in older material do not exist: requires_action (the real 3DS-pending state is THREE_DS_PENDING) and ach_returned (the real state for a bank-returned ACH entry is RETURNED).

Webhook events

What happenedEvent
Sale capturedtransaction.captured
Auth-only hold placedtransaction.authorized
Declined / failedtransaction.failed
Settledtransaction.settled
Voidedtransaction.voided
Hold releasedtransaction.auth_reversed
Refund created / parent fully refundedtransaction.refund_issued / transaction.refunded
ACH accepted into the batchtransaction.ach_submitted
ACH returned by the banktransaction.returned
Disputedtransaction.disputed, chargeback.received
💡Tip

Webhooks are the primary signal for payment state — build on them. Polling GET /api/v1/transactions/{transactionId} is the sanctioned fallback for gaps (missed deliveries, reconciliation), not the main loop.

Retries and state guards

Replay safety is provided by the Idempotency-Key header (24 hours, X-Idempotent-Replay: true on the cached response) — not by the state machine. A new capture request (fresh key) against an already-captured parent is rejected by a state guard (422 invalid_state_transition, transaction_already_settled, parent_not_voidable_in_state, …), it does not echo the existing object. Retry with the same key; don't re-issue operations with new keys expecting a no-op.