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

# User Balance

> The endpoint page for reading one user's per-currency wallet balances (free / freeze / total) in the DeCard-Managed model: how to call GET /user-asset/v1/balance, what the balance model means, and the custody arrangement that makes these balances queryable in the first place.

## One call returns every asset a user holds

In the DeCard-Managed model, every end user holds their own wallet balance, kept in custody by DCS and ledgered per currency, and a single call returns the available, frozen and total amount of each of their assets. As a licensed issuer running its own BINs, DCS keeps this user-level ledger in custody for you, and both authorization and settlement act directly on that user's own balance. This endpoint is how that model is exposed to you.

A user can hold several assets at once, and the balance endpoint returns the available, frozen and total amount **per currency**.

This page covers **balance queries only**. Money moving in, out and around is documented on the sibling pages, with no overlap:

| What you want to do                                 | Endpoint or page                                                                                                                              |
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **Read** a user's balances per currency (this page) | `GET /user-asset/v1/balance`                                                                                                                  |
| **Top up or debit** a user                          | `POST /user-asset/v1/credit` · `POST /user-asset/v1/debit`, see [Account and Asset Model (Ledgering)](../../basic-concepts/ledgering-system)  |
| Read **asset transactions and movement history**    | `POST /user-asset/v1/transactions` · `POST /user-asset/v1/transaction-detail`, see [Overview (transaction and statement queries)](./overview) |
| Read **internal transfer records**                  | `GET /user-asset/v1/transfer-query`, see the same page as above                                                                               |

## The balance model: free / freeze / total

Under custody, DCS maintains three figures for each user and each asset:

| Field    | Meaning               | Description                                                                                                                                                                                      |
| -------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `free`   | **Available balance** | The portion immediately usable for spending, transfers and withdrawals. An authorization (a card payment) is deducted from here and moved into `freeze`.                                         |
| `freeze` | **Frozen balance**    | The portion already committed and temporarily unusable, typically in-flight transactions that are **authorized but not yet settled** (authorization moves the amount from `free` into `freeze`). |
| `total`  | **Total balance**     | Always equal to `free + freeze`.                                                                                                                                                                 |

> When an authorization happens, `free` decreases, `freeze` increases and `total` is unchanged; at settlement (the actual deduction) the amount comes out of `freeze` and `total` falls with it. For how authorization and settlement rewrite these three figures, see [Authorizing Transactions](./authorizing-transactions) and [Settlement](./settlement); for the boundary of DCS custody, see [Account and Asset Model (Ledgering)](../../basic-concepts/ledgering-system).

<Note>
  **Term alignment**: the "availableBalance / frozenBalance" you may see in conceptual material are the `free` and `freeze` of this endpoint. **Always integrate against the API field names `free` / `freeze` / `total`**; `availableBalance` and `frozenBalance` are conceptual aliases only.
</Note>

## Prerequisites

* The user is registered through [Managing Users](../managing-users/overview) and you hold their `externalUserId`.
* Balances are normally non-zero only after the user has passed KYC and assets have arrived (a top-up or a transfer); a new user may return an empty array or all zeros.
* The caller is a partner onboarded to the DeCard-Managed model and sends the site-wide authentication headers (see [Quickstart](../../getting-started/quickstart)).

## Endpoint contract

The `user-asset` module also offers `credit`, `debit`, `transactions`, `transaction-detail` and `transfer-query`, documented in [Overview (transaction and statement queries)](./overview) and [Account and Asset Model (Ledgering)](../../basic-concepts/ledgering-system) within this group. This page covers only the balance query.

**`GET /user-asset/v1/balance`**

| Parameter        | In    | Type   | Required | Description                                                                                           |
| ---------------- | ----- | ------ | -------- | ----------------------------------------------------------------------------------------------------- |
| `externalUserId` | query | string | ✓        | User ID (the unique identifier of the user on your side). Redacted placeholder: `<external-user-id>`. |

> That is the only query parameter; there are **no path parameters and no request body**. This endpoint takes no path parameters and has no notion of a `tenant`, since balances are always read for one user keyed by `externalUserId`.

### Request example

```
GET /user-asset/v1/balance?externalUserId=<external-user-id>
```

```bash theme={null}
curl -X GET \
  "https://<decard-host>/user-asset/v1/balance?externalUserId=usr_xxxxxxxx" \
  -H "X-DAPI-API-KEY: <your-api-key>" \
  -H "X-DAPI-SIGN: <hmac-sha256-signature>" \
  -H "X-DAPI-TIMESTAMP: <timestamp>" \
  -H "X-DAPI-NONCE: <nonce>"
```

> The `usr_xxxxxxxx`, key and signature in the example are all placeholders. **Never paste a real user ID, API key or secret into any document, log or support ticket.**

