---
title: "Show a customer their wallets and balances"
description: "List every wallet a customer holds with its coin balances in one call, and add them up as decimals for a balances screen."
---
This recipe lists every wallet a customer holds, with its coin balances, in one call, and adds the balances up as decimals for a balances screen. It is for a wallet app that is building a "My balances" screen.

**Status.** Available.

## Money example

1. Ada has a Polygon wallet holding 250 USDC and a Stellar wallet holding 120 USDC.
2. One list call returns both wallets, with their balances.
3. Your screen shows "USDC 370 across 2 wallets".

## Before you start

You have the customer id. Reading wallets needs no permission.

## Find out what is required

| Filter | Use |
| :-- | :-- |
| `customer_id` | One customer's wallets |
| `network` | One network, in lower case |
| `wallet_address` | One address, exactly as Gravv returned it |
| `wallet_name` | A name you set (not the generated label) |
| `wallet_type` | `customer` or `master` |
| `include_balances` | `true` adds `assets` to each item |
| `page`, `items_per_page` | Up to 100 per page |

## Steps

### 1. List the wallets with their balances

<CodeGroup>
```bash title="cURL"
curl --request GET \
     --url 'https://api.gravv.xyz/v1/wallets?customer_id=401d68fb-fe97-4c56-84a6-5651cdbde747&include_balances=true&items_per_page=50' \
     --header 'Api-Key: <API_KEY>'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/wallets?customer_id=401d68fb-fe97-4c56-84a6-5651cdbde747&include_balances=true&items_per_page=50", {
  method: "GET",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
  },
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.get(
    "https://api.gravv.xyz/v1/wallets?customer_id=401d68fb-fe97-4c56-84a6-5651cdbde747&include_balances=true&items_per_page=50",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

```json title="Response"
{
  "data": {
    "items": [
      {
        "id": "30803889-fa61-4774-8d11-8e3781728a07",
        "address": "GBJPEJTFUYGBFUUJDBOZKDXIQE3ASFTPNMIT2F4NNQH5HEA76I42CH5P",
        "network": "stellar",
        "name": "Ada USDC",
        "date_created": "2026-10-13T10:02:41Z",
        "customer_id": "401d68fb-fe97-4c56-84a6-5651cdbde747",
        "wallet_type": "customer",
        "assets": [{ "symbol": "USDC", "balance": "120.0000000", "decimals": 7, "updated_at": "2026-10-13T10:20:05Z" }]
      },
      {
        "id": "bbab27f6-04b8-457d-83ed-b92009758340",
        "address": "0xc47B2D22812ee674Ee5182320FCCA83854f21962",
        "network": "polygon",
        "name": "Ada top-up wallet",
        "date_created": "2026-10-13T09:14:03Z",
        "customer_id": "401d68fb-fe97-4c56-84a6-5651cdbde747",
        "wallet_type": "customer",
        "assets": [{ "symbol": "USDC", "balance": "250.000000", "decimals": 6, "updated_at": "2026-10-13T09:31:20Z" }]
      }
    ],
    "page": 1,
    "items_per_page": 50,
    "total_items": 2,
    "total_pages": 1,
    "has_next_page": false,
    "has_previous_page": false
  },
  "error": null
}
```

The list returns the newest wallet first. Without `include_balances=true`, items carry no `assets`. If you ask for an `items_per_page` above 100, you get 100, so read the value back from the response. Page until `has_next_page` is `false`.

### 2. Add up the balances

Add balances as **decimal strings**, never as floats. For example, `250.000000` plus `120.0000000` is `370`. Treat a missing coin as "unknown", not 0. If an item has `"stale": true`, show "updating" and read that wallet again later with `GET /v1/wallets/{wallet_id}`.

## What can go wrong

| Response | Why | Fix |
| :-- | :-- | :-- |
| 400 `invalid request payload` | `page` or `items_per_page` is not a number, `include_balances` is not `true` or `false`, or you sent a `wallet_ids` filter | Send numbers and `true` or `false`. Do not use `wallet_ids` |
| An empty list for `network=Polygon` | Filters are exact and case-sensitive | Send `network=polygon` |
| An empty list for a lower-case `0x…` address | Gravv stores EVM addresses in checksum (mixed) case | Use the address exactly as Gravv returned it |
| `wallet_name` finds nothing | It matches only names you set | Filter by `customer_id` |
| 400 `wallet not found` on one wallet | The id is unknown or from the other environment | Use an id from the same environment |

## Webhooks you will receive

None. Reading wallets sends no webhook.

## Testing in sandbox

The same calls work with sandbox wallets. On EVM sandbox wallets, `USDC` shows the sandbox test dollar, and a new wallet reads `"0"` without the decimal padding.

## Reference

- [List wallets](/api-reference/wallets/get-v1-wallets)
- [Get a single wallet](/api-reference/wallets/get-v1-wallets-wallet-id)
- [Retrieve wallets (guide)](/platform/wallets/retrieve-wallets)
