# Moving from the old Taostats API to the new one

This guide is for anyone, person or AI agent, whose code calls the old Taostats API. It
lists every old endpoint, the new endpoint that replaces it, and exactly what changes:
parameters, response fields and behaviour. Old endpoints with no replacement are listed
too, with where the data lives now if anywhere.

_Source: https://taostats.io/blog/api-migration-guide_  
_Author: Doug Sillars, Head of Community and Education_  
_Published: 2026-10-08_  
_Category: Guides_

Each mapping below was checked by calling both APIs for the same subnet, account or block
and comparing the answers field by field.

## What stays the same

- **The host and the key.** Both APIs live at `https://api.taostats.io`. Use the same API
  key, in the same header: `Authorization: <your key>`, with no `Bearer` prefix.
- **Paging.** List responses are still `{ "pagination": {...}, "data": [...] }`, with the
  same pagination fields (`current_page`, `per_page`, `total_items`, `total_pages`,
  `next_page`, `prev_page`), and `page` and `limit` work as before.

## What changes everywhere

These apply to every endpoint, so the per-endpoint entries below do not repeat them.

1. **Paths.** Old paths look like `/api/block/v1`. New paths look like `/v1/blocks`: the
   version comes first, there is no `/api` prefix, and names are plural.
2. **Sorting.** The old `order=<column>_<direction>` (for example
   `order=block_number_desc`) is now two parameters: `order_by=<column>` and
   `order_dir=asc` or `desc`. Each endpoint accepts its own list of sort columns, which is
   often shorter than before.
3. **Unknown parameters are errors.** The old API ignored a parameter it did not know. The
   new API answers `400` and names the parameter and the values it accepts, for example
   ``query parameter `order`: unknown field `order`, expected one of `network`, `block_number`, ...``.
   The same goes for an unknown sort column or `network` value. Read the message: it lists
   what the endpoint takes.
4. **`limit` above 200 is an error.** The old API quietly gave you 200 rows when you asked
   for more. The new API answers `400 limit must be <= 200`. Page through instead. A few
   endpoints allow more, and their entries say so.
5. **Addresses are plain strings.** Where the old API returned an address as
   `{ "ss58": "5F...", "hex": "0x..." }`, the new API returns the SS58 string alone.
6. **Big and decimal numbers are strings.** Balances, prices and other values that do not
   fit safely in a JSON number arrive as strings, for example `"1234567890123"`. Parse them
   with a decimal or big-integer type, not a float.
7. **Timestamps carry milliseconds.** `2026-09-05T08:28:36Z` is now
   `2026-09-05T08:28:36.000Z`. Both are ISO 8601 in UTC.
8. **Deep paging stops at the millionth row.** The new API serves a page only while
   `(page - 1) × limit` is below 1,000,000. Past that it answers `400 page is beyond the maximum
   pagination window`, and `total_pages` never goes above what you can reach. To read
   older history, narrow the request with `block_start`/`block_end` or
   `timestamp_start`/`timestamp_end` instead of paging further.
9. **`network`** accepts `finney` (the default), `nakamoto` and `kusanagi`. `testnet` is no
   longer accepted. On most endpoints `all` is still accepted but now means `finney`; ask
   for each network separately if you need them all.

10. **Single-item endpoints return one object.** Where the old API wrapped a single answer
    in a one-row list with pagination, endpoints that can only ever return one thing (for
    example `/v1/network/stats`) now return `{ "data": { ... } }`, with no `pagination`.
    Their entries say so.
11. **The default page size is 50.** Some old endpoints returned everything in one answer
    when you left `limit` out (up to 1,024 rows: a whole subnet, or every subnet). The new
    API returns 50 rows unless you ask for up to 200 with `limit`, so check `next_page`.

Where an endpoint breaks one of these rules, its entry says so.

### Endpoints that break these rules

- **CoinGecko, CoinMarketCap and TradingView endpoints** keep the formats those services
  expect: no `data`/`pagination` wrapper, and an unknown parameter is ignored rather than
  rejected. TradingView history returns up to 5,000 bars in one answer.
- **`/v1/alpha/portfolio`** has no paging. Sending `page` or `limit` is a `400`.
- **`/v1/validators/active`** has no paging, and **`/v1/miners/coldkey-summary`** takes no
  `limit`. Sending either is a `400`.
- **Basket figures** (`nav_per_share`, `rate`, `performance`, the returns, `twr`) and the
  validator yield APY figures are JSON numbers, not strings. The basket field
  `twr_first_block` is a string.
- **`POST /v1/validators/yield`** takes `order_by` and `order_dir` in the JSON body, not the
  query string.
- **`/v1/alpha/hotkey-shares`** takes no `order_by` or `order_dir`; it always sorts by
  alpha, largest first.
- **`/v1/subnets/distribution/*`** (three endpoints) take only `netuid` and return the
  whole list in one answer. Sending `page` or `limit` is a `400`.
- **`/v1/subnets/hyperparameters`** takes no `order_by` or `order_dir`.
- **`/v1/price` and `/v1/price/simple`** still return a one-row list with `pagination`.
- **`/v1/accounts/{address}`** returns a one-element `data` list.
- **Numbers inside `args`** on `/v1/extrinsics`, `/v1/events` and `/v1/proxy-calls` are
  JSON numbers, not strings. On `/v1/proxy-calls` some of them arrive wrapped in a
  one-item list, for example `"netuid": [100]`.
- **`/v1/evm/blocks`, `/v1/evm/contracts`, `/v1/evm/logs`, `/v1/evm/transactions` and
  `/v1/contract-events`** cut a `limit` above 200 down to 200 instead of answering `400`,
  and their timestamps have no milliseconds.
- **`/v1/transfers`** rejects `network=all`.

## Index

173 old endpoints: 113 replaced, 21 partly replaced, 39 with no replacement. Each one has its own entry further down.

