Payment Lifecycle
The authoritative payment-status reference — the lifecycle enum, every transition, what each status allows next, capture, cancellation, refunds, failures and webhooks.
This page is the one place payment status is defined. Other guides link here rather than restate it.
Status fields
Every response that carries a payment — GET /payments/{payment_id}, POST /initialize-payment, POST /finalize-payment, POST /payments/{payment_id}/capture — and the PaymentCompleted webhook carry the same status fields:
| Field | Values | Use it for |
|---|---|---|
lifecycleStatus |
the seven lifecycle values below | Branch on this. A closed enum: a new value is a documented, versioned change. |
status |
the previous values today; the lifecycle values after the switch announced in the changelog (no earlier than 2026-12-28) | Existing integrations. Read lifecycleStatus now and the switch does not affect you. |
legacyStatus |
the previous values (provider_completed, settled, …) — deprecated |
Only while migrating off the previous values. It is removed after a notice period. |
settlementStatus |
pending, in_flight, settled, deposit_confirmed — on GET /payments/{payment_id} only, once money is captured |
How far captured money has travelled. |
In GraphQL, GenericPayment.lifecycleStatus is the same closed enum (PaymentLifecycleStatus); GenericPayment.status is the internal value and does not switch.
Lifecycle status
lifecycleStatus |
Meaning | Final? |
|---|---|---|
pending |
Created, being routed, or waiting on the provider or the customer (3-D Secure, a redirect). Nothing is reserved on the card yet. | No |
under_review |
Held by a compliance or provider risk review before authorization. It resolves to pending (review cleared, processing resumes), captured, failed or cancelled. |
No |
authorized |
Funds are reserved on the card and waiting for your capture (manual capture only). | No |
captured |
Money was taken. It stays captured through settlement, after a partial refund, and while a refund is in flight or has failed. |
No — it can still be refunded |
refunded |
The whole captured amount was refunded. | Yes |
failed |
Declined or errored before any money was taken. failureCode, retry and failureCategory say why and whether to retry. |
Yes, with one exception (below) |
cancelled |
Called off before any money was taken, including an expired checkout. | Yes, with one exception (below) |
The one exception. A payment is recorded failed, or cancelled by an expired checkout, when Fynex could not see that the charge went through. If the provider's own authoritative event later proves the money was taken, the payment is corrected to captured. No ordinary event can revive a failed or cancelled payment; only that proof can.
Previous values
legacyStatus (and status, until the switch) carries the previous, finer-grained values. Each maps to exactly one lifecycle status:
legacyStatus |
lifecycleStatus |
settlementStatus |
|---|---|---|
draft, new, routed, provider_pending |
pending |
— |
compliance_review, provider_risk_review |
under_review |
— |
authorized |
authorized |
— |
provider_completed |
captured |
pending |
funds_in_flight |
captured |
in_flight |
settled |
captured |
settled |
deposit_confirmed |
captured |
deposit_confirmed |
refund_pending, refund_failed, refund_cancelled |
captured |
the stage reached before the refund |
refunded |
refunded |
the stage reached before the refund |
failed |
failed |
— |
cancelled |
cancelled |
— |
Transitions
| From | To | When |
|---|---|---|
pending |
authorized |
The provider authorized a manual-capture payment. |
pending |
captured |
The provider authorized and captured an automatic-capture payment. |
pending |
under_review |
A compliance or risk review holds the payment before authorization. |
pending |
failed / cancelled |
Declined, errored, 3-D Secure abandoned, or the checkout expired. |
under_review |
pending |
A compliance review cleared the payment; processing resumes. |
under_review |
captured |
A provider risk review released the payment. |
under_review |
failed / cancelled |
The review declined it, or it was not resolved in time. |
authorized |
captured |
You captured it (POST /payments/{payment_id}/capture). |
authorized |
under_review |
The provider placed it in risk review. |
authorized |
failed / cancelled |
The capture failed, or the provider voided the authorization. |
captured |
refunded |
Refunds reached the whole captured amount. |
captured |
failed / cancelled |
Rare: the provider reversed a capture it had reported. |
failed / cancelled |
captured |
Only a provider-proven correction (see above). |
A partial refund, a refund in flight and a failed refund leave the payment captured; each refund has its own status (see Refunds).
Initial, intermediate, final. Every payment starts pending. under_review and authorized are intermediate: something still has to happen. captured is where a successful payment rests; only refunds move it on. refunded, failed and cancelled are final.
Retrying a failed payment. Branch on retry: safe means the same request with the same Idempotency-Key can succeed; fix_first and never mean it cannot. On hosted checkout the buyer can try again on the same session after a decline — the payment goes back to pending for the new attempt.
What you can do next
GET /payments/{payment_id} answers this for you: allowedActions lists exactly the actions below that the payment accepts right now (capture, partial_capture, refund, partial_refund; empty when none), and captureMode says whether it captures automatically or waits for your capture. The table spells out the rules behind it.
| Action | Allowed when | Result |
|---|---|---|
Capture — POST /payments/{payment_id}/capture |
lifecycleStatus is authorized and the payment was created with manual capture |
captured |
Refund — POST /payments/{payment_id}/refund |
lifecycleStatus is captured, settlementStatus is not in_flight, no refund is in flight, and refunds are enabled for your account |
A refund object with status: pending; the payment stays captured until the whole amount is refunded |
Cancel a refund — POST /refunds/{refund_id}/cancel |
The refund is still pending (supported for card refunds) |
Refund cancelled; the payment stays captured |
| Cancel an authorization | Not available yet. An uncaptured authorization is not released by Fynex; the card issuer releases the hold on its own schedule. | — |
A capture or refund requested outside these conditions is refused — with 409 when the payment's status does not allow it.
Manual and automatic capture
A payment captures automatically when created with autoSettlement: true on POST /initialize-payment, or when the request leaves autoSettlement out and your account's default is automatic capture. Otherwise — including autoSettlement left out on an account without that default — it is a manual-capture payment: it rests at authorized until you capture it.
Partial capture
Pass an amount lower than the authorized amount to POST /payments/{payment_id}/capture. The payment becomes captured, the same as a full capture; the capture response's amount is what was captured. A second capture of the same authorization is not supported.
Cancellation and expiry
cancelled is set by the system, not by an API call: the provider voided the payment, or a hosted checkout expired before payment (failureCode 9002, "checkout session expired"). There is no Fynex-side expiry of an uncaptured authorization.
A customer who abandons 3-D Secure ends in whichever expiry comes first: the authentication session's, which fails the payment with failureCode 3003 (authentication not completed), or the hosted checkout's, which cancels it with 9002. Neither authorized anything, and neither is revived by replaying the request — the customer has to pay again.
Refunds
Each refund is its own object with its own status — pending, succeeded, failed or cancelled — on GET /payments/{payment_id}/refunds and GET /refunds/{refund_id}. The payment's lifecycleStatus:
- stays
capturedwhile a refund ispending, after itfailedor wascancelled, and after a partial refund; - becomes
refundedonce succeeded refunds add up to the whole captured amount.
Only one refund can be pending at a time. See Captures & Refunds for the requests.
Webhooks
| Event | Fires when | Status it carries |
|---|---|---|
PaymentCompleted |
The payment reaches captured, failed or cancelled — once per outcome. A payment reported failed and later proven captured (see the exception above) sends a second event with lifecycleStatus: captured; a repeat of an outcome already sent is not re-sent. |
The same status, lifecycleStatus and legacyStatus as GET /payments/{payment_id} |
PaymentRefunded |
A refund reaches succeeded. |
The refund's amount; partial says whether this refund was less than the payment |
A PaymentCompleted event is not by itself a success: branch on lifecycleStatus. There is no event yet for authorized, under_review, a failed refund or settlement progress — poll GET /payments/{payment_id} for those.
Payout status
Payouts represent wallet-to-payee transfers sent via the banking provider.
Status values
| Status | Meaning | Terminal? |
|---|---|---|
pending |
Payout created; funds held in the wallet; not yet submitted to the banking provider. Above the seller's approval threshold it also carries approvalStatus: awaiting_approval until approved. |
No |
dispatching |
Claimed by the dispatcher; submission to the banking provider is in progress. | No |
processing |
Payout submitted to the banking provider. | No |
manual_reconciliation |
The provider's answer could not be matched to the row; an operator resolves it. It does not move on its own — raise it with Fynex. | No |
completed |
The banking provider confirmed the payment reached the destination. | Yes |
failed |
The banking provider rejected the payment or an error occurred. See failureCode and failureDescription. |
Yes |
cancelled |
Payout was cancelled before it reached the banking provider. | Yes |
Status transitions
| From | To | Trigger |
|---|---|---|
pending |
dispatching |
Internal dispatcher claims the row. |
dispatching |
processing |
Submission to the banking provider accepted. |
processing |
completed |
The banking provider's webhook confirms success. |
processing |
failed |
The banking provider rejects or a timeout occurs. |
dispatching |
manual_reconciliation |
The provider's answer could not be matched to the row; parked for an operator. |
manual_reconciliation |
dispatching |
An operator resumes the dispatch. |
pending |
cancelled |
Seller or system cancels before dispatch. |
State diagram
Payout amount field
Send the payout amount as amount, a decimal string in major units ("49.99" for £49.99), like every other endpoint. The integer amountMinor (4999) is a deprecated fallback that amount overrides when both are present; responses return both.
Failure codes
When a payment reaches failed, the response includes a numeric failureCode:
| Code | Name | Stage |
|---|---|---|
0 |
None | — |
1001 |
Validation failed | validation |
1002 |
Risk rejected | risk |
1003 |
Routing failed | routing |
1004 |
Compliance screening declined the transaction | compliance |
1005 |
Compliance screening paused the transaction for review (and timed out or was rejected on review) | compliance |
1006 |
Initialization interrupted before the provider was reached (retry safely) | checkout |
1007 |
Card expired (rejected before the provider is called) | validation |
1008 |
Card brand not accepted by the seller's acquiring agreement — refused by Fynex before the provider is called, or by the acquirer when the payment is set up or authorized; no funds move in any case | validation, or authorization when the acquirer refuses |
2001 |
Provider declined | authorization |
2002 |
Provider error | authorization |
2003 |
Provider timeout | authorization |
2004 |
Refund requested before settlement was ready (transient) | — (refund responses carry no stage) |
2005 |
Address verification (AVS) failed | authorization |
3001 |
Capture failed | capture |
3002 |
Authentication required — issuer soft decline asking for 3-D Secure | authorization |
3003 |
Authentication not completed — the customer did not finish 3-D Secure before the session expired; nothing was authorized | checkout |
4001 |
Settlement failed | settlement |
5001 |
Deposit-confirm timeout | deposit_confirm |
9001 |
Cancelled by merchant | — |
9002 |
Cancelled by system | — |
9999 |
Unknown | — |
On POST /initialize-payment, 1007 and 1008 are also answered with HTTP 422 and a machine-readable code (card_expired, card_brand_not_supported) — replaying the same Idempotency-Key returns the same 422. See Common 422 responses in Errors.
The failureDescription field carries a human-readable message from the provider. The failureStage field (validation, risk, compliance, routing, checkout, authorization, capture, settlement, deposit_confirm) tells you where in the pipeline the failure occurred — read it from the response rather than from the stage column above, which is indicative. The retry and failureCategory fields beside failureCode say whether re-sending can help; the full catalogue is in Errors.
Polling for status
Webhooks are the fast path; polling is the backstop:
- Poll
GET /payments-api/v1/payments/{payment_id}(bearer token; the path value is yourexternalOrderRef). Stop onrefunded,failedorcancelled, or oncapturedif you do not need settlement progress. - Poll
GET /payments-api/v1/payouts/{id}for payout status. - While a customer is on the hosted checkout page, the browser can use the SSE stream at
GET /checkout/{session_id}/events, which uses its own checkout vocabulary.
See Polling & SSE for details.
See also
- Captures & Refunds — How to capture authorized payments and issue refunds.
- Payouts — Create and track wallet-to-payee payouts.
- Polling & SSE — Monitor payment status changes in real time.
- 3DS Authentication — Handle 3DS challenges in the server-to-server flow.