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

# Money model

> Per-currency virtual balances, FX conversion, holds and the immutable ledger

## Ten independent virtual balances

Every account holds **ten virtual balances, one per asset**:

| Asset | What it is | Decimals | How it is funded |
| - | - | - | - |
| `USD` | US dollars — **the principal balance** | 2 | Fiat payins, swaps, transfers, adjustments |
| `USDT` | USD stablecoin | 6 | Fiat payins, on-chain deposits (TRON/Ethereum), transfers |
| `USDC` | USD stablecoin | 6 | On-chain deposits (Ethereum), transfers |
| `BTC` | Bitcoin | 8 (satoshis) | On-chain deposits, operator credits and internal transfers |
| `GOLD` | Grams of fine gold, custodian-backed | 6 | Operator credits and internal transfers |
| `SILVER` | Grams of fine silver, custodian-backed | 6 | Operator credits and internal transfers |
| `PLATINUM` | Grams of fine platinum, custodian-backed | 6 | Operator credits and internal transfers |
| `BOB` | Bolivian bolivianos — local hold | 2 | Fiat payins with local hold, transfers, adjustments |
| `MXN` | Mexican pesos — local hold | 2 | Fiat payins with local hold, transfers, adjustments |
| `ARS` | Argentine pesos — local hold | 2 | Fiat payins with local hold, transfers, adjustments |

They are fully independent: they never mix and are never converted
automatically. (`BANK_USD` and `BANK_EUR` are separate banking mirror
balances — see [Banking](/en/guides/banking).)

`GET /v1/balances` always returns all ten (zeros if you have not used that
asset yet), as **decimal strings**:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "account_id": "…",
  "balances": [
    { "asset": "USD", "available": "1000.00", "held": "0.00" },
    { "asset": "USDT", "available": "125.430000", "held": "10.000000" },
    { "asset": "USDC", "available": "50.000000", "held": "0.000000" },
    { "asset": "BTC", "available": "0.00060000", "held": "0.00000000" },
    { "asset": "GOLD", "available": "12.500000", "held": "0.000000" },
    { "asset": "SILVER", "available": "0.000000", "held": "0.000000" },
    { "asset": "PLATINUM", "available": "0.000000", "held": "0.000000" },
    { "asset": "BOB", "available": "0.00", "held": "0.00" },
    { "asset": "MXN", "available": "0.00", "held": "0.00" },
    { "asset": "ARS", "available": "0.00", "held": "0.00" }
  ]
}
```

<Note>
  Internally each amount is stored as an integer in its asset's minimal
  unit (cents, micro-USDT, satoshis, micro-grams) and computed with exact
  rational arithmetic. There are no floats and no accumulated rounding
  errors.
</Note>

**USD is the principal balance**: payouts, fiat payins
and service fees use USD unless the account configures otherwise. An
empty asset setting normalizes to USD.

## Choose which balance pays

**Payouts** and **service fees** (KYC, wallet creation, banking) can be
debited from any of your ten balances. The pricing pipeline does not
change: the operation is quoted in USDT as always, and at the end the total
translates to the chosen asset at the **effective settlement price** of the
moment.

* **Per-account default**: `PUT /v1/settlement` with
  `{"default_settlement_asset": "BTC"}`. From then on, every payout and
  service fee comes out of the BTC balance (if it covers the amount; there
  are no cascades into other balances).
* **Per-operation override**: send `settlement_asset` in
  `POST /v1/payouts` (or in the QR confirm) to pay that single operation
  from another balance without touching the default.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Set BTC as the default paying balance
curl -X PUT "https://api.qbank.cl/platform/v1/settlement" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"default_settlement_asset": "BTC"}'
```

Multi-asset settlement rules:

| Rule | Detail |
| - | - |
| Execution price | BTC and GOLD use an on-chain execution feed (not the reference price). If the feed is stale or unavailable, the operation returns `503 pricing_unavailable` — it never executes on a doubtful price. |
| Debit, hold and refund | All three live in the chosen asset. If the payout fails, the **exact** `settlement_amount` is refunded — never re-quoted. |
| Idempotency | Replaying with the same key returns the original amount; the price is never recomputed. |
| Per-operation limit | Volatile assets (BTC/GOLD/SILVER/PLATINUM) have a per-operation limit (USDT equivalent, visible in `GET /v1/settlement`); exceeding it returns `422 settlement_limit_exceeded`. |
| Per-account daily limit | Volatile assets also have a rolling 24h volume cap (`volatile_daily_limit_usdt` in `GET /v1/settlement`); exceeding it returns `422 settlement_daily_limit_exceeded`. Settle in USD/USDT/USDC or retry later. |
| USD | The principal balance. USD settles 1:1 with USDT, exact to the cent. |

The `settlement` block of `GET /v1/rates` shows the effective per-asset
price (spread included) so you can estimate before operating, and the
payout response records `settlement_asset`, `settlement_amount` and
`settlement_rate` for auditability.

## Choose which balance receives your payins

**Payins** (QR, bank transfer, collect, and card) credit
the USD balance directly in cents. If you configure another payin asset, the net amount
follows the post-credit conversion flow at the real price, with no extra
swap spread; the payin already paid its fee and rate. The same limits as a
regular swap apply.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Credit my payins in USDC
curl -X PUT "https://api.qbank.cl/platform/v1/settlement" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"default_payin_asset": "USDC"}'
```

| Rule | Detail |
| - | - |
| Post-credit conversion | The payin credits in the account's principal asset (USD is the principal balance) and the conversion runs right after, as a swap (you will see `swap_out`/`swap_in` in your statement). |
| Price and limits | The conversion executes **at the real price, with no swap spread** (no double cost: the payin already paid its fee and rate). The per-operation/24h limits of volatile assets (BTC/GOLD/SILVER/PLATINUM) apply. |
| If the conversion fails | The payin stays credited in the principal asset with `conversion_status: pending_retry` and the system retries automatically — funds are never lost or double-converted. |
| Checkout and POS | Each link keeps the `settlement_asset` chosen at creation; this setting never re-converts them. A link created **without** `settlement_asset` uses your `default_payin_asset`. |
| Surfaces | `GET /v1/payins`, the detail and the `payin_credited` webhook expose `settlement_asset` and `conversion_status` when a conversion applies. |

## `available` and `held`

Each balance has its own two counters:

| Field | Meaning |
| - | - |
| `available` | Balance available to operate |
| `held` | Reserved by in-flight operations (pending payouts and withdrawals) |

When you create a payout or withdrawal, the debit (`amount + fee`) leaves
`available` and sits in `held` until the operation reaches a final state:

* **`completed`** → the hold is consumed; the money left.
* **`failed`** → the full debit (amount + fee) is refunded to `available`.

## FX conversion (fiat ↔ USDT, quoted)

Fiat operations are quoted in USDT at **your account's rates** at execution
time (the same ones returned by `GET /v1/rates`, USD base): `rate` for
payouts and `payin_rate` for payins. Conversion rounds **up** on debits and
**down** on credits, with at most 1 micro-USDT of difference. The quoted
total then debits (or credits) in the settlement asset — USD-principal
accounts settle 1:1 in USD cents.

Example — a 50,000 CLP payout at a 950.25 rate:

```
usdt_amount = ceil(50000 / 950.25 × 10^6) / 10^6 = 52.617733 USDT
total_debit = usdt_amount + fee
```

Example — a 50,000 CLP payin at a 955.10 `payin_rate`:

```
usdt_gross    = floor(50000 / 955.10 × 10^6) / 10^6 = 52.350539 USDT
usdt_credited = usdt_gross − fee
```

The rate used is recorded on the object (`fx_rate`) for auditability.

## Reference and settlement prices

`GET /v1/rates` includes an `asset_prices` block with the **USD reference
price** of USD, USDT, USDC, BTC and the metals (BTC per unit; GOLD, SILVER and PLATINUM per gram;
USD, USDT and USDC are 1 by convention) to value your balances on screen,
plus a `settlement` block with the **effective price** your balance would
be valued at if you pay an operation from that asset (spread included):

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "asset_prices": {
    "USD": { "currency": "USD", "unit": "usd", "price": "1" },
    "USDT": { "currency": "USD", "unit": "usdt", "price": "1" },
    "USDC": { "currency": "USD", "unit": "usdc", "price": "1" },
    "BTC": { "currency": "USD", "unit": "btc", "price": "109853.24",
             "updated_at": "2026-07-07T11:59:41Z",
             "settlement_grade": true },
    "GOLD": { "currency": "USD", "unit": "gram", "price": "107.5341",
              "updated_at": "2026-07-07T09:12:05Z",
              "settlement_grade": true },
    "SILVER": { "currency": "USD", "unit": "gram", "price": "1.2345",
                "updated_at": "2026-07-07T09:12:05Z",
                "settlement_grade": true },
    "PLATINUM": { "currency": "USD", "unit": "gram", "price": "45.6789",
                  "updated_at": "2026-07-07T09:12:05Z",
                  "settlement_grade": true }
  },
  "settlement": {
    "default_asset": "USD",
    "assets": [
      { "asset": "USD", "available": true, "settlement_rate": "1" },
      { "asset": "USDT", "available": true, "settlement_rate": "1" },
      { "asset": "USDC", "available": true, "settlement_rate": "0.99900000" },
      { "asset": "BTC", "available": true, "settlement_rate": "109029.34070000" },
      { "asset": "GOLD", "available": true, "settlement_rate": "106.99642950" }
    ]
  }
}
```

