> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stableyard.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Settlement lifecycle

> Read a payment's status, stage and settlement snapshot to know when value reached the destination.

A receive payment is `accepted` when the payer's funds are verified and `succeeded` when the net has reached the destination and confirmed. Read the payment, and treat `status` and `operationalState` as separate columns.

```bash theme={null}
curl https://staging-api-v2.stableyard.fi/v2/payments/payment_123 \
  -u "$APP_ID:$APP_SECRET"
```

```mermaid theme={null}
flowchart LR
  A["Funds verified · accepted"] --> B["Net transferred to the destination"]
  B --> C["Confirmed on the destination network · succeeded"]
```

## `accepted` is not `succeeded`

| `status` | What Stableyard has proven | What it does not mean |
| - | - | - |
| `accepted` | The payer's funds were independently verified as received | The destination has not been credited |
| `succeeded` | Value reached the destination and the transfer confirmed | Nothing further is pending |

Each has its own timestamp, `acceptedAt` and `succeededAt`, and its own event, `payment.accepted` and `payment.succeeded`. Financial status never regresses once a payment is `accepted`: if settlement fails afterwards, `operationalState` moves instead.

<Warning>
  A payment can sit at `accepted` for a long time while settlement retries, and can stay at `accepted` permanently if settlement stops for a human. Choose deliberately which status releases goods or credits a user in your product, and write it down. Reading `accepted` as completion is the most expensive mistake available here.
</Warning>

## The payment freezes where value lands

Every receive payment carries an immutable `settlement` snapshot, taken at creation:

```json theme={null}
{
  "status": "accepted",
  "settlement": {
    "type": "settlement_destination",
    "settlementDestinationId": "destination_123",
    "destinationType": "connected_wallet",
    "destinationAddress": "0x1111111111111111111111111111111111111111",
    "chainId": 42161,
    "assetCode": "USDC",
    "tokenAddress": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
    "decimals": 6
  }
}
```

* Changing the account's profile later cannot redirect value already in flight.
* `settlement` is `null` on payment types that do not use a receive settlement destination, including a send.
* The amount delivered is `fees.merchantNetAmountAtomic` on the same payment. See [Settlement fees](/settlement/assessing-fees).
* Settlement is one destination, one chain, one asset. There is no split and no per-currency routing.

## Build against what settlement waits on, not a clock

No delivery time is quoted anywhere in the API, and no field returns an estimate.

| Determinant | Why it moves the timing |
| - | - |
| The evidence path of the funding method | Some methods are verified from a provider notification; others need the payer to submit a transaction hash before anything advances |
| Whether the funds had to cross chains or convert | Value has to reach the destination chain before settlement can start |
| Confirmation on the destination network | A broadcast transfer is not a credit until the network confirms it |
| Retries in progress | `operationalReasonCode: settlement_retry_scheduled` means automation is still working |
| A stopped settlement | `settlement_requires_intervention` means a human decides, and no automatic progress happens |

`stage` narrates the position: `settlement_pending`, `settlement_broadcast`, `settlement_confirming`, and `settlement_returned` when a broadcast settlement comes back. It is diagnostic and can move backwards, so nothing customer-facing should depend on it. See [Status codes](/status-codes).

## Read the record that answers your question

| Question | Call | What to read |
| - | - | - |
| Is this order done? | `GET /v2/payments/{paymentId}` | `status`, then `operationalState`. A terminal `status` with `operationalState: requires_intervention` still needs attention |
| What was delivered, and with which hash? | `GET /v2/accounts/{accountId}/transactions` | The row with `financialLegKind: "settlement"`: `settlement.amount` and `settlement.txHash`. Fees are their own rows, so a statement can itemise them |
| Did a deposit-address arrival settle? | `GET /v2/accounts/{accountId}/deposits` | `settlement.status`, `settlement.txHash`, `settlement.settledAt`, `netSettlementAmount` and the `settlementProfileSnapshot` captured at detection. Deposit status runs `detected`, `confirming`, `settling`, `settled` |

<Note>
  `GET /v2/accounts/{accountId}/balances` is not one of these answers. It returns `balanceType: "recorded_activity_projection"` with `custodyScope: "not_a_custody_balance"`, and it does not decrease when value settles out to the customer's own wallet. Do not show it as funds available or gate a spend on it.
</Note>

## A settlement that stalls moves `operationalReasonCode`, not `status`

| `operationalReasonCode` | What it means for the recipient |
| - | - |
| `settlement_retry_scheduled` | Automation is retrying. Do not create a replacement payment |
| `settlement_unconfirmed` | The transfer was submitted and is not confirmed |
| `settlement_failed` | The transfer did not complete |
| `settlement_requires_intervention` | Automation stopped safely and operations must act |

`payment.settlement_returned` fires when a settlement transfer comes back. A deposit that needs the same attention reports `settlement.status: "requires_intervention"` with a stable `reasonCode`. A webhook is a prompt to read the payment, never a substitute for it.

<Card title="Next: Merchant settlement" icon="store" href="/settlement/merchant-settlement">
  Deliver collected value to the destination a merchant chose.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.