| Old endpoint | Status | New endpoint |
|---|---|---|
| `GET /api/account/latest/v1` | Replaced | `GET /v1/accounts/{address}`, `GET /v1/accounts/leaderboard` |
| `GET /api/account/history/v1` | Replaced | `GET /v1/accounts/{address}/history` |
| `GET /api/accounting/tax/v1` | Replaced | `GET /v1/tax/report` |
| `GET /api/accounting/tax_csv/v1` | Replaced | `GET /v1/tax/report?format=csv` |
| `GET /api/accounting/tax_token/v1` | Replaced | `GET /v1/tax/active-tokens` |
| `GET /api/accounting/coldkey_report/v1` | None | — |
| `GET /api/accounting/coldkey_report_csv/v1` | None | — |
| `GET /api/accounting/v1` | Partly | `GET /v1/subnets/neuron-registration-events` |
| `GET /api/block/v1` | Replaced | `GET /v1/blocks` |
| `GET /api/block/emission/v1` | Replaced | `GET /v1/tokenomics/emission` |
| `GET /api/block/interval/v1` | Partly | `GET /v1/subnets/pools/total-price/history` |
| `GET /api/call/v1` | Replaced | `GET /v1/calls` |
| `GET /api/event/v1` | Replaced | `GET /v1/events` |
| `GET /api/extrinsic/v1` | Replaced | `GET /v1/extrinsics` |
| `GET /api/proxy_call/v1` | Replaced | `GET /v1/proxy-calls` |
| `GET /api/transfer/v1` | Replaced | `GET /v1/transfers` |
| `GET /api/evm/address_from_ss58/v1` | Replaced | `GET /v1/evm/address_from_ss58` |
| `GET /api/evm/block/v1` | Replaced | `GET /v1/evm/blocks` |
| `GET /api/evm/contract/v1` | Replaced | `GET /v1/evm/contracts` |
| `GET /api/evm/log/v1` | Replaced | `GET /v1/evm/logs` |
| `GET /api/evm/transaction/v1` | Replaced | `GET /v1/evm/transactions` |
| `GET /api/evm/erc20/token/v1` | Partly | `GET /v1/evm/contracts` |
| `GET /api/evm/erc20/transfer/v1` | Partly | `GET /v1/evm/logs?event_name=Transfer&address=<token address>` |
| `GET /api/evm/erc20/account/v1` | None | — |
| `GET /api/contract_event/v1` | Replaced | `GET /v1/contract-events` |
| `GET /api/contract_event/{id}/v1` | Replaced | `GET /v1/contract-events?id={id}` |
| `GET /api/runtime_version/latest/v1` | Replaced | `GET /v1/network/runtime-version` |
| `GET /api/runtime_version/history/v1` | Replaced | `GET /v1/network/runtime-version/history` |
| `GET /api/pending_coldkey_swap/v1` | Replaced | `GET /v1/accounts/pending-coldkey-swaps` |
| `GET /api/root_claim/v1` | Replaced | `GET /v1/alpha/root-claims` |
| `GET /api/exchange/v1` | None | — |
| `GET /api/status/v1` | Replaced | `GET /v1/status` |
| `POST /api/v1/rpc/http` | Partly | `POST /v1/rpc/http` |
| `GET /api/v1/rpc/ws/{target}` | Replaced | `WS /v1/rpc/ws/{target}` |
| `POST /api/seal_blob/v1` | None | — |
| `GET /api/subnet/latest/v1` | Partly | `GET /v1/subnets/metrics`, `GET /v1/subnets/hyperparameters` |
| `GET /api/subnet/history/v1` | Replaced | `GET /v1/subnets/history` |
| `GET /api/subnet/identity/v1` | Replaced | `GET /v1/subnets/identities` |
| `GET /api/subnet/identity_set/v1` | Replaced | `GET /v1/subnets/identities/history` |
| `GET /api/subnet/metadata/v1` | None | — |
| `GET /api/subnet/owner/v1` | Replaced | `GET /v1/subnets/owners` |
| `GET /api/subnet/registration/v1` | Replaced | `GET /v1/subnets/registrations` |
| `GET /api/subnet/registration_cost/latest/v1` | Replaced | `GET /v1/subnets/registration-cost` |
| `GET /api/subnet/registration_cost/history/v1` | Replaced | `GET /v1/subnets/registration-cost/history` |
| `GET /api/subnet/neuron/registration/v1` | Replaced | `GET /v1/subnets/neuron-registration-events` |
| `GET /api/subnet/neuron/deregistration/v1` | Replaced | `GET /v1/subnets/neuron-deregistration-events` |
| `GET /api/subnet/distribution/coldkey/v1` | Replaced | `GET /v1/subnets/distribution/coldkey` |
| `GET /api/subnet/distribution/incentive/v1` | Replaced | `GET /v1/subnets/distribution/incentive` |
| `GET /api/subnet/distribution/ip/v1` | Replaced | `GET /v1/subnets/distribution/ip` |
| `GET /api/subnet/pruning/latest/v1` | Replaced | `GET /v1/subnets/deregistrations` |
| `GET /api/subnet/pruning/history/v1` | Replaced | `GET /v1/subnets/deregistrations/history` |
| `GET /api/dtao/pool/latest/v1` | Replaced | `GET /v1/subnets/pools`, `GET /v1/subnets/pools/aggregate` |
| `GET /api/dtao/pool/v1` | Replaced | `GET /v1/subnets/pools`, `GET /v1/subnets/pools/aggregate` |
| `GET /api/dtao/pool/history/v1` | Replaced | `GET /v1/subnets/pools/history` |
| `GET /api/dtao/pool/total_price/latest/v1` | Replaced | `GET /v1/subnets/pools/total-price` |
| `GET /api/dtao/pool/total_price/history/v1` | Replaced | `GET /v1/subnets/pools/total-price/history` |
| `GET /api/dtao/pool/total_price/v1` | Replaced | `GET /v1/subnets/pools/total-price/history` |
| `GET /api/dtao/liquidity/distribution/v1` | None | — |
| `GET /api/dtao/liquidity/position/v1` | None | — |
| `GET /api/dtao/liquidity/position/history/v1` | None | — |
| `GET /api/dtao/liquidity/position_event/v1` | None | — |
| `GET /api/dtao/liquidity/tick_to_price/v1` | None | — |
| `GET /api/metagraph/latest/v1` | Replaced | `GET /v1/subnets/metagraph` |
| `GET /api/metagraph/history/v1` | Replaced | `GET /v1/subnets/metagraph/history` |
| `GET /api/metagraph/root/latest/v1` | None | — |
| `GET /api/metagraph/root/history/v1` | None | — |
| `GET /api/neuron/latest/v1` | Replaced | `GET /v1/subnets/metagraph` |
| `GET /api/neuron/history/v1` | Replaced | `GET /v1/subnets/metagraph/history` |
| `GET /api/neuron/aggregated/latest/v1` | Replaced | `GET /v1/subnets/metagraph/aggregate` |
| `GET /api/neuron/aggregated/history/v1` | Replaced | `GET /v1/subnets/metagraph/aggregate/history` |
| `GET /api/neuron/incentive_distribution/v1` | Replaced | `GET /v1/subnets/metagraph/history` |
| `GET /api/dtao/validator/latest/v1` | Replaced | `GET /v1/validators` |
| `GET /api/dtao/validator/history/v1` | Replaced | `GET /v1/validators/{hotkey}/history` |
| `GET /api/dtao/validator/available/v1` | Replaced | `GET /v1/validators/active` |
| `GET /api/dtao/validator/basket/latest/v1` | Replaced | `GET /v1/validators/baskets` |
| `GET /api/dtao/validator/basket/history/v1` | Replaced | `GET /v1/validators/baskets/history` |
| `GET /api/dtao/validator/dividends/latest/v1` | None | — |
| `GET /api/dtao/validator/dividends/history/v1` | None | — |
| `GET /api/dtao/validator/performance/latest/v1` | Replaced | `GET /v1/validators/performance/{hotkey}` |
| `GET /api/dtao/validator/performance/history/v1` | Replaced | `GET /v1/validators/performance/{hotkey}/history` |
| `GET /api/dtao/validator/yield/latest/v1` | Replaced | `GET /v1/validators/yield` |
| `POST /api/dtao/validator/yield/latest/v1` | Replaced | `POST /v1/validators/yield` |
| `GET /api/dtao/validator/yield/history/v1` | None | — |
| `GET /api/validator/latest/v1` | None | — |
| `GET /api/validator/history/v1` | Partly | `GET /v1/validators/{hotkey}/history/pre-dtao` |
| `GET /api/validator/identity/v1` | None | — |
| `GET /api/validator/metrics/latest/v1` | Partly | `GET /v1/subnets/metagraph?netuid=&hotkey=` |
| `GET /api/validator/metrics/history/v1` | Partly | `GET /v1/subnets/metagraph/history` |
| `GET /api/validator/performance/v1` | Partly | `GET /v1/subnets/metagraph/history?netuid=&uid=` |
| `GET /api/validator/weight_copier/v1` | None | — |
| `GET /api/validator/weights/latest/v2` | Replaced | `GET /v1/validators/weights` |
| `GET /api/validator/weights/history/v2` | Replaced | `GET /v1/validators/weights/history` |
| `GET /api/validator/weights/latest/v1` | Partly | `GET /v1/validators/weights` |
| `GET /api/validator/weights/history/v1` | Partly | `GET /v1/validators/weights/history` |
| `GET /api/delegation/v1` | Replaced | `GET /v1/subnets/stake-events`, `GET /v1/historic/stake-events` |
| `GET /api/stake/v1` | None | — |
| `GET /api/stake_balance/history/v1` | None | — |
| `GET /api/hotkey/family/latest/v1` | Replaced | `GET /v1/validators/hotkey-family` |
| `GET /api/hotkey/family/history/v1` | Replaced | `GET /v1/validators/hotkey-family/history` |
| `GET /api/identity/latest/v1` | Replaced | `GET /v1/accounts/identities`, `GET /v1/accounts/{address}/identity` |
| `GET /api/identity/history/v1` | None | — |
| `GET /api/miner/autostake/v1` | Replaced | `GET /v1/miners/autostakes` |
| `GET /api/miner/coldkey/v1` | Replaced | `GET /v1/miners/coldkey-summary` |
| `GET /api/miner/weights/latest/v1` | Replaced | `GET /v1/miners/weights` |
| `GET /api/miner/weights/history/v1` | Replaced | `GET /v1/miners/weights/history` |
| `GET /api/conviction/latest/v1` | Replaced | `GET /v1/subnets/conviction` |
| `GET /api/conviction/history/v1` | Replaced | `GET /v1/subnets/conviction/history` |
| `GET /api/dtao/stake_balance/latest/v1` | Replaced | `GET /v1/alpha/leaderboard` |
| `GET /api/dtao/stake_balance/history/v1` | Replaced | `GET /v1/alpha/history` |
| `GET /api/dtao/stake_balance/portfolio/v1` | Replaced | `GET /v1/alpha/portfolio` |
| `GET /api/dtao/stake_balance_aggregated/latest/v1` | Partly | `GET /v1/accounts/leaderboard`, `GET /v1/accounts/{address}` |
| `GET /api/dtao/hotkey_alpha_shares/latest/v1` | Replaced | `GET /v1/alpha/hotkey-shares` |
| `GET /api/dtao/hotkey_alpha_shares/history/v1` | None | — |
| `GET /api/dtao/coldkey_alpha_shares/latest/v1` | Partly | `GET /v1/alpha/leaderboard` |
| `GET /api/dtao/coldkey_alpha_shares/history/v1` | Partly | `GET /v1/alpha/history` |
| `GET /api/dtao/trade/v1` | Replaced | `GET /v1/subnets/trades` |
| `GET /api/dtao/burned_alpha/v1` | Partly | `GET /v1/subnets/burns` |
| `GET /api/dtao/burned_alpha/total/v1` | Replaced | `GET /v1/subnets/burns/total` |
| `GET /api/dtao/subnet_emission/v1` | Replaced | `GET /v1/subnets/epochs` |
| `GET /api/dtao/hotkey_emission/v1` | None | — |
| `GET /api/dtao/tao_flow/v1` | None | — |
| `GET /api/dtao/delegation_volume/v1` | None | — |
| `GET /api/dtao/slippage/v1` | None | — |
| `GET /api/dtao/tradingview/udf/config` | Replaced | `GET /v1/tradingview/udf/config` |
| `GET /api/dtao/tradingview/udf/symbol_info` | Replaced | `GET /v1/tradingview/udf/symbol_info` |
| `GET /api/dtao/tradingview/udf/history` | Replaced | `GET /v1/tradingview/udf/history` |
| `GET /api/price/latest/v1` | Replaced | `GET /v1/price` |
| `GET /api/price/simple/latest/v1` | Replaced | `GET /v1/price/simple` |
| `GET /api/price/history/v1` | Replaced | `GET /v1/price/history` |
| `GET /api/price/ohlc/v1` | Replaced | `GET /v1/price/ohlc` |
| `GET /api/stats/latest/v1` | Replaced | `GET /v1/network/stats` |
| `GET /api/stats/history/v1` | Replaced | `GET /v1/network/stats/history` |
| `GET /api/network_parameter/latest/v1` | Replaced | `GET /v1/network/parameters` |
| `GET /api/coingecko/latest-block` | Replaced | `GET /v1/coingecko/latest-block` |
| `GET /api/coingecko/asset` | Replaced | `GET /v1/coingecko/asset` |
| `GET /api/coingecko/pair` | Replaced | `GET /v1/coingecko/pair` |
| `GET /api/coingecko/events` | Replaced | `GET /v1/coingecko/events` |
| `GET /api/dev_activity/latest/v1` | None | — |
| `GET /api/dev_activity/history/v1` | None | — |
| `GET /api/dev_changelog/v1` | None | — |
| `GET /api/otc/listing/v1` | Replaced | `GET /v1/otc/contract-v1/listings` |
| `GET /api/otc/listing/history/v1` | Replaced | `GET /v1/otc/contract-v1/listings/history` |
| `GET /api/otc/offer/v1` | Replaced | `GET /v1/otc/contract-v1/offers` |
| `GET /api/otc/offer/history/v1` | Replaced | `GET /v1/otc/contract-v1/offers/history` |
| `GET /api/otc/trade/v1` | Replaced | `GET /v1/otc/contract-v1/trades` |
| `GET /api/otc/user/stats/v1` | Replaced | `GET /v1/otc/contract-v1/users/stats` |
| `GET /api/otc/subnet/status/v1` | Replaced | `GET /v1/otc/contract-v1/subnets/status` |
| `GET /api/otc/listing/v2` | Replaced | `GET /v1/otc/listings` |
| `GET /api/otc/listing/history/v2` | Replaced | `GET /v1/otc/listings/history` |
| `GET /api/otc/offer/v2` | Replaced | `GET /v1/otc/offers` |
| `GET /api/otc/offer/history/v2` | Replaced | `GET /v1/otc/offers/history` |
| `GET /api/otc/trade/v2` | Replaced | `GET /v1/otc/trades` |
| `GET /api/otc/user/stats/v2` | Replaced | `GET /v1/otc/users/stats` |
| `GET /api/otc/subnet/status/v2` | Replaced | `GET /v1/otc/subnets/status` |
| `GET /api/otc/lockup/listing/v1` | Replaced | `GET /v1/otc/lockup/listings` |
| `GET /api/otc/lockup/listing/history/v1` | Replaced | `GET /v1/otc/lockup/listings/history` |
| `GET /api/otc/lockup/purchase/v1` | Replaced | `GET /v1/otc/lockup/purchases` |
| `GET /api/otc/lockup/claim/v1` | Replaced | `GET /v1/otc/lockup/claims` |
| `GET /api/otc/lockup/user/stats/v1` | Replaced | `GET /v1/otc/lockup/users/stats` |
| `GET /api/v1/live/blocks/head` | Partly | `GET /v1/blocks?limit=1` |
| `GET /api/v1/live/blocks/{height}` | Partly | `GET /v1/blocks?block_number={height}` |
| `GET /api/v1/live/blocks` | Partly | `GET /v1/blocks?block_start=<a>&block_end=<b>` |
| `GET /api/v1/live/blocks/{height}/extrinsics/{index}` | Partly | `GET /v1/extrinsics?id={height}-{index}&include_args=true`, `GET /v1/events?extrinsic_id={height}-{index}` |
| `GET /api/v1/live/blocks/{height}/extrinsics-raw` | None | — |
| `GET /api/v1/live/accounts/{address}/balance-info` | Partly | `GET /v1/accounts/{address}` |
| `GET /api/v1/live/node/transaction-pool` | None | — |
| `GET /api/v1/live/node/version` | None | — |
| `GET /api/v1/live/pallets/{pallet_id}/consts` | None | — |
| `GET /api/v1/live/pallets/{pallet_id}/consts/{id}` | None | — |
| `GET /api/v1/live/pallets/{pallet_id}/events` | None | — |
| `GET /api/v1/live/pallets/{pallet_id}/events/{id}` | None | — |
| `GET /api/v1/live/pallets/{pallet_id}/storage` | None | — |
| `GET /api/v1/live/pallets/{pallet_id}/storage/{id}` | None | — |

# Endpoint by endpoint

## Accounts

### `GET /api/account/latest/v1`

**Replaced by:** `GET /v1/accounts/{address}` for one account, and `GET /v1/accounts/leaderboard` for a list of accounts.

**Parameters:** To look up one account, put the address in the path: `/v1/accounts/{address}`. The leaderboard has no `address` filter. On the leaderboard, the balance range filters (`balance_free_min`, `balance_total_max` and the rest) take whole numbers in RAO. The sort columns are unchanged.

**Response:** `/v1/accounts/{address}` returns a single object. `balance_liquidity` and `balance_liquidity_24hr_ago` have been removed from both routes. Leaderboard rows do not include the `*_24hr_ago` fields, `alpha_balances` or `coldkey_swap`. The old API returned those as null on lists anyway. Timestamps include milliseconds.

### `GET /api/account/history/v1`

**Replaced by:** `GET /v1/accounts/{address}/history`

**Parameters:** `address` moves into the path. `order_by` accepts only `timestamp`. Every other filter is unchanged. As before, all networks are returned unless you pass `network`.

**Response:** The balance fields are strings in RAO. The old API returned them as JSON numbers on this route. `balance_liquidity` and `coldkey_swap` have been removed. Timestamps include milliseconds.

**Differences:** For coldkey `5HRPxma1TuTY4gPdAs4bPgyTcen13P43rucRiHppV6geJrqM`, both APIs return 1,930 rows with the same balances. Three fields differ. At the same block, `rank` is 81 on the old API and 80 on the new one. `root_basket_claimable_tao` is null on the old API and filled in on the new one. On `kusanagi` rows from 2021, `root_claim_type` is `IGNORE` on the old API and null on the new one.

## Accounting and tax

### `GET /api/accounting/tax/v1`

**Replaced by:** `GET /v1/tax/report`

**Parameters:** unchanged.

**Response:** unchanged. The whole report comes back on one page. Checked on one coldkey for one day: 327 rows on both APIs, with the same fields and the same values.

### `GET /api/accounting/tax_csv/v1`

**Replaced by:** `GET /v1/tax/report?format=csv`

**Parameters:** Add `format=csv`. The other parameters are unchanged.

**Response:** The header is the same, and both APIs return the same 328 lines. Rows that fall in the same block may come back in a different order.

### `GET /api/accounting/tax_token/v1`

**Replaced by:** `GET /v1/tax/active-tokens`

**Parameters:** unchanged.

**Response:** The same tokens come back. Subnet tokens are listed in netuid order.

### `GET /api/accounting/coldkey_report/v1`

**No replacement.** The new API has no combined coldkey report. You can rebuild its daily balance rows from two routes:

- `GET /v1/accounts/{address}/history?network=finney` gives the daily balances. Its `balance_total`, `balance_free` and `balance_staked` are in RAO, where the old report gave TAO. For example, `balance_total` 109993431919652 is the old `total_balance` 109993.431919652.
- `GET /v1/price/ohlc?asset=TAO&period=1d` gives a TAO price for `tao_price`.

The report's transaction rows (`transaction_type`, `debit_amount`, `credit_amount`) are only available one token at a time, from `GET /v1/tax/report`. To get every token, call `GET /v1/tax/active-tokens` first. `daily_income` and `daily_income_usd` have no equivalent.

### `GET /api/accounting/coldkey_report_csv/v1`

**No replacement.** This was the CSV form of `/api/accounting/coldkey_report/v1`. The same rebuild applies. For the transaction rows, `GET /v1/tax/report?format=csv` gives CSV for one token at a time.

### `GET /api/accounting/v1`

**Partly replaced by:** `GET /v1/subnets/neuron-registration-events`

**Parameters:** `coldkey` is unchanged. Replace `date_start` and `date_end` with `timestamp_start` and `timestamp_end` in Unix seconds.

**Response:** The rows in the old `neuron_registrations` array are now the rows of this list. `hotkey` and `coldkey` are plain SS58 strings. The new API has no `neuron_registration_cost`; add up `registration_cost` across the rows instead. OLD fields `income` and `stake_balances` have no new equivalent. In every sample we took, the old API returned `income` as `"0"` and `stake_balances` as empty.

## Blocks

### `GET /api/block/v1`

**Replaced by:** `GET /v1/blocks`

**Parameters:** The `spec_version` and `validator` filters have been removed. `order_by` accepts only `timestamp`. `network` no longer accepts `testnet`.

**Response:** The fields are unchanged. Timestamps include milliseconds.

### `GET /api/block/emission/v1`

**Replaced by:** `GET /v1/tokenomics/emission`

**Parameters:** `order_by` accepts only `timestamp`.

**Response:** The fields and values are unchanged on the blocks we checked. Timestamps include milliseconds.

**Differences:** History on the new API starts at block 1,404,225. On the old API it starts at block 0. The new API has 7,827,980 rows and the old API has 9,232,204.

### `GET /api/block/interval/v1`

