- APIs
- Stacks Blockchain API
- V1 To V3 Migration
Migrating from v1 to v3
Map every deprecated /extended/v1 endpoint to its /extended/v3 replacement.
Overview
Most /extended/v1 endpoints are now deprecated in favor of /extended/v3. The v3 API is a
redesign, not a rename: it uses cursor-based pagination, splits large "kitchen sink" responses
into focused resources, and nests related fields into objects instead of flattening them into
prefixed keys.
Deprecated endpoints still work today. Every response from one carries a Warning header:
Warning: 299 - "Deprecated: See https://docs.hiro.so/stacks/api for more information"
At the sunset date, deprecated endpoints stop executing and return 410 Gone instead. Migrate
before then.
What changed in v3
Before mapping endpoints one by one, these are the cross-cutting changes you will hit on almost every route.
Cursor pagination replaces offsets
v1 list endpoints take limit and offset and return { limit, offset, total, results }. v3
list endpoints take limit and cursor, and return { limit, total, cursor: { next, previous, current }, results }. See Pagination for the full
walkthrough.
The practical consequence: you cannot jump to an arbitrary page. Walk the list with
cursor.next until it is null.
Summaries by default, details on request
v3 list endpoints return a summary of each object (the fields most callers need) rather than
the full record. The single-resource endpoints return the full record, and the heavy fields are
opt-in via ?include=:
$curl 'https://api.hiro.so/extended/v3/transactions/{tx_id}?include=function_args,post_conditions,result,source_code'
Available include values on GET /extended/v3/transactions/{tx_id}: function_args,
source_code, post_conditions, result. They may be repeated (?include=a&include=b) or
comma-separated (?include=a,b).
This replaces the v1 exclude_function_args pattern, inverted: v1 sent everything unless you
opted out, v3 sends the lean payload unless you opt in.
Nested objects replace prefixed fields
v1 flattened everything into the top level (block_height, burn_block_time,
execution_cost_runtime, pending_balance_inbound). v3 groups them (block.height,
bitcoin_block.time, execution_cost.runtime, mempool.inbound).
Microblock and unanchored fields are gone
Microblocks were removed in the Nakamoto upgrade. v3 has no microblock_hash,
microblock_sequence, microblock_canonical, is_unanchored, or unanchored query parameter.
There is also no canonical field. v3 only returns canonical data.
ISO timestamp duplicates are gone
v1 returned both burn_block_time and burn_block_time_iso. v3 returns Unix seconds only
(block.time, bitcoin_block.time). Format them client-side.
GET /extended/v1/tx accepts type, from_address, to_address, contract_id,
function_name, nonce, start_time, end_time, sort_by, and order.
GET /extended/v3/transactions accepts only limit and cursor. The same applies to the
mempool endpoints (sender_address, recipient_address, address, order_by are not
available in v3). If you depend on server-side filtering, keep using the v1 endpoint until a
v3 equivalent ships, and filter client-side where you can.
Transactions
| Deprecated v1 endpoint | v3 replacement |
|---|---|
GET /extended/v1/tx | GET /extended/v3/transactions |
GET /extended/v1/tx/{tx_id} | GET /extended/v3/transactions/{tx_id} |
GET /extended/v1/tx/{tx_id}/raw | Stacks node RPC GET /v3/transaction/{tx_id} |
GET /extended/v1/tx/multiple | GET /extended/v3/transactions/batch |
GET /extended/v1/tx/mempool | GET /extended/v3/mempool/transactions |
GET /extended/v1/tx/block/{block_hash} | GET /extended/v3/blocks/{height_or_hash}/transactions |
GET /extended/v1/tx/block_height/{height} | GET /extended/v3/blocks/{height_or_hash}/transactions |
GET /extended/v1/tx/events | No direct replacement — see Endpoints without a v3 replacement |
The two v1 "transactions in a block" endpoints collapse into one: {height_or_hash} accepts a
block height, a block hash, or the literal latest.
Batch transaction lookups
GET /extended/v1/tx/multiple → GET /extended/v3/transactions/batch
Ids are supplied the same way — repeated (?tx_id=A&tx_id=B) or comma-separated (?tx_id=A,B),
up to 20 — but the response differs in two ways that need code changes, not just a URL swap:
v1 /tx/multiple | v3 /transactions/batch | |
|---|---|---|
| Shape | Map keyed by transaction id | { results: [...] } array |
| Unresolved ids | Present as { found: false, result: { tx_id } } | Absent — diff the response against the ids you sent |
| Mempool | Included | Excluded; mined canonical transactions only |
| Detail | Full transaction, with events | Transaction summary |
| Order | Unordered map | Canonical chain order, newest first — not the order ids were supplied |
The v3 batch endpoint reads mined transactions only, so a broadcast transaction that has not yet
been mined is simply absent from results — indistinguishable from an unknown id. For the common
"poll until confirmed" flow, call GET /extended/v3/transactions/{tx_id} per transaction instead;
that endpoint returns both mined and mempool transactions.
Transaction field mapping
| v1 field | v3 field |
|---|---|
tx_type | type |
tx_status | status |
tx_result | result (only with ?include=result) |
sender_address | sender.address |
nonce | sender.nonce |
sponsor_address | sponsor.address (sponsor is null when unsponsored) |
sponsor_nonce | sponsor.nonce (sponsor is null when unsponsored) |
sponsored | Removed — check sponsor !== null |
block_hash | block.hash |
block_height | block.height |
block_time | block.time |
tx_index | block.tx_index |
parent_block_hash | parent_block.hash (single-transaction endpoint only) |
burn_block_height | bitcoin_block.height |
burn_block_time | bitcoin_block.time |
block_time_iso | Removed — derive from block.time |
burn_block_time_iso | Removed — derive from bitcoin_block.time |
execution_cost_* | execution_cost.* — e.g. execution_cost_runtime becomes execution_cost.runtime |
contract_call.function_args | Same path, only with ?include=function_args |
smart_contract.source_code | Same path, only with ?include=source_code |
post_conditions | Same field, only with ?include=post_conditions |
post_condition_mode | Removed |
anchor_mode | Removed |
canonical | Removed — v3 only returns canonical data |
is_unanchored | Removed |
microblock_* | Removed — microblocks no longer exist |
| — | block.index_hash (new) |
| — | vm_error (new) |
status gained a problematic_skipped value in Epoch 4.0 alongside success,
abort_by_response, and abort_by_post_condition.
Mempool transactions use receipt_time and receipt_block_height in place of block fields, and
their status is one of pending or the dropped_* values.
Mempool
| Deprecated v1 endpoint | v3 replacement |
|---|---|
GET /extended/v1/tx/mempool/stats | GET /extended/v3/mempool |
The mempool is now a resource with a summary, rather than a stats sub-route of transactions.
v1 returned four parallel maps keyed by transaction type, so a question about one type meant
joining four objects, and a question about the whole mempool was not answerable at all —
percentiles cannot be averaged. v3 inverts the nesting: top-level metrics cover the whole mempool,
with a by_type breakdown underneath.
Mempool field mapping
| v1 field | v3 field |
|---|---|
tx_type_counts.{type} | by_type.{type}.count |
tx_simple_fee_averages.{type} | by_type.{type}.fee_rate |
tx_byte_sizes.{type} | by_type.{type}.tx_size |
tx_ages.{type} | Removed — use by_type.{type}.receipt_block_height |
| — | count, fee_rate, tx_size, receipt_time, receipt_block_height for the whole mempool (new) |
| — | by_type.{type}.receipt_time (new) |
*.poison_microblock | Removed from every map — microblocks no longer exist |
Each metric is still { p25, p50, p75, p95 }, null when a bucket is empty. The top-level count
always equals the sum of the per-type counts. Versioned smart-contract transactions are counted as
smart_contract, as in v1.
Three behavior changes need code changes, not a find-and-replace:
- Percentiles are discrete. v1 interpolated, so a p50 could be a fee no transaction paid, and
came back fractional. v3 returns a value some pending transaction actually has. Fees are exact
µSTX integers, returned as strings. Despite its name, v1's
tx_simple_fee_averageswas never an average — it has always held percentiles. - Age in blocks is gone. v1's
tx_ageswas computed against the chain tip on the server. v3 returns absolutereceipt_block_heightandreceipt_timepercentiles instead — subtract from the current tip or your own clock for an age. This keeps cached responses accurate: a server-side age went stale whenever a block arrived that left the mempool unchanged. - The percentile direction inverts. For an age,
p95was the oldest transaction. For a receipt height or time, the oldest pending transactions are atp25. Code ported fromtx_ageswill read them backwards unless you flip it.
Accounts and principals
The v1 "address" resource is the v3 "principal" resource.
| Deprecated v1 endpoint | v3 replacement |
|---|---|
GET /extended/v1/address/{principal}/stx | GET /extended/v3/principals/{principal}/balances/stx |
GET /extended/v1/address/{principal}/balances | Split across /balances/stx, /balances/ft, and /balances/nft |
GET /extended/v1/address/{principal}/transactions | GET /extended/v3/principals/{principal}/transactions |
GET /extended/v1/address/{principal}/transactions_with_transfers | GET /extended/v3/principals/{principal}/transactions |
GET /extended/v1/address/{principal}/{tx_id}/with_transfers | GET /extended/v3/principals/{principal}/transactions/{tx_id}/balance-changes |
GET /extended/v1/address/{principal}/mempool | GET /extended/v3/principals/{principal}/mempool/transactions |
GET /extended/v1/address/{principal}/nonces | GET /extended/v3/principals/{principal}/nonces |
GET /extended/v1/address/{principal}/assets | No direct replacement — closest is GET /extended/v3/principals/{principal}/balance-changes |
GET /extended/v1/address/{principal}/stx_inbound | GET /extended/v3/principals/{principal}/transfers/stx/inbound |
GET /extended/v1/tokens/nft/holdings?principal= | GET /extended/v3/principals/{principal}/balances/nft |
v3 also adds two transfer feeds with no v1 counterpart:
GET /extended/v3/principals/{principal}/transfers/stx/outbound— the debit side ofstx_inbound.GET /extended/v3/principals/{principal}/transfers/ft/{asset_identifier}— a principal's history for one fungible token, credits and debits interleaved in a single feed, newest first, in the token's own base units.
All three transfer endpoints return one result per event rather than per transaction, so a
transaction that moves the asset several times for this principal yields several rows. Mints have
a null sender and burns a null recipient.
GET /extended/v3/principals/{principal}/balances/nft accepts an optional asset_identifier
query parameter, which replaces the v1 asset_identifiers array filter. It takes a single asset
class, not a list.
STX balance field mapping
GET /extended/v1/address/{principal}/stx → GET /extended/v3/principals/{principal}/balances/stx
| v1 field | v3 field |
|---|---|
balance | balance |
| — | available (new — balance minus locked STX) |
locked | locked.amount (locked is null when nothing is locked) |
lock_tx_id | locked.lock_tx_id |
lock_height | locked.stacks_lock_height |
burnchain_lock_height | locked.burn_lock_height |
burnchain_unlock_height | locked.burn_unlock_height |
| — | locked.pox_version (new) |
estimated_balance | mempool.estimated_balance (mempool is null when nothing is pending) |
pending_balance_inbound | mempool.inbound |
pending_balance_outbound | mempool.outbound |
total_sent | Removed |
total_received | Removed |
total_fees_sent | Removed |
total_miner_rewards_received | Removed |
token_offering_locked | Removed |
In v1, estimated_balance was the total balance plus the pending mempool delta. In v3,
mempool.estimated_balance is the available (spendable) balance plus the pending delta, so
locked STX is excluded. If you were subtracting locked yourself, stop.
v1 accepted until_block and unanchored on the balance endpoints. v3 always reports the
current chain tip.
FT and NFT balances
GET /extended/v1/address/{principal}/balances returned FT and NFT balances as objects keyed by
asset identifier, with the NFT entry being a count. v3 returns cursor-paginated arrays instead:
GET /extended/v3/principals/{principal}/balances/ft—{ asset_identifier, balance }per token, sorted by balance descending.GET /extended/v3/principals/{principal}/balances/ft/{asset_identifier}— a single token's balance; returns zero rather than 404 when the principal does not hold it.GET /extended/v3/principals/{principal}/balances/nft— one entry per owned NFT instance,{ asset_identifier, value: { hex, repr } }, not a per-collection count.
The v1 total_sent / total_received counters on each token are not carried over.
Nonce field mapping
GET /extended/v1/address/{principal}/nonces → GET /extended/v3/principals/{principal}/nonces
| v1 field | v3 field |
|---|---|
possible_next_nonce | next_nonce |
last_executed_tx_nonce | last_confirmed_nonce |
last_mempool_tx_nonce | mempool.last_nonce |
detected_mempool_nonces | mempool.pending_nonces |
detected_missing_nonces | mempool.missing_nonces |
The v1 endpoint accepted block_height and block_hash to read the nonce at a past block. v3
only reports current nonce state.
Account transactions and transfers
v1 had three overlapping endpoints. v3 has two, with a cleaner split between "which transactions touched this principal" and "what changed for this principal".
GET /extended/v3/principals/{principal}/transactions returns, per transaction:
transaction— the transaction summary (same shape asGET /extended/v3/transactions).involvement—sender,sponsor, oraffected.balance_changes.stx—{ sent, received, net }in micro-STX, fee included insent.affected_balances—{ stx, ft, nft }booleans telling you whether it is worth fetching the detailed balance changes.
For the FT and NFT detail that v1 packed into stx_transfers / ft_transfers / nft_transfers,
call GET /extended/v3/principals/{principal}/transactions/{tx_id}/balance-changes, or fetch
several transactions at once with
GET /extended/v3/principals/{principal}/balance-changes?tx_id=A,B,C (up to 20 IDs).
Each balance change is { asset: { type, identifier? }, balance_change: { sent, received, net } },
where type is stx, ft, or nft.
Blocks
Blocks did not move to v3 — only the transactions in a block did. The v1 block endpoints are superseded by v2.
| Deprecated v1 endpoint | Replacement |
|---|---|
GET /extended/v1/block | GET /extended/v2/blocks |
GET /extended/v1/block/{hash} | GET /extended/v2/blocks/{height_or_hash} |
GET /extended/v1/block/by_height/{height} | GET /extended/v2/blocks/{height_or_hash} |
GET /extended/v1/block/by_burn_block_height/{burn_block_height} | GET /extended/v2/burn-blocks/{height_or_hash}/blocks |
GET /extended/v1/block/by_burn_block_hash/{burn_block_hash} | GET /extended/v2/burn-blocks/{height_or_hash}/blocks |
The v1 block responses embedded a txs array of transaction IDs. In v2 the block object carries
a tx_count; fetch the transactions from
GET /extended/v3/blocks/{height_or_hash}/transactions.
Smart contracts
| Deprecated v1 endpoint | Replacement |
|---|---|
GET /extended/v1/contract/{contract_id} | GET /extended/v3/smart-contracts/{contract_id} |
GET /extended/v1/contract/{contract_id}/events | GET /extended/v2/smart-contracts/{contract_id}/logs |
GET /extended/v1/contract/by_trait | None — see Endpoints without a v3 replacement |
Contract field mapping
GET /extended/v1/contract/{contract_id} → GET /extended/v3/smart-contracts/{contract_id}
| v1 field | v3 field |
|---|---|
contract_id | contract_id |
clarity_version | clarity_version |
tx_id | tx_id |
block_height | block.height |
source_code | source_code, only with ?include=source_code |
abi | Removed — use the Stacks node RPC GET /v2/contracts/interface/{address}/{name} |
canonical | Removed — v3 returns canonical data only |
| — | block.hash, block.index_hash, block.time, block.tx_index (new) |
| — | bitcoin_block (new: height, time) |
v1 wrote a row for every contract-deploy transaction, successful or not, and returned it with
abi: null and no indication that the deploy had aborted. v3 returns only contracts that were
successfully deployed; a contract id whose deploy transaction failed responds 404.
Stacking rewards
The burnchain reward endpoints report the Bitcoin reward addresses and BTC payouts of the pox-1
through pox-4 reward model. That model is keyed on the pox-addr a stacker supplies when
stacking, and pox-5 has no such address: stakers lock BTC or sBTC against a bond, and rewards
accrue as sBTC on the Stacks layer rather than as BTC sent to a burnchain address.
These endpoints therefore serve historical pox-4-and-earlier data only. No new records are written to them once the last pox-4 lock unlocks.
| Deprecated v1 endpoint | Replacement |
|---|---|
GET /extended/v1/burnchain/reward_slot_holders | None — reward slots do not exist in pox-5. The nearest concept is the cycle signer set, GET /extended/v3/staking/cycles/{cycle_number}/signers |
GET /extended/v1/burnchain/reward_slot_holders/{address} | None |
GET /extended/v1/burnchain/rewards | No global feed. Per-bond payouts: GET /extended/v3/staking/bonds → balances.paid_out.btc |
GET /extended/v1/burnchain/rewards/{address} | GET /extended/v3/principals/{principal}/staking/bonds → rewards.btc |
GET /extended/v1/burnchain/rewards/{address}/total | GET /extended/v3/principals/{principal}/staking → bonds.rewards.btc and stx.rewards.btc |
Three things change at once. The lookup key flips from a Bitcoin address to a Stacks
principal — the v1 endpoints accept either and convert a STX address to its Bitcoin
equivalent, and pox-5 has no such relationship to convert through. The asset flips from BTC on
Bitcoin to sBTC on Stacks (both denominated in sats, so amounts look interchangeable when
they are not). And the granularity flips from per-burn-block payout events to running
accrued / claimed / claimable totals per position — v3 has no per-block reward history.
For per-burn-block BTC payouts under the current model, see
GET /extended/v2/burn-blocks/{height_or_hash}/pox-transactions and
GET /extended/v2/addresses/{burnchain_address}/pox-transactions, which are not deprecated.
Stacking events
The /extended/v1/pox{2,3,4} routes read the pox-2, pox-3, and pox-4 event tables and have no
pox-5 counterpart, so like the burnchain reward endpoints they serve historical data only. The
pox-5 equivalent differs per route — two have a partial one, two have none — so there is no single
replacement to point them all at.
| Deprecated v1 endpoint | pox-5 equivalent |
|---|---|
GET /extended/v1/pox{2,3,4}/events | None — there is no global pox-5 event feed. A single bond's history is at GET /extended/v3/staking/bonds/{bond_index}/events. |
GET /extended/v1/pox{2,3,4}/tx/{tx_id} | None. GET /extended/v3/transactions/{tx_id}/events returns a transaction's events, but not decoded PoX operations. |
GET /extended/v1/pox{2,3,4}/stacker/{principal} | For a principal's current position, GET /extended/v3/principals/{principal}/staking. There is no pox-5 event-history equivalent. |
GET /extended/v1/pox{2,3,4}/{pool_principal}/delegations | GET /extended/v3/staking/signers/{principal}/stakers |
The pool-delegation mapping is the closest to a like-for-like swap: a pox-4 pool aggregating delegators corresponds to a pox-5 signer with stakers.
Fees
| Deprecated v1 endpoint | Replacement |
|---|---|
POST /extended/v1/fee_rate | Stacks node RPC POST /v2/fees/transaction |
STX supply
All four v1 supply endpoints — including the JSON one — are deprecated in favor of a single v3 endpoint.
| Deprecated v1 endpoint | Replacement |
|---|---|
GET /extended/v1/stx_supply | GET /extended/v3/tokens/stx/supply |
GET /extended/v1/stx_supply/total/plain | GET /extended/v3/tokens/stx/supply → total |
GET /extended/v1/stx_supply/circulating/plain | GET /extended/v3/tokens/stx/supply → total |
GET /extended/v1/stx_supply/legacy_format | GET /extended/v3/tokens/stx/supply |
Supply field mapping
| v1 field | v3 field |
|---|---|
total_stx | total |
total_stx_year_2050 | projected_total_2050 |
unlocked_stx | Removed |
unlocked_percent | Removed |
block_height | Removed |
v1 returned decimal STX strings ("1470469916.700000"). v3 returns string-quoted integer
micro-STX ("1470469916700000"). Multiply by 10^6 when comparing against stored v1 values.
The quantity itself is also defined differently. v1 total_stx was the circulating supply at a
given block height, with unlocked_stx tracking the unlocked portion separately. v3 total is
the total liquid supply at the current chain tip: all STX minted (vesting unlocks included)
plus matured miner coinbase rewards, minus burned STX. There is no separate locked/unlocked
split, and v3 always reports the chain tip — the v1 height and unanchored query parameters
are gone.
Fungible tokens
| Deprecated v1 endpoint | v3 replacement |
|---|---|
GET /extended/v1/tokens/ft/{token}/holders | GET /extended/v3/tokens/ft/{asset_identifier}/holders |
GET /extended/v1/tokens/ft/stx/holders | GET /extended/v3/tokens/stx/holders |
v1 took the literal string stx in the token path parameter to mean STX holders. v3 splits
that into its own route, matching how /tokens/stx/supply is already separated, and validates
{asset_identifier} as a real Clarity asset identifier.
Holder field mapping
| v1 field | v3 field |
|---|---|
address | principal |
balance | balance |
total_supply | Moved to GET /extended/v3/tokens/ft/{asset_identifier}/supply → total |
The v1 response fused total_supply into the paginated envelope as an extra top-level field. In
v3 the holders response is the standard cursor envelope and nothing else, and supply is its own
endpoint — { asset_identifier, total } for fungible tokens, or the existing
/tokens/stx/supply for STX.
ft_balances rows are never deleted, so a principal that has spent its entire position stays in
the table with a 0 balance. v1 listed those rows and counted them in total; v3 filters them
out, matching GET /extended/v3/principals/{principal}/balances/ft. Expect a smaller total
than v1 reported for the same token.
Sort order also changed: v1 ordered by balance DESC with no tiebreaker, so holders with equal
balances came back in an arbitrary order and offset paging could skip or repeat them. v3 orders
by (balance DESC, principal ASC), which is what makes the cursor stable.
Balances are in the token's own base units. This API does not know a token's decimal precision — fetch that from the Token Metadata API.
For /tokens/stx/holders, the balance is the total µSTX held, including STX locked for
stacking. It is not the spendable figure that GET /extended/v3/principals/{principal}/balances/stx
reports as available.
Non-fungible tokens
| Deprecated v1 endpoint | v3 replacement |
|---|---|
GET /extended/v1/tokens/nft/history | GET /extended/v3/tokens/nft/{asset_identifier}/{value}/history |
asset_identifier moved from a query parameter into the path, matching the fungible token routes.
The token instance moved into the path too, and is accepted in two forms:
- A plain integer — a SIP-009 token id, e.g.
.../the-explorer-guild/2051/history. This is the form to use for almost every collection. - A
0x-prefixed serialized Clarity value — required for assets not keyed by auint. BNS names are the notable case:bns.clardefines them as{ name: (buff 48), namespace: (buff 20) }, a tuple, so they have no integer id.
v1 accepted value with or without it. In a path segment a bare hex string is ambiguous with a
decimal token id — and a serialized uint happens to be all decimal digits — so hex stripped of
its prefix is read as a (very large) token id and resolves to an empty page rather than erroring.
Always send the prefix.
To tell which form a collection needs, look at value.repr from
GET /extended/v3/principals/{principal}/balances/nft: a repr like u2051 means the integer
form works.
Field mapping
| v1 field | v3 field |
|---|---|
asset_event_type | Removed — a mint has a null sender, a burn a null recipient |
sender | sender (null on mints) |
recipient | recipient (null on burns) |
event_index | transaction.event_index |
tx_id | transaction.tx_id |
value | value (mints only — for history it is the request parameter) |
tx | Removed — the tx_metadata parameter is gone |
| — | block (new: height, hash, index_hash, time, tx_index) |
v1 could inline a full transaction object into each row via tx_metadata=true. v3 returns the
transaction id and event index only; fetch the transaction separately from
GET /extended/v3/transactions/{tx_id} when you need its detail. The unanchored parameter is
also gone, as everywhere else in v3.
Network block times
| Deprecated v1 endpoint | Replacement |
|---|---|
GET /extended/v1/info/network_block_times | None |
GET /extended/v1/info/network_block_time/{network} | None |
These return hardcoded legacy values (600s mainnet, 120s testnet) that no longer reflect actual
Stacks block production since the Nakamoto upgrade. For real block timing, use
GET /extended/v2/blocks/average-times, which is not deprecated.
BNS
All BNS endpoints are deprecated. They are no longer maintained.
| Deprecated endpoint | Replacement |
|---|---|
GET /v1/names | None |
GET /v1/names/{name} | None |
GET /v1/names/{name}/subdomains | None |
GET /v1/names/{name}/zonefile | None |
GET /v1/names/{name}/zonefile/{zoneFileHash} | None |
GET /v1/namespaces | None |
GET /v1/namespaces/{tld}/names | None |
GET /v2/prices/names/{name} | None |
GET /v2/prices/namespaces/{tld} | None |
GET /v1/addresses/{blockchain}/{address} | GET /extended/v3/principals/{principal}/balances/nft?asset_identifier=SP000000000000000000002Q6VF78.bns::names |
Querying NFT balances filtered to the BNS asset class returns only NFT-backed names. It does
not include subdomains, nor names imported from Blockstack v1, both of which
GET /v1/addresses/{blockchain}/{address} did return.
Search
| Deprecated v1 endpoint | v3 replacement |
|---|---|
GET /extended/v1/search/{id} | GET /extended/v3/search?q={term} |
v1 resolved one exact identifier to a single entity. v3 is a real search: the term moves from the
path to a q query parameter, and it can be the beginning of an identifier as well as a complete
one. Contract and asset names match anywhere in the name, so ?q=arkadiko finds the contracts and
tokens named after it.
v1 /search/{id} | v3 /search | |
|---|---|---|
| Term | Path segment, exact | q query parameter, prefix or name substring |
| Response | One result with a found flag | { results: [...] }, up to 20, best match first |
| No match | found: false with an error | Empty results array, 200 |
| Entity types | Addresses, contracts, blocks, transactions, mempool transactions | block, bitcoin_block, transaction, address, smart_contract, token |
| Type filter | None | ?type=block,transaction (repeated or comma-separated) |
| Extra detail | include_metadata=true | Removed — fetch the entity from its own endpoint |
There is no pagination; narrow the term to surface something that did not appear. Terms have
minimum lengths: 8 characters for hex, 6 for an address, 3 for a contract or asset name. Block
heights have no minimum, and a term that fits none of these forms returns 400.
v1 could resolve a mempool transaction id. v3 searches canonical, mined entities only, so a
transaction that has been broadcast but not mined returns no result. To look one up directly, use
GET /extended/v3/transactions/{tx_id}, which covers both mined and mempool transactions.
Faucets
| Deprecated v1 endpoint | v3 replacement |
|---|---|
POST /extended/v1/faucets/stx | POST /extended/v3/faucets/stx |
POST /extended/v1/faucets/btc | POST /extended/v3/faucets/btc |
POST /extended/v1/faucets/sbtc | POST /extended/v3/faucets/sbtc |
All three are testnet-only. The request and response both change shape:
| v1 | v3 | |
|---|---|---|
| Address | ?address= query parameter (the body form was already deprecated) | { "address": "…" } JSON body, required |
| Amount | Size flags: stacking for STX, large / xlarge for BTC | Fixed per deployment, reported in the response |
| Success | { success: true, txId, txRaw } | { transaction: { tx_id, chain }, amount: { stx | btc | sbtc } } |
| Error | { success: false, error, help } | { error } |
The amount is keyed by the asset it is denominated in — stx in µSTX, btc and sbtc in
satoshis — so the response says which token was sent and in what units. txRaw is gone, and the
BTC faucet's transaction id is now 0x-prefixed like the Stacks ones.
The size flags have no v3 equivalent. If you relied on stacking=true to get enough STX to stack,
or need more than the fixed amount for testing, reach out on Discord to request a custom faucet
transaction.
Endpoints without a v3 replacement
These are deprecated with no successor. Plan around them rather than swapping a URL.
| Deprecated endpoint | Notes |
|---|---|
GET /extended/v1/tx/events | Global event feed filtered by principal, transaction, or event type. Several v3 endpoints cover parts of it: per-transaction events at GET /extended/v3/transactions/{tx_id}/events, a principal's history for one fungible token at GET /extended/v3/principals/{principal}/transfers/ft/{asset_identifier}, a principal's STX transfers at GET /extended/v3/principals/{principal}/transfers/stx/{inbound,outbound}, and per-principal asset movement at GET /extended/v3/principals/{principal}/balance-changes. There is no single global event feed. |
GET /extended/v1/address/{principal}/assets | Closest equivalent is GET /extended/v3/principals/{principal}/balance-changes, which reports net balance deltas rather than raw asset events. |
GET /extended/v1/contract/by_trait | Searches deployed contracts by Clarity trait ABI. No v3 equivalent. To look up a specific contract you already know, use GET /extended/v3/smart-contracts/{contract_id}. |
GET /extended/v1/microblock | Microblocks were removed in the Nakamoto upgrade and are no longer produced. |
GET /extended/v1/microblock/{hash} | Same. |
GET /extended/v1/microblock/unanchored/txs | Same. |
GET /extended/v1/tokens/nft/mints | Mint events for an asset class. Retired rather than migrated — the endpoint serves negligible traffic. A single instance's mint is the oldest entry in GET /extended/v3/tokens/nft/{asset_identifier}/{value}/history, but there is no collection-wide mint feed. |
GET /extended/v1/faucets/btc/{address} | Testnet-only BTC balance helper. No replacement. |
Also deprecated: v2 endpoints
A handful of /extended/v2 routes are deprecated alongside v1 and move to v3. If you already
migrated from v1 to v2, these are your next hop.
| Deprecated v2 endpoint | v3 replacement |
|---|---|
GET /extended/v2/addresses/{address}/transactions | GET /extended/v3/principals/{principal}/transactions |
GET /extended/v2/addresses/{address}/transactions/{tx_id}/events | GET /extended/v3/principals/{principal}/transactions/{tx_id}/balance-changes |
GET /extended/v2/addresses/{principal}/balances/stx | GET /extended/v3/principals/{principal}/balances/stx |
GET /extended/v2/addresses/{principal}/balances/ft | GET /extended/v3/principals/{principal}/balances/ft |
GET /extended/v2/addresses/{principal}/balances/ft/{token} | GET /extended/v3/principals/{principal}/balances/ft/{asset_identifier} |
GET /extended/v2/blocks/{height_or_hash}/transactions | GET /extended/v3/blocks/{height_or_hash}/transactions |
Endpoints that are not deprecated
As of API 9.4.0, every /extended/v1 data endpoint is deprecated. The one route that is not is
GET /extended, which reports the API's version and chain tip. It is service metadata rather than
part of the versioned data API, so it has no v3 counterpart and does not need one.
These /extended/v2 routes are also current and have no v3 successor:
GET /extended/v2/blocks and its siblings, GET /extended/v2/burn-blocks/*,
GET /extended/v2/block-tenures/{tenure_height}/blocks, GET /extended/v2/pox/cycles*,
GET /extended/v2/mempool/fees, GET /extended/v2/smart-contracts/*, and the two
pox-transactions routes noted under Stacking rewards.
Reach out on the #api channel on Discord under the Hiro Developer Tools section.