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

# States

> Every status across the lifecycles, what each one means, and what moves it.

One table per resource. Each row is a state, what it means, and what moves it out — which is the question the status alone never answers.

<Note>
  Compare status values **case-insensitively** rather than matching exact strings. Each table below shows the values as they arrive.
</Note>

## Sub-client

| State       | Meaning                         | What moves it                       |
| ----------- | ------------------------------- | ----------------------------------- |
| `CREATED`   | Registered, nothing checked yet | The checks start on their own       |
| `VERIFYING` | Being checked                   | The provider reaches a result       |
| `REVIEW`    | A human is looking              | The reviewer decides                |
| `VERIFIED`  | Can hold and move money         | Terminal for the happy path         |
| `REJECTED`  | Declined on the data            | Fix the data and ask for a re-check |

Branch on this field. `verification_status` reports the result of the identity check — see [Sub-client verification](/lifecycles/sub-client-verification).

A document rejected on its own is not in this table: it moves `verification_status` to `needs_action` and leaves `status` where it was. [User values](/reference/users/values#verification_status) has the set.

## Virtual account

Which set comes back depends on the version you are pinned to; the values are on [Virtual account values](/reference/virtual-accounts/values#status), where both sets are listed side by side.

| State         | Meaning                                  | What moves it                                    |
| ------------- | ---------------------------------------- | ------------------------------------------------ |
| `pending`     | Waiting on the sub-client's verification | That verification reaching a terminal approval   |
| `activating`  | The bank is opening the account          | The bank deciding, with no upper bound           |
| `active`      | Can take deposits                        | Being closed, or frozen                          |
| `failed`      | Could not be opened                      | A retry, back to `activating`                    |
| `deactivated` | Closed                                   | Terminal                                         |
| `frozen`      | Frozen by an operator                    | Being unfrozen. It blocks payouts while it lasts |

**Nothing but the active state can receive money.** Wait for `virtual_account.activated` rather than for the account to merely exist — [Account opening](/lifecycles/account-opening) follows the whole sequence.

## Deposit

| State          | Meaning                            | What moves it                                                                                            |
| -------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `PENDING`      | Seen, settlement not finished      | Settlement completing, a failure, a return, or a compliance hold                                         |
| `COMPLETED`    | On the books and spendable         | **Not terminal** — a compliance hold or a bank clawback can still move it                                |
| `FAILED`       | Settlement did not finish          | Terminal                                                                                                 |
| `REFUNDED`     | Returned to the sender             | Terminal                                                                                                 |
| `KYT_PENDING`  | Held while a compliance check runs | Back to where it was before the hold, to `KYT_REJECTED`, or to `REFUNDED` if the money is returned first |
| `KYT_REJECTED` | Frozen after the check declined it | A compliance decision, either to `REFUNDED` or to `COMPLETED` if the rejection is withdrawn              |

A fiat deposit arrives `COMPLETED`, with no settlement step to wait through.

`KYT_REJECTED` is deliberately not `FAILED`: a failure is technical, this one is a compliance decision, and keeping them apart is what makes the audit trail readable.

**Only `FAILED` and `REFUNDED` are terminal.** A `COMPLETED` deposit can still be held or clawed back, so code that treats it as final is treating a state as an ending it does not have.

## Payout

| State         | Meaning                                  | What moves it                                                          |
| ------------- | ---------------------------------------- | ---------------------------------------------------------------------- |
| `CREATED`     | Recorded                                 | Queueing                                                               |
| `PENDING`     | Queued                                   | Being handed to the rail                                               |
| `PROCESSING`  | With the rail                            | The rail delivering, failing or returning it                           |
| `IN_REVIEW`   | Held for a manual check                  | A reviewer                                                             |
| `KYT_PENDING` | Held for a compliance check              | The check completing                                                   |
| `COMPLETED`   | Delivered                                | **Not terminal** — a bank return after settlement moves it to `FAILED` |
| `FAILED`      | Did not go through, or was returned      | Terminal                                                               |
| `CANCELLED`   | Stopped before sending                   | Terminal                                                               |
| `EXPIRED`     | A crypto payout was never funded in time | Terminal, crypto only                                                  |

**`IN_REVIEW` and `KYT_PENDING` only ever arrive on `payout.status_changed`.** No dedicated event carries either.

**Only `FAILED`, `CANCELLED` and `EXPIRED` are terminal.** A bank return moves a `COMPLETED` payout to `FAILED`; [Payout](/lifecycles/payout) has when and why.

## RFI

| State          | Meaning                                        | What moves it                                        |
| -------------- | ---------------------------------------------- | ---------------------------------------------------- |
| `pending`      | Something needs answering                      | You answering it                                     |
| `answered`     | An answer has been given and is being assessed | The assessment, back to `pending` or to an ending    |
| `resolved`     | Satisfied                                      | Terminal — what it blocked is unblocked              |
| `not_resolved` | Closed unsatisfied                             | Terminal, with `expired` or `rejected` as the reason |

An RFI has items, and each is answered separately. One item being returned does not undo the others.

## The states you cannot read back

Two pieces of information exist only on the event that carried them, and no read ever returns them:

| What                                          | Where it is                                    |
| --------------------------------------------- | ---------------------------------------------- |
| Why verification failed                       | `data.reasons[]` on `user.verification.failed` |
| That a payout is `IN_REVIEW` or `KYT_PENDING` | `payout.status_changed`                        |

Capture both when they arrive. There is no going back for them.