**Partly replaced by:** `GET /v1/subnets/pools/total-price/history`

**Parameters:** The parameters are unchanged, including `frequency`, which also accepts `by_block`. `order=date_asc` and `order=date_desc` become `order_dir`.

**Response:** Each row is the same block as on the old API. NEW fields `price`, `alpha_volume`, `alpha_buy_volume`, `alpha_sell_volume`, `root_volume`, `root_buy_volume` and `root_sell_volume` are new.

**Differences:** Data starts on 2025-02-13, at block 4,921,036. Earlier windows return no rows: a window in January 2024 returned 3 rows on the old API and 0 on the new one. A block that falls exactly on `timestamp_end` at midnight is included as an extra row. One three-day window returned 4 rows on the new API and 3 on the old.

## Calls, events and extrinsics

The new API writes `args` differently from the old API. This applies to calls and extrinsics, to the call inside a proxy call, and to the `args` of events:

- Keys are snake_case, for example `amount_staked` where the old API had `amountStaked`.
- An account is `{"Id": "5..."}`, an SS58 address, where the old API had `{"__kind": "Id", "value": "0x..."}`.
- A whole number is a JSON number. It becomes a string only if it is larger than 9007199254740991. The old API always used strings.
- An enum is its variant name, for example `"Normal"`, where the old API had `{"__kind": "Normal"}`.
- An optional argument is `"None"` or `{"Some": value}`. The old API left the key out, or gave the bare value.
- A nested call is `{"Pallet": {"call_name": {...}}}`. The old API used `{"__kind": "Pallet", "value": {"__kind": "call_name", ...}}`.

### `GET /api/call/v1`

**Replaced by:** `GET /v1/calls`

**Parameters:** NEW parameters `pallet`, `name`, `signer_address`, `include_args` and `fields` are new. `full_name` still works. `network` no longer accepts `testnet`.

**Response:** `args` is left out unless you pass `include_args=true`. `full_name` has been removed; it was always `pallet` + `.` + `name`. `origin_address` is now an SS58 address; on the old API it was hex. NEW fields `signer_address` and `args_summary` are new. Timestamps include milliseconds.

**Differences:** `origin` is filled in only on the top-level call of an extrinsic, and is null on the calls nested under it. The old API filled it in on nested calls too. On extrinsic `9000001-0009`, both APIs return the same 3 calls with the same ids.

### `GET /api/event/v1`

**Replaced by:** `GET /v1/events`

**Parameters:** `order_by` accepts only `timestamp`. The old sorts on `phase`, `pallet`, `name`, `id` and `extrinsic_id` have been removed. `network` no longer accepts `testnet`.

**Response:** `full_name` has been removed; use `pallet` and `name`. `extrinsic_index` has been removed; it is the number after the dash in `extrinsic_id`. `args` uses the new encoding described above, for example `"weight": {"proof_size": 26563, "ref_time": 2886592370}`. Timestamps include milliseconds.

**Differences:** `call_id` is filled in. On the old API it was null. For example, event `9000001-0166` has `call_id` `9000001-0009` on the new API. Both APIs return the same 11 events for extrinsic `9000001-0009`.

### `GET /api/extrinsic/v1`

**Replaced by:** `GET /v1/extrinsics`

**Parameters:** NEW parameters `pallet`, `name`, `include_args` and `fields` are new. `order_by` accepts only `timestamp`. The old sorts on `id`, `success` and `signer_address` have been removed. `network` no longer accepts `testnet`.

**Response:**
- `call_args` is now `args`, and it is left out unless you pass `include_args=true`.
- `full_name` has been removed; use `pallet` and `name`.
- `version` and `call_id` have been removed. On the extrinsics we checked, `call_id` was equal to `id`.
- `signer_address` is an SS58 address; on the old API it was hex.
- `signature` is now the hex-encoded signature string, prefixed with its signature-type byte. The old API returned an object with `address`, `signature` and `signedExtensions`, which held the nonce and the mortality. Those signed-extension values have no new equivalent.
- In `error`, OLD field `extra_info` is now `docs`, and `pallet` is capitalised as the chain names it (`Proxy`, where the old API had `proxy`).
- NEW fields `fee_payer` and `args_summary` are new. `fee_payer` is the account that paid the fee.
- Timestamps include milliseconds.

## Proxy calls

### `GET /api/proxy_call/v1`

**Replaced by:** `GET /v1/proxy-calls`

**Parameters:** `order_by` accepts only `timestamp`. The block sort has been removed.

**Response:** `args` uses the new encoding described under "Calls, events and extrinsics", for example `{"SubtensorModule": {"add_stake": {...}}}`. In this route's `args`, some number arguments come back wrapped in a one-item array, for example `"amount_staked": [5000000000]` and `"netuid": [100]`. Timestamps include milliseconds.

**Differences:** The two APIs list different proxy calls, so `total_items` will not match. The new API also lists proxy calls nested inside batch, sudo and multisig calls. Their `id` has extra parts, for example `finney-9000177-0007-0-0`. The new API leaves out a proxy call that the chain rejected, such as one that failed with `NotProxy`, because the inner call never ran. The old API lists those. In blocks 9,000,000 to 9,000,300, the old API returned 45 proxy calls and the new API returned 73. All 44 top-level calls the two lists share have the same ids. The other 29 on the new API are nested calls. The one call only the old API returned failed with `NotProxy`.

## Transfers

### `GET /api/transfer/v1`

**Replaced by:** `GET /v1/transfers`

**Parameters:** You can no longer sort by `block_number`; use `order_by=timestamp` or `order_by=amount`. `network` accepts `finney`, `kusanagi` or `nakamoto`; `all` is no longer accepted.

**Response:** unchanged, apart from `from` and `to` being plain SS58 strings. On blocks 9,000,000 to 9,000,100, both APIs return the same 103 transfers.

## EVM

### `GET /api/evm/address_from_ss58/v1`

**Replaced by:** `GET /v1/evm/address_from_ss58`

**Parameters:** unchanged.

**Response:** unchanged: a plain JSON string with the EVM address. An account with no known EVM address still returns 404. The new API also has `GET /v1/evm/conversions/ss58-to-address`, which converts any SS58 address to its EVM address by calculation, without a lookup.

### `GET /api/evm/block/v1`

**Replaced by:** `GET /v1/evm/blocks`

**Parameters:** unchanged. `order_by` accepts `block_number` or `timestamp`.

**Response:** unchanged.

### `GET /api/evm/contract/v1`

**Replaced by:** `GET /v1/evm/contracts`

**Parameters:** `order_by` accepts only `timestamp`. You can no longer sort by block.

**Response:** unchanged.

### `GET /api/evm/log/v1`

**Replaced by:** `GET /v1/evm/logs`

**Parameters:** unchanged. `order_by` accepts `id`, `block_number` or `timestamp`.

**Response:** unchanged.

### `GET /api/evm/transaction/v1`

**Replaced by:** `GET /v1/evm/transactions`

**Parameters:** unchanged. `order_by` accepts `block_number` or `timestamp`.

**Response:** unchanged.

## ERC-20 tokens

### `GET /api/evm/erc20/token/v1`

**Partly replaced by:** `GET /v1/evm/contracts`

**Parameters:** Only `address` is kept. The `name` and `symbol` filters have been removed, and there is no filter for ERC-20 contracts only: page through the list and keep rows with `erc20: true`. `order_by` accepts only `timestamp`.

**Response:** `name`, `symbol`, `decimals`, `created_by` and `transaction_hash` are present. OLD field `created_at_block_number` is now `block_number`, and `created_at_timestamp` is now `timestamp`. The values match on the same token. Each row also carries the other contract fields, such as `erc20`, `erc721` and `owner`.

### `GET /api/evm/erc20/transfer/v1`

**Partly replaced by:** `GET /v1/evm/logs?event_name=Transfer&address=<token address>`

**Parameters:** Filter by token with `address`, by transaction with `transaction_hash`, and by block or time range as before. The `from`, `to`, `token_name`, `token_symbol`, `amount_min` and `amount_max` filters have no equivalent. `order_by` accepts `id`, `block_number` or `timestamp`.

**Response:** Each transfer is a log row. OLD field `amount` is `args.value`, and `from` and `to` are `args.from` and `args.to`. The new API writes those two addresses in mixed case. The values match on the same transfer. The token is the row's `address`. OLD fields `token_name`, `token_symbol` and `token_decimals` are not on the row; look them up with `GET /v1/evm/contracts?address=`. Tokens of other standards emit a `Transfer` event too, so keep only addresses that `/v1/evm/contracts` marks `erc20: true`.

### `GET /api/evm/erc20/account/v1`

**No replacement.** The new API does not list ERC-20 token holders or their balances. Neither `balance` nor `total_transfers`, nor the first and last active block, is available.

## Contract events

### `GET /api/contract_event/v1`

**Replaced by:** `GET /v1/contract-events`

**Parameters:** unchanged. `order_by` accepts `id`, `block_number`, `timestamp` or `name`.

**Response:** unchanged, including `args`, which keeps the old encoding.

### `GET /api/contract_event/{id}/v1`

**Replaced by:** `GET /v1/contract-events?id={id}`

**Parameters:** The id moves from the path into the `id` query parameter.

**Response:** The event comes back as the single row of a normal page, in `data[0]`. The old API returned it as an object in `data`. An unknown id returns an empty page with status 200. The old API returned 404.

## Runtime versions

### `GET /api/runtime_version/latest/v1`

**Replaced by:** `GET /v1/network/runtime-version`

**Parameters:** unchanged (none).

**Response:** Returns a single object. The fields and values are unchanged. Timestamps include milliseconds.

### `GET /api/runtime_version/history/v1`

**Replaced by:** `GET /v1/network/runtime-version/history`

**Parameters:** `order_by` accepts only `timestamp`.

**Response:** unchanged. Timestamps include milliseconds.

## Coldkey swaps

### `GET /api/pending_coldkey_swap/v1`

**Replaced by:** `GET /v1/accounts/pending-coldkey-swaps`

**Parameters:** unchanged (none).

**Response:** `old_coldkey` is a plain SS58 string. NEW fields `disputed` and `disputed_block_number` are new; they say whether the swap has been disputed, and in which block. Timestamps include milliseconds.

**Differences:**
- `block_number` and `timestamp` are the block in which the swap was announced, and that block's time. On the old API they were the current block and the time of the request.
- Once the execution block has passed, `predicted_execution_timestamp` is that block's real time. The old API kept an estimate. For example, for the swap with `execution_block_number` 7,765,759, the old API says `2026-03-17T23:54:24Z` and the new API says `2026-03-17T14:26:48.000Z`, which is the block's real time.
- For swaps whose execution block is still in the future, the two APIs agree.
- Both APIs list the same 17 swaps.

## Root claims

### `GET /api/root_claim/v1`

**Replaced by:** `GET /v1/alpha/root-claims`

**Parameters:** `order_by` accepts only `timestamp`. The `coldkey` and `block_number` sorts have been removed.

**Response:** `coldkey` is a plain SS58 string. NEW field `tao` is new. It is the TAO the claim paid out, in RAO, and is null for claims before block 8,765,684. Timestamps include milliseconds.

**Differences:** The new API returns one row per claim. The old API merged two claims by the same coldkey in the same block into one row, and it is missing claims around blocks 8,720,000 to 8,779,999. In blocks 9,000,000 to 9,001,000, both APIs return the same 9 claims.

## Exchanges

### `GET /api/exchange/v1`

**No replacement.** The new API has no list of known exchange addresses. The old list had 11 entries, each with `coldkey`, `name` and `icon`.

## Status

### `GET /api/status/v1`

**Replaced by:** `GET /v1/status`

**Parameters:** unchanged (none).

**Response:** `ok` and `version` are still there; `version` is the new API's own version number. OLD field `status.timestamp` has no new equivalent. NEW field `timestamp` is new: it is the server's current time.

## RPC

### `POST /api/v1/rpc/http`

**Partly replaced by:** `POST /v1/rpc/http`

**Parameters:** The request body is the JSON-RPC 2.0 request itself, or a batch array of requests. The old API expected `{"target": ..., "request": {...}}`. You can no longer choose a target. Every request goes to the `finney_lite` node, so archive queries are available only over the WebSocket route.

**Response:** The node's JSON-RPC response is returned as it is. The old API wrapped it as `{"target": ..., "response": {...}}`. A batch's replies can come back in a different order from the requests, so match them by `id`. Not checked live.

### `GET /api/v1/rpc/ws/{target}`

**Replaced by:** `WS /v1/rpc/ws/{target}`

**Parameters:** unchanged. `target` is `finney_lite` or `finney_archive`. The route is served over `wss://` only.

**Response:** If the node cannot be reached, the connection is opened and then closed with code 1011. Not checked live.

## Seal blob

### `POST /api/seal_blob/v1`

**No replacement.** The new API has no route that encrypts a blob to a public key. The old route took `pk_hex` and `tx_hex` and returned `ciphertext_hex`. Not checked live.

## Subnets

### `GET /api/subnet/latest/v1`

**Partly replaced by:** `GET /v1/subnets/metrics` and `GET /v1/subnets/hyperparameters`, joined on `netuid`. Subnet activity figures (emission, registrations, owner, recycled amounts) are on `/v1/subnets/metrics`; the subnet's chain settings are on `/v1/subnets/hyperparameters`.

**Parameters:** `netuid`, `page` and `limit` work on both routes. The old API returned every subnet in one page by default; the new API returns 50 a page, so ask for `limit=200` to get all subnets. The `emission_asc` and `emission_desc` orders have no equivalent: `/v1/subnets/metrics` sorts by `netuid` only, and `/v1/subnets/hyperparameters` takes no sort parameter.

