State diagram
A payment rejected before it reaches the card networks (for example, by validation at the provider) moves directly fromPENDING to FAILED.
A status is a snapshot of the current state, not a step on a progress
bar. Non-terminal statuses can alternate: a direct payment that is
PROCESSING may move to REQUIRES_ACTION when the issuer requests 3D
Secure, then back to PROCESSING once the customer completes it. Only the
four terminal states (SUCCEEDED, FAILED, EXPIRED, CANCELED) are
final. Transition history is preserved in status_transitions.Statuses
| Status | Terminal | Meaning |
|---|---|---|
PENDING | No | Accepted by Flowlix, waiting to be processed. |
REQUIRES_ACTION | No | The customer must act — complete 3D Secure or the hosted payment page. The action URL is in next_action.redirect_url. Can occur before or after PROCESSING. |
PROCESSING | No | Submitted to downstream payment systems; the outcome is not yet known. Flowlix synchronizes the provider result automatically — no merchant action is needed. |
SUCCEEDED | Yes | Funds were collected. The payment becomes refundable (amount_refundable). |
FAILED | Yes | Declined or failed permanently. decline_code and decline_message say why. |
CANCELED | Yes | Canceled before completion (for example, the customer canceled on the hosted page). |
EXPIRED | Yes | The customer did not complete a required action before its expiry time. |
status_transitions
(processing_at, succeeded_at, failed_at, …), all as Unix timestamps in
seconds.
Tracking the outcome
Two complementary mechanisms:Webhooks (recommended)
Flowlix calls your endpoint the moment a payment reaches a new state. Best
latency, no polling load.
Polling
Call
GET /v1/payments/{id} until the status is terminal. Simple and
dependable; use it as a fallback even when you use webhooks.Polling guidance
- Poll every 2–5 seconds while a payment is
PROCESSINGorREQUIRES_ACTIONand the customer is waiting on your page. - Switch to a slower background schedule (for example every minute, then every 10 minutes) after the customer leaves.
- Treat only terminal statuses as final. A payment in
PROCESSINGresolves automatically — you never need to re-submit it. - If a payment is still non-terminal after 24 hours, contact support with
the payment ID and
Request-Id; do not create a duplicate charge.
Reacting to each status
SUCCEEDED— fulfil the order. Recordamount_refundableif you may need refunds.FAILED— readdecline_codeto decide: ask for another payment method (insufficient_funds,expired_card), allow a plain retry (processor_unavailable,try_later), or do not retry (stolen_card,fraud_filter).EXPIRED/CANCELED— the attempt is over; create a new payment if the customer wants to try again. Reuse yourmerchant_referenceso all attempts for the order stay linked.
Multiple attempts per order
One order in your system may legitimately produce several Payment objects: a decline followed by a retry, or an abandoned hosted page followed by a new one. Usemerchant_reference to group attempts, and make sure at most one of
them is fulfilled — the Idempotency-Key header protects you against
accidental duplicates of the same attempt, while merchant_reference only
labels attempts and never blocks them.