# Payment Statuses

A payment in ODUS carries two separate status fields: `status` and `displayStatus`. Understanding the difference between them — and how they relate to the boolean lifecycle flags — helps you build integrations that correctly handle every payment outcome.

## The `status` field

`status` represents the core lifecycle of a payment. It has four possible values:

| Value             | Description                                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `open`            | The payment has been created and is waiting to be processed. This is the initial state for every payment.                 |
| `requires_action` | The customer must complete an action before processing can continue, typically a 3DS redirect.                            |
| `succeeded`       | The payment has been completed successfully. Funds have been authorized (and captured, if capture method is `automatic`). |
| `cancelled`       | The payment has been permanently stopped. No further processing will occur.                                               |

### Terminal vs. non-terminal

`open` and `requires_action` are **non-terminal** — the payment can move forward from these states. `cancelled` is **terminal** — once cancelled, a payment cannot change. `succeeded` is the normal end state; in the narrow case where an uncaptured authorization is voided, it may also transition to `cancelled`.

### State transitions

<!-- -->

**What causes each transition:**

* **`open` → `requires_action`** — The PSP requires the customer to complete an authentication step, such as 3DS. The payment object receives an `action.redirectUrl` pointing to the authentication page.
* **`requires_action` → `open`** — The action was not completed within 24 hours. The payment is reset to `open` so that a new attempt can be made.
* **`open` / `requires_action` → `succeeded`** — The PSP confirms the payment is authorized (and captured, for automatic capture).
* **`open` / `requires_action` / `succeeded` → `cancelled`** — The payment is cancelled programmatically or by the merchant via the Dashboard. This is also the outcome when all retry attempts are exhausted.

## The `displayStatus` field

`displayStatus` is a derived, user-friendly value computed from `status` and the boolean lifecycle flags below. It is useful for displaying a meaningful label to your team or customers, but you should not use it in webhook or API logic. Use `status` and the individual flags for that.

| Value                | Meaning                                                                        |
| -------------------- | ------------------------------------------------------------------------------ |
| `unattempted`        | Payment is `open` and no transaction has been attempted yet.                   |
| `incomplete`         | Payment is in `requires_action` — waiting for customer to complete a redirect. |
| `failed`             | Payment is `open` but a previous attempt failed. Can still be retried.         |
| `retrying`           | Payment is actively cycling through retry attempts after a failure.            |
| `succeeded`          | Payment succeeded and has been fully captured.                                 |
| `uncaptured`         | Payment succeeded but capture has not yet occurred (manual capture mode).      |
| `partially_reversed` | Payment succeeded and has been partially refunded.                             |
| `reversed`           | Payment succeeded and has been fully refunded or voided.                       |
| `chargeback`         | A chargeback has been recorded against this payment.                           |
| `cancelled`          | Payment is cancelled.                                                          |

## Boolean lifecycle flags

The `status` field alone does not tell you whether a payment has been captured, refunded, or chargebacked. These outcomes are tracked by separate boolean fields returned alongside `status`.

| Field             | Type    | Meaning                                                                   |
| ----------------- | ------- | ------------------------------------------------------------------------- |
| `isCaptured`      | boolean | Funds have been captured from the customer.                               |
| `isReversed`      | boolean | The payment has been at least partially refunded or voided.               |
| `isFullyReversed` | boolean | The entire authorized or captured amount has been reversed.               |
| `isChargebacked`  | boolean | A chargeback has been recorded for this payment.                          |
| `isRetrying`      | boolean | The payment is currently in a retry cycle after a failed attempt.         |
| `isRecovered`     | boolean | The payment eventually succeeded after one or more failed retry attempts. |

Example

A payment can have `status: "succeeded"`, `isCaptured: false`, and `isFullyReversed: false` at the same time. This means the authorization was approved but the funds have not yet been captured — the `displayStatus` would be `uncaptured`.

warning

Do not use `displayStatus` as the primary signal in your integration logic. It can expand with new values in future releases. Always branch on `status` and the individual boolean flags.

## Amounts

The captured and refunded amounts are also surfaced directly on the payment object:

| Field            | Meaning                                                                      |
| ---------------- | ---------------------------------------------------------------------------- |
| `amountCaptured` | Amount that has been captured, in minor currency units (e.g. cents).         |
| `amountReversed` | Amount that has been reversed (refunded or voided), in minor currency units. |