**Response:**
- These old fields have new names on `/v1/subnets/hyperparameters`: `max_neurons` is `max_allowed_uids`, `max_validators` is `max_allowed_validators`, `max_regs_per_block` is `max_registrations_per_block`, `bonds_moving_avg` is `bonds_moving_average`, `bonds_reset_on` is `bonds_reset_enabled`, `subtoken_enabled` is `subnet_is_active`, `transfer_toggle` is `transfers_enabled`, `mech_count` is `mechanism_count`, `mech_emission_split` is `mechanism_emission_split`, and `immune_owner_uids_limit` is `owner_immune_neuron_limit`.
- `yuma3_on` (true or false) is replaced by `yuma_version`, which is `2` or `3`.
- `commit_reveal_weights_interval` and `reveal_period_epochs` are replaced by one field, `commit_reveal_period`.
- On `/v1/subnets/metrics`, `blocks_since_last_step` is `blocks_since_last_epoch` and `recycled_24_hours` is `tao_from_neuron_registration_24_hours`.
- Some values are now expressed differently:
  - `kappa` was the raw integer (for example `32767`). It is now a fraction of 65,535 (`"0.4999923…"`).
  - `difficulty`, `min_difficulty`, `max_difficulty` and `adjustment_alpha` were fractions of the largest 64-bit number. They are now the raw 64-bit integer, as a string.
  - `bonds_moving_average` is a fraction (as a string). The old `bonds_moving_avg` was the raw integer, scaled by 1,000,000.
  - `mechanism_emission_split` is the raw split, out of 65,535 per mechanism. It is empty when the subnet has not set one, which means an even split. The old `mech_emission_split` gave fractions.
- These old fields have no new equivalent: `tao_flow`, `ema_tao_flow`, `fee_rate`, `modality`, `projected_emission`, `ema_price_halving_blocks`, `net_flow_1_day`, `net_flow_7_days`, `net_flow_30_days`, `swap_v3_initialized`, `enabled_user_liquidity`.
- New fields on `/v1/subnets/hyperparameters`: `activity_cutoff_factor_milli`, `min_allowed_uids`, `scaling_law_power`, `recycle_or_burn`, `root_claim_threshold`, `voting_power_tracking`, `voting_power_ema_alpha`.

**Differences:**
- `bonds_penalty` was wrong in the old API (`0.00000000000000355266`). The new API gives the chain's value (for example `"1"`).
- On 6 of 129 subnets the old `activity_cutoff` was out of date. The new API gives the value the chain currently uses.
- `burn_increase_mult`, `alpha_high` and `alpha_low` are given to a different number of decimal places.

### `GET /api/subnet/history/v1`

**Replaced by:** `GET /v1/subnets/history`

**Parameters:** `block_number` is gone; use `block_start` and `block_end` set to the same block. `order_by` accepts `timestamp` or `block_number`. `netuid` is still required, and `frequency` still takes `by_block`, `by_hour` and `by_day`.

**Response:** Each row now has 7 fields: `block_number`, `timestamp`, `netuid`, `emission`, `excess_tao`, `neuron_registration_cost` and `recycled_24_hours` (which can be null). The old rows carried about 75 fields, including the subnet's settings. For those, use `GET /v1/subnets/hyperparameters` (current values only). Where both APIs have a row for the same block, the shared values are identical.

**Differences:**
- The daily points fall on different blocks. The new API's `by_day` points are the blocks divisible by 7,200, which is about 10:02 UTC each day. The old API's daily points were the last block of each UTC day, with the current block as the newest point.
- `by_block` in the new API returns one row every 300 blocks, the same rows as `by_hour`. The old API returned every block.
- History starts on 14 February 2025 (block 4,924,800). The old API went back to 21 December 2024.

### `GET /api/subnet/identity/v1`

**Replaced by:** `GET /v1/subnets/identities`

**Parameters:** unchanged. The old API returned every subnet in one page by default; the new API returns 50 a page.

**Response:** unchanged.

