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

# Lifecycles

> The state machines behind payouts, collections, orders, and checkout — and which webhook fires at each step.

Every money-moving resource is created quickly and then *moves* — through providers, chains, and approvals. Your integration should react to states, not to HTTP responses.

## Payouts

```mermaid theme={null}
stateDiagram-v2
  [*] --> pending: POST /v1/payouts
  pending --> processing: provider accepted
  processing --> completed: funds delivered
  processing --> failed: provider rejected / timeout
  pending --> failed
```

* `pending` → `processing` → `completed` fires **`payout.completed`**; any → `failed` fires **`payout.failed`** with `statusMessage`.
* A failed payout **refunds the balance automatically** — no refund call needed.
* Retries against providers are internal; you'll see them as `attempts` on `GET /v1/payouts/{id}` and in the `timeline`.

## Collections (mobile money charges)

```mermaid theme={null}
stateDiagram-v2
  [*] --> pending: POST /v1/collections — prompt sent to payer
  pending --> completed: payer approved
  pending --> failed: declined / timed out / wallet error
```

`collection.pending` on creation, then `collection.completed` (balance credited) or `collection.failed`. The "customer never approved" case is a normal `failed`.

## Deposits (virtual accounts & crypto addresses)

Deposits aren't requested — they arrive. Each one becomes a collection of type deposit and credits your balance; you get **`account.credited`** and the collection webhooks. Crypto deposits wait for chain confirmations first (the checkout shows this as "confirming").

## Orders (cross-rail pass-through)

```mermaid theme={null}
stateDiagram-v2
  [*] --> awaiting_funds: POST /v1/orders — deposit instructions issued
  awaiting_funds --> awaiting_confirmations: seen on-chain
  awaiting_confirmations --> funds_received: confirmed
  awaiting_funds --> funds_received: fiat deposit
  funds_received --> processing_payout: converted (if cross-currency)
  processing_payout --> completed: payout delivered
  processing_payout --> failed: payout failed — funds stay on your balance
  awaiting_funds --> expired: no deposit in time
```

Two extra states describe *how much* arrived: **`overpaid`** and **`underpaid`**. Both proceed — the order is **recomputed on the actual amount received** and pays out that amount; it fails only if the received amount is below the destination method's minimum. Every transition fires an `order.*` webhook of the same name (`order.funds_received`, `order.underpaid`, …).

## Conversions

Quote → execute. A quote is valid for **10 minutes**; executing it moves money between two of your balances synchronously and returns `completed`. Executing the same quote twice returns the original conversion.

## Checkout sessions (hosted payment links)

```mermaid theme={null}
stateDiagram-v2
  [*] --> awaiting_payment: payer picked a method
  awaiting_payment --> confirming: money seen, not final
  confirming --> complete
  awaiting_payment --> complete
  awaiting_payment --> failed: declined
  awaiting_payment --> expired: timer ran out (5 min momo · 30 min bank · 15–90 min crypto)
```

A **payment link** is `active` until its sessions collect the full amount (`paid`), it passes its own `expiresAt` (`expired`), or you close it (`closed`). A failed or expired *session* never changes the link — the payer just picks another method. Partial payments accumulate on the link (`totalReceived` / `remaining`).

## Reading state safely

* Poll `GET …/{id}` for a one-off; use webhooks for everything else.
* Webhooks can arrive out of order or twice. Treat the payload's `status` as authoritative for that resource and make handlers idempotent on the resource id + status.
* `timeline` on payout and order detail is the audit trail — it's what the dashboard shows, assembled from the same records.
