# Payment Lifecycle

This page is the authoritative reference for status values and transitions. Whenever a response body contains a `status` field, the values come from one of the two enums described here.

---

## GenericPayment status

### Status values

| Status | Meaning | Terminal? |
|--------|---------|-----------|
| `draft` | Payment row created but not yet submitted to any processor (e.g. a hosted-checkout session opened but the customer has not submitted card data). | No |
| `new` | Submitted to the processing pipeline; routing not yet resolved. | No |
| `routed` | A terminal (processor + MID) has been selected; submission to the provider is imminent. | No |
| `provider_pending` | Request sent to the upstream provider; waiting for an async confirmation or 3DS challenge. **This is the status returned when `requiresAction: true`** — the payment waits here until `/finalize-payment` is called. | No |
| `authorized` | Provider has authorized the funds but not yet captured them. Capture is required before settlement. Eligible for `POST /capture`. | No |
| `provider_completed` | Provider confirmed capture. Also eligible for `POST /capture` (some providers report completion at this stage). | No |
| `provider_risk_review` | The provider has placed the payment into a risk-review queue. Fynex waits for a review decision before proceeding. | No |
| `funds_in_flight` | Captured funds are moving through the settlement pipeline. | No |
| `settled` | Funds have been received into the operational account. Refunds become eligible at this point. | No |
| `deposit_confirmed` | Settlement confirmed at the safeguarding/deposit layer. Refunds remain eligible. | No |
| `refund_pending` | A refund has been requested and is being processed by the provider. | No |
| `refunded` | Refund completed successfully. | **Yes** |
| `refund_failed` | Refund attempt failed. The engine can re-queue to `refund_pending`. | No |
| `refund_cancelled` | Refund was cancelled. The engine can re-queue to `refund_pending`. | No |
| `failed` | Payment failed at any stage. See `failureCode` and `failureDescription` in the response for details. | **Yes** |
| `cancelled` | Payment was cancelled (by merchant or system) before completion. | **Yes** |

### What triggers each status

| Transition | Trigger |
|------------|---------|
| `draft` → `new` | `POST /initialize-payment` is processed; routing starts. |
| `new` → `routed` | Internal routing engine selects a terminal. |
| `routed` → `provider_pending` | Payment sent to provider; 3DS or async response required. |
| `provider_pending` → `authorized` | `POST /finalize-payment` called after 3DS; provider confirms authorization. |
| `provider_pending` → `failed`/`cancelled` | Customer cancels 3DS, OTP fails, issuer declines, or system timeout. |
| `authorized` → `provider_completed` | `POST /payments/{id}/capture` called (manual-capture mode) or auto-capture by provider. |
| `provider_completed` → `funds_in_flight` | Settlement pipeline picks up the captured payment. |
| `funds_in_flight` → `settled` | Operational account receives the funds. |
| `settled` → `deposit_confirmed` | Safeguarding layer confirms the deposit. |
| `provider_completed`/`settled`/`deposit_confirmed` → `refund_pending` | `POST /payments/{id}/refund` called. |
| `refund_pending` → `provider_completed` | Provider confirms a partial refund while refundable balance remains. |
| `refund_pending` → `refunded` | Provider confirms the cumulative refunded amount equals the captured amount. |
| `refund_pending` → `refund_failed`/`refund_cancelled` | Provider rejects or system cancels the refund. |
| `refund_failed`/`refund_cancelled` → `refund_pending` | Refund can be retried. |
| any non-terminal → `failed`/`cancelled` | Provider decline, system error, or merchant cancellation. |

### Capture pre-conditions

`POST /payments/{id}/capture` enforces two pre-conditions:

1. `captureMode` must be `manual` (set on `/initialize-payment`). Auto-settlement payments return `409`.
2. Current status must be `authorized` or `provider_completed`. Any other status returns `409`.

### ASCII state diagram