**Differences:** `summary`, `tags` and `twitter` are always null in the new API. The old API filled them for some subnets (for example, subnet 64's `twitter` was `@chutes_ai`).

### `GET /api/subnet/identity_set/v1`

**Replaced by:** `GET /v1/subnets/identities/history`

**Parameters:** To sort by subnet, use `order_by=netuid`. The old order value was `net_uid_asc` or `net_uid_desc`.

**Response:** unchanged.

**Differences:** An empty identity field is null in the new API. The old API returned either `""` or null.

### `GET /api/subnet/metadata/v1`

**No replacement.** The new API has no route that gives a subnet token's `name`, `symbol`, `decimals`, `platform`, `contract_address`, `circulating_supply`, `total_supply`, `max_supply`, `release_schedule`, `exchange_url`, `block_explorer` or `logo`. The nearest data:
- The subnet's name and logo are on `GET /v1/subnets/identities` (`subnet_name`, `logo_url`).
- The token symbol and the subnet's total alpha are on `GET /v1/subnets/pools` (`symbol`, `total_alpha`). `total_alpha` is a different figure from the old `circulating_supply`.

### `GET /api/subnet/owner/v1`

**Replaced by:** `GET /v1/subnets/owners`

**Parameters:** `order_by` accepts `timestamp` only. The old API could also sort by block number, which gives the same order.

**Response:** unchanged.

### `GET /api/subnet/registration/v1`

**Replaced by:** `GET /v1/subnets/registrations`

**Parameters:** `order_by` accepts `timestamp` only. Sorting by registration cost (`register_cost_asc`, `register_cost_desc`) has no equivalent.

**Response:** `recycled_at_registration` has no new equivalent.

### `GET /api/subnet/registration_cost/latest/v1`

**Replaced by:** `GET /v1/subnets/registration-cost`

**Response:** Returns a single object.

### `GET /api/subnet/registration_cost/history/v1`

**Replaced by:** `GET /v1/subnets/registration-cost/history`

**Parameters:** `order_by` accepts `timestamp` only.

**Response:** unchanged.

**Differences:**
- The new API returns one row per block. The old API returned one row per day, on the last block of each UTC day. To get one of those daily values, set `block_start` and `block_end` to that block; the value is identical.
- History starts on 13 February 2025 (block 4,920,351). The old API went back to March 2023.

### `GET /api/subnet/neuron/registration/v1`

**Replaced by:** `GET /v1/subnets/neuron-registration-events`

**Parameters:** `order_by` accepts `timestamp` only. Sorting by registration cost (`registration_cost_asc`, `registration_cost_desc`) has no equivalent.

**Response:** unchanged.

### `GET /api/subnet/neuron/deregistration/v1`

**Replaced by:** `GET /v1/subnets/neuron-deregistration-events`

**Parameters:** New `coldkey` filter. `order_by` accepts `timestamp` only.

**Response:** unchanged.

### `GET /api/subnet/distribution/coldkey/v1`

**Replaced by:** `GET /v1/subnets/distribution/coldkey`

**Parameters:** unchanged (`netuid`, required). The whole list comes back in one response. Sending `page` or `limit` is an error.

**Response:** unchanged. Rows are sorted by `count`, highest first.

### `GET /api/subnet/distribution/incentive/v1`

**Replaced by:** `GET /v1/subnets/distribution/incentive`

**Parameters:** unchanged (`netuid`, required). The whole list comes back in one response. Sending `page` or `limit` is an error.

**Response:** `incentive` has 10 decimal places.

### `GET /api/subnet/distribution/ip/v1`

**Replaced by:** `GET /v1/subnets/distribution/ip`

**Parameters:** unchanged (`netuid`, required). The whole list comes back in one response. Sending `page` or `limit` is an error.

**Response:** unchanged.

### `GET /api/subnet/pruning/latest/v1`

**Replaced by:** `GET /v1/subnets/deregistrations`

**Parameters:** `order_by` accepts `rank` only. Sorting by `netuid`, registration block, immunity blocks remaining, immunity or moving price has no equivalent. The old API returned every subnet in one page by default; the new API returns 50 a page.

**Response:** `pruning_rank` is now `rank`.

### `GET /api/subnet/pruning/history/v1`

**Replaced by:** `GET /v1/subnets/deregistrations/history`

**Parameters:** `order_by` accepts `timestamp` only.

**Response:** `pruning_rank` is now `rank`.

## Pools

### `GET /api/dtao/pool/latest/v1`

**Replaced by:** `GET /v1/subnets/pools` for each pool's reserves, price and market cap, and `GET /v1/subnets/pools/aggregate` for 24-hour trading figures, price changes and the sentiment index. Join them on `netuid`.

**Parameters:** `netuid`, `page` and `limit` work on both routes. The old API returned every subnet in one page by default; the new API returns 50 a page. Sort columns:
- `/v1/subnets/pools` sorts by `netuid` (the default), `price`, `liquidity`, `market_cap`, `tao_in_pool`, `total_alpha`, `alpha_in_pool`, `alpha_staked` or `root_prop`.
- `/v1/subnets/pools/aggregate` sorts by `netuid`, `market_cap_change_1_day`, `price_change_1_hour`, `price_change_1_day`, `price_change_1_week`, `price_change_1_month` or `tao_volume_24_hr`.
- The old `total_tao` and `tao_volume_one_day` orders are `tao_in_pool` and `tao_volume_24_hr`. The `*_one_hour`, `*_one_day`, `*_one_week` and `*_one_month` orders are `*_1_hour`, `*_1_day`, `*_1_week` and `*_1_month`.
- Sorting by `rank`, `fear_and_greed_index` or `enabled_user_liquidity` has no equivalent.

**Response:**
- `total_tao` is now `tao_in_pool` (on `/v1/subnets/pools`).
- `fear_and_greed_index` is now `sentiment_index`, and `fear_and_greed_sentiment` is now `sentiment` (on `/v1/subnets/pools/aggregate`).
- `seven_day_prices`, the buy, sell and total volumes, the counts of buys, sells, buyers and sellers, `highest_price_24_hr`, `lowest_price_24_hr`, `last_price`, the price changes and `market_cap_change_1_day` are all on `/v1/subnets/pools/aggregate`, with unchanged names.
- These old fields have no new equivalent: `name`, `rank`, `fee_rate`, `enabled_user_liquidity`, `swap_v3_initialized`, `user_provided_tao`, `user_provided_alpha`, `protocol_provided_tao`, `protocol_provided_alpha`, `alpha_sqrt_price`, `current_tick`, `fee_global_tao`, `fee_global_alpha`, `liquidity_raw`. The subnet's name is on `GET /v1/subnets/identities` (`subnet_name`).

**Differences:**
- `alpha_staked` is lower in the new API by a fixed amount for each subnet (12,363 alpha on subnet 64, the same every day). `market_cap` is lower in the same proportion, because both APIs compute it as `price` × (`alpha_in_pool` + `alpha_staked`).
- `tao_volume_24_hr_change_1_day` and `alpha_volume_24_hr_change_1_day` can differ by a few points even when the 24-hour volumes agree. Measured on subnet 64: −29.2 in the new API and −31.7 in the old, with 24-hour TAO volume of 1,847.9 and 1,849.8.
- `sentiment_index` differs slightly from the old `fear_and_greed_index`, typically by less than half a point on the 0–100 scale.

### `GET /api/dtao/pool/v1`

**Replaced by:** `GET /v1/subnets/pools` and `GET /v1/subnets/pools/aggregate`. This old route returned the same data as `GET /api/dtao/pool/latest/v1`, and everything in that entry applies.

### `GET /api/dtao/pool/history/v1`

**Replaced by:** `GET /v1/subnets/pools/history`

**Parameters:**
- `netuid` is now required.
- `block_number` is gone; use `block_start` and `block_end` set to the same block.
- `order_by` accepts `timestamp` only. Sorting by `price` has no equivalent.
- `frequency` is unchanged.

**Response:** `total_tao` is now `tao_in_pool`. These old fields have no new equivalent: `name`, `rank`, `fee_rate`, `enabled_user_liquidity`, `swap_v3_initialized`, `user_provided_tao`, `user_provided_alpha`, `protocol_provided_tao`, `protocol_provided_alpha`, `alpha_sqrt_price`, `current_tick`, `fee_global_tao`, `fee_global_alpha`, `liquidity_raw`. New fields: `subnet_emission_enabled`, and `subnet_protocol_alpha`, which is always null on this route.

**Differences:** `alpha_staked` and `market_cap` are lower, as described under `GET /api/dtao/pool/latest/v1`. The daily points fall on the same blocks in both APIs.

### `GET /api/dtao/pool/total_price/latest/v1`

**Replaced by:** `GET /v1/subnets/pools/total-price`

**Response:** Returns a single object. `fear_and_greed_index` is now `sentiment_index`, and `fear_and_greed_sentiment` is now `sentiment`.

**Differences:** Volume fields can differ, for the reasons given under `GET /api/dtao/pool/total_price/history/v1`.

### `GET /api/dtao/pool/total_price/history/v1`

**Replaced by:** `GET /v1/subnets/pools/total-price/history`

**Parameters:** New `block_start`, `block_end`, `timestamp_start` and `timestamp_end` filters. `order_by` accepts `timestamp` only. `frequency` is unchanged.

**Response:** `fear_and_greed_index` is now `sentiment_index`, and `fear_and_greed_sentiment` is now `sentiment`.

**Differences:**
- `price` is identical on the same block.
- The volume fields differ. From block 6,067,944, the new API does not count moving stake between hotkeys within the same subnet as trading volume. It does count the payout made when a subnet is removed as sell volume.
- On the daily row for 6 October 2026, `alpha_volume` was 194,743 TAO in the new API against 249,115 in the old, and `root_volume` was 45,488 against 35,316.

### `GET /api/dtao/pool/total_price/v1`

**Replaced by:** `GET /v1/subnets/pools/total-price/history`. This old route returned the same data as `GET /api/dtao/pool/total_price/history/v1`, and everything in that entry applies.

## Liquidity

The new API does not serve user liquidity positions, their history or events, or the liquidity distribution of a pool. None of the five routes below has a replacement, and no field of theirs appears anywhere in the new API.

### `GET /api/dtao/liquidity/distribution/v1`

**No replacement.** The old route returned an empty list (checked on subnet 64).

### `GET /api/dtao/liquidity/position/v1`

**No replacement.** The newest position on the old route was opened on 22 December 2025.

### `GET /api/dtao/liquidity/position/history/v1`

**No replacement.**

### `GET /api/dtao/liquidity/position_event/v1`

**No replacement.** The old route returned no events.

### `GET /api/dtao/liquidity/tick_to_price/v1`

**No replacement.** This route was a calculation, not stored data: the price for a tick is 1.0001 raised to the power of the tick (so tick `0` is price `1`).

## Metagraph

### `GET /api/metagraph/latest/v1`

**Replaced by:** `GET /v1/subnets/metagraph`

**Parameters:**
- `is_immunity_period` is now `is_immune`.
- New filters: `in_danger`, `has_dividends`, `has_incentive`.
- `order_by` accepts `total_alpha_stake`, `netuid`, `uid`, `emission`, `incentive`, `dividends`, `consensus` and `validator_trust`. Sorting by `updated`, `stake`, `trust`, `active`, `hotkey`, `coldkey`, `validator_permit`, `axon`, `daily_reward`, `registered_at` or `is_immunity_period` has no equivalent.
- The old API returned a whole subnet (up to 1,024 neurons) in one page by default; the new API returns 50 a page.

**Response:**
- `is_immunity_period` is now `is_immune`.
- `axon` is an `"ip:port"` string instead of an object.
- These old fields have no new equivalent:
  - `daily_reward`: it equalled `emission` × 20 in the rows checked.
  - `rank`: the new `miner_rank` and `validator_rank` are different rankings.
  - `trust` and `stake`: both were `"0"` on every row. Use `total_alpha_stake`.
  - `collateral`: it was null on every row.
- New fields: `stake_weight`, `hotkey_alpha`, `free_alpha`, `locked_alpha`, `min_locked_alpha`, `collateral_earned_alpha`, `miner_rank`, `validator_rank`, `name`, `in_danger`.

**Differences:** `total_alpha_stake` is a whole number. The old API sometimes gave it with a fractional part.

### `GET /api/metagraph/history/v1`

**Replaced by:** `GET /v1/subnets/metagraph/history`

**Parameters:**
- `netuid` is now required.
- The `hotkey` and `coldkey` filters are gone; filter by `uid` instead.
- New `has_incentive` filter.
- `order_by` accepts `timestamp` only.

**Response:** The same field changes as `GET /api/metagraph/latest/v1`.

**Differences:**
- The new API returns one row per neuron each time the subnet runs its epoch (every 360 blocks on subnet 64). The old API returned one row per neuron per day, on the last block of each UTC day. That old daily row equals the new API's latest row at or before that block.
- History starts on 13 February 2025. The old API went back to 3 February 2025.

### `GET /api/metagraph/root/latest/v1`

**No replacement.** The new API does not serve root weights or the old root fields `senator`, `subnet_weights`, `rank` and `pruning_score`. The old route had not updated since block 6,811,680 (4 November 2025), and gave `stake` as `"0"` for every neuron. The root subnet's current neurons, with their `uid`, `hotkey`, `coldkey` and stake, are listed by `GET /v1/subnets/metagraph?netuid=0`.

### `GET /api/metagraph/root/history/v1`

**No replacement.** The new API does not serve root weights or the old root fields `senator`, `subnet_weights`, `rank` and `pruning_score`. The old route had no rows after block 6,811,680 (4 November 2025). The root subnet's neuron history is available from `GET /v1/subnets/metagraph/history?netuid=0`.

## Neurons

### `GET /api/neuron/latest/v1`

**Replaced by:** `GET /v1/subnets/metagraph`

**Parameters:** The filters are unchanged. Sorting by `hotkey` or `coldkey` has no equivalent; the other sorts are listed under `GET /api/metagraph/latest/v1`.

**Response:**
- `registration_block` is now `registered_at_block`.
- `pruning_score` and `trust` have no new equivalent. Both were `"0"` on every row.
- Each row also carries the metagraph's stake and daily-reward fields, such as `total_alpha_stake`, `alpha_stake`, `root_stake` and `daily_total_rewards_as_tao`.

### `GET /api/neuron/history/v1`

**Replaced by:** `GET /v1/subnets/metagraph/history`

**Parameters:**
- `netuid` is now required.
- The `hotkey`, `coldkey`, `is_immune`, `in_danger` and `has_dividends` filters are gone. `uid` and `has_incentive` remain.
- `order_by` accepts `timestamp` only.

**Response:** The same changes as `GET /api/neuron/latest/v1`.

**Differences:** Both APIs return a row per epoch, on the same blocks, with the same values. History starts on 13 February 2025. The old API went back to 3 February 2025.

### `GET /api/neuron/aggregated/latest/v1`

**Replaced by:** `GET /v1/subnets/metagraph/aggregate`

**Parameters:** unchanged.

**Response:** The six `*_pruning_score` fields (`max_pruning_score`, `max_mining_pruning_score`, `max_danger_pruning_score`, `max_immune_pruning_score`, `min_non_immune_pruning_score`, `last_dereg_pruning_score`) have no new equivalent. In their place are six `*_emission` fields (`max_emission`, `max_mining_emission`, `max_danger_emission`, `max_immune_emission`, `min_non_immune_emission`, `last_dereg_emission`). These give emission in rao, not a pruning score, so do not compare them with the old values. The old pruning-score fields currently read `"0"`.

### `GET /api/neuron/aggregated/history/v1`

**Replaced by:** `GET /v1/subnets/metagraph/aggregate/history`

**Parameters:** `order_by` accepts `timestamp` only.

**Response:** The same change as `GET /api/neuron/aggregated/latest/v1`: the `*_pruning_score` fields are gone, and `*_emission` fields are new.

**Differences:** History starts on 13 February 2025. The old API went back to 21 December 2024.

### `GET /api/neuron/incentive_distribution/v1`

**Replaced by:** `GET /v1/subnets/metagraph/history` with `has_incentive=true` and `timestamp_start` set to the start of the period you want.

**Parameters:** There is no `days` parameter. For the last N days, set `timestamp_start` to now minus N × 86,400 seconds. `netuid` is still required. The old route returned everything in one response; the new one is paged, at up to 200 rows a page.

**Response:** Each row is a full metagraph row. `registration_block` is now `registered_at_block`, and `incentive` has 10 decimal places. Where both were checked, the rows are the same: the same neurons on the same blocks, with the same incentive.

## Validators

### `GET /api/dtao/validator/latest/v1`

**Replaced by:** `GET /v1/validators`

**Parameters:** unchanged. All 11 sort columns are kept, and the default is `rank` ascending.

**Response:** `claim_types` has been removed. The old API always sent an empty list. `name` is null when the validator has no identity.

**Differences:** Both APIs return 596 validators. `global_nominators` is higher on the new API: 41,510 against 34,887 for the same validator. The new figure matches the chain. `created_on_date` can be earlier on the new API, because it is the first day the hotkey held any stake (2025-02-04 against 2025-02-06 for the validator checked). `dominance` has 9 decimal places instead of 2.

### `GET /api/dtao/validator/history/v1`

**Replaced by:** `GET /v1/validators/{hotkey}/history`

**Parameters:** `hotkey` moves into the path and is required. The `block_number` filter has been removed: pass the same block as `block_start` and `block_end` instead. `order_by` accepts only `timestamp`, and the default direction is descending.

**Response:** `claim_types` has been removed.

**Differences:** Both APIs return 601 rows for the validator checked. The same `global_nominators`, `created_on_date` and `dominance` differences apply as on the latest route. The `*_24_hr_change` values differ slightly.

### `GET /api/dtao/validator/available/v1`

**Replaced by:** `GET /v1/validators/active`

**Parameters:** Only `netuid` is accepted. `limit` and `page` return a 400 error, and there is no paging: the whole list comes back in one response.

**Response:** unchanged. Rows may come back in a different order.

**Differences:** On subnet 1 both APIs return the same 53 validators with the same names. `hotkey_alpha` differs on every row, because the new API takes it from the last daily snapshot at which the validator earned. Earnings are recorded once a day, so a validator can appear or drop off up to one day later than on the old API.

### `GET /api/dtao/validator/basket/latest/v1`

**Replaced by:** `GET /v1/validators/baskets`

**Parameters:** `order_by` accepts `nav_tao` (the default), `spot_nav_tao`, `shares`, `nav_per_share`, `performance`, `return_7d`, `return_30d`, `staker_return_7d`, `staker_return_30d` and `hotkey`.

**Response:** `nav_per_share`, `rate`, `performance`, `return_7d`, `return_30d`, `twr`, `staker_return_7d` and `staker_return_30d` are JSON numbers. The old API sent them as strings. `twr_first_block` is a string; the old API sent a number. `day` is new. `rate` is never null.

### `GET /api/dtao/validator/basket/history/v1`

**Replaced by:** `GET /v1/validators/baskets/history`

**Parameters:** `day_start` and `day_end` (YYYY-MM-DD) are replaced by `timestamp_start` and `timestamp_end` in Unix seconds. Each one selects the whole UTC day it falls in. `order_by` accepts `day` (the default) and the same columns as the latest route, except `hotkey`.

**Response:** The ratio fields are JSON numbers and `twr_first_block` is a string, as on the latest route. The current, unfinished day is not included.

**Differences:** Each day's row is taken at the last block of the day. The old API took it earlier, so values differ a little. For 2026-10-05 the new API's row is at block 9,220,186 (23:59:48) and the old API's at block 9,220,023 (23:27:12); `return_7d` is 0.00740 against 0.00875.

### `GET /api/dtao/validator/dividends/latest/v1`

**No replacement.** No new route returns per-hotkey dividend splits (`nominator_alpha_dividends`, `validator_alpha_dividends`, the root dividend fields, `nominator_return_per_kt_*`, `epochs` or `tempo`). The hotkey's total stake is `hotkey_alpha` on `GET /v1/subnets/metagraph?netuid=&hotkey=`. Daily totals are `daily_validating_alpha` on the same route, and `nominator_return_per_day` and `validator_return_per_day` on `GET /v1/validators/performance/{hotkey}`.

### `GET /api/dtao/validator/dividends/history/v1`

**No replacement.** No new route keeps a history of the per-hotkey dividend splits. The closest history is `GET /v1/validators/performance/{hotkey}/history`, which has `nominator_return_per_day` and `validator_return_per_day`.

### `GET /api/dtao/validator/performance/latest/v1`

**Replaced by:** `GET /v1/validators/performance/{hotkey}`

**Parameters:** `hotkey` moves into the path. To get the same rows as the old API, pass `scope=own_and_children`; the default, `scope=hotkey`, returns a different set. The sort column `v_trust` is now `vtrust`, and `type` is now `validator_type`.

**Response:** `parent_hotkey` is new. Decimal values carry more decimal places.

**Differences:** `alpha`, `take` and `vtrust` match. `nominators` is higher on the new API (312 against 178 on one row). `position` and `ratio` differ, and the `family_*` values differ because suspended parent hotkeys are left out of the family totals.

### `GET /api/dtao/validator/performance/history/v1`

**Replaced by:** `GET /v1/validators/performance/{hotkey}/history`

**Parameters:** `hotkey` moves into the path. Pass `scope=own_and_children` to get the same rows as the old API: for the validator checked that returns 1,442 rows on both APIs, while the default returns 902. The `block_number` filter has been removed: pass the same block as `block_start` and `block_end`. `order_by` accepts only `timestamp`, and the default direction is descending.

**Response:** `parent_hotkey` is new.

**Differences:** `nominators` is higher on the new API, as on the latest route. A child hotkey with several parents can appear under each of them.

### `GET /api/dtao/validator/yield/latest/v1`

**Replaced by:** `GET /v1/validators/yield`

**Parameters:** unchanged. All 7 sort columns are kept, and the default direction is descending.

**Response:** `stake` is a string. The old API sent a number. The APY fields are still JSON numbers.

### `POST /api/dtao/validator/yield/latest/v1`

**Replaced by:** `POST /v1/validators/yield` (not checked live)

**Parameters:** The body keeps `positions` (each with `hotkey` and `netuid`), `min_stake`, `page` and `limit`. `order` is replaced by `order_by` and `order_dir`. The maximum `limit` is 200; the old API accepted up to 1,000.

**Response:** As on the `GET` route: `stake` is a string.

### `GET /api/dtao/validator/yield/history/v1`

**No replacement.** The new API returns only current yields, from `GET /v1/validators/yield`. No route keeps their history.

### `GET /api/validator/latest/v1`

**No replacement.** This route returns a snapshot of 75 validators taken before dTAO, at block 4,920,349 (2025-02-13). The nearest data is the end-of-day `stake` and `nominators` per hotkey on `GET /v1/validators/{hotkey}/history/pre-dtao`, which ends on 2025-02-12.

### `GET /api/validator/history/v1`

**Partly replaced by:** `GET /v1/validators/{hotkey}/history/pre-dtao`

**Parameters:** `hotkey` moves into the path. The `block_number` filter has been removed. `order_by` accepts only `timestamp`.

**Response:** Only `hotkey`, `block_number`, `timestamp`, `stake` and `nominators` are kept. These old fields have no new equivalent: `apr`, `apr_7_day_average`, `apr_30_day_average`, `blocks_until_next_reward`, `coldkey`, `created_on_date`, `dominance`, `last_reward_block`, `name`, `nominator_return_per_k`, `nominator_return_per_k_7_day_average`, `nominator_return_per_k_30_day_average`, `nominators_24_hr_change`, `pending_emission`, `permits`, `rank`, `registrations`, `stake_24_hr_change`, `subnet_dominance`, `system_stake`, `take`, `total_daily_return`, `validator_return` and `validator_stake`.

**Differences:** The new API has more early days: 9 rows against 7 for the validator checked, adding 2025-02-04 and 2025-02-05. The shared values match.

### `GET /api/validator/identity/v1`

**No replacement.** The old route currently answers HTTP 500, so it could not be compared. The nearest data is `GET /v1/accounts/identities?validator_hotkey=`, which returns the identity of the coldkey that owns the hotkey, without a `signature` field.

### `GET /api/validator/metrics/latest/v1`

**Partly replaced by:** `GET /v1/subnets/metagraph?netuid=&hotkey=`

**Parameters:** Filter by `netuid` and `hotkey`.

**Response:** `active`, `consensus`, `dividends`, `emission`, `incentive`, `uid`, `updated`, `validator_permit` and `validator_trust` keep their names. `registered_block_number` is now `registered_at_block`. `is_immunity_period` is now `is_immune`. These old fields have no new equivalent: `daily_reward`, `rank`, `stake`, `trust` and `axon_info`. The old API always sent `stake` and `trust` as 0. The metagraph route adds many new fields.

**Differences:** `dividends` and `validator_trust` carry fewer decimal places.

### `GET /api/validator/metrics/history/v1`

**Partly replaced by:** `GET /v1/subnets/metagraph/history`

**Parameters:** `netuid` is required. There is no `hotkey` or `coldkey` filter: look up the hotkey's `uid` first and filter by `uid`. `order_by` accepts only `timestamp`.

**Response:** Field names change as on the latest route. The new API stores one row per epoch (about every 99 blocks on subnet 1). The old API stored one row per day plus the latest.

**Differences:** The old API's history starts on 2025-03-08. Its end-of-day row at block 9,227,386 has the same `emission` and `validator_trust` as the new API's epoch row at block 9,227,315.

### `GET /api/validator/performance/v1`

**Partly replaced by:** `GET /v1/subnets/metagraph/history?netuid=&uid=`

**Parameters:** Look up the hotkey's `uid` first, then filter by `netuid` and `uid`. If the uid has changed hands, keep only the rows whose `hotkey` is yours.

**Response:** `blocks_since_weights_set` is now `updated`. `update_status` and `tempo` have no new equivalent. The metagraph route adds many new fields.

**Differences:** The latest 4 rows match on block, `emission` and `updated`.

### `GET /api/validator/weight_copier/v1`

**No replacement.** The new API has no list of weight-copying validators.

## Validator weights

### `GET /api/validator/weights/latest/v2`

**Replaced by:** `GET /v1/validators/weights`

**Parameters:** `mechanism` is new and defaults to 0. A `netuid` of 4096 or more is a 400 error: instead of the old combined value `netuid + 4096 × mechanism`, pass the subnet and the mechanism separately. For example, old `netuid=4140` is new `netuid=44&mechanism=1`. `order_by` accepts `netuid` (the default) and `uid`, and the default direction is ascending.

**Response:** Each entry in `weights` carries the target's `hotkey` as a string. It is `"unknown"` when the uid has no registered neuron.

**Differences:** The same uids and weights come back, but the entries in `weights` may be in a different order.

### `GET /api/validator/weights/history/v2`

**Replaced by:** `GET /v1/validators/weights/history`

**Parameters:** `mechanism` is new, as on the latest route. `order_by` accepts only `timestamp`.

**Response:** As on the latest route.

**Differences:** The new API keeps far more history. For the validator checked it returns 24,988 rows going back to 2025-05-09; the old API returns 2,177 rows going back to 2026-09-07.

### `GET /api/validator/weights/latest/v1`

**Partly replaced by:** `GET /v1/validators/weights`

**Parameters:** As for `GET /api/validator/weights/latest/v2` above.

**Response:** `call`, `version_key`, `weights_hash` and `reveal_round` have no new equivalent. Each entry in `weights` carries a new `hotkey` field. The old API scaled the weights so the largest was 1; the new API's weights add up to 1. The proportions are the same. For example uid 248 has weight 1 on the old API and 0.6909 on the new one.

**Differences:** The old API returned one row per weight-setting call, so its block can differ slightly from the new API's (9,232,172 against 9,232,166 for the same set of weights).

### `GET /api/validator/weights/history/v1`

**Partly replaced by:** `GET /v1/validators/weights/history`

**Parameters:** As for `GET /api/validator/weights/history/v2` above.

**Response:** As for `GET /api/validator/weights/latest/v1` above: `call`, `version_key`, `weights_hash` and `reveal_round` have no new equivalent, and the weights add up to 1 instead of having a largest value of 1.

**Differences:** The old API's history for the validator checked starts on 2025-10-17 (40,552 rows).

## Delegation and stake

### `GET /api/delegation/v1`

**Replaced by:** `GET /v1/subnets/stake-events` for events from block 4,920,351 on (dTAO), and `GET /v1/historic/stake-events` for events before it.

**Parameters:** `nominator` is now `coldkey` and `delegate` is now `hotkey`. `action` takes `stake`, `unstake` or `all`, instead of `delegate`, `undelegate` or `all`. `amount_min` and `amount_max` take whole numbers in RAO. `is_transfer=false` now matches every row that is not a transfer. `trades_only` is new: it keeps only buys and sells, leaving out stake transfers, hotkey-swap legs and, from block 6,067,944, moves within one subnet. `order_by` accepts only `timestamp`. `GET /v1/historic/stake-events` has no `netuid`, `is_transfer`, `transfer_address`, `amount_min` or `amount_max` filter.

**Response:** `delegate` is now `hotkey`, `nominator` is now `coldkey` and `delegate_name` is now `hotkey_name`. `action` is `stake` or `unstake` instead of `DELEGATE` or `UNDELEGATE`. `is_transfer` is always true or false, never null. `registration_collateral` is new: it is true when the stake is the collateral paid to register a miner. `validator_swap` is new: it is true when the row is one half of a move between validators within one subnet. `id` has a new format and does not match the old ids. `alpha_price_in_tao` has 9 decimal places. Rows from `GET /v1/historic/stake-events` have no `alpha`, `usd`, `alpha_price_in_tao`, `alpha_price_in_usd`, `slippage`, `fee`, `netuid`, `is_transfer`, `transfer_address` or `hotkey_name`.

**Differences:** For one validator on subnet 1 both APIs return 9,551 rows, with the same `amount`, `alpha`, `fee` and `usd`. `slippage` differs slightly on every row checked (for example 0.000106313 against 0.000100045). Before dTAO, both APIs return the same 5 rows for the validator checked.

### `GET /api/stake/v1`

**No replacement.** This route holds each coldkey's stake per hotkey before dTAO, up to block 4,920,351. `GET /v1/alpha/history?coldkey=&hotkey=&netuid=0` starts at block 4,920,351, where its value matches the old route's last row. `GET /v1/validators/{hotkey}/history/pre-dtao` has only each validator's total stake.

### `GET /api/stake_balance/history/v1`

**No replacement.** The old route currently answers HTTP 404, so it could not be compared. No new route holds stake per coldkey and hotkey from before dTAO.

## Hotkey families

### `GET /api/hotkey/family/latest/v1`

**Replaced by:** `GET /v1/validators/hotkey-family`

**Parameters:** unchanged.

**Response:** `stake` and `family_stake` have been removed, from each row and from each entry in its parents and children. `proportion_staked` is now filled in; the old API always sent 0. Decimal values carry more decimal places.

**Differences:** Suspended parent hotkeys are left out of the family totals, so the `family_*` values can differ (for example `family_root_stake` 136326340507715.84 against 136326361171234). The `family_*` values are never negative.

### `GET /api/hotkey/family/history/v1`

**Replaced by:** `GET /v1/validators/hotkey-family/history`

**Parameters:** The `block_number` filter has been removed. `order_by` accepts only `timestamp`.

**Response:** As on the latest route. There is one row per day, taken at the last block of the day, and only for a hotkey with at least one parent or child. The current day is not included, and there are no rows for subnet 0. History starts on 2025-02-13.

**Differences:** At the same block the values match, apart from decimal places.

## Identity

### `GET /api/identity/latest/v1`

**Replaced by:** `GET /v1/accounts/identities`, or `GET /v1/accounts/{address}/identity` for one coldkey.

**Parameters:** `address` and `validator_hotkey` are kept on `GET /v1/accounts/identities`. `validator_hotkey` returns the coldkey that owns that hotkey. `GET /v1/accounts/{address}/identity` takes the coldkey in the path and answers 404 when the coldkey has no identity.

**Response:** The old API returned one row per coldkey and validator hotkey, plus one row with a null `validator_hotkey`. The new API returns one row per coldkey, with `validator_hotkeys` as a list. Empty strings, such as `additional` or `github_repo`, come back as null.

**Differences:** For the coldkey checked the old API returns 2 rows and the new API 1, with the same values.

### `GET /api/identity/history/v1`

**No replacement.** The new API has no history of coldkey identities. `GET /v1/subnets/identities/history` covers subnet identities only.

## Miners

### `GET /api/miner/autostake/v1`

**Replaced by:** `GET /v1/miners/autostakes`

**Parameters:** `order_by` accepts only `timestamp`.

**Response:** unchanged. Both APIs return 55,193 rows for subnet 1, with the same values.

### `GET /api/miner/coldkey/v1`

**Replaced by:** `GET /v1/miners/coldkey-summary`

**Parameters:** `days` can be at most 36,500. `limit` returns a 400 error.

**Response:** unchanged.

**Differences:** With `days=7`, every total matches. `total_balance` and the staked balances differ slightly (2903214897 against 2903227822 for the coldkey checked).

### `GET /api/miner/weights/latest/v1`

**Replaced by:** `GET /v1/miners/weights`

**Parameters:** `mechanism` is new. `order_by` accepts `validator_uid` (the default), `netuid` and `miner_uid`, and the default direction is ascending.

**Response:** `mechanism` is new. `weight` carries fewer digits (0.0026771653543307085 against 0.00267716535433070866). Rows with the same sort value may come back in a different order.

### `GET /api/miner/weights/history/v1`

**Replaced by:** `GET /v1/miners/weights/history`

**Parameters:** `mechanism` is new. `order_by` accepts only `timestamp`.

**Response:** As on the latest route.

**Differences:** The new API keeps older history. For the pair checked it returns 1,221 rows going back to 2026-01-12; the old API returns 1,216 rows going back to 2026-09-12.

## Conviction

### `GET /api/conviction/latest/v1`

**Replaced by:** `GET /v1/subnets/conviction`

**Parameters:** `order_by` accepts `amount_locked` (the default), `amount_tao`, `conviction` and `netuid`, and the default direction is descending. Sorting by `coldkey` or `hotkey` has been removed.

**Response:** Rows are updated hourly. For a few seconds after an update a response can mix rows from two updates; each row's `block_number` shows which one it came from.

**Differences:** Both APIs return 395 rows with the same values.

### `GET /api/conviction/history/v1`

**Replaced by:** `GET /v1/subnets/conviction/history`

**Parameters:** `order_by` accepts only `timestamp`. Sorting by `coldkey` or `block_number` has been removed.

**Response:** unchanged.

**Differences:** For subnet 79 both APIs return 260 rows, with the same values at block 9,227,386.

## Alpha stake positions

### `GET /api/dtao/stake_balance/latest/v1`

**Replaced by:** `GET /v1/alpha/leaderboard`

**Parameters:** `coldkey`, `hotkey`, `netuid` are unchanged. `balance_min`, `balance_max`, `balance_as_tao_min` and `balance_as_tao_max` are now whole numbers in RAO. Sorting is by `global_rank` (the default, largest position by TAO value first) or `subnet_rank` only; the old `netuid`, `balance` and `balance_as_tao` sorts are gone.

**Response:** New fields: `global_rank` (rank across all subnets by TAO value), `locked_alpha` and `free_alpha` (the part of `balance` held as miner registration collateral, and the part you can withdraw; they add up to `balance`).

**Differences:** The new API refreshes these positions once an hour, so a row can be up to an hour old; the old API was close to live. On the same position, `balance` was identical (665,012,418,306,538).

### `GET /api/dtao/stake_balance/history/v1`

**Replaced by:** `GET /v1/alpha/history`

**Parameters:** `coldkey`, `hotkey` and `netuid` are still required. `block_number` is removed: use `block_start`/`block_end` or `timestamp_start`/`timestamp_end`. Sorting is by `timestamp` only.

**Response:** New fields: `global_rank`, `subnet_rank`, `subnet_total_holders`, `locked_alpha`, `free_alpha`.

**Differences:** The new API returns one row per day, the position at the day's last block (stamped 23:59:48). The old API also returned a row each time the position changed during the day. Over 26 to 29 Sep 2026 on one position, the old API returned 14 rows and the new one 4; the 4 end-of-day rows have the same values on both. You can no longer ask for the balance at an exact block.

### `GET /api/dtao/stake_balance/portfolio/v1`

**Replaced by:** `GET /v1/alpha/portfolio`

**Parameters:** Only `coldkey` (required), `hotkey`, `netuid` and `days` remain. `balance_min`, `balance_max`, `balance_as_tao_min`, `balance_as_tao_max`, `page`, `limit` and `order` are removed, and sending any of them is a `400`.

**Response:** No `pagination`: every position for the coldkey comes back in one response. New fields: `block_number`, `timestamp`.

**Differences:** Rows can come back in a different order, and there is no way to choose it.

### `GET /api/dtao/stake_balance_aggregated/latest/v1`

**Partly replaced by:** `GET /v1/accounts/leaderboard` and `GET /v1/accounts/{address}`

**Parameters:** To rank coldkeys by total stake, call `/v1/accounts/leaderboard?order_by=balance_staked&order_dir=desc`. `total_balance_as_tao_min`/`_max` become `balance_staked_min`/`_max`, whole numbers in RAO. To look up one coldkey, call `/v1/accounts/{address}` instead of passing `coldkey`.

**Response:** `total_balance_as_tao` is `balance_staked` (root stake plus alpha stake valued in TAO). On the same coldkey the two agreed: 282,655,058,255,990 against 282,655,126,926,410, a few blocks apart. The account endpoints return many more fields per account.

**Differences:** The new `rank` ranks accounts by total balance (free plus staked), not by stake, so it can differ from the old `rank`. The leaderboard lists every account, including ones with no stake; add `balance_staked_min=1` to leave those out.

### `GET /api/dtao/hotkey_alpha_shares/latest/v1`

**Replaced by:** `GET /v1/alpha/hotkey-shares`

**Parameters:** Only `netuid`, `hotkey`, `alpha_min` (a whole number in RAO), `page` and `limit` remain. `alpha_max` and `order` are removed. Rows are always sorted by `alpha`, largest first.

**Differences:** The new API returns only hotkeys that hold shares on the subnet now, refreshed once an hour. The old API kept a hotkey's last row for ever after it left, so it returned far more rows, many of them out of date: on subnet 64, the old API had 2,797 rows and the new one 308, and the old API's largest row was last written in May 2026. Old rows written before about block 7,742,011 can show `shares` 2^64 times too large; the new API does not have this fault.

### `GET /api/dtao/hotkey_alpha_shares/history/v1`

**No replacement.** The new API serves only each hotkey's current alpha and shares, through `/v1/alpha/hotkey-shares`, not their history.

### `GET /api/dtao/coldkey_alpha_shares/latest/v1`

**Partly replaced by:** `GET /v1/alpha/leaderboard`

**Parameters:** `coldkey`, `hotkey` and `netuid` are unchanged. `alpha_min`/`alpha_max` become `balance_min`/`balance_max`, whole numbers in RAO. Sorting is by `global_rank` or `subnet_rank` only.

**Response:** The old `alpha` is the new `balance`: on one position at block 9,227,203 both were 663,774,741,729,695. The old `shares` field is not served anywhere.

### `GET /api/dtao/coldkey_alpha_shares/history/v1`

**Partly replaced by:** `GET /v1/alpha/history`

**Parameters:** `coldkey`, `hotkey` and `netuid` are all required. `block_number` is removed. Sorting is by `timestamp` only.

**Response:** The old `alpha` is the new `balance`. `shares` is not served.

**Differences:** One row per day, at the day's last block, instead of a row each time the position changed.

## Alpha trades and burns

### `GET /api/dtao/trade/v1`

**Replaced by:** `GET /v1/subnets/trades`

**Parameters:** Every filter is kept. `tao_value_min` and `tao_value_max` are whole numbers in RAO. Sorting is by `timestamp`, `from_amount`, `to_amount`, `tao_value` or `usd_value`; the `block_number` sort is gone.

**Response:** New field: `id`. `usd_value` can be `null`.

**Differences:** On a buy, `tao_value` is now the TAO actually spent (for example 2,000,000,000), where the old API gave the value of the alpha received at the spot price (2,002,206,733). `usd_value` follows it. On a sell where part of the alpha paid the transaction fee, the new `from_amount` leaves the fee out: on extrinsic 9232001-0010 the old API said 1,105,235,540 and the new one 1,078,902,450, and `to_amount` moved with it. The new API also lists trades made through the EVM staking precompile, which the old API left out.

### `GET /api/dtao/burned_alpha/v1`

**Partly replaced by:** `GET /v1/subnets/burns`

**Parameters:** `amount_min` and `amount_max` are removed, and so are the `netuid` and `amount` sorts. `burn_type` accepts only `call`.

**Differences:** The new API lists only alpha burned by a call. The old API also served incentive burns (`burn_type=incentive`, 922,074 rows); asking the new API for them is a `400`. Call burns are identical: 19,346 rows on subnet 64 on both, same values.

### `GET /api/dtao/burned_alpha/total/v1`

**Replaced by:** `GET /v1/subnets/burns/total`

**Parameters:** The `amount` sort is removed.

**Differences:** The new `amount` is the running total the chain itself keeps, so it can go down as well as up, and it starts again from zero when a new subnet takes over the netuid. The old total was counted another way and does not match: on subnet 64 the old API said 261,844,763,095,323 and the new one 274,207,517,615,115. The new API also lists subnet 0, with an amount of 0.

## Subnet emission and flow

### `GET /api/dtao/subnet_emission/v1`

**Replaced by:** `GET /v1/subnets/epochs`

**Parameters:** `block_number` is removed: use `block_start` and `block_end` set to the same block. Sorting is by `timestamp` only.

**Response:** `tao_in_pool` is now `tao_in_emission`, `alpha_in_pool` is `alpha_in_emission`, and `alpha_rewards` is `alpha_out_emission`; the values matched on subnet 64 at block 9,231,883. `name` and `symbol` are removed. New fields: `server_emission`, `validator_emission`, `root_alpha_divs` and `owner_cut`, the amounts building up until the subnet's next payout.

**Differences:** The new API has a row for every block. The old API had one row every 360 blocks or so.

### `GET /api/dtao/hotkey_emission/v1`

**No replacement.** No new endpoint gives emission per hotkey per subnet over time. The `emission` field on `/v1/subnets/metagraph/history` measures something else and does not match.

### `GET /api/dtao/tao_flow/v1`

**No replacement.** The new API does not serve a subnet's TAO flow.

### `GET /api/dtao/delegation_volume/v1`

**No replacement.** The new API has no delegation volume endpoint. The old one currently answers `500` to every request.

### `GET /api/dtao/slippage/v1`

**No replacement.** The new API has no slippage quote calculator. Each stake event on `/v1/subnets/stake-events` reports the slippage that trade actually had.

## TradingView charts

These three keep the TradingView UDF formats they had before. They do not use the new API's usual envelope, and they ignore parameters they do not know instead of answering `400`.

### `GET /api/dtao/tradingview/udf/config`

**Replaced by:** `GET /v1/tradingview/udf/config`

**Parameters:** unchanged

**Response:** unchanged (identical byte for byte).

### `GET /api/dtao/tradingview/udf/symbol_info`

**Replaced by:** `GET /v1/tradingview/udf/symbol_info`

**Parameters:** unchanged

**Response:** unchanged (identical for one subnet and for all 130 symbols).

### `GET /api/dtao/tradingview/udf/history`

**Replaced by:** `GET /v1/tradingview/udf/history`

**Parameters:** unchanged (`symbol` such as `SUB-64` or `SUB--1`, `resolution`, `from`, `to`, `countback`).

**Differences:** Each bar's time `t` is the start of its period; the old API labelled each bar one period later. Prices are given in full; the old API cut them to 6 decimal places. The bar that starts exactly at `from` is included. Volume `v` differs by a few percent in either direction. Weekly bars (`7D`) are 7-day periods starting on a Thursday and monthly bars (`30D`) are fixed 30-day periods, not calendar weeks and months. Up to 5,000 bars are returned.

## Prices

### `GET /api/price/latest/v1`

**Replaced by:** `GET /v1/price`

**Parameters:** unchanged. `asset` ignores case.

**Response:** unchanged

### `GET /api/price/simple/latest/v1`

**Replaced by:** `GET /v1/price/simple`

**Parameters:** unchanged

**Response:** unchanged

### `GET /api/price/history/v1`

**Replaced by:** `GET /v1/price/history`

**Parameters:** Sorting is by `timestamp` only.

**Response:** unchanged

### `GET /api/price/ohlc/v1`

**Replaced by:** `GET /v1/price/ohlc`

**Parameters:** `period` is still required (`1m`, `1h`, `1d`).

**Response:** unchanged

**Differences:** `timestamp_end` is exclusive: a candle that starts exactly at `timestamp_end` is left out. The old API documented it as inclusive.

## Network statistics and parameters

### `GET /api/stats/latest/v1`

**Replaced by:** `GET /v1/network/stats`

**Response:** Returns a single object. Removed: `subnet_registration_cost`, `staked_root_on_delegate`, `staked_root_on_keep`, `staked_root_on_partial_keep` and `staked_root_on_swap`.

**Differences:** `staked_alpha` is about 24% lower than the old API's (1,984,028,268,463,932 against 2,596,919,576,010,487, 41 blocks apart). On the new API `staked` always equals `staked_alpha` plus `staked_root`; on the old API it did not. The other figures agree within a few blocks.

### `GET /api/stats/history/v1`

**Replaced by:** `GET /v1/network/stats/history`

**Parameters:** Sorting is by `timestamp` only.

**Response:** The same five fields as on `/v1/network/stats` are removed.

**Differences:** One row per day at the day's last block, as before, but the old API also returned a row for today so far; the new API's newest row is yesterday's. On recent days `staked_alpha` is about 24% lower than the old API's. Older rows can differ in `accounts` too: on 29 Sep 2025 the old API said 399,271 and the new one 352,371.

### `GET /api/network_parameter/latest/v1`

**Replaced by:** `GET /v1/network/parameters`

**Response:** Returns a single object. All 22 values are identical; only the order of the keys changed.

## CoinGecko

These four keep the CoinGecko DEX formats they had before. They do not use the new API's usual envelope, and they ignore parameters they do not know instead of answering `400`.

### `GET /api/coingecko/latest-block`

**Replaced by:** `GET /v1/coingecko/latest-block`

**Parameters:** unchanged

**Response:** unchanged

### `GET /api/coingecko/asset`

**Replaced by:** `GET /v1/coingecko/asset`

**Parameters:** unchanged

**Response:** unchanged

**Differences:** A subnet token's `totalSupply` and `circulatingSupply` can be slightly lower: for subnet 64, 6,105,560.49 against the old API's 6,117,922.11, 14 blocks apart. Subnet 0 was identical.

### `GET /api/coingecko/pair`

**Replaced by:** `GET /v1/coingecko/pair`

**Parameters:** unchanged

**Response:** unchanged

### `GET /api/coingecko/events`

**Replaced by:** `GET /v1/coingecko/events`

**Parameters:** unchanged. `toBlock` is still at most 20 blocks after `fromBlock`.

**Response:** unchanged

**Differences:** Swaps made through EVM transactions are included: blocks 9,232,000 to 9,232,010 gave 47 events against the old API's 45. `priceNative` can differ from about the seventh significant digit.

## Developer activity

### `GET /api/dev_activity/latest/v1`

**No replacement.** The new API does not serve subnet developer activity.

### `GET /api/dev_activity/history/v1`

**No replacement.** The new API does not serve subnet developer activity.

### `GET /api/dev_changelog/v1`

**No replacement.** The new API does not serve repository changelogs.

## OTC trading: the version-1 contract

The old API's `/v1` OTC routes and its `/v2` OTC routes read two different OTC contracts, and they hold different data. The new API keeps them apart: the version-1 contract is under `/v1/otc/contract-v1/...`, and the version-2 contract is under `/v1/otc/...`. A version-1 row has an absolute `price`. A version-2 row has `price_offset_bps` instead, plus `executed_price` on fills.

### `GET /api/otc/listing/v1`

**Replaced by:** `GET /v1/otc/contract-v1/listings`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `created_block`, `updated_block`, `price`, `amount`; the old `created_*` and `updated_*` values are now `created_block` and `updated_block`). Everything else is unchanged, including `price_min` and `price_max`, which take RAO strings.

