# User asset balances

Source: https://docs.settlemint.com/docs/api-reference/tokens/user-asset-balances
List the authenticated participant's token holdings through the DALP API, aggregated across their linked wallets, with balances, base-currency value, and yield denomination details.



Use the user asset balances endpoint when an integration needs the authenticated
participant's current token holdings in a DALP system. It returns one row per
token the participant holds, with the total, frozen, and available balance, the
resolved base-currency value, the token's decimals, and a per-wallet breakdown.

The endpoint reads indexed balance state. It returns only tokens with a positive
balance in the active system, so an empty `data` array means the participant holds
no tracked assets in that system rather than that the data is missing.

## Endpoint [#endpoint]

```text
GET /api/v2/user-asset-balances
```

The endpoint returns a JSON:API paginated collection with `data`, `meta`, and
`links`. Each `data` item is one aggregated token balance for the participant.

```bash
curl --globoff --request GET \
  "$DALP_API_URL/api/v2/user-asset-balances?page[limit]=50&sort=-balance" \
  --header "X-Api-Key: $DALP_API_TOKEN"
```

## Holder scope and wallet aggregation [#holder-scope-and-wallet-aggregation]

Balances are calculated for the authenticated **participant**, not for a single
address. A participant can hold the same token through more than one linked
wallet, typically a signing account (EOA) and a smart wallet under account
abstraction. By default the endpoint aggregates each token's balance across the
participant's full set of linked wallets in the active system, so an
account-abstraction user sees one combined balance per token without your
integration fetching and summing each address separately.

Each row also includes a `byWallet` array that breaks the aggregate balance down
per wallet, so you can show both the combined total and the per-wallet split.

The result is scoped to the active system from the request context. If a
participant holds assets in more than one DALP system, the result for one system
does not include rows from another system.

## Read another participant's holdings [#read-another-participants-holdings]

Send `filter[wallet]=0x…` to scope the result to a specific wallet instead of the
authenticated participant's own holdings. The platform honors the override for the
participant reading their own wallet, for platform admins reading any wallet, and
for active-organization user readers when the target wallet belongs to a user in
the caller's current organization. An organization user reader requesting a wallet
outside their organization is rejected with `FORBIDDEN`.

An honored override that resolves to a participant expands to that participant's
full linked wallet set, so the response stays an aggregate-holdings view rather
than a single-address view. A platform admin requesting a wallet that is not
attached to any participant reads that single wallet only. This is the request the
Console uses to show another user's holdings on a participant detail workspace
without requiring platform admin access.

## Query parameters [#query-parameters]

The endpoint uses the canonical collection query parameters.

| Parameter                | Use it for                                                                             |
| ------------------------ | -------------------------------------------------------------------------------------- |
| `page[limit]`            | Page size. Defaults to 50, with a maximum of 200.                                      |
| `page[offset]`           | Number of rows to skip for pagination.                                                 |
| `sort`                   | Sort order. Defaults to `-balance` (largest balance first).                            |
| `filter[q]`              | Global search across the token name and symbol.                                        |
| `filter[wallet]`         | Gated wallet override described above.                                                 |
| `filter[<field>]`        | Filter by `tokenAddress`, `tokenName`, `tokenSymbol`, or `tokenDecimals`.              |
| `filter[metadata.<key>]` | Filter by a metadata key declared on the token's asset-type template.                  |
| `groupBy`                | Group results by a bucketable metadata key and return per-group summaries (see below). |

`sort` accepts `balance`, `tokenAddress`, `tokenName`, and `tokenSymbol`. Prefix a
field with `-` for descending order. `tokenDecimals` can be filtered but not
sorted.

### Group by a metadata key [#group-by-a-metadata-key]

Send `groupBy=<key>` to group the participant's filtered holdings by a bucketable
metadata key declared on the token's asset-type template. The key must be declared
and bucketable, otherwise the request is rejected. When `groupBy` is set, the
response `meta` block adds a `groups` array of per-group summaries and a `groupBy`
object naming the active axis and its display label. A returned row carries a
`metadataValues` object holding the grouped key's value only when the token has a
value for that key; rows without a value for the grouped key omit the field.

