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

# Wallet balances

> Returns the latest balance of each wallet and asset, across one or more chains.

Returns the latest balance of each requested wallet, with one row per chain, wallet and asset. `wallets` takes 1 to 100 comma-separated addresses. `chains` limits results to specific chains; omit it to include every chain.

## Response

`balances` lists one row per wallet and asset with at least one transaction, ordered by chain, wallet, then asset. A wallet and asset with no observed balance has no row, and a missing row does not mean a zero balance.

`balance` is the amount after the most recent transaction that changed it, in the asset's own units. `trigger` is the event type that changed it, such as `trade` or `deposit`. New `trigger` and `asset` values can be added, so keep unrecognized values rather than discarding them.

`blockNumber` and `txIndex` give the row's position in its chain. To merge this response with the [`wallet.balances`](https://docs.metastreams.io/reference/streams/wallet-balances#message-format) stream, follow the rule on that page.

## Errors

| Code | When |
| - | - |
| `UNSUPPORTED_CHAIN` | A `chains` value is not a supported slug |
| `VALIDATION_ERROR` | No wallet or more than 100, a malformed address, or an unknown parameter |

```bash cURL theme={null}
curl "https://api.metastreams.io/v1/wallets/balances?wallets=7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5&chains=solana" \
  -H "Authorization: Bearer $API_KEY"
```

```typescript TypeScript theme={null}
const url = new URL("https://api.metastreams.io/v1/wallets/balances");
url.searchParams.set("wallets", "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5");
url.searchParams.set("chains", "solana");

const response = await fetch(url, {
  headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const { balances } = await response.json();
```

```rust Rust theme={null}
use serde_json::Value;

let response: Value = reqwest::Client::new()
    .get("https://api.metastreams.io/v1/wallets/balances")
    .query(&[("wallets", "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5"), ("chains", "solana")])
    .bearer_auth(std::env::var("API_KEY")?)
    .send()
    .await?
    .error_for_status()?
    .json()
    .await?;
let balances = &response["balances"];
```

```json Balances theme={null}
{
  "balances": [
    {
      "chain": "solana",
      "wallet": "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5",
      "asset": "SOL",
      "balance": "41.208113",
      "trigger": "trade",
      "blockNumber": 371204118,
      "signature": "4xQmVb8e2kT1nR7pZcW3sLdHfA9jEuY6gVnX1oB5iC0wQ2rT8yU3iO7pA1sD4fG6h",
      "txIndex": 812,
      "updatedAt": 1789632015120
    }
  ]
}
```

```json Never moved theme={null}
{
  "balances": []
}
```


## OpenAPI

````yaml specs/openapi.json GET /v1/wallets/balances
openapi: 3.1.0
info:
  title: Metastreams API
  description: >-
    The Metastreams market-data API. Amounts are decimal strings, timestamps are
    Unix milliseconds, and every field name is camelCase.
  license:
    name: Proprietary
    identifier: Proprietary
  version: 1.0.0
servers:
  - url: https://{host}
    variables:
      host:
        default: api.metastreams.io
        description: API host.
security:
  - bearerKey: []