**Response:** `seller` and `hotkey` are plain SS58 strings. Timestamps always include milliseconds: `2025-12-03T17:06:36Z` is now `2025-12-03T17:06:36.000Z`. This is the same instant. `price` has the same digits as before (raw RAO per whole alpha, unscaled).

**Differences:** The `seller` and `hotkey` filters work now. On the old API they matched nothing. For example, `seller=5E5Ctr2D9SjvLwNn45UNhBpjuQ7QWuinMqpAXY1ueRfJr5PT` returns 0 rows on the old API and 1 row on the new one. Both SS58 and hex addresses are accepted.

### `GET /api/otc/listing/history/v1`

**Replaced by:** `GET /v1/otc/contract-v1/listings/history`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`).

**Response:** `seller`, `hotkey` and `buyer` are plain SS58 strings. Timestamps always include milliseconds. On a `cancelled` row, `amount` and `price` are `"0"` and the returned alpha is in `amount_returned`. The old API returns these rows the same way.

### `GET /api/otc/offer/v1`

**Replaced by:** `GET /v1/otc/contract-v1/offers`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `created_block`, `updated_block`, `price`, `amount`; the old `created_*` and `updated_*` values are now `created_block` and `updated_block`).

**Response:** `buyer` is a plain SS58 string. Timestamps always include milliseconds.

**Differences:** The `buyer` filter now matches. On the old API it matched nothing, the same fault as `/api/otc/listing/v1`. This one comes from the new API's documentation and was not re-run against this route.

### `GET /api/otc/offer/history/v1`

**Replaced by:** `GET /v1/otc/contract-v1/offers/history`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`).