## Response shape [#response-shape]

Each `data` item is one token the participant holds.

```json
{
  "data": [
    {
      "id": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
      "value": "1.000000000000000000",
      "frozen": "0.000000000000000000",
      "available": "1.000000000000000000",
      "valueInBaseCurrency": "1000.00",
      "priceInBaseCurrencyReliable": true,
      "token": {
        "id": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
        "name": "Bond Token",
        "symbol": "BOND",
        "type": "bond",
        "isExternal": false,
        "decimals": 18,
        "totalSupply": "1000000",
        "bond": { "isMatured": false },
        "yield": {
          "schedule": {
            "id": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
            "denominationAsset": {
              "id": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
              "symbol": "USDC",
              "decimals": 6
            }
          }
        }
      },
      "byWallet": [
        {
          "wallet": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
          "value": "1.000000000000000000",
          "frozen": "0.000000000000000000",
          "available": "1.000000000000000000"
        }
      ]
    }
  ],
  "meta": {
    "total": 1,
    "facets": {}
  },
  "links": {
    "self": "/v2/user-asset-balances?page[limit]=50&page[offset]=0",
    "first": "/v2/user-asset-balances?page[limit]=50&page[offset]=0",
    "prev": null,
    "next": null,
    "last": "/v2/user-asset-balances?page[limit]=50&page[offset]=0"
  }
}
```

Each item includes:

* `id`: the token contract address for the aggregated balance row.
* `value`, `frozen`, `available`: the total, frozen, and available balance,
  scaled by the token's `decimals` and returned as decimal strings.
* `valueInBaseCurrency`: the balance multiplied by the token's resolved price,
  expressed in the organization's base currency. It is `null` when no price path
  is available for the token.
* `priceInBaseCurrencyReliable`: `false` when no price path is available, in which
  case `valueInBaseCurrency` is also `null`, or when a price is returned but a
  conversion hop fell back to a stale rate. When a value is present and this flag
  is `false`, treat the value with lower confidence.
* `token`: the token's name, symbol, type, decimals, total supply, and feature
  details such as bond maturity and yield.
* `byWallet`: the per-wallet breakdown of the aggregate balance, with each
  wallet's `value`, `frozen`, and `available` returned as decimal strings scaled
  by the token's `decimals`, matching the aggregate row.

The `meta` block reports `total`, the count of distinct tokens matching the
request, and `facets`, the available metadata facet axes for the result. When a
request sets `groupBy`, `meta` also includes `groups` and `groupBy`.

## Yield denomination details [#yield-denomination-details]

For a token with a yield schedule, `token.yield.schedule.denominationAsset`
reports the asset the schedule pays in, with its `symbol` and `decimals`. The
platform resolves the denomination token's metadata canonically by chain and
address, so a 6-decimal denomination asset reports `"decimals": 6` even when that
asset sits outside the participant's active system scope. Use the reported
`decimals` to scale denomination amounts rather than assuming 18.

When the schedule records a denomination asset address but its metadata is not
found, `denominationAsset.id` keeps that denomination asset address while `symbol`
and `decimals` fall back to `UNKNOWN` and 18. When the schedule has no recorded
denomination asset at all, `denominationAsset.id` is the schedule address with the
same `UNKNOWN`/18 fallback.

## Errors [#errors]

| Condition                                                             | Result         |
| --------------------------------------------------------------------- | -------------- |
| The participant has no wallet on file in the active system.           | `UNAUTHORIZED` |
| A `filter[wallet]` override targets a wallet the caller may not read. | `FORBIDDEN`    |

See the [platform API error reference](/docs/api-reference/errors/platform-api-error-reference)
for the full error contract.

## Related [#related]

* [Portfolio statistics](/docs/api-reference/tokens/portfolio-statistics) for the participant's aggregate value time series and asset-type breakdown.
* [Token holders and transfers](/docs/api-reference/tokens/token-holders-transfers) for per-token holder balances and transfer operations.
* [Getting started with API integration](/docs/api-reference/reference/getting-started)