```
                     ┌──────────────────────────────────────────────┐
                     │              POST /initialize-payment          │
                     ▼                                                │ idempotent
                   draft                                             │ replay
                     │                                               │
                     ▼
                    new
                     │
                     ▼
                  routed
                     │
                     ▼
            provider_pending ───────────────────────────► failed
                     │                                       ▲
   POST /finalize-   │                          cancelled ◄──┤ (any stage)
   payment (3DS ok)  │                                        │
                     ▼
               authorized ──────────────────────────────────►│
                     │   POST /capture                        │
                     ▼                                        │
          provider_completed                                  │
                     │────────────── POST /refund ───────────▼
          provider_risk_review ─────────────────────────────►│
                     │                                        │
                     ▼                                        │
            funds_in_flight                                   │
                     │                                        │
                     ▼
                  settled ─────────────────────────────────►deposit_confirmed
                     │                                              │
              POST /refund                                   POST /refund
                     │                                              │
                     ▼                                              ▼
             refund_pending ◄──────────── refund_failed / refund_cancelled
                     │\\
       partial success│ \\ full cumulative refund
                     ▼  ▼
          provider_completed refunded  (terminal)
```

---

## 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. | No |
| `processing` | Payout submitted to the banking provider. | 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` | `processing` | Internal dispatcher submits to the banking provider. |
| `processing` | `completed` | The banking provider's webhook confirms success. |
| `processing` | `failed` | The banking provider rejects or a timeout occurs. |
| `pending` | `cancelled` | Seller or system cancels before dispatch. |

### ASCII state diagram

```
POST /payouts
      │
      ▼
   pending
      │
      ▼
  processing
      │
   ┌──┴──────────┐
   ▼             ▼
completed      failed   (both terminal)

pending ──► cancelled   (terminal, if cancelled before dispatch)
```

### Payout amount field

Payout amounts use **minor units** in the API wire format (`amountMinor`). This differs from payment endpoints, which use major units. For example, £49.99 is `4999` in a payout request.

---

## Cross-reference: actions and status transitions

| API action | Required pre-status | Resulting status |
|-----------|---------------------|-----------------|
| `POST /initialize-payment` | — (new payment) | `provider_pending` (if 3DS needed) or `authorized`/`provider_completed` (if frictionless) |
| `POST /finalize-payment` | `provider_pending` | `authorized` or `provider_completed` (on success) / `failed`/`cancelled` (on provider decline) |
| `POST /payments/{id}/capture` | `authorized` or `provider_completed` | `provider_completed` → continues toward `funds_in_flight` |
| `POST /payments/{id}/refund` | `provider_completed`, `settled`, `deposit_confirmed`, `refund_failed`, or `refund_cancelled` | `refund_pending` |
| `POST /payouts` | — (new payout) | `pending` |

> [!CAUTION]
> There are no `captured` or `partially_captured` statuses. Partial capture is supported by passing a lower `amount` to `POST /capture`, but the status after capture is always `provider_completed`.

---

## 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 |
| `2001` | Provider declined | authorization |
| `2002` | Provider error | authorization |
| `2003` | Provider timeout | authorization |
| `3001` | Capture failed | capture |
| `4001` | Settlement failed | settlement |
| `5001` | Deposit-confirm timeout | deposit_confirm |
| `9001` | Cancelled by merchant | — |
| `9002` | Cancelled by system | — |
| `9999` | Unknown | — |

The `failureDescription` field carries a human-readable message from the provider. The `failureStage` field (`validation`, `risk`, `routing`, `authorization`, `capture`, `settlement`, `deposit_confirm`) tells you where in the pipeline the failure occurred.

---

## Polling for status

Fynex delivers a `PaymentCompleted` webhook to the webhook URL(s) configured on your seller account (your receiver must return HTTP 200). Polling remains available as a backstop. To track status changes:

- Poll `genericPayment(id)` via GraphQL (dashboard-authenticated).
- 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`.

See [Polling & SSE](https://api.fynex.ai/payments-api/v2/docs#tag/polling-sse) for details.

## See also

- **[Captures & Refunds](https://api.fynex.ai/payments-api/v2/docs#tag/captures-refunds)** — How to capture authorized payments and issue refunds.
- **[Payouts](https://api.fynex.ai/payments-api/v2/docs#tag/payouts)** — Create and track wallet-to-payee payouts.
- **[Polling & SSE](https://api.fynex.ai/payments-api/v2/docs#tag/polling-sse)** — Monitor payment status changes in real time.
- **[3DS Authentication](https://api.fynex.ai/payments-api/v2/docs#tag/3ds)** — Handle 3DS challenges in the server-to-server flow.