`settlement_grade: true` means the price is fresh enough to execute
operations; if it drops to `false`, payments from that asset answer
`503 pricing_unavailable` until the price recovers.

## Immutable ledger

Every movement produces an immutable entry with the resulting balance
(`balance_after`) **in the movement's currency**. Your full history lives
at `GET /v1/movements` (filter by currency with `?asset=`):

| `type` | What it represents |
| - | - |
| `payin_credit` | Credit from a fiat collection |
| `payout_debit` / `payout_refund` | Payout debit / refund on failure |
| `transfer_in` / `transfer_out` | Internal transfer received / sent |
| `funding` | On-chain deposit credited (USDT or USDC, each on its own balance) |
| `withdrawal_debit` / `withdrawal_refund` | On-chain withdrawal / refund on failure |
| `compliance_fee` / `compliance_refund` | KYC/KYB service charge / refund |
| `wallet_creation_fee` / `wallet_creation_refund` | Wallet creation charge / refund |
| `adjustment` | Manual adjustment by CBPay (audited) |

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl "https://api.qbank.cl/platform/v1/movements?type=payout_debit&from=2026-07-01&to=2026-07-07&page_size=20" \
  -H "Authorization: Bearer <token>"

# Only the GOLD balance movements
curl "https://api.qbank.cl/platform/v1/movements?asset=GOLD&from=2026-07-01&to=2026-07-07" \
  -H "Authorization: Bearer <token>"
```

Every list endpoint (`/v1/movements`, `/v1/payouts`, `/v1/payins`,
`/v1/crypto/transactions`, `/v1/banking/operations`) accepts pagination
(`page`, `page_size` up to 200) and `from`/`to` date filters
(YYYY-MM-DD, organization timezone, inclusive).

## Operation states

Payouts and crypto withdrawals follow the same lifecycle:

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart LR
    pending --> processing
    processing --> completed
    processing --> failed
    pending --> failed
```

Final states (`completed`/`failed`) arrive via [webhook](/en/webhooks); no
polling required.

### Custody-backed metal balances

`GOLD`, `SILVER` and `PLATINUM` are ledger-only, custodian-backed balances
measured in fine grams with six decimal places. Settlement and swaps use a
price oracle and the fixed `31.1034768` grams-per-troy-ounce conversion; no
on-chain metal deposit, withdrawal or spending rail is implied.


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