Docs
API reference
157 operations in 11 sections, generated from openapi.yaml (Btcintel native API 0.1.0) on every build. Hashes are canonical display byte order everywhere; every answer carries the index and node heights; errors use one envelope — the rules are on the semantics page. Agents get the same operations as MCP tools: For agents.
Chain and blocks
Status, the tip, blocks by height or hash and their transactions. Facts from btcintel's own index; the node tip rides along for confirmations.
| Operation | What it answers |
|---|---|
GET /v1/status | Chain, node and mempool status · MCP get_status |
GET /v1/blocks | Recent blocks |
GET /v1/blocks/tip/height | Index tip height |
GET /v1/blocks/tip/hash | Index tip hash |
GET /v1/blocks/{id} | Block by height or canonical hash · MCP get_block |
GET /v1/blocks/{id}/txs | Txids of a block |
GET /v1/blocks/{id}/status | Block chain-status |
Transactions
A transaction with resolved inputs and outputs, its confirmation status and the spend status of its outputs.
| Operation | What it answers |
|---|---|
GET /v1/tx/{txid} | Transaction by canonical txid · MCP get_tx |
GET /v1/tx/{txid}/status | Confirmation status |
GET /v1/tx/{txid}/outspends | Spend status of every output |
GET /v1/tx/{txid}/outspend/{vout} | Spend status of one output |
Addresses and scripts
Address summaries keyed by the rendered address, history, unspent outputs, and the same summary by script hash.
| Operation | What it answers |
|---|---|
GET /v1/address/{address} | Address summary · MCP get_address |
GET /v1/address/{address}/txs | Address history (newest first) |
GET /v1/address/{address}/utxos | Unspent outputs |
GET /v1/scripthash/{hash} | Lookup by script hash |
Mempool and fees
The node's mempool as btcintel mirrors it, the projected next blocks, replacements and fee estimates — projection and node figures kept apart.
| Operation | What it answers |
|---|---|
GET /v1/mempool | Recent mempool transactions |
GET /v1/mempool/txids | Txids of the mempool sample |
GET /v1/mempool/stats | Whole-mempool statistics |
GET /v1/mempool/projected | Projected blocks (mempool engine, ADR-0003) |
GET /v1/mempool/replacements | Recent RBF replacements (mempool engine, ADR-0003) |
GET /v1/fees/estimates | Fee recommendations (mempool engine, ADR-0003) |
Intel: claims, entities, sources
The Curated band: claims with their provenance and citation, entities and relations, sources, the change feed and the vocabularies. Absent is not empty.
| Operation | What it answers |
|---|---|
GET /v1/address/{address}/annotations | Claims on an address |
GET /v1/entities | Entities (cursor or offset page) |
GET /v1/entities/{id} | Entity with identifiers, aliases, relations, events and subjects |
GET /v1/sources | Sources with licence, attribution and last fetch · MCP list_sources |
GET /v1/annotations | Search current claims (cursor page, newest first) · MCP search_annotations |
POST /v1/annotations/lookup | Bulk lookup of claims by subject · MCP lookup_subjects |
GET /v1/claims/{claim_id} | One claim by id, current version or a given one · MCP get_claim |
GET /v1/claims/{claim_id}.stix | One claim as a STIX 2.1 bundle |
GET /v1/claims/{claim_id}/versions | Every recorded version of a claim |
GET /v1/claims/{claim_id}/members.csv | The members of a campaign as CSV |
GET /v1/claims/{claim_id}/members | The members of a campaign, a page of claims · MCP list_campaign_members |
GET /v1/claims/{claim_id}/disputes | The public dispute record of a claim |
POST /v1/claims/{claim_id}/disputes | Dispute a Curated claim · MCP dispute_claim |
GET /v1/sanctions/facts/{address} | Sanction listings of an address, with the fetch they are as of |
GET /v1/changes | Append-only feed of claim changes (cursor) |
GET /v1/taxonomy/concepts | The vocabulary (DW-VA, btcintel extensions, confidence classes, event and relation kinds) |
GET /v1/blocks/{id}/attribution | Attributions of a block (no stored winner) |
GET /v1/blocks/{id}/audit | Template diff of a block (evidence, never a verdict) |
GET /v1/tx/{txid}/classification | Structural observations of a transaction (tx-obs-v1) |
GET /v1/subjects/{subject_kind}/{subject_key} | The Curated siblings of a subject, without the chain facts · MCP get_annotations |
GET /v1/community/labelers | The public labeler directory (Community) · MCP list_labelers |
GET /v1/community/recent | The Community firehose — recent notes across subjects |
GET /v1/community/events/{id} | One Community event with its thread · MCP get_community_event |
GET /v1/community/{subject_kind}/{subject_key} | Community notes about one subject — comments and labels, with a lens · MCP get_community |
POST /v1/community/publish | Publish a signed Community event through the API · MCP publish_community_event |
POST /v1/community/delete | Delete own Community events through the API (NIP-09) · MCP delete_community_event |
POST /v1/annotations/propose | Propose a Curated claim (t2 agents, t3 humans; a human reviews it) · MCP propose_annotation |
Keys and quotas
Minting an anonymous token, reading your own key, and the ops routes that issue and revoke keys.
| Operation | What it answers |
|---|---|
POST /v1/keys/anon | Mint an anonymous t1 token (shown once) |
POST /v1/keys/agent | An agent issues its own t2 key, bound to the key that signs the request |
POST /v1/keys | Issue a btci_ key (ops) |
DELETE /v1/keys/{id} | Revoke a key (ops) |
GET /v1/keys/me | The calling key's tier, quota and usage today · MCP get_auth_identity |
Accounts and organisations
The t4 band (S5.5): sign-up and sign-in by password, link or passkey, the second factor and the step-up, the account's own data, organisations with members, invitations and API keys. Never an MCP tool; 501 not_configured while accounts are off.
| Operation | What it answers |
|---|---|
POST /v1/auth/signup | Create an account with an e-mail address and a password |
POST /v1/auth/verify | Finish a sign-up with the link's token |
POST /v1/auth/password | Sign in with an e-mail address and a password |
PUT /v1/auth/password | Set a new password |
POST /v1/auth/link | Ask for a one-time sign-in link |
POST /v1/auth/link/verify | Sign in with the link's token |
POST /v1/auth/reset | Ask for a password-reset link |
POST /v1/auth/reset/verify | Open the reset link's session |
PATCH /v1/auth/account | Change the display name or the e-mail address |
DELETE /v1/auth/account | Close the account |
POST /v1/auth/email/verify | Confirm a new e-mail address with the link's token |
GET /v1/auth/export | The account's data as one JSON document |
POST /v1/auth/totp/enrol | Start enrolling an authenticator app |
POST /v1/auth/totp/verify | Confirm the app with its current code |
POST /v1/auth/totp/disable | Remove the authenticator app |
POST /v1/auth/recovery-codes | Regenerate the recovery codes |
POST /v1/auth/step-up | Lift this session to aal 2 for ten minutes |
GET /v1/orgs | The caller's organisations |
POST /v1/orgs | Create an organisation |
POST /v1/orgs/invites/accept | Join an organisation with an invitation's token |
GET /v1/orgs/{id} | An organisation and its members |
PATCH /v1/orgs/{id}/members/{account_id} | Change a member's role |
DELETE /v1/orgs/{id}/members/{account_id} | Remove a member, or leave |
GET /v1/orgs/{id}/invites | The open invitations |
POST /v1/orgs/{id}/invites | Invite an address |
GET /v1/orgs/{id}/audit | The organisation's audit rows |
GET /v1/orgs/{id}/keys | The organisation's keys |
POST /v1/orgs/{id}/keys | Issue a key owned by the organisation |
DELETE /v1/orgs/{id}/keys/{key_id} | Revoke a key of the organisation |
GET /v1/auth/keys | The account's keys |
POST /v1/auth/keys | Issue a key owned by the account |
DELETE /v1/auth/keys/{key_id} | Revoke a key of the account |
GET /v1/auth/webauthn | The account's passkeys |
POST /v1/auth/webauthn/register/begin | Start registering a passkey |
POST /v1/auth/webauthn/register/finish | Finish registering a passkey |
POST /v1/auth/webauthn/authenticate/begin | Start a passkey sign-in or step-up |
POST /v1/auth/webauthn/authenticate/finish | Finish a passkey sign-in or step-up |
DELETE /v1/auth/webauthn/{id} | Remove a passkey |
Feedback
Tell us what is wrong or missing, and the triage queue ops read.
| Operation | What it answers |
|---|---|
GET /v1/ops/feedback | The feedback queue (ops), newest first |
PATCH /v1/ops/feedback/{id} | Triage one entry (ops) |
DELETE /v1/ops/feedback/{id} | Delete one entry on the requester's word (ops) |
POST /v1/feedback | Send feedback (the web sheet, agents, automatic failure reports) · MCP send_feedback |
Community
What people say on Nostr about addresses, transactions and blocks: NIP-22 comments and NIP-32 labels indexed from our relay and the public relays, never endorsed by btcintel. The lens (labelers=) picks whose labels you see; zaps are a community signal, not an endorsement; the relay itself answers at GET /relay.
| Operation | What it answers |
|---|---|
GET /relay | The embedded Nostr relay (WebSocket) and its NIP-11 document |
Ops
Operator routes: imports, operators, drafts and their approval, retractions, the audit log. Every call needs an operator credential and is audited.
| Operation | What it answers |
|---|---|
GET /v1/ops/operators | Operators (ops) |
POST /v1/ops/operators | Create or replace an operator (human admin) |
PATCH /v1/ops/operators/{id} | Change roles, budget or the kill switch (human admin) |
GET /v1/ops/drafts | Drafts awaiting or past decision (ops) |
POST /v1/ops/drafts | Propose a claim, entity, relation or event (ops; the gate of P42) |
GET /v1/ops/drafts.csv | The drafts to sample for a batch, as CSV (human curator or admin) |
GET /v1/ops/operators/{id}/record | An operator's drafts per source over a window (human curator or admin) |
POST /v1/ops/drafts/batch | Approve a batch of drafts after reviewing a sample (human curator or admin) |
POST /v1/ops/drafts/{id}/approve | Approve a draft (human curator or admin, never its proposer) |
POST /v1/ops/drafts/{id}/reject | Reject a draft with a reason (human curator or admin) |
POST /v1/ops/claims/{claim_id}/retract | Retract a claim with a reason (human curator or admin) |
POST /v1/ops/campaigns/{claim_id}/promote | Promote a source's provisional members of a campaign (human curator or admin) |
POST /v1/ops/claims/{claim_id}/release | Release one campaign member that waits for a review (human curator or admin) |
POST /v1/ops/claims/{claim_id}/reject | Reject one campaign member that waits for a review (human curator or admin) |
GET /v1/ops/disputes | The dispute queue (ops) |
POST /v1/ops/disputes/{id}/resolve | Resolve a dispute (human curator or admin) |
GET /v1/ops/audit | The audit log (ops), paginated by id |
GET /v1/ops/relay/policy | The relay's write policy (ops) |
PATCH /v1/ops/relay/policy | Change the relay's write policy (ops, human admin) |
GET /v1/ops/community/moderation | The moderation trail (ops), newest first |
POST /v1/ops/community/moderation | Hide or unhide an event, ban or unban a pubkey (ops, human admin or moderator) |
GET /v1/ops/community/labelers | The labeler directory, listed or not (ops) |
POST /v1/ops/community/labelers | Add a labeler to the directory (ops, human admin or curator) |
PATCH /v1/ops/community/labelers/{pubkey} | Change a labeler's directory entry (ops, human admin or curator) |
POST /v1/sources/{id}/import | Push a source file through its parser (ops) |
GET /v1/ops/imports/{id} | One import run (ops) |
Discovery and health
The MCP endpoint, the discovery descriptor, llms.txt, the contract itself, and the probes.
| Operation | What it answers |
|---|---|
GET /health | Liveness probe |
GET /ready | Readiness probe |
GET /metrics | Prometheus metrics |
GET /v1/export/stix | STIX 2.1 bundle of one subject, one entity, one source or one campaign |
GET /v1/export/tagpack | TagPack (GraphSense YAML) of one source or one campaign |
GET /v1/campaigns/{claim_id} | One campaign, with its members counted by role and state · MCP get_campaign |
GET /v1/watch | The caller's watchlist · MCP list_watched |
GET /v1/watch/changes | The change feed of the watched subjects · MCP get_watch_changes |
PUT /v1/watch/{kind}/{key} | Watch a subject · MCP watch_subject |
DELETE /v1/watch/{kind}/{key} | Stop watching a subject · MCP unwatch_subject |
POST /v1/auth/nip98 | Sign in with a NIP-98 event and open a T3 session |
GET /v1/auth/nonce | A nonce that binds the next NIP-98 login to this browser |
GET /v1/auth/me | The signed-in key or account, its tier, quota and live sessions |
POST /v1/auth/logout | Revoke the current session and clear the cookie |
DELETE /v1/auth/sessions/{id} | Revoke one of the caller's sessions |
GET /v1/auth/backup | Download the NIP-49 backup |
PUT /v1/auth/backup | Store the NIP-49 backup of the signed-in key |
DELETE /v1/auth/backup | Delete the NIP-49 backup (NIP-98 only) |
GET /v1/auth/oauth/{provider}/start | Start a sign-in with a provider |
GET /v1/auth/oauth/{provider}/callback | The provider's return |
POST /v1/auth/oauth/{provider}/callback | The provider's return as a form POST (Apple) |
POST /v1/auth/oauth/confirm | Link a provider to the account with the same verified address |
POST /v1/auth/npub/custodied | Create a custodied signing key for the account |
POST /v1/auth/npub/challenge | A challenge to prove an own key before linking it |
POST /v1/auth/npub/link | Link the person's own key to the account |
DELETE /v1/auth/npub/{pubkey} | Unlink the account's key |
POST /v1/auth/npub/sign | Sign an event with the account's custodied key |
POST /v1/auth/npub/export | Export the custodied key as an nsec |
POST /v1/auth/npub/bunker | A bunker link to use the custodied key in another app |
GET /v1/auth/npub/clients | The apps connected to the custodied key |
DELETE /v1/auth/npub/clients/{client_pubkey} | Disconnect an app from the custodied key |
POST /mcp | MCP Streamable HTTP endpoint (JSON-RPC 2.0) |
GET /.well-known/btcintel.json | Discovery descriptor for agents |
GET /.well-known/mcp/server.json | The MCP Registry entry (server.json) |
GET /llms.txt | llms.txt (mirror of the web's) |
Worked example
# Address summary with annotations
curl -s https://api.btcintel.io/v1/address/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa \
| jq '{balance_sat, tx_count, keyed_by, annotations: [.annotations[]? | {label, citation, source: .source.id}]}'
# HEAD is 200 on every GET /v1 route
curl -sI -X HEAD https://api.btcintel.io/v1/status | head -n 1
# Page through its history
curl -s "https://api.btcintel.io/v1/address/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa/txs?limit=50&offset=50" \
| jq 'length'Caching
Answers declare Cache-Control matched to how fast the data can change: curated intel carries max-age=60, stale-while-revalidate=300; content addressed by hash (a block by its hash, its txid list) is immutable for a week; tip-coupled data lives seconds. Errors are always no-store — today’s 404 flips to 200 the moment the index catches up, and no cache may remember otherwise. Chain-read routes ship their cache headers with the Phase 1 cut-over of the chain index; until then they simply omit the header.