Payment Lifecycle States
Overview
Every payment in the v2 system follows a state machine. Understanding which states are transient, which are terminal, and what triggers each transition is fundamental to working on payment code.
Complete State Machine
State Reference
Transient States (non-terminal)
| State | Trigger | Next States | Notes |
|---|---|---|---|
INITIATED | POST /v2/payments accepted | PENDING, PROCESSING, PENDING_FOR_CUSTOMER_CREATION, PENDING_FOR_PAYMENT_METHOD_CREATION | Entry state for all payments |
PENDING | Payment queued | PROCESSING, CANCEL_INITIALIZED | Waiting for processing slot |
PENDING_FOR_CUSTOMER_CREATION | Customer lookup failed, creation needed | INITIATED, FAILED | Retries customer resolution |
PENDING_FOR_PAYMENT_METHOD_CREATION | Payment method needs setup | INITIATED, FAILED | Retries PM setup |
PROCESSING | Vendor request in flight | COMPLETED, FAILED, AUTHORIZED, ACCEPTED, AUTH_REQUIRED, PROCESSING_DEDUP_CHECK | Active Stripe call |
PROCESSING_DEDUP_CHECK | Pay-and-save dedup | PROCESSING | Checks for duplicate PM before saving |
AUTH_REQUIRED | 3DS challenge issued | CONFIRMATION_INITIALIZED | Waiting for customer 3DS completion |
CONFIRMATION_INITIALIZED | 3DS challenge completed | AUTHORIZED, COMPLETED, FAILED | Post-3DS confirmation |
AUTHORIZED | Pre-auth hold placed | CAPTURE_INITIALIZED, CANCEL_INITIALIZED | Funds held, awaiting merchant action. Expires after 7 days. |
ACCEPTED | ACH accepted by processor | COMPLETED, FAILED, CANCEL_INITIALIZED | Bank account settlement pending |
CAPTURE_INITIALIZED | PATCH /capture received | COMPLETED, FAILED | Stripe capture in progress |
CANCEL_INITIALIZED | PATCH /cancel received | CANCELLED, CANCEL_FAILED | Stripe void/cancel in progress |
Terminal States
| State | Meaning | Webhook Event |
|---|---|---|
COMPLETED | Payment fully processed and settled | PAYMENT_SUCCEEDED |
FAILED | Payment permanently failed | PAYMENT_FAILED |
CANCELLED | Payment cancelled by merchant or system | PAYMENT_CANCELLED |
CANCEL_FAILED | Cancellation attempt failed; original state unchanged | — (requires manual intervention) |
Allocation-Level States
In split-tender payments, each allocation has its own state independent of the payment-level state.
| Allocation Status | Description | Unique to Split-Tender? |
|---|---|---|
PENDING | Queued | No |
AUTH_REQUIRED | 3DS needed | No |
CONFIRMATION_INITIALIZED | Post-3DS | No |
AUTHORIZED | Funds held | No |
CAPTURE_INITIALIZED | Capturing | No |
ACCEPTED | ACH accepted | No |
CANCEL_INITIALIZED | Cancelling | No |
CANCELED | Successfully cancelled | No |
ROLLED_BACK | System reversed (sibling failed) | Yes |
COMPLETED | Settled | No |
FAILED | Declined/error | No |
State Transition Rules
Cancellation Eligibility
Only payments in these states can be cancelled:
| State | Cancel Allowed? | Notes |
|---|---|---|
AUTHORIZED | ✅ | Pre-auth void |
ACCEPTED | ✅ | ACH reversal |
PENDING | ✅ | Before processing starts |
COMPLETED | ❌ | Use refund instead |
FAILED | ❌ | Already terminal |
CANCELLED | ❌ | Already terminal |
PROCESSING | ❌ | In-flight — wait for terminal state |
Capture Eligibility
| State | Capture Allowed? | Notes |
|---|---|---|
AUTHORIZED | ✅ | Full or partial capture |
| All others | ❌ | Only AUTHORIZED payments can be captured |
Standard Flow Patterns
| Flow | State Path |
|---|---|
| Card — Sale | INITIATED → PROCESSING → COMPLETED |
| Card — Pre-Auth + Capture | INITIATED → PROCESSING → AUTHORIZED → CAPTURE_INITIALIZED → COMPLETED |
| Card — Pre-Auth + Cancel | INITIATED → PROCESSING → AUTHORIZED → CANCEL_INITIALIZED → CANCELLED |
| Card — 3DS | INITIATED → PROCESSING → AUTH_REQUIRED → CONFIRMATION_INITIALIZED → COMPLETED |
| Bank Account (ACH) | INITIATED → PROCESSING → ACCEPTED → COMPLETED |
| Pay-and-Save | INITIATED → PROCESSING → PROCESSING_DEDUP_CHECK → PROCESSING → COMPLETED |
| Split-Tender (both succeed) | INITIATED → PROCESSING → COMPLETED (both allocations) |
| Split-Tender (one fails) | INITIATED → PROCESSING → allocation[0]=COMPLETED, allocation[1]=FAILED → rollback → allocation[0]=ROLLED_BACK → payment=FAILED |