btcintel
English
nodook
último bloque973.237
mempool46.531 tx
próximo, según el nodo1,01 sat/vB
reajuste491 bloques
cadenamainnet

Documentación

Semantics

Most explorer bugs are not crashes — they are confident answers to questions the backend cannot actually answer yet. This page is the contract that prevents them. It is short; build against it and staleness, misses and races become states you can handle instead of surprises.

Canonical hashes

Every hash — txid, block hash, merkle root — is display byte order, the order Bitcoin Core and every explorer print. URLs using the legacy internal byte order still resolve: they answer 301 Moved Permanently to the canonical form, so old links never break and never fork the URL space.

curl -sI https://api.btcintel.io/v1/tx/<internal-order-hex> | grep -i location
location: /v1/tx/<canonical-hex>

One error envelope

{ "error": { "code": "...", "message": "...", "request_id": "..." } }
HTTPcodeMeaning
400invalid_inputMalformed hash, height, or an address for the wrong network
404not_foundNot in the index and, for transactions, not in the node mempool either
409not_indexed_yetConfirmed on-chain, but above what the index has processed — retry later, it will appear
500 / 503internalOur fault or a backend down. The message says which; quote the request_id when reporting

not_indexed_yet is the deliberate one: while the index trails the node, a confirmed transaction above the index tip is not reported as nonexistent. You get a 409 that says exactly what is known.

Index lag is disclosed, never hidden

X-Btcintel-Index-Height: 323207
X-Btcintel-Node-Height:  965950
  • Data derived from the index (address balances, block lists) is as of the index height. The headers say so on every response; the web UI banners it whenever lag exceeds 2 blocks.
  • Confirmations are always computed against the node tip, never the index tip — a lagging index must not undercount how deep your transaction is buried.
  • /ready answers 503 while lag exceeds 2 blocks, so load balancers and uptime checks share the same honesty.

Caches cannot lie either

Error responses carry Cache-Control: no-store: a 404 or 409 is a statement about now, and it must flip the moment the index catches up. Canonicalization redirects are cacheable for a day (permanent by definition); hash-addressed content is immutable for a week — a reorged-away block still serves its own bytes under its own hash, which remains true forever.

Stale blocks and reorgs

Two miners sometimes find a block at the same height, and the network settles on one: the other goes stale. A stale block is not an orphan, since its parent is known. Asked for by hash, a block off the best chain carries stale.replaced_by, the best chain’s block at its height; a block of the best chain has no stale key. Its transactions count as confirmed only where the best chain has them.

GET /v1/blocks/stale lists the node’s chain tips other than the active one, from Bitcoin Core’s getchaintips. Each tip keeps the node’s own status (valid-fork, valid-headers, headers-only or invalid), its branch length and the active chain’s block at its fork point. The API computes no fork of its own, and a node that does not answer is a 503, never an empty list. GET /v1/blocks/reorgs lists the reorgs the mempool engine saw on bitcoind’s sequence feed since it started (since); with the engine off it answers 501. A fork is an event, not a grade of a pool or of the network. The explorer shows both on Forks and reorgs.

Three bands that never fuse

Every subject page — address, transaction, block — is three bands, and the API’s siblings map onto them one to one. Chain is what the index and the extractors say: facts, the coinbase observation, transaction observations, the template audit. Curated · btcintel is what btcintel claims with its sources: annotations, attributions, exposure and relations, each row with its method, source, fetch, confidence class and level, validity and citation. Community is what others said on Nostr, shown as they signed it and never merged with the bands above. Nothing in one band is computed from another, and a list never mixes them.

Absent is not empty

A sibling that was never computed is absent from the response (no key); one that was computed and found nothing is []. The web draws the first with a dashed frame (“not computed yet”) and the second with a solid one (“computed · none”). classification is absent while the extractor has no raw transaction to read; observation and audit are absent for blocks the engine never saw; attributions: [] means the matcher ran and no catalog matched, and the page then says “no attribution”, never “unknown miner”.

Claims are a set, not a verdict

Labels come from more than one source, and sources may contradict. The API returns each assertion with its source, attribution text, fetch, confidence class and level; it does not collapse them into a score, and the web draws no colour scale. If two sources disagree about an address you see both claims under a “sources disagree” marker. Attributions work the same way: the read policy orders them, disputed is true when the two best rows name different entities, and no winner is stored.

Citations you can verify

btcintel:annotations:9990@v1 sha256:f861bfd04e4f577a

curl -s "https://api.btcintel.io/v1/claims/ann_9990?version=1" | jq -r .content_sha256
# starts with f861bfd04e4f577a: the row is the one the citation names

Every claim row carries btcintel:<table>:<id>@v<version> sha256:<first 16 hex of the content hash>, and the copy action copies exactly that. Versions are immutable: a claim that expires or is retracted keeps every version addressable, with the date and the reason. ?include=expired on a subject page adds the claims that are no longer current, marked as such.