**Response:** `buyer` and `seller` are plain SS58 strings. Timestamps always include milliseconds.

### `GET /api/otc/trade/v1`

**Replaced by:** `GET /v1/otc/contract-v1/trades`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`, `tao_amount`, `alpha_amount`).

**Response:** `seller` and `buyer` are plain SS58 strings. Timestamps always include milliseconds. There is no `executed_price`, and the old version-1 route had none either.

### `GET /api/otc/user/stats/v1`

**Replaced by:** `GET /v1/otc/contract-v1/users/stats`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `last_activity_block`, `volume_tao`, `volume_alpha`, `total_trades`). `last_activity_*` is now `last_activity_block`.

**Response:** `account` is a plain SS58 string. Timestamps always include milliseconds.

**Differences:** The `account` filter works now. On the old API it matched nothing: `account=5E5Ctr2D9SjvLwNn45UNhBpjuQ7QWuinMqpAXY1ueRfJr5PT` returns 0 rows on the old API and 1 row on the new one. This route and `/api/otc/user/stats/v2` hold different data (7 rows against 1 today), so do not swap one for the other.

### `GET /api/otc/subnet/status/v1`

**Replaced by:** `GET /v1/otc/contract-v1/subnets/status`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `netuid`, `timestamp`, `block_number`). `frozen` still takes `frozen`, `unfrozen` or `all`. It is not a boolean.

**Response:** `changed_by` is a plain SS58 string. Timestamps always include milliseconds.

**Differences:** Both APIs return no rows today. The field list was compared from the two specifications, and the two lists are the same.

## OTC trading: the version-2 contract

### `GET /api/otc/listing/v2`

**Replaced by:** `GET /v1/otc/listings`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `created_block`, `updated_block`, `price_offset_bps`, `amount`; the old `created_*` and `updated_*` values are now `created_block` and `updated_block`).

**Response:** `seller` and `hotkey` are plain SS58 strings. Timestamps always include milliseconds.

**Differences:** Both APIs return no rows today. The field list was compared from the two specifications, and the two lists are the same.

### `GET /api/otc/listing/history/v2`

**Replaced by:** `GET /v1/otc/listings/history`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`).

