# Tokens (v1)

> The v1 token list, token search, wallet balances and natural-language autocomplete.

> API v1 is deprecated. It stays supported, but new integrations should use the [Khalani API](/). See [Migrate to v2](/v1/migrate/).

The token endpoints serve the v1 token list: a curated set of tokens across the v1 chains. Being listed does not guarantee a route for every pair. Only a quote tells you whether one exists.

## The token object

Every endpoint below returns tokens in this shape:

```json
{
  "chainId": 1,
  "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
  "name": "USD Coin",
  "symbol": "USDC",
  "decimals": 6,
  "logoURI": "https://api.hyperstream.dev/v1/tokens/icon/fe4f9d5f34ef4ebeb5d80e1f5ff63dcaf5a0d5495f4adf206e4c3011d1f5c57d.svg",
  "extensions": {
    "price": { "usd": "1.000144065102203723352712851816158", "provider": "okx" }
  }
}
```

| Field | Type | Description |
|---|---|---|
| `chainId` | integer | The chain. |
| `address` | string | The token address, lowercase on EVM chains. A chain's native token is `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`. Pass it as `fromToken` or `toToken` unchanged. |
| `name`, `symbol` | string | Display name and symbol. |
| `decimals` | integer | Decimals of this token on this chain. |
| `logoURI` | string | An SVG icon served by the API. |
| `extensions.price` | object | `usd`, a decimal string, and `provider`, its source (for example `okx`, `coingecko` or `kraken`). Can be missing. |
| `extensions.balance` | string | `GET /v1/tokens/balances/{address}` only. The wallet's balance, in base units. |

Check that a field exists before you use it. Prices carry many decimals, so round them for display.

## List tokens

```text
GET /v1/tokens
```

| Parameter | Description |
|---|---|
| `q` | Optional. A search term. With a non-empty `q`, this behaves like `GET /v1/tokens/search`. |
| `chainIds` | Optional. Comma-separated chain ids. |

The response shape depends on `q`:

- **Without `q`**, or with an empty one: a flat array of top tokens. On 19 October 2026 it held 20 tokens.
- **With `q`**: an object, `{ "data": [ … ] }`.

```bash
curl "https://api.hyperstream.dev/v1/tokens"
curl "https://api.hyperstream.dev/v1/tokens?chainIds=1,42161"
curl "https://api.hyperstream.dev/v1/tokens?q=usdc"
```

## Search tokens

```text
GET /v1/tokens/search
```

| Parameter | Description |
|---|---|
| `q` | Required. Name, symbol or address. Without it, the response is `400 ValidationException`. |
| `chainIds` | Optional. Comma-separated chain ids. |

Returns `{ "data": [ … ] }`. As of 19 October 2026, `q=usdc` with `chainIds=1,42161,8453` returned USDC on each of the three chains.

```bash
curl "https://api.hyperstream.dev/v1/tokens/search?q=usdc&chainIds=1,42161,8453"
```

## Wallet balances

```text
GET /v1/tokens/balances/{address}
```

| Parameter | Description |
|---|---|
| `address` | Path. An EVM, Solana, TRON, Bitcoin or CKB address. Any other value returns `400 ValidationException`. |
| `chainIds` | Optional. Comma-separated chain ids. |

Returns a flat array of the listed tokens the wallet holds, each with `extensions.balance` in base units:

```json
[
  {
    "chainId": 1,
    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    "name": "Ether",
    "symbol": "ETH",
    "decimals": 18,
    "logoURI": "https://api.hyperstream.dev/v1/tokens/icon/130f400afbc54c9096f4faa98fb61019108f515b1966311c20f4aaf1fde1e0c5.svg",
    "extensions": {
      "price": { "usd": "2399.594302201605853431766388244627", "provider": "okx" },
      "balance": "200000000000000"
    }
  }
]
```

## Autocomplete

```text
GET /v1/tokens/autocomplete/{keyword}
```

Parses what a user types, such as `100 usdc on base` or `$50 eth`, into token suggestions.

| Parameter | Description |
|---|---|
| `keyword` | Path. 1 to 64 characters, URL-encoded. Longer input returns `400`. |
| `chainIds` | Optional. Comma-separated chain ids. |
| `limit` | Optional. 1 to 20 suggestions. Default 10. A larger value returns `400`. |

```bash
curl "https://api.hyperstream.dev/v1/tokens/autocomplete/100%20usdc%20on%20ethereum"
```

As of 19 October 2026 the response was, with the chain object shortened:

```json
{
  "data": [
    {
      "description": "Receive 100 USDC on Ethereum",
      "chain": { "type": "eip155", "id": 1, "name": "Ethereum", "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 } },
      "token": {
        "chainId": 1,
        "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "name": "USD Coin",
        "symbol": "USDC",
        "decimals": 6,
        "logoURI": "https://api.hyperstream.dev/v1/tokens/icon/fe4f9d5f34ef4ebeb5d80e1f5ff63dcaf5a0d5495f4adf206e4c3011d1f5c57d.svg",
        "extensions": { "price": { "usd": "1.000144065102203723352712851816158", "provider": "okx" } }
      },
      "amount": "100000000",
      "usdAmount": "100.0144065102203723"
    }
  ],
  "parsed": { "amount": "100", "tokenQuery": "usdc", "chainQuery": "ethereum", "hasOn": true },
  "nextSlots": ["keyword"]
}
```

| Field | Type | Description |
|---|---|---|
| `data[].description` | string | A label for the suggestion. `Receive 100 USDC on Ethereum` when the input has an amount; `USDC on Ethereum` when it does not. |
| `data[].chain` | object | The chain, in the [`GET /v1/chains`](/v1/reference/chains/) shape, with extra viem fields on EVM chains. |
| `data[].token` | object | The token object, `extensions` included. |
| `data[].amount` | string | Only when the input has an amount: the amount in the token's base units. |
| `data[].usdAmount` | string | Only when the input has an amount and a price is known: its USD value, unrounded. |
| `parsed.amount` | string | The number, when the input starts with one (`100 usdc`). |
| `parsed.usdAmount` | string | The dollar amount, when the input starts with `$` (`$50 eth`). |
| `parsed.tokenQuery` | string | The token part. |
| `parsed.chainQuery` | string | The chain part, after `on`. |
| `parsed.hasOn` | boolean | Whether the input contains `on`. |
| `nextSlots` | string[] | What the user can type next: `usdAmount`, `amount`, `tokenSymbol`, `chain` or `keyword`. |

`nextSlots` narrows as the input gets more specific. As of 19 October 2026:

| Input | `nextSlots` |
|---|---|
| `usdc` | `["usdAmount", "amount", "tokenSymbol", "chain", "keyword"]` |
| `usdc on base` | `["usdAmount", "amount", "tokenSymbol", "chain", "keyword"]` |
| `100 usdc` | `["chain", "keyword"]` |
| `$50 eth` | `["chain", "keyword"]` |
| `100 usdc on` | `["chain", "keyword"]` |
| `100 usdc on ethereum` | `["keyword"]` |

## Errors

| Status | `name` | When |
|---|---|---|
| `400` | `ValidationException` | A missing `q` on search, an invalid address, a `keyword` over 64 characters, or a `limit` over 20. |
