> For the complete documentation index, see [llms.txt](https://docs.nansen.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nansen.ai/reference/native-tokens.md).

# Native Tokens

How to query native tokens (ETH, BTC, SOL, …) and where their coverage is thinner than for contract tokens.

A **native token** is the coin a chain issues itself — ETH on Ethereum, BTC on Bitcoin, SOL on Solana, TON on TON. Unlike an ERC-20 or SPL token, a native token has **no contract address**, so there is no real `token_address` to send.

The API solves this with a **per-chain placeholder address**. You pass the placeholder as `token_address` and pair it with the `chain` you want.

{% hint style="warning" %}
Native-token coverage is genuinely **narrower** than contract-token coverage. Several endpoints reject native tokens outright, and others serve them from a different data path — in one case with fewer filter and sort options. Read [Coverage limitations](#coverage-limitations) before assuming parity with an ERC-20 — this is the most common source of confusion in native-token queries.
{% endhint %}

### Placeholder addresses

| Chain         | `chain` value                     | `token_address` placeholder                                                    |
| ------------- | --------------------------------- | ------------------------------------------------------------------------------ |
| Any EVM chain | `ethereum`, `base`, `arbitrum`, … | `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`                                   |
| Bitcoin       | `bitcoin`                         | `1111111111111111111114oLvT2`                                                  |
| NEAR          | `near`                            | `native-token.near`                                                            |
| Solana        | `solana`                          | `So11111111111111111111111111111111111111112`                                  |
| SUI           | `sui`                             | `0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI` |
| TON           | `ton`                             | `0:0000000000000000000000000000000000000000000000000000000000000000`           |
| Tron          | `tron`                            | `TXka46PPwttNPWfFDPtt3GUodbPThyufaV`                                           |
| Injective     | `injective`                       | `0x0000000088827d2d103ee2d9a6b781773ae03ffb`                                   |

Chains not listed above have no native-token placeholder. See [Supported Chains](/reference/chains.md) for the full chain list.

### Pairing the EVM placeholder with a chain

There is **one** placeholder for all EVM chains. It does not mean "ETH" — it means "whatever this chain's native coin is". The `chain` field decides which coin you get:

```json
// ETH on Ethereum
{"chain": "ethereum", "token_address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}

// BNB on BNB Chain
{"chain": "bnb", "token_address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}

// POL on Polygon
{"chain": "polygon", "token_address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}
```

The placeholder itself is valid on any EVM chain — `arbitrum`, `arc`, `avalanche`, `base`, `bitlayer`, `bnb`, `chiliz`, `citrea`, `ethereum`, `gravity`, `hyperevm`, `iotaevm`, `katana`, `linea`, `mantle`, `metis`, `monad`, `optimism`, `plasma`, `polygon`, `robinhood`, `sei`, `sonic`, `viction`.

Passing address validation is not the same as the endpoint supporting that chain, though. Individual endpoints accept narrower chain sets than the list above — TGM Holders, for instance, omits several of them. Treat the placeholder as valid on **any EVM chain the endpoint itself supports**, and check the endpoint's own `chain` values in [Supported Chains](/reference/chains.md).

{% hint style="info" %}
**Injective is not an EVM chain here.** Its placeholder looks like a 40-hex EVM address, but Injective is classified as non-EVM by the API. Use `0x0000000088827d2d103ee2d9a6b781773ae03ffb` with `chain: "injective"`. Sending the EVM placeholder `0xeeee…` with `chain: "injective"` is rejected, and sending the Injective placeholder with `chain: "ethereum"` is rejected too.
{% endhint %}

#### Mismatched chain and placeholder

Pairing a placeholder with a chain it doesn't belong to returns **HTTP 422** with error code `invalid_address_format`:

```json
// Request — Solana's placeholder on Ethereum
{"chain": "ethereum", "token_address": "So11111111111111111111111111111111111111112"}
```

```json
// 422 response — abbreviated to the fields specific to this error
{
  "error": "Invalid address format",
  "code": "invalid_address_format",
  "message": "Address 'So11111111111111111111111111111111111111112' appears to be a solana address format but the chain is set to ethereum. Please verify the address is correct for the ethereum chain."
}
```

The real response also carries the standard envelope fields (`status`, `request_id`, `doc_url`, and `param` where applicable). See [Error Handling](/getting-started/error-handling.md) for the full shape.

#### Copy each placeholder exactly as listed

**Send every placeholder byte-for-byte as it appears in the table above.** Hex-shaped addresses are lowercased for you, but the base58 and type-string placeholders are compared literally, and what happens when you miscase one is not consistent:

| Miscased input                               | Result                                                                                                                                                                               |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `0xEEEE…` (EVM), `0x…88827D2D…` (Injective)  | **Accepted.** Both are hex addresses and are lowercased before the native-token lookup.                                                                                              |
| `NATIVE-TOKEN.NEAR`                          | **Rejected** — fails address-format validation.                                                                                                                                      |
| `txka46pp…` (Tron)                           | **Rejected** — the lowercase form no longer matches the Tron address pattern.                                                                                                        |
| `so1111…112` (Solana), `0x…::sui::sui` (SUI) | **Silently not native.** Still a structurally valid address, so validation passes, but it is not recognized as the native token and is treated as an ordinary token address instead. |

That last row is the dangerous one: the request succeeds, so nothing tells you the placeholder was wrong. If a Solana or SUI native-token query returns results you did not expect, check the placeholder's casing first.

In short: case-sensitivity tracks the *address format*, not whether the chain is EVM. That is why Injective, despite being non-EVM, is as forgiving as Ethereum here.

### Example: ETH holders

`chain` is what makes the shared EVM placeholder mean ETH rather than BNB or POL:

```bash
curl -s -X POST "https://api.nansen.ai/api/v1/tgm/holders" \
  -H "Content-Type: application/json" \
  -H "apikey: YOUR_API_KEY" \
  -d '{
    "chain": "ethereum",
    "token_address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    "label_type": "all_holders",
    "pagination": {"page": 1, "per_page": 10}
  }'
```

This request lands on the restricted path described in [Token God Mode Holders behaves differently for native tokens](#token-god-mode-holders-behaves-differently-for-native-tokens) — native token, `all_holders`, no entity aggregation, not Bitcoin — so sort by `token_amount` only, and expect sub-$1 holders in the response.

### Coverage limitations

Native tokens are held by tens of millions of addresses and move in every gas payment on the chain, so the analytics that work well for a contract token are often either unavailable or computed differently. Concretely:

#### Endpoints that reject native tokens

These return **HTTP 422** with error code `invalid_field_value` and a message naming the endpoint. There is no workaround — use a different endpoint.

| Endpoint                                             | Native tokens rejected on                                                          |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `POST /api/v1/tgm/flows`                             | All chains                                                                         |
| `POST /api/v1/tgm/pnl-leaderboard`                   | All chains                                                                         |
| `POST /api/v1/tgm/historical-pnl-leaderboard`        | All chains                                                                         |
| `POST /api/v1/tgm/jup-dca`                           | All chains                                                                         |
| `POST /api/v1/tgm/transfers`                         | All chains **except** `bitcoin`                                                    |
| `POST /api/v1/tgm/dex-trades`                        | `solana` only                                                                      |
| `POST /api/v1/tgm/historical-dex-trades`             | `solana` only                                                                      |
| `POST /api/v1/tgm/historical-token-flow-summary`     | `solana` only                                                                      |
| `POST /api/v1/tgm/holders`                           | `solana` only                                                                      |
| `POST /api/v1/profiler/address/counterparties`       | `solana` only                                                                      |
| `POST /api/v1/profiler/address/counterparties/batch` | `solana` only — checked per address, so one native address rejects the whole batch |

Two patterns are worth internalising:

* **Per-holder PnL is unavailable for native tokens on every chain.** Both PnL leaderboards reject them outright, as does TGM Flows. A native coin is spent as gas in nearly every transaction on its chain, so a per-holder cost basis does not carry the same meaning it does for a traded contract token.
* **Solana is blocked on more endpoints than other chains.** Native SOL appears in almost every Solana transaction, which makes these queries prohibitively expensive to serve.

Note that this does **not** mean all flow analytics are off-limits: [Flow Intelligence](#flow-intelligence-uses-a-different-source) does support native tokens, and only serves them from a different source.

#### Token God Mode Holders behaves differently for native tokens

`POST /api/v1/tgm/holders` **does** support native tokens (except on Solana), but one specific combination is served from a different, purpose-built data path that trades flexibility for the ability to return at all. You are on that path when **all** of the following hold:

* the token is a native token (or a major stablecoin), **and**
* `label_type` is `"all_holders"`, **and**
* `aggregate_by_entity` is `false`, **and**
* the chain is **not** `bitcoin` — Bitcoin always uses the entity-based path instead.

Change any one of those and the endpoint behaves normally. On that path, unsupported options return **HTTP 400**:

| Restriction      | Detail                                                                                                                                                                                                                              |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Filters          | Only `include_smart_money_labels`, `exclude_smart_money_labels`, `address`, `token_amount`, `total_inflow`, `total_outflow`. Filters such as `value_usd`, `ownership_percentage`, and balance-change filters are **not** available. |
| `address` filter | Accepts a **single** address only, not a list.                                                                                                                                                                                      |
| Sorting          | Only `token_amount` is sortable (default `DESC`).                                                                                                                                                                                   |

{% hint style="info" %}
**Dust holders are included.** Elsewhere this endpoint applies a default minimum of $1 in holdings. On the path described above that default is **not** applied, so results include holders worth well under $1. Add a `token_amount` filter if you need a floor.
{% endhint %}

#### Flow Intelligence uses a different source

`POST /api/v1/tgm/flow-intelligence` serves native tokens from an entity-based flow dataset rather than the standard token-transfer dataset. The response shape is the same, but figures are not directly comparable to a contract token's, and segment breakdowns may be coarser. Treat native-token flow figures as directional rather than as an exact match to contract-token methodology.

#### Two status codes worth recognising

Native tokens cover far more holders and transfers than a typical contract token, so these two responses are worth knowing when you query them:

| Status | What the API returns                                                          | What it means                                                                                                                                                                                                                                                                                                 |
| ------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `512`  | `Query timed out. Please try adjusting the time range or filtering the data.` | The query exceeded its time budget. Narrow the date range or add filters, as the message says.                                                                                                                                                                                                                |
| `514`  | `Unauthorized. Please try with different parameters or another endpoint.`     | Despite the wording, this is **not** an API-key problem — a valid key returns it. It signals that the backend would not serve this particular query. Some Token God Mode analytics on native tokens are a known cause, so try different parameters or another endpoint before treating it as an auth failure. |

See [Error Handling](/getting-started/error-handling.md) for the general error model.

### The `include_native_tokens` filter

Some endpoints return a portfolio, flow, or screen across *many* tokens rather than taking a single `token_address`. Because native holdings usually dominate those aggregates in USD terms, these endpoints let you include or exclude native tokens explicitly via a filter:

```json
{
  "filters": {
    "include_native_tokens": true
  }
}
```

| Endpoint                                                  | Default                              |
| --------------------------------------------------------- | ------------------------------------ |
| `POST /api/v1/smart-money/holdings`                       | `false` — native tokens **excluded** |
| `POST /api/v1beta1/funds/holdings`                        | `false` — native tokens **excluded** |
| `POST /api/v1/smart-money/netflow`                        | `false` — native tokens **excluded** |
| `POST /api/v1/smart-money/historical-holdings`            | `false` — native tokens **excluded** |
| `POST /api/v1/token-screener`                             | `false` — native tokens **excluded** |
| `POST /api/v1beta1/smart-money/historical-token-balances` | `true` — native tokens **included**  |

On two of these the flag covers more than the native coin itself:

* **Token screener** — also admits wrapped-native assets and liquid staking / restaking derivatives (LSTs and LRTs).
* **`historical-token-balances`** — also admits LSTs and LRTs.

So on those endpoints, toggling the flag moves a broader set of rows than the native coin alone.

{% hint style="warning" %}
**The default is not the same everywhere.** Most of these endpoints default to *excluding* native tokens, but `historical-token-balances` defaults to *including* them. If you are comparing results across these endpoints, set `include_native_tokens` explicitly rather than relying on the default.
{% endhint %}

This filter exists only on the endpoints listed above. Sending it elsewhere is not reliably an error: most filter models reject unknown keys with **HTTP 422**, but some accept and silently ignore them, so the request succeeds while the flag does nothing. Don't infer from a `200` that an endpoint honoured `include_native_tokens` — only rely on it where it is documented.

### Quick reference

* Native tokens are addressed by a per-chain placeholder, not a contract address.
* One placeholder covers every EVM chain; `chain` selects which native coin you mean.
* Copy placeholders exactly; miscasing the Solana or SUI placeholder fails silently rather than erroring.
* PnL leaderboards and TGM Flows reject native tokens on all chains; DEX trades and transfers are blocked on some chains; holders, balances, and Flow Intelligence work with restrictions.
* On multi-token endpoints, set `include_native_tokens` explicitly rather than relying on the default.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.nansen.ai/reference/native-tokens.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