### Response

The response uses the site-wide envelope `{ code, message, messageDetail, data }`, where `data` is an **array** with one entry per asset the user holds, each describing the balance of one currency.

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": "",
  "messageDetail": {
    "message": "",
    "title": "",
    "type": "",
    "icon": "",
    "action": "",
    "linkTitle": "",
    "linkUrl": ""
  },
  "data": [
    {
      "asset": "USDT",
      "logo": "https://<asset-logo-cdn>/usdt.png",
      "network": "Ethereum",
      "free": 100.000000,
      "freeze": 20.000000,
      "total": 120.000000
    },
    {
      "asset": "USDC",
      "logo": "https://<asset-logo-cdn>/usdc.png",
      "network": "Polygon",
      "free": 0.0,
      "freeze": 0.0,
      "total": 0.0
    }
  ]
}
```

Fields of each `data[]` element:

| Field     | Type   | Description                                                                                                             |
| --------- | ------ | ----------------------------------------------------------------------------------------------------------------------- |
| `asset`   | string | Asset currency code; currently `USDT`, `USDC` and `USD` are known, the set may grow, so trust what is actually returned |
| `logo`    | string | Currency logo image URL                                                                                                 |
| `network` | string | Network name, such as `Bitcoin`, `Ethereum` or `Polygon`                                                                |
| `free`    | number | **Available balance**                                                                                                   |
| `freeze`  | number | **Frozen balance**                                                                                                      |
| `total`   | number | **Total balance** (= `free` + `freeze`)                                                                                 |

<Warning>
  `data` is an **array**, not a single object. Iterate over it by `asset` (and by `network` where that matters), and **do not** assume an object carrying `availableBalance` and `frozenBalance` fields.

  The site-wide response envelope is `{ code, message, messageDetail, data }`, and on success the `code` literal is `SYS_SUCCESS` (identical in both integration models).
</Warning>

## Error handling

* **The user does not exist, or `externalUserId` is invalid**: `code` is not the success value, `message` and `messageDetail` explain why, and `data` carries no valid balance. Confirm first that the `externalUserId` was registered through the create-user endpoint.
* **A required parameter is missing**: a request without `externalUserId` is rejected.
* **Authentication failure**: a missing authentication header (`X-DAPI-API-KEY` / `X-DAPI-SIGN` / `X-DAPI-TIMESTAMP` / `X-DAPI-NONCE`), a bad signature or a replayed `X-DAPI-NONCE` all return the standard authentication error (see Quickstart).
* **Empty account**: when the user exists but holds no assets yet, `data` may be an empty array `[]` or contain all zeros. **That is not an error.**

## About the per-user account and DeCard-Managed model (why balances are queryable)

In the DeCard-Managed model, DCS holds each user's funds in custody internally, keyed by `externalUserId`, with sub-accounts isolated per currency. That is precisely what allows this endpoint to return a balance **per user and per currency**. By contrast:

* **Partner-Managed**: limits and authorization decisions belong to the partner, and DCS exposes no per-user balance endpoint.
* **DeCard-Managed (this documentation set)**: DCS keeps the user's own balance in custody and decides authorizations internally, acting directly on that user's `free` and `freeze`. This endpoint is how that model is exposed to you.

It also explains why whether an authorization succeeds depends mainly on **whether the user's `free` balance is sufficient** and **whether card transactions are blocked for that user**; see [Authorizing Transactions](./authorizing-transactions).

### Real-time push of balance changes (WebSocket BALANCE\_CHANGE)

Whenever an authorization, a settlement, a top-up (`credit`), a debit (`debit`) or an internal transfer changes a user's `free` or `freeze`, DCS pushes a `BALANCE_CHANGE` event in real time over **WebSocket**, carrying `freeDelta` (the change in available balance), `freezeDelta` (the change in frozen balance) and the absolute `free` and `freeze` after the change. You **do not need to poll** `/user-asset/v1/balance` to track balances: subscribe to the WebSocket channel and receive the pushes. See [Webhook & WebSocket](../../integration-resources/webhook-websocket).

## Next steps

* Top-ups and debits (`credit` / `debit`) and the accounts DCS holds in custody: [Account and Asset Model (Ledgering)](../../basic-concepts/ledgering-system)
* How authorization rewrites `free` and `freeze`: [Authorizing Transactions](./authorizing-transactions)
* How settlement deducts from `freeze`: [Settlement](./settlement)
* Asset transactions and movement history (`transactions` / `transaction-detail` / `transfer-query`): [Overview (transaction and statement queries)](./overview)
* User status and transaction restrictions (`forbidCardTransaction`): [Managing Users](../managing-users/overview)