**Response:** `seller`, `hotkey` and `buyer` are plain SS58 strings. Timestamps always include milliseconds.

**Differences:** Both APIs return no rows today. The field list was compared from the two specifications, and the two lists are the same.

### `GET /api/otc/offer/v2`

**Replaced by:** `GET /v1/otc/offers`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `created_block`, `updated_block`, `price_offset_bps`, `amount`; the old `created_*` and `updated_*` values are now `created_block` and `updated_block`).

**Response:** `buyer` is a plain SS58 string. Timestamps always include milliseconds.

### `GET /api/otc/offer/history/v2`

**Replaced by:** `GET /v1/otc/offers/history`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`).

**Response:** `buyer` and `seller` are plain SS58 strings. Timestamps always include milliseconds.

### `GET /api/otc/trade/v2`

**Replaced by:** `GET /v1/otc/trades`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`, `tao_amount`, `alpha_amount`, `executed_price`).

**Response:** `seller` and `buyer` are plain SS58 strings. Timestamps always include milliseconds.

**Differences:** Both APIs return no rows today. The field list was compared from the two specifications, and the two lists are the same.

### `GET /api/otc/user/stats/v2`

**Replaced by:** `GET /v1/otc/users/stats`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `last_activity_block`, `volume_tao`, `volume_alpha`, `total_trades`). `last_activity_*` is now `last_activity_block`.

**Response:** `account` is a plain SS58 string. Timestamps always include milliseconds.

### `GET /api/otc/subnet/status/v2`

**Replaced by:** `GET /v1/otc/subnets/status`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `netuid`, `timestamp`, `block_number`). `frozen` still takes `frozen`, `unfrozen` or `all`.

**Response:** `changed_by` is a plain SS58 string. Timestamps always include milliseconds.

**Differences:** Both APIs return no rows today. The field list was compared from the two specifications, and the two lists are the same.

## OTC lockup

### `GET /api/otc/lockup/listing/v1`

**Replaced by:** `GET /v1/otc/lockup/listings`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `created_block`, `updated_block`, `price_offset_bps`, `lockup_duration`, `total_amount`, `remaining_amount`; the old `created_*` and `updated_*` values are now `created_block` and `updated_block`).

**Response:** `seller` and `hotkey` are plain SS58 strings. Timestamps always include milliseconds.

### `GET /api/otc/lockup/listing/history/v1`

**Replaced by:** `GET /v1/otc/lockup/listings/history`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`).

**Response:** `seller` and `buyer` are plain SS58 strings. `escrow_account` was a hex public key (`0xc407…c13d`) and is now the SS58 address of the same key (`5GVjWfjhfg6hPcLJYeJezExwE7ZmqLmvDKtYJ5EqAB5TF3ev`). Timestamps always include milliseconds.

### `GET /api/otc/lockup/purchase/v1`

**Replaced by:** `GET /v1/otc/lockup/purchases`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `created_block`, `unlock_block`, `alpha_amount`, `tao_amount`, `executed_price`; the old `created_*` value is now `created_block`).

**Response:** `buyer` and `seller` are plain SS58 strings. `escrow_account` was a hex public key and is now the SS58 address of the same key. Timestamps always include milliseconds.

### `GET /api/otc/lockup/claim/v1`

**Replaced by:** `GET /v1/otc/lockup/claims`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `block_number`, `timestamp`, `amount_claimed`, `unlock_block`). `escrow_account` accepts an SS58 address or a hex key.

**Response:** `buyer` is a plain SS58 string. `escrow_account` is an SS58 address. On the old API's other lockup routes it was a hex key.

**Differences:** Neither API has a claim row today. The field list was compared from the two specifications, and the two lists are the same.

### `GET /api/otc/lockup/user/stats/v1`

**Replaced by:** `GET /v1/otc/lockup/users/stats`

**Parameters:** `order` → `order_by` + `order_dir` (columns: `last_activity_block`, `total_listings_created`, `total_purchases_made`, `total_claims_made`, `volume_sold_tao`, `volume_bought_tao`). Three sort columns are renamed: `last_activity_*` is now `last_activity_block`, `total_volume_sold_tao_*` is now `volume_sold_tao`, and `total_volume_bought_tao_*` is now `volume_bought_tao`. The response fields keep their `total_volume_…` names.

**Response:** `account` is a plain SS58 string. Timestamps always include milliseconds.

## Live chain reads

On the old API, the `/api/v1/live/...` routes read straight from a chain node and returned decoded JSON. The new API has no matching REST routes. Some of the data is in its indexed routes (`/v1/blocks`, `/v1/extrinsics`, `/v1/events`, `/v1/accounts/{address}`). Everything else has to be read from the node yourself, through the new API's JSON-RPC pass-through: `POST /v1/rpc/http`, or the WebSocket `wss://…/v1/rpc/ws/{target}` with target `finney_lite` or `finney_archive`. The HTTP route always uses `finney_lite`. To read state at older blocks, use the WebSocket with `finney_archive`. The pass-through returns the node's own JSON-RPC answer, so storage values and metadata come back SCALE-encoded and you have to decode them. We did not call the pass-through when checking this guide, because it is a POST.

### `GET /api/v1/live/blocks/head`

**Partly replaced by:** `GET /v1/blocks?limit=1`. Rows come newest first by default.

**Parameters:** unchanged (none).

**Response:** A paginated list with one row, not a bare object. Renamed: `number` (string) → `block_number` (number), `parentHash` → `parent_hash`, `stateRoot` → `state_root`. `extrinsicRoot` was always `null` on the old route; the new `extrinsics_root` is filled in. `authorId` was `null`; the new `validator` is also `null`. Removed: `finalized`, `logs`, `onInitialize`, `onFinalize`, `extrinsics`. Added: `timestamp`, `spec_version`, `spec_name`, `impl_name`, `impl_version`, `events_count`, `extrinsics_count`, `calls_count`.

**Differences:** The new row does not include the block's extrinsics and events. Get them from `GET /v1/extrinsics?block_number=<n>&include_args=true` and `GET /v1/events?block_number=<n>`. The new API serves the newest block it has indexed, not the node's head. In our check the two were the same block, 9,232,197.

### `GET /api/v1/live/blocks/{height}`

**Partly replaced by:** `GET /v1/blocks?block_number={height}`

**Parameters:** the path `height` → query `block_number`.

**Response:** The same changes as `/api/v1/live/blocks/head`. On block 9,232,197, `hash`, `parent_hash` and `state_root` match the old values. The 266 events and 34 extrinsics in the old block body match the new `events_count` (266) and `extrinsics_count` (34).

**Differences:** The new API indexes blocks from genesis.

### `GET /api/v1/live/blocks`

**Partly replaced by:** `GET /v1/blocks?block_start=<a>&block_end=<b>`

**Parameters:** `block_start` and `block_end` are unchanged. The new route also takes `page`, `limit`, `order_by` and `order_dir`, plus `timestamp_start`, `timestamp_end`, `block_number` and `hash`.

**Response:** A paginated `data` list, not a bare array. Each row changes as described for `/api/v1/live/blocks/head`.

**Differences:** The new API returns at most 200 blocks a page.

### `GET /api/v1/live/blocks/{height}/extrinsics/{index}`

**Partly replaced by:** `GET /v1/extrinsics?id={height}-{index}&include_args=true`. The index is zero-padded to four digits, for example `id=9232197-0018`. For that extrinsic's events, use `GET /v1/events?extrinsic_id={height}-{index}`.

**Parameters:** The two path values become one `id` query value.

**Response:** Pallet and call names are now in runtime spelling, so `subtensorModule` / `addStakeLimit` is now `pallet: "SubtensorModule"`, `name: "add_stake_limit"`. Numbers inside `args` are JSON numbers, where the old API used strings (`"30000000"` is now `30000000`). Added: `id`, `index`, `block_number`, `timestamp`, `signer_address`, `fee`, `fee_payer`, `error`, `args_summary`. Events are not embedded; they are on `/v1/events`, with named `args` instead of a positional `data` array.

**Differences:** The old route returned HTTP 500 on all three calls we made, on two different blocks. We matched values against the same extrinsic as it appears inside the old `/api/v1/live/blocks/{height}` body: `hash`, `args` and signer all match on extrinsic 18 of block 9,232,197.

### `GET /api/v1/live/blocks/{height}/extrinsics-raw`

**No replacement.** The new REST routes do not carry raw encoded extrinsics. The node's `chain_getBlock` method, called through `POST /v1/rpc/http`, returns the header and the hex extrinsics (not checked live). The header roots are on `GET /v1/blocks`: on block 9,232,197 the old `extrinsicRoot` matches the new `extrinsics_root`.

### `GET /api/v1/live/accounts/{address}/balance-info`

**Partly replaced by:** `GET /v1/accounts/{address}`. It returns a list with one row.

**Parameters:** unchanged (`address` in the path).

**Response:** `free` → `balance_free` and `reserved` → `balance_reserved`. These are the latest indexed values, not a live node read. Removed: `nonce`, `frozen`, `miscFrozen`, `feeFrozen`, `locks`, `tokenSymbol`, `at`. No new REST route carries those. To get them, read `System.Account` through the JSON-RPC pass-through (not checked live). The new row adds staked balances, alpha positions and 24-hour-ago values.

**Differences:** The old route returned HTTP 500 for both addresses we tried, so we could not compare values.

### `GET /api/v1/live/node/transaction-pool`

**No replacement.** No new REST route returns pending transactions. The node method `author_pendingExtrinsics` can be called through `POST /v1/rpc/http`, if the node allows it (not checked live).

### `GET /api/v1/live/node/version`

**No replacement.** The node's client name and version (`chain`, `clientImplName`, `clientVersion`) are not on any new REST route. They can be read with the node methods `system_chain`, `system_name` and `system_version` through `POST /v1/rpc/http` (not checked live). `GET /v1/network/runtime-version` is a different thing: it returns the chain's runtime version number (`runtime_version`). Returns a single object.

### `GET /api/v1/live/pallets/{pallet_id}/consts`

**No replacement.** Pallet constants come from the chain metadata. Read it with `state_getMetadata` through `POST /v1/rpc/http`. It comes back SCALE-encoded, and you have to decode it yourself (not checked live).

### `GET /api/v1/live/pallets/{pallet_id}/consts/{id}`

**No replacement.** It is the same as `/api/v1/live/pallets/{pallet_id}/consts`: read it from `state_getMetadata` through the JSON-RPC pass-through.

**Differences:** The old route returned `"metadata": null` for `balances` / `ExistentialDeposit` under both spellings we tried, so it was not returning the constant.

### `GET /api/v1/live/pallets/{pallet_id}/events`

**No replacement.** Event definitions (names, fields, docs) come from the chain metadata, through `state_getMetadata` on the JSON-RPC pass-through. To find events that actually happened, use `GET /v1/events?pallet=<Pallet>&name=<Event>`. That is a different dataset.

### `GET /api/v1/live/pallets/{pallet_id}/events/{id}`

**No replacement.** It is the same as `/api/v1/live/pallets/{pallet_id}/events`.

**Differences:** The old route returned `"metadata": null` for `balances` / `Transfer` under both spellings we tried.

### `GET /api/v1/live/pallets/{pallet_id}/storage`

**No replacement.** Storage item definitions come from the chain metadata, through `state_getMetadata` on the JSON-RPC pass-through.

### `GET /api/v1/live/pallets/{pallet_id}/storage/{id}`

**No replacement.** No new REST route reads an arbitrary storage item. Call `state_getStorage` with the item's storage key through `POST /v1/rpc/http`. The value comes back SCALE-encoded hex, not decoded JSON as on the old route (not checked live). Many common storage values are already served decoded by the new API's indexed routes. For example, total issuance is on `/v1/network/stats`.

## New endpoints with no old counterpart

These are new. Nothing in the old API maps to them.

### `GET /v1/subnets/swaps`

Cross-subnet alpha swaps: one row per swap, with `coldkey`, `from_name` and `to_name` (for example `SN41` and `SN51`), `from_amount`, `to_amount`, `tao_value` (RAO, as strings) and `usd_value`. Filter by `coldkey`, `extrinsic_id`, `from_name`, `to_name`, value ranges (`tao_value_min`/`_max`, `usd_value_min`/`_max`), and block or time range. Paged as usual.

### `GET /v1/subnets/burns/daily`

One bar per UTC day of alpha burned on one subnet, built from the chain's running burn total. Parameters: `netuid` and `days`.

### CoinMarketCap endpoints

These follow CoinMarketCap's own formats: no `data`/`pagination` wrapper.

- `GET /v1/cmc/assets`: every tradeable subnet token, keyed by symbol (`SN0`, `SN1`, ...).
- `GET /v1/cmc/summary`: a market summary for every active trading pair (`trading_pairs`, `last_price`, `lowest_ask` and so on), as a list.
- `GET /v1/cmc/ticker`: a ticker for every active trading pair, keyed by id.
- `GET /v1/cmc/circulating-supply?netuid=<n>` and `GET /v1/cmc/total-supply?netuid=<n>`: one bare JSON number.
- `GET /v1/cmc/trades/market-pair?market_pair=<pair>`: trades on one pair in the last five minutes. The pair is written as it appears in `trading_pairs`, for example `TAO_SN0`; any other form is a `400 Invalid market_pair format`.
- `GET /v1/cmc/order-book/market-pair?market_pair=<pair>`: always an empty list. There is no order book.