paths:
  /v1/wallets/balances:
    get:
      tags:
        - wallets
      summary: The latest balance of each named wallet, per chain and asset.
      description: >-
        `wallets` names 1 to 100 addresses. `chains` narrows the scope, and
        every spot chain is

        read when it is absent. Each row holds the balance after the last
        transaction that moved

        it. A few movements write no row, such as Solana rent, so a balance can
        lag until the

        next one. Each `wallet` comes back in canonical form: base58 on Solana,
        lowercase hex on

        EVM chains.
      operationId: wallet_balances
      parameters:
        - name: wallets
          in: query
          description: Wallet addresses, CSV; one to 100.
          required: true
          schema:
            type: string
          example: 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin
        - name: chains
          in: query
          description: >-
            Chains to scope to, CSV of the chain slugs. Absent means every spot
            chain.
          required: false
          schema:
            type: string
          example: solana,base
      responses:
        '200':
          description: >-
            The latest balance of each named wallet and asset. A pair with no
            observed balance has no row, which is not a zero.
          headers:
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UiWalletBalances'
        '400':
          description: >-
            Unsupported chain, a malformed wallet address, a wallet count
            outside 1-100, or a malformed parameter.
          headers:
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: >-
            Missing or invalid credential: an API key, or a session token a key
            minted.
          headers:
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '402':
          description: >-
            The organization's credits this billing period reach its plan's
            limit.
          headers:
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: >-
            A key whose plan excludes this endpoint gets `FORBIDDEN`. A session
            token from an

            origin it does not name gets `ORIGIN_NOT_ALLOWED`.
          headers:
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limit exceeded.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying.
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: Unexpected server failure.
          headers:
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '503':
          description: Dependency down or maintenance.
          headers:
            X-Credits-Cost:
              schema:
                type: integer
              description: >-
                Credits charged for this request. Zero on any non-2xx. Sent on a
                metered tier only.
            X-Credits-Remaining:
              schema:
                type: integer
              description: Credit balance after this request. Sent on a metered tier only.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests left in the bucket this request spent from. Not sent
                with a 401.
            X-Request-ID:
              schema:
                type: string
              description: >-
                This request's trace ID. Echoed from the request, or generated
                when it sent none.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  schemas:
    UiWalletBalances:
      type: object
      description: The latest balance of each wallet and asset a read named.
      required:
        - balances
      properties:
        balances:
          type: array
          items:
            $ref: '#/components/schemas/UiWalletBalance'
          description: >-
            One row per observed wallet and asset, ordered by chain, wallet,
            then asset.
    ErrorEnvelope:
      type: object
      description: The complete error response body — every error is exactly this.
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
          description: The error.
    UiWalletBalance:
      type: object
      description: >-
        One wallet's balance of one asset, as of the transaction that last moved
        it.
      required:
        - chain
        - wallet
        - asset
        - balance
        - trigger
        - blockNumber
        - signature
        - txIndex
        - updatedAt
      properties:
        asset:
          type: string
          description: >-
            The asset the balance is in. This is an open enumeration: keep a
            value you do not recognize.
          examples:
            - SOL
            - ETH
            - BNB
            - POL
            - USDC
            - TRX
            - USDT
            - USDG
            - PUSD
        balance:
          $ref: '#/components/schemas/Decimal'
          description: Post-transaction balance, human units.
        blockNumber:
          type: integer
          format: int64
          description: Block or Solana slot where the balance was observed.
          minimum: 0
        chain:
          $ref: '#/components/schemas/SpotChain'
          description: Chain the balance lives on.
        signature:
          type: string
          description: Transaction that moved it.
        trigger:
          type: string
          description: >-
            What moved the balance. This is an open enumeration: keep a value
            you do not recognize.
          examples:
            - trade
            - deposit
            - withdrawal
            - failed_tx
        txIndex:
          type: integer
          format: int64
          description: Transaction index within the observed block or slot.
          minimum: 0
        updatedAt:
          $ref: '#/components/schemas/UnixMilliseconds'
          description: Block time of the transaction that moved it.
        wallet:
          type: string
          description: Wallet holding it.
    ErrorDetail:
      type: object
      description: The `error` object inside the envelope.
      required:
        - code
        - message
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
          description: >-
            Stable, machine-readable. Clients switch on this, never on
            `message`.
        details:
          description: Optional; shape is fixed per code.
        message:
          type: string
          description: |-
            Human-readable, written for the integrating developer:
            `[What happened]. [What to do next — if actionable].`
    Decimal:
      type: string
      format: decimal
      description: An exact decimal, as a string.
      example: '123.456789'
    SpotChain:
      type: string
      description: >-
        Chain slug. One spelling per chain, in paths and bodies alike. Only a
        chain with spot data is published.
      enum:
        - solana
        - base
        - bsc
        - robinhood
        - arc
    UnixMilliseconds:
      type: integer
      format: int64
      description: An instant, as milliseconds since the Unix epoch.
    ErrorCode:
      type: string
      description: |-
        Every wire error code the API can return.

        Append-only: a new code is non-breaking, since clients fall back on the
        HTTP status for one they do not recognize, and a published code is never
        renamed or removed.
      enum:
        - UNAUTHORIZED
        - FORBIDDEN
        - VALIDATION_ERROR
        - UNSUPPORTED_CHAIN
        - NOT_FOUND
        - RATE_LIMITED
        - CREDITS_EXHAUSTED
        - INTERNAL_ERROR
        - SERVICE_UNAVAILABLE
        - RANGE_TOO_LARGE
        - INVALID_CREDENTIALS
        - ORIGIN_NOT_ALLOWED
        - NOT_ORG_MEMBER
        - MEMBERSHIP_INACTIVE
        - EMAIL_NOT_VERIFIED
        - EMAIL_TAKEN
        - ALREADY_MEMBER
        - INVITATION_ALREADY_SENT
        - INVITATION_ALREADY_ACCEPTED
        - LAST_ADMIN
        - CANNOT_REMOVE_SELF
        - KEY_LIMIT_REACHED
        - TOKEN_EXPIRED
        - PAYLOAD_TOO_LARGE
        - UNSUPPORTED_MEDIA_TYPE
        - IMAGE_TOO_LARGE
  securitySchemes:
    bearerKey:
      type: http
      scheme: bearer
      description: >-
        Send an API key, or a session token a key minted, as `Authorization:
        Bearer <credential>`. A browser opening `/v1/stream` offers its session
        token in `Sec-WebSocket-Protocol` instead.

````

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