BTCintel
nodeok
mempool68,600 tx
node next1.08 sat/vB
retarget40 blocks
chainmainnet

Docs

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.

Generated from openapi.yaml (Btcintel native API 0.1.0). Every hash is canonical display order; every answer carries the index and node heights; errors use one envelope — see Semantics.

GET /v1/address/{address}/annotations

Claims on an address

Parameters

NameInTypeDescription
address requiredpathstringMainnet address; other networks answer 400 with an explanation.
includequerystringComma-separated: expired adds expired and retracted claims; provisional adds the provisional claims a human has not promoted yet (S1.11 FR-11).
confidence_classquerystring · max length 100Only claims of this confidence class (e.g. authority_data; the confidence: prefix is optional). Levels are never combined (P6).
source_kindquerystring · max length 100Only claims from sources of this kind (sanctions, crime-intel, osint-report, …).

Response 200

Claims (may be empty).

schema
  • subject Subject
    • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
    • key string — Canonical key (CC-3).
  • items array of Claim
  • relations array of Relation — Relations of the entities the claims name; about entities, never the address (P17).
    • claim_id string
    • kind string required · one of "relation"
    • about string · one of "entity"
    • version integer
    • content_sha256 string
    • citation string
    • from_entity object
      • id string
      • name string
      • kind string — entity:… concept.
    • to_entity object
      • id string
      • name string
      • kind string — entity:… concept.
    • type string — relation:… concept.
    • source object
    • fetch object
    • confidence object
    • validity object
    • evidence array of object

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/address/bc1qz654h5qcqzalv6ltpxsk4ksdcc3e20wkedqntgnarv3a0t2e2p7scr48pl/annotations | jq

GET /v1/entities

Entities (cursor or offset page)

Actors, services, families and pools the Curated band names. Never a score; counts are how many claims name each entity, and a count orders the list without ranking it (spec S2.4). The default is the id order with a keyset cursor; any other order pages by offset.

Parameters

NameInTypeDescription
kindquerystringConcept id, e.g. entity:pool.
qquerystringMatches id, name or alias.
nonemptyquerystring · one of "1", "true", "0", "false"Only entities a current claim, attribution, relation or event names.
abusequerystring · one of "any"any: only entities a current claim names with an abuse category.
sortquerystring · one of "id", "annotations", "attributions", "relations", "events" · default "id"The id, or how many current claims (annotations), attributions, relations or events name the entity.
orderquerystring · one of "asc", "desc"Ascending by default for the id, descending for a count; ties fall back to the id ascending.
limitqueryinteger · ≤ 200 · default 50—
offsetqueryinteger · ≥ 0 · ≤ 100000 · default 0—
cursorquerystringKeyset cursor of the id order ascending; with another order or an offset it is a 400.

Response 200

Entity summaries.

schema
  • items array of EntitySummary required
    • id string
    • name string
    • kind string
    • status string · one of "active", "defunct", "seized", "rebranded", "unknown"
    • description string
    • jurisdictions array of string
    • aliases array of string
    • identifiers array of object
      • scheme string
      • value string
      • url string | null
      • source_id string
    • counts object
      • annotations integer
      • attributions integer
      • relations integer
      • events integer
    • abuse array of object — What the current claims naming the entity say it is involved in, per abuse category, most claims first: how many claims and from how many sources. Side by side and unweighted, never a score (P1); empty when no current claim names an abuse category.
      • abuse string required — abuse:… concept.
      • claims integer required
      • sources integer required
  • next_cursor string | null required — Set only in the id order ascending.
  • total integer required — Every entity the filters match.

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/entities | jq '{next_cursor, total}'

GET /v1/entities/{id}

Entity with identifiers, aliases, relations, events and subjects

Parameters

NameInTypeDescription
id requiredpathstring—

Response 200

The entity. Relations are about entities, never about a subject (P17).

schema

EntityDetail

Errors

  • 404 — Unknown to the index and, for transactions, to the node mempool.

Example

curl -s https://api.btcintel.io/v1/entities/storm-1567 | jq

GET /v1/sources

Sources with licence, attribution and last fetch

MCP tool
list_sources — see For agents

Response 200

Every registered source (no sign-off names).

schema
array of Source
  • id string
  • name string
  • kind string
  • url string | null
  • license string | null
  • license_url string | null
  • attribution string | null — Text rendered with every claim of the source (P38).
  • redistributable boolean
  • personal_data boolean
  • reliability_prior integer
  • default_confidence string
  • cadence string | null
  • active boolean
  • community_proposals boolean — Spec S5.1 FR-10: proposals from t2/t3 may name this source.
  • last_fetch object
    • id integer
    • fetched_at string (date-time)
    • sha256 string
    • record_count integer | null
    • size_bytes integer

Example

curl -s https://api.btcintel.io/v1/sources | jq

GET /v1/annotations

Search current claims (cursor page, newest first)

MCP tool
search_annotations — see For agents

Parameters

NameInTypeDescription
qquerystringMatches subject key or label.
categoryquerystringConcept id (entity:… or abuse:…); legacy words sanctions, ransomware, exchange, privacy are mapped.
sourcequerystring—
entityquerystring—
subject_kindquerystring · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"—
limitqueryinteger · ≤ 200 · default 50—
cursorquerystring—
includequerystring · one of "provisional"provisional adds the provisional claims a human has not promoted yet (S1.11 FR-11).
confidence_classquerystring · max length 100Only claims of this confidence class (e.g. authority_data; the confidence: prefix is optional). Levels are never combined (P6).
source_kindquerystring · max length 100Only claims from sources of this kind (sanctions, crime-intel, osint-report, …).

Response 200

Claims.

schema
  • items array of Claim
  • next_cursor string | null

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/annotations | jq

POST /v1/annotations/lookup

Bulk lookup of claims by subject

Up to 20 subjects per call at tier T0 (CC-8); keys are canonicalised and duplicates collapsed. A subject with nothing found is listed in not_found.

MCP tool
lookup_subjects — see For agents

Request body

schema
  • subjects array of object required
    • kind string required
    • key string required
  • include array of string — What to return: annotations (the default), attributions, and provisional to add the provisional claims a human has not promoted yet (S1.11 FR-11).
  • confidence_class string — Only claims of this confidence class (e.g. authority_data; the confidence: prefix is optional). Levels are never combined. · max length 100
  • source_kind string — Only claims from sources of this kind (sanctions, crime-intel, osint-report, …). · max length 100

Response 200

Results per subject.

schema
  • results array of object
    • subject Subject
      • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
      • key string — Canonical key (CC-3).
    • annotations array of Claim
    • attributions array of Attribution
      • claim_id string
      • kind string required · one of "attribution"
      • version integer
      • content_sha256 string
      • citation string
      • subject Subject
        • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
        • key string — Canonical key (CC-3).
      • entity object
        • id string
        • name string
      • method string · one of "coinbase_tag", "coinbase_address", "coinbase_script", "prev_template", "manual"
      • signature_id integer
      • matcher_version string
      • source object
        • id string
        • name string
      • fetch object
      • confidence object
        • class string
        • level integer
      • validity object
      • evidence object
      • created_at string (date-time)
    • disputed boolean
  • not_found array of object
    • kind string
    • key string
    • reason string

Errors

  • 400 — Malformed input (invalid_input).
  • 413 — Over the subject limit (too_large).

Example

curl -s -X POST https://api.btcintel.io/v1/annotations/lookup \
  -H 'Content-Type: application/json' \
  -d '{"subjects":[{"kind":"address","key":"bc1qz654h5qcqzalv6ltpxsk4ksdcc3e20wkedqntgnarv3a0t2e2p7scr48pl"}],"include":["annotations"]}' | jq

GET /v1/claims/{claim_id}

One claim by id, current version or a given one

ann_<n>, att_<n>, rel_<n> or evt_<n>. The version in force carries the full content; a superseded version is addressable by its hash and citation, its content is not retained. An annotation carries its status (S1.11): a provisional one is served with it and Cache-Control: no-store; a held or rejected one is a 404 except to an operator.

MCP tool
get_claim — see For agents

Parameters

NameInTypeDescription
claim_id requiredpathstring—
versionqueryinteger · ≥ 1—

Response 200

The claim object (CC-4) with citation and content hash; ETag = content hash.

Headers: ETag

schema
  • Claim — An annotation (CC-4): what a named source says about a subject, with citation. Never a score. Its fetch is the fetch that first stated the claim's current content, the one content_sha256 covers (CC-5, P74); a later fetch that restates it moves last_seen, never the version.
  • Attribution — Who built a block's template according to one method and one source; several per block, no stored winner (P7).
    • claim_id string
    • kind string required · one of "attribution"
    • version integer
    • content_sha256 string
    • citation string
    • subject Subject
      • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
      • key string — Canonical key (CC-3).
    • entity object
      • id string
      • name string
    • method string · one of "coinbase_tag", "coinbase_address", "coinbase_script", "prev_template", "manual"
    • signature_id integer
    • matcher_version string
    • source object
      • id string
      • name string
    • fetch object
    • confidence object
      • class string
      • level integer
    • validity object
    • evidence object
    • created_at string (date-time)
  • Relation — A relation between two entities as one source states it; about entities, never about an address (P17).
    • claim_id string
    • kind string required · one of "relation"
    • about string · one of "entity"
    • version integer
    • content_sha256 string
    • citation string
    • from_entity object
      • id string
      • name string
      • kind string — entity:… concept.
    • to_entity object
      • id string
      • name string
      • kind string — entity:… concept.
    • type string — relation:… concept.
    • source object
    • fetch object
    • confidence object
    • validity object
    • evidence array of object
  • Event — A dated claim that cites other claims.
    • claim_id string
    • kind string required · one of "event"
    • version integer
    • content_sha256 string
    • citation string
    • event_kind string
    • occurred_at string (date)
    • occurred_precision string · one of "day", "month", "year"
    • title string
    • summary string
    • source object
    • fetch object
    • cites array of object
    • refs array of object
    • subjects array of object — The first 100 subjects the event links (the matcher's links), in kind and key order.
    • subjects_total integer — How many subjects the event links in all.
    • entities array of object
    • members CampaignMemberCounts — The event's members (S1.11 FR-3): count is the current ones, by_role how many hold each role in each state, delisted and retracted members left out. Counts, never the list: the members page through /v1/claims/{claim_id}/members. An event with no members answers count 0 and an empty by_role.
      • count integer required
      • by_role object required
    • retracted_at string | null (date-time)
    • created_at string (date-time)
  • SupersededVersion — A version that is no longer in force; addressable by hash, content not retained.
    • claim_id string
    • kind string required · one of "superseded"
    • claim_kind string · one of "annotation", "attribution", "relation", "event"
    • version integer
    • content_sha256 string
    • citation string
    • actor string
    • created_at string (date-time)
    • superseded_by integer
    • content_retained boolean · one of false

Errors

  • 400 — Malformed input (invalid_input).
  • 404 — Unknown to the index and, for transactions, to the node mempool.

Example

curl -s https://api.btcintel.io/v1/claims/ann_33932 | jq

GET /v1/claims/{claim_id}.stix

One claim as a STIX 2.1 bundle

Spec S6.1 FR-1 (ADR-0004 §Export). The claim's objects with their observable, entity and source; deterministic ids; x_btcintel_bundle_sha256 over the canonical objects. Attributions are not exported (404); neither is an annotation that is not current (404: provisional, held or rejected, S1.11); a claim from a non-redistributable source answers 403 (P38).

Parameters

NameInTypeDescription
claim_id requiredpathstring—

Response 200

The bundle.

schema
  • type string required · one of "bundle"
  • id string required
  • objects array of object required
    • type string required
    • id string required
    • any other property allowed
  • x_btcintel_bundle_sha256 string required — SHA-256 of the RFC 8785 serialisation of objects.
  • x_btcintel_omitted_sources array of string
  • x_btcintel_next_cursor string

Errors

  • 400 — Malformed input (invalid_input).
  • 403 — The operator lacks the role or kind the action needs, or is switched off (forbidden).
  • 404 — Unknown to the index and, for transactions, to the node mempool.

Example

curl -s https://api.btcintel.io/v1/claims/ann_33932.stix | jq '{type, id, x_btcintel_bundle_sha256}'

GET /v1/claims/{claim_id}/versions

Every recorded version of a claim

Parameters

NameInTypeDescription
claim_id requiredpathstring—

Response 200

Versions, oldest first.

schema
  • claim_id string
  • items array of ClaimVersion
    • version integer
    • content_sha256 string
    • actor string
    • created_at string (date-time)
    • citation string

Errors

  • 400 — Malformed input (invalid_input).
  • 404 — Unknown to the index and, for transactions, to the node mempool.

Example

curl -s https://api.btcintel.io/v1/claims/ann_33932/versions | jq

GET /v1/claims/{claim_id}/members.csv

The members of a campaign as CSV

Spec S1.11 FR-4 (P73). The members read as a CSV file, with the members route's filters and access (held and rejected for operators only), one row per member with its role and its status, in id order. An empty cell is an absent field. A cell that a spreadsheet would read as a formula starts with an apostrophe. At most 10,000 rows a file: X-Next-Cursor continues it.

Parameters

NameInTypeDescription
claim_id requiredpathstringAn event id, evt_<n>.
rolequerystring · one of "victim", "sweep", "vault", "cash_out"—
statusquerystring · one of "current", "provisional", "held", "rejected"One state; not with include=provisional.
includequerystring · one of "provisional"provisional adds the provisional members to the current ones.
confidence_classquerystring · max length 100Only claims of this confidence class (e.g. authority_data; the confidence: prefix is optional). Levels are never combined (P6).
source_kindquerystring · max length 100Only claims from sources of this kind (sanctions, crime-intel, osint-report, …).
limitqueryinteger · ≥ 1 · ≤ 10000 · default 10000—
cursorquerystring—

Response 200

The CSV file, a header row first: claim_id, citation, campaign, role, status, status_reason, subject_kind, subject, label, abuse, category, entity_id, confidence_class, source_id, source_kind, valid_from, first_reported_at, chain_check, chain_checked_at.

Headers: X-Next-Cursor

schema

string

Errors

  • 400 — Malformed input (invalid_input).
  • 403 — The operator lacks the role or kind the action needs, or is switched off (forbidden).
  • 404 — Unknown to the index and, for transactions, to the node mempool.

Example

curl -s https://api.btcintel.io/v1/claims/ann_33932/members.csv | jq

GET /v1/claims/{claim_id}/members

The members of a campaign, a page of claims

Spec S1.11 FR-3 and FR-11 (P73). The members of an event (evt_<n>): annotations that name it, each a full claim with campaign, in id order, at most 500 a page. Current members by default; include=provisional adds the provisional ones a human has not promoted yet; status picks one state instead, held and rejected for operators only (403 otherwise). Delisted and retracted members are left out. campaign.members carries the counts by role and state.

MCP tool
list_campaign_members — see For agents

Parameters

NameInTypeDescription
claim_id requiredpathstringAn event id, evt_<n>.
rolequerystring · one of "victim", "sweep", "vault", "cash_out"—
statusquerystring · one of "current", "provisional", "held", "rejected"One state; not with include=provisional.
includequerystring · one of "provisional"provisional adds the provisional members to the current ones.
confidence_classquerystring · max length 100Only claims of this confidence class (e.g. authority_data; the confidence: prefix is optional). Levels are never combined (P6).
source_kindquerystring · max length 100Only claims from sources of this kind (sanctions, crime-intel, osint-report, …).
limitqueryinteger · ≥ 1 · ≤ 500 · default 100—
cursorquerystring—

Response 200

A page of members (may be empty).

schema
  • campaign object required
    • id string
    • title string
    • event_kind string
    • members CampaignMemberCounts — The event's members (S1.11 FR-3): count is the current ones, by_role how many hold each role in each state, delisted and retracted members left out. Counts, never the list: the members page through /v1/claims/{claim_id}/members. An event with no members answers count 0 and an empty by_role.
      • count integer required
      • by_role object required
  • items array of Claim required
  • next_cursor string | null required

Errors

  • 400 — Malformed input (invalid_input).
  • 403 — The operator lacks the role or kind the action needs, or is switched off (forbidden).
  • 404 — Unknown to the index and, for transactions, to the node mempool.

Example

curl -s https://api.btcintel.io/v1/claims/ann_33932/members | jq

GET /v1/claims/{claim_id}/disputes

The public dispute record of a claim

Spec S5.3 FR-3 (P8). Every dispute on the claim, newest first: reason, status, outcome, the resolver's note, the version disputed — never the opener's identity; the opener's text, evidence and the Community note they cited (event_id, which names its author) only when they chose public. counts is what the claim object carries as disputes.

Parameters

NameInTypeDescription
claim_id requiredpathstringann_<n>, att_<n>, rel_<n> or evt_<n>.

Response 200

The record.

schema
  • claim_id string required
  • counts DisputeCounts required
    • open integer required
    • resolved integer required
  • items array of PublicDispute required
    • id integer required
    • opened_at string (date-time) required
    • reason string required · one of "wrong_subject", "wrong_entity", "outdated", "source_misread", "other"
    • status string required · one of "open", "resolved", "withdrawn"
    • claim_version integer
    • outcome string | null · one of "upheld", "rejected", "partially_upheld", null
    • resolved_at string | null (date-time)
    • note string | null — The resolver's public note.
    • text string — Only when the opener chose public.
    • evidence array of object
    • event_id string

Errors

  • 400 — Malformed input (invalid_input).
  • 404 — Unknown to the index and, for transactions, to the node mempool.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s https://api.btcintel.io/v1/claims/ann_33932/disputes | jq

POST /v1/claims/{claim_id}/disputes

Dispute a Curated claim

Spec S5.3 FR-1 (P8, P43). Any caller above t0 — a minted btci_anon_ token, a btci_ key, or a signed-in npub — opens a dispute with a reason, a text (≤ 4,096) and up to ten evidence entries; event_id may cite the Community note that carries the dispute (P8: the note is the citable form; this call is how it reaches the Curated side); public: true shows the text and evidence in the public record (the identity never appears). One open dispute per caller and claim (409); quota disputes_per_day per caller (t1 2, t2/t3 10, t4 20). A human operator resolves it; the outcome is published next to the claim. The brand signs nothing.

MCP tool
dispute_claim — see For agents
Auth
An operator credential as the bearer; every call is audited.

Parameters

NameInTypeDescription
claim_id requiredpathstringann_<n>, att_<n>, rel_<n> or evt_<n>.

Request body

schema
  • reason string required · one of "wrong_subject", "wrong_entity", "outdated", "source_misread", "other"
  • text string required · max length 4096
  • evidence array of object
    • kind string required · one of "url", "nostr_event", "txid", "text"
    • value string required · max length 2048
    • note string · max length 2048
  • public boolean — Show the text and evidence in the public record (the identity never appears).
  • event_id string — The Community note (64 hex or note1…) that carries the dispute; it must be held by this relay.

Response 201

Opened.

schema
  • id integer required
  • claim_id string required
  • claim_version integer
  • status string required · one of "open"
  • reason string required
  • opened_at string (date-time) required
  • public boolean
  • note string

Errors

  • 400 — Malformed input (invalid_input).
  • 401 — Missing or invalid bearer (unauthorized).
  • 403 — The operator lacks the role or kind the action needs, or is switched off (forbidden).
  • 404 — Unknown to the index and, for transactions, to the node mempool.
  • 409 — The state refuses the change (conflict): an open dispute by this caller exists already, or the dispute or claim is not open any more.
  • 422 — The NIP-98 event was refused (nip98_invalid): wrong URL or method, stale, bad signature, wrong payload hash, or used before; the message names the reason.
  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s -X POST https://api.btcintel.io/v1/claims/ann_33932/disputes \
  -H 'Authorization: Bearer $BTCI_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"reason":"wrong_subject","text":"…"}' | jq

An operator credential: the ops bearer or a btci_ key with the ops:agent scope.

GET /v1/sanctions/facts/{address}

Sanction listings of an address, with the fetch they are as of

Every abuse:sanction claim ever recorded for the address, current or expired (validity tells which). A valid, unlisted address is a computed answer: 200 with empty listings.

Parameters

NameInTypeDescription
address requiredpathstringMainnet address; other networks answer 400 with an explanation.

Response 200

Listings and the latest fetch per sanctions source.

schema
  • subject Subject
    • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
    • key string — Canonical key (CC-3).
  • listings array of Claim
  • as_of object
    • fetch object

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/sanctions/facts/bc1qz654h5qcqzalv6ltpxsk4ksdcc3e20wkedqntgnarv3a0t2e2p7scr48pl | jq

GET /v1/changes

Append-only feed of claim changes (cursor)

Rows in seq order; store next_cursor and pass it as since to never miss a row. Without since, the last 100.

Parameters

NameInTypeDescription
sincequeryinteger · ≥ 0—
limitqueryinteger · ≤ 1000 · default 100—
subjectquerystringkind:key, e.g. address:bc1q…

Response 200

Changes.

schema
  • items array of Change
    • seq integer
    • at string (date-time)
    • claim_id string
    • kind string · one of "annotation", "attribution", "relation", "event"
    • action string · one of "created", "updated", "expired", "retracted"
    • subject Subject
      • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
      • key string — Canonical key (CC-3).
  • next_cursor integer

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/changes | jq

GET /v1/taxonomy/concepts

The vocabulary (DW-VA, btcintel extensions, confidence classes, event and relation kinds)

Parameters

NameInTypeDescription
schemequerystring · one of "dwva-entity", "dwva-abuse", "btcintel", "confidence", "event-kind", "relation-type"—

Response 200

Concepts.

schema
  • items array of Concept
    • id string — Qualified id, e.g. abuse:sanction.
    • scheme string
    • concept string
    • label string
    • description string | null
    • uri string | null
    • parent string | null
    • level integer
    • stix_map object
    • origin string

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/taxonomy/concepts | jq

GET /v1/blocks/{id}/attribution

Attributions of a block (no stored winner)

Every attribution the matcher recorded for the block (S1.7), in the order of read policy policy_version (method rank prev_template < coinbase_address < coinbase_tag < coinbase_script < manual, then confidence level, then source prior); disputed when the two best name different entities; pool is the first row, an answer and never a verdict (P7); observation is the coinbase extraction once it ran. Absent keys mean not computed yet (CC-6): observation and pool are absent before the extractor and matcher ran, the list is empty when they ran and no catalog matched.

Parameters

NameInTypeDescription
id requiredpathstringHeight (decimal) or canonical block hash (64 hex).

Response 200

Attributions in policy order.

schema
  • attributions array of Attribution required
    • claim_id string
    • kind string required · one of "attribution"
    • version integer
    • content_sha256 string
    • citation string
    • subject Subject
      • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
      • key string — Canonical key (CC-3).
    • entity object
      • id string
      • name string
    • method string · one of "coinbase_tag", "coinbase_address", "coinbase_script", "prev_template", "manual"
    • signature_id integer
    • matcher_version string
    • source object
      • id string
      • name string
    • fetch object
    • confidence object
      • class string
      • level integer
    • validity object
    • evidence object
    • created_at string (date-time)
  • disputed boolean required
  • pool Pool — The first attribution of the read policy; present only when the block has one. An answer with its method, never a stored winner (P7).
    • entity object required
      • id string
      • name string
    • method string required · one of "prev_template", "coinbase_address", "coinbase_tag", "coinbase_script", "manual"
    • disputed boolean required
  • observation Observation — derived.coinbase_observations — a pure function of the block by extractor coinbase-v1, no author (ADR-0004 Chain band).
    • block_hash string — Canonical display byte order.
    • height integer — The height the block claims; orphans keep their row.
    • coinbase_txid string — Canonical display byte order.
    • tag_text string — Printable ASCII runs of the coinbase scriptSig (after the BIP34 height push) joined by one space; empty is a fact.
    • tag_runs array of string
    • script_sig_hex string
    • output_scripts array of object
      • n integer
      • script_hash string — sha256 of the scriptPubKey, hex.
      • address string | null — Rendered address; null for OP_RETURN, P2PK and non-standard scripts.
      • value_sat integer
    • reward_sat integer
    • fees_sat integer — reward minus the subsidy at the claimed height; clamped at zero.
    • extractor string · one of "coinbase-v1"
    • extracted_at string (date-time)
  • policy_version string required · one of "v1"

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/blocks/968212/attribution | jq '{disputed, policy_version}'

GET /v1/blocks/{id}/audit

Template diff of a block (evidence, never a verdict)

What the mempool engine's template held against what the block included, written once at block connect (spec S1.9): the txids the template had and the block omitted (missing, with fee rate and age), the ones the block added from our mempool (added, fresh when they arrived within 30 s), the ones our mempool never saw (never_seen), the full-RBF replacements (fullrbf), the match rate, the expected fees and weight, and the missing txids that spend a sanctioned address against the OFAC snapshot in force (sanctioned_missing, sanctions_fetch_id). There is no censored field: interpretation is a Curated claim from a named source (ADR-0004). audit is absent for blocks connected while the engine was down; no backfill (CC-6).

Parameters

NameInTypeDescription
id requiredpathstringHeight (decimal) or canonical block hash (64 hex).

Response 200

The audit, or the subject alone when the engine wrote none.

schema
  • subject Subject required
    • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
    • key string — Canonical key (CC-3).
  • audit Audit — derived.block_template_diffs (spec S1.9) — one bounded row per block written by the mempool engine at block connect; evidence without a verdict.
    • block_hash string required — Canonical display byte order.
    • height integer required
    • template_at string (date-time) required — The last projection recompute before the block.
    • template_ntx integer required
    • template_weight integer
    • template_fees_sat integer
    • template_min_rate number — Lowest package fee rate the template included, sat/vB.
    • block_min_rate number — Lowest base fee rate among the block's transactions our mempool knew, sat/vB.
    • missing array of object required
      • txid string — Canonical display byte order.
      • fee_rate number
      • age_s integer
    • added array of object required
      • txid string — Canonical display byte order.
      • fee_rate number
    • never_seen array of string required
    • fresh array of string required
    • sigop array of string required — Empty until the projection tracks sigop limits.
    • fullrbf array of string required
    • match_rate number required — |template ∩ block| / |template| in %.
    • expected_fees_sat integer
    • expected_weight integer
    • sanctioned_missing array of object required
      • txid string — Canonical display byte order.
      • address string
      • claim_id string
    • sanctions_fetch_id integer | null — The latest OFAC fetch when the row was written.
    • extractor string required · one of "template-diff-v1"
    • extracted_at string (date-time)

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/blocks/968212/audit | jq

GET /v1/tx/{txid}/classification

Structural observations of a transaction (tx-obs-v1)

The observations of extractor tx-obs-v1 (spec S1.8): OP_RETURN protocol markers, meta-protocol envelopes, CoinJoin amount patterns, script features and the Patoshi pattern on early coinbases. Computed on demand from the raw transaction and cached; observations and extracted_at are absent when the extractor is off or the raw transaction is unavailable (CC-6), and observations is an empty list when it ran and no rule matched. Structural facts only; no rule names a wallet or an owner (P18).

Parameters

NameInTypeDescription
txid requiredpathstringCanonical txid (64 hex, display byte order).

Response 200

Observations, or the subject alone when not computed.

schema
  • subject Subject required
    • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
    • key string — Canonical key (CC-3).
  • observations array of TxObservation
    • kind string required · one of "op_return", "meta_protocol", "coinjoin", "feature", "pattern"
    • value string required — The rule that matched: omni, opentimestamps, runes, counterparty, …, inscription, src20_stamp, atomicals, whirlpool, wasabi-1, wabisabi, joinmarket, locktime_recent, bip69, rbf_signal, patoshi.
    • detail object required — Rule evidence: prefix_hex / text / heuristic for OP_RETURN, content_type for inscriptions, inputs / outputs / equal_outputs / denomination for CoinJoin patterns, nonce_lsb / extranonce for Patoshi.
    • extractor string required · one of "tx-obs"
    • extractor_version string required · one of "v1"
  • extracted_at string (date-time)
  • extractor string · one of "tx-obs-v1"

Errors

  • 400 — Malformed input (invalid_input).

Example

curl -s https://api.btcintel.io/v1/tx/71e4dae29ed1bc9fe008bba7f3542fd5961b780c220ca8778100a7cb8bd4c81b/classification | jq '{extracted_at, extractor}'

GET /v1/subjects/{subject_kind}/{subject_key}

The Curated siblings of a subject, without the chain facts

The intel siblings the subject page carries (spec S1.6), without the chain facts: for an address annotations and relations; for a transaction also exposure and classification; for a block also attributions, disputed, pool, observation and audit. Absent keys mean not computed; empty lists mean computed, nothing found (CC-6). The same answers as the page route, so a claim seen here is the claim seen there.

MCP tool
get_annotations — see For agents

Parameters

NameInTypeDescription
subject_kind requiredpathstring · one of "address", "tx", "block"address, tx or block.
subject_key requiredpathstringThe address, the canonical txid, or the block height or canonical hash.
includequerystring · one of "expired"expired to include expired and retracted claims in annotations (attributions and hop-0 stay current-only).

Response 200

The subject and its siblings.

schema
  • subject Subject required
    • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
    • key string — Canonical key (CC-3).
  • annotations array of Claim
  • relations array of Relation
    • claim_id string
    • kind string required · one of "relation"
    • about string · one of "entity"
    • version integer
    • content_sha256 string
    • citation string
    • from_entity object
      • id string
      • name string
      • kind string — entity:… concept.
    • to_entity object
      • id string
      • name string
      • kind string — entity:… concept.
    • type string — relation:… concept.
    • source object
    • fetch object
    • confidence object
    • validity object
    • evidence array of object
  • exposure Exposure — Read-time exposure from current annotations on the addresses the transaction touches; never walks further than the transaction itself.
    • hop0 array of Hop0 required
      • direction string required — in: the claim is on an address the transaction spends from; out: on an address it pays to. · one of "in", "out"
      • amount_sat integer required — Sats the address moved in that direction across every input or output of the transaction.
      • claim_id string required
      • citation string — CC-5 citation of the claim's current version.
      • label string
      • subject Subject required
        • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
        • key string — Canonical key (CC-3).
    • truncated boolean — Present and true when the transaction touches more than 1000 distinct addresses and only the first 1000 were looked up.
  • classification Classification — The tx-obs-v1 result (spec S1.8 FR-7); the same object as GET /v1/tx/{txid}/classification.
    • observations array of TxObservation required
      • kind string required · one of "op_return", "meta_protocol", "coinjoin", "feature", "pattern"
      • value string required — The rule that matched: omni, opentimestamps, runes, counterparty, …, inscription, src20_stamp, atomicals, whirlpool, wasabi-1, wabisabi, joinmarket, locktime_recent, bip69, rbf_signal, patoshi.
      • detail object required — Rule evidence: prefix_hex / text / heuristic for OP_RETURN, content_type for inscriptions, inputs / outputs / equal_outputs / denomination for CoinJoin patterns, nonce_lsb / extranonce for Patoshi.
      • extractor string required · one of "tx-obs"
      • extractor_version string required · one of "v1"
    • extracted_at string (date-time) required
    • extractor string · one of "tx-obs-v1"
  • attributions array of Attribution
    • claim_id string
    • kind string required · one of "attribution"
    • version integer
    • content_sha256 string
    • citation string
    • subject Subject
      • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
      • key string — Canonical key (CC-3).
    • entity object
      • id string
      • name string
    • method string · one of "coinbase_tag", "coinbase_address", "coinbase_script", "prev_template", "manual"
    • signature_id integer
    • matcher_version string
    • source object
      • id string
      • name string
    • fetch object
    • confidence object
      • class string
      • level integer
    • validity object
    • evidence object
    • created_at string (date-time)
  • disputed boolean
  • pool Pool — The first attribution of the read policy; present only when the block has one. An answer with its method, never a stored winner (P7).
    • entity object required
      • id string
      • name string
    • method string required · one of "prev_template", "coinbase_address", "coinbase_tag", "coinbase_script", "manual"
    • disputed boolean required
  • observation Observation — derived.coinbase_observations — a pure function of the block by extractor coinbase-v1, no author (ADR-0004 Chain band).
    • block_hash string — Canonical display byte order.
    • height integer — The height the block claims; orphans keep their row.
    • coinbase_txid string — Canonical display byte order.
    • tag_text string — Printable ASCII runs of the coinbase scriptSig (after the BIP34 height push) joined by one space; empty is a fact.
    • tag_runs array of string
    • script_sig_hex string
    • output_scripts array of object
      • n integer
      • script_hash string — sha256 of the scriptPubKey, hex.
      • address string | null — Rendered address; null for OP_RETURN, P2PK and non-standard scripts.
      • value_sat integer
    • reward_sat integer
    • fees_sat integer — reward minus the subsidy at the claimed height; clamped at zero.
    • extractor string · one of "coinbase-v1"
    • extracted_at string (date-time)
  • audit Audit — derived.block_template_diffs (spec S1.9) — one bounded row per block written by the mempool engine at block connect; evidence without a verdict.
    • block_hash string required — Canonical display byte order.
    • height integer required
    • template_at string (date-time) required — The last projection recompute before the block.
    • template_ntx integer required
    • template_weight integer
    • template_fees_sat integer
    • template_min_rate number — Lowest package fee rate the template included, sat/vB.
    • block_min_rate number — Lowest base fee rate among the block's transactions our mempool knew, sat/vB.
    • missing array of object required
      • txid string — Canonical display byte order.
      • fee_rate number
      • age_s integer
    • added array of object required
      • txid string — Canonical display byte order.
      • fee_rate number
    • never_seen array of string required
    • fresh array of string required
    • sigop array of string required — Empty until the projection tracks sigop limits.
    • fullrbf array of string required
    • match_rate number required — |template ∩ block| / |template| in %.
    • expected_fees_sat integer
    • expected_weight integer
    • sanctioned_missing array of object required
      • txid string — Canonical display byte order.
      • address string
      • claim_id string
    • sanctions_fetch_id integer | null — The latest OFAC fetch when the row was written.
    • extractor string required · one of "template-diff-v1"
    • extracted_at string (date-time)
  • community object — Spec S4.2 FR-1: the collapsed Community form (counts and up to three comments); absent until the ingester has ever run (CC-6). Indexed from Nostr, not endorsed.
    • counts CommunityCounts required
      • comments integer required — Served comments.
      • labels integer required — Served labels under the current lens.
      • hidden integer required — Events held but kept from view (deleted by the author, hidden by moderation, or by a banned pubkey).
    • sample array of CommunityEvent required
      • id string required
      • pubkey string required
      • npub string | null
      • kind integer required
      • created_at string (date-time) required
      • content string required — Plain text as signed; never HTML or markdown.
      • tags array of array of string required — The i/I/e/p/l/L/k/K/nonce tags.
      • pow_bits integer required — Committed NIP-13 difficulty.
      • low_pow boolean required
      • seen_on array of string required — Public relays the event was seen on.
      • relay_url string required — Where it came from first (our relay's URL for events accepted at our door).
      • replies_count integer required
      • zap_count integer required — Distinct zappers (community signal, not endorsement).
      • zap_sats integer — Present when zap_count > 0.
    • notice string required

Errors

  • 400 — Malformed input (bad hex, wrong-network address, bad vout).
  • 404 — Unknown to the index and, for transactions, to the node mempool.
  • 409 — Confirmed on-chain but not indexed yet (not_indexed_yet).

Example

curl -s https://api.btcintel.io/v1/subjects/tx/71e4dae29ed1bc9fe008bba7f3542fd5961b780c220ca8778100a7cb8bd4c81b | jq

GET /v1/community/labelers

The public labeler directory (Community)

Spec S4.2 FR-4 (P28): the listed labelers a reader may choose as a lens — pubkey, name, criteria, how many labels of theirs are served and since when. No labeler is a default; an empty list is a real empty (the directory is kept by ops). Community content is indexed from Nostr and not endorsed (the _meta.notice).

MCP tool
list_labelers — see For agents

Response 200

The listed labelers.

schema
  • items array of CommunityLabeler required
    • pubkey string required
    • npub string | null
    • name string required
    • namespace string required
    • description string | null
    • url string | null
    • criteria_url string | null
    • listed boolean required
    • since string (date-time) required
    • labels_count integer — Served labels by this labeler.
  • _meta CommunityMeta required
    • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
    • endorsement boolean required — Always false.

Errors

  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s https://api.btcintel.io/v1/community/labelers | jq

GET /v1/community/recent

The Community firehose — recent notes across subjects

Spec S4.2 FR-4: served comments that carry a subject and labels from listed labelers, newest first, low-PoW excluded. 501 not_configured until the ingester has run once (CC-6). Indexed from Nostr, not endorsed.

Parameters

NameInTypeDescription
kindsquerystringComma-separated: 1111 (comments) and/or 1985 (labels); both by default.
cursorquerystringThe next_cursor of the previous page.
limitqueryinteger · ≤ 200 · default 50—

Response 200

A page of notes.

schema
  • items array of CommunityEvent required
    • id string required
    • pubkey string required
    • npub string | null
    • kind integer required
    • created_at string (date-time) required
    • content string required — Plain text as signed; never HTML or markdown.
    • tags array of array of string required — The i/I/e/p/l/L/k/K/nonce tags.
    • pow_bits integer required — Committed NIP-13 difficulty.
    • low_pow boolean required
    • seen_on array of string required — Public relays the event was seen on.
    • relay_url string required — Where it came from first (our relay's URL for events accepted at our door).
    • replies_count integer required
    • zap_count integer required — Distinct zappers (community signal, not endorsement).
    • zap_sats integer — Present when zap_count > 0.
  • next_cursor string | null required
  • _meta CommunityMeta required
    • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
    • endorsement boolean required — Always false.

Errors

  • 400 — Malformed input (invalid_input).
  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s https://api.btcintel.io/v1/community/recent | jq

GET /v1/community/events/{id}

One Community event with its thread

Spec S4.2 FR-4: a served comment or label by id (64 hex or note1…) with its replies two levels deep. 404 when unknown, deleted by its author, hidden by moderation or (without include_low_pow) under the proof-of-work floor. Indexed from Nostr, not endorsed.

MCP tool
get_community_event — see For agents

Parameters

NameInTypeDescription
id requiredpathstring64 hex characters or a note1… id.
include_low_powqueryboolean · default falseAlso serve events under the proof-of-work floor (counts as two requests).

Response 200

The event and its thread.

schema

CommunityThread

Errors

  • 400 — Malformed input (invalid_input).
  • 404 — Unknown to the index and, for transactions, to the node mempool.
  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s https://api.btcintel.io/v1/community/events/1 | jq

GET /v1/community/{subject_kind}/{subject_key}

Community notes about one subject — comments and labels, with a lens

Spec S4.2 FR-1…FR-3: what people say on Nostr about an address, transaction or block — NIP-22 comments and NIP-32 labels indexed from our relay and the public relays, not endorsed by btcintel (the _meta.notice says so on every answer, P22). labelers= chooses whose labels to show (pubkeys, hex or npub); without it, labels come from listed labelers only; labelers=* shows every pubkey's labels with a warning and counts as two requests. order=recent (default) | discussed (replies) | zapped — by zaps, a community signal and not an endorsement (P26): never the default, self-zaps excluded, each zapper counted once with their largest zap, only receipts whose invoice commits to the zap request. include_low_pow=true also serves events under the proof-of-work floor and counts as two requests. Anonymous callers (t0) receive the collapsed form (counts and a sample of three comments, CC-8). A subject nobody has commented on answers counts: 0 and empty lists; before the ingester has ever run the route answers 501 not_configured (CC-6: absent, not empty).

MCP tool
get_community — see For agents

Parameters

NameInTypeDescription
subject_kind requiredpathstring · one of "address", "tx", "block"—
subject_key requiredpathstringThe canonical key (address as rendered; txid or block hash in display order).
labelersquerystringComma-separated pubkeys (hex or npub1…), or * for all.
orderquerystring · one of "recent", "discussed", "zapped" · default "recent"—
include_low_powqueryboolean · default false—
cursorquerystringThe next_cursor of the previous page.
limitqueryinteger · ≤ 200 · default 50—

Response 200

The page (full form), or the collapsed form for anonymous callers.

schema
  • CommunityPage
    • subject CommunitySubject required
      • kind string required · one of "address", "tx", "block"
      • key string required
      • nip73 string — The NIP-73 id, e.g. bitcoin:address:<address>.
    • comments array of CommunityEvent required
      • id string required
      • pubkey string required
      • npub string | null
      • kind integer required
      • created_at string (date-time) required
      • content string required — Plain text as signed; never HTML or markdown.
      • tags array of array of string required — The i/I/e/p/l/L/k/K/nonce tags.
      • pow_bits integer required — Committed NIP-13 difficulty.
      • low_pow boolean required
      • seen_on array of string required — Public relays the event was seen on.
      • relay_url string required — Where it came from first (our relay's URL for events accepted at our door).
      • replies_count integer required
      • zap_count integer required — Distinct zappers (community signal, not endorsement).
      • zap_sats integer — Present when zap_count > 0.
    • labels array of CommunityLabel required
      • id string required
      • pubkey string required
      • npub string | null
      • labeler object — Present when the pubkey is in the directory.
        • name string
        • listed boolean
      • namespace string required
      • value string required
      • target object required
        • subject CommunitySubject

          …

      • created_at string (date-time) required
      • pow_bits integer required
    • counts CommunityCounts required
      • comments integer required — Served comments.
      • labels integer required — Served labels under the current lens.
      • hidden integer required — Events held but kept from view (deleted by the author, hidden by moderation, or by a banned pubkey).
    • next_cursor string | null required
    • lens object required
      • all boolean required
      • chosen integer
      • warning string
      • labelers array of CommunityLabeler required
        • pubkey string required
        • npub string | null
        • name string required
        • namespace string required
        • description string | null
        • url string | null
        • criteria_url string | null
        • listed boolean required
        • since string (date-time) required
        • labels_count integer — Served labels by this labeler.
    • order string required · one of "recent", "discussed", "zapped"
    • _meta CommunityMeta required
      • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
      • endorsement boolean required — Always false.
  • CommunityCollapsed — The anonymous (t0) form (CC-8) and the community sibling of a subject page.
    • subject CommunitySubject required
      • kind string required · one of "address", "tx", "block"
      • key string required
      • nip73 string — The NIP-73 id, e.g. bitcoin:address:<address>.
    • counts CommunityCounts required
      • comments integer required — Served comments.
      • labels integer required — Served labels under the current lens.
      • hidden integer required — Events held but kept from view (deleted by the author, hidden by moderation, or by a banned pubkey).
    • sample array of CommunityEvent required
      • id string required
      • pubkey string required
      • npub string | null
      • kind integer required
      • created_at string (date-time) required
      • content string required — Plain text as signed; never HTML or markdown.
      • tags array of array of string required — The i/I/e/p/l/L/k/K/nonce tags.
      • pow_bits integer required — Committed NIP-13 difficulty.
      • low_pow boolean required
      • seen_on array of string required — Public relays the event was seen on.
      • relay_url string required — Where it came from first (our relay's URL for events accepted at our door).
      • replies_count integer required
      • zap_count integer required — Distinct zappers (community signal, not endorsement).
      • zap_sats integer — Present when zap_count > 0.
    • _meta CommunityMeta required
      • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
      • endorsement boolean required — Always false.

Errors

  • 400 — Malformed input (invalid_input).
  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s https://api.btcintel.io/v1/community/tx/71e4dae29ed1bc9fe008bba7f3542fd5961b780c220ca8778100a7cb8bd4c81b | jq

POST /v1/community/publish

Publish a signed Community event through the API

Spec S5.1 FR-8 (P4, P12, P23). The body carries an event signed by its author: a comment (kind 1111), a label (kind 1985) or a deletion (kind 5) about a Bitcoin subject (NIP-73), with the proof of work the relay's floor asks for (NIP-13, mined by the client; the floor is /v1/status community.relay.min_pow, 24 bits while attack_mode is on). Who may send it: a signed-in human (session cookie with the CSRF proof, or NIP-98) as their own key, or a t2/t4 btci_ key holding the community:publish scope as one of its allowed_npubs; the event's pubkey must be that key, else 422 unbound:. The event then passes exactly the relay's door (kinds, subject tags, window, size, PoW, bans; blocked:, invalid:, pow: answer 422 event_rejected with the relay's message), is stored as accepted by this relay, is fanned out to the relay's subscribers and, best effort and asynchronously, to broadcast_to. Tier caps: event_max_bytes (t2 4,096; t3/t4 16,384) and publish_per_min / publish_per_day per author (CC-8). The API signs nothing: an account's custodied key is signed for by the signer service (POST /v1/auth/npub/sign, while features.signing is on), never here. 501 not_configured while WRITES_ENABLED is off (/v1/status features.writes; on since CP3, P60). Over MCP this is publish_community_event (S5.10, P70): the caller is the session's bearer, a t2 or t4 key bound to the event's pubkey (a minted t1 token cannot publish; POST /v1/keys/agent issues a t2 key to the npub that signs that request with NIP-98); the event is signed by the agent's own key, never by btcintel.

MCP tool
publish_community_event — see For agents
Auth
An operator credential as the bearer; every call is audited.

Request body

schema
  • event object required — A Nostr event exactly as signed (NIP-01); the server recomputes the id and verifies the signature.
    • id string required
    • pubkey string required
    • created_at integer required
    • kind integer required
    • tags array of array of string required
    • content string required
    • sig string required

Response 200

Already held (duplicate: true), or a deletion that deleted nothing held here (stored: false, still broadcast).

schema
  • id string required
  • pubkey string required
  • kind integer required
  • pow_bits integer required — Committed NIP-13 difficulty.
  • stored boolean required — The event row exists on this relay.
  • accepted_by array of string required — self when this relay holds it.
  • broadcast_to array of string required — Outbound relays the event is being sent to (best effort, asynchronous).
  • duplicate boolean required
  • deleted integer — Deletions only: events of the author marked deleted here.
  • _meta CommunityMeta required
    • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
    • endorsement boolean required — Always false.

Response 201

Accepted and stored; broadcast_to lists the relays it is being sent to.

schema
  • id string required
  • pubkey string required
  • kind integer required
  • pow_bits integer required — Committed NIP-13 difficulty.
  • stored boolean required — The event row exists on this relay.
  • accepted_by array of string required — self when this relay holds it.
  • broadcast_to array of string required — Outbound relays the event is being sent to (best effort, asynchronous).
  • duplicate boolean required
  • deleted integer — Deletions only: events of the author marked deleted here.
  • _meta CommunityMeta required
    • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
    • endorsement boolean required — Always false.

Errors

  • 400 — Malformed input (invalid_input).
  • 401 — Missing or invalid bearer (unauthorized).
  • 403 — The operator lacks the role or kind the action needs, or is switched off (forbidden).
  • 422 — The event was refused at the door (event_rejected): the message carries the relay's NIP-01 prefix — unbound: (not this caller's key), invalid: (shape, subject, window, size, signature), pow: (below the floor), blocked: (kind, banned, read-only).
  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s -X POST https://api.btcintel.io/v1/community/publish \
  -H 'Authorization: Bearer $BTCI_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"event":{"id":"…","pubkey":"…","created_at":10,"kind":10,"tags":[],"content":"…","sig":"…"}}' | jq

An operator credential: the ops bearer or a btci_ key with the ops:agent scope.

POST /v1/community/delete

Delete own Community events through the API (NIP-09)

Spec S5.1 FR-9. The body carries a kind 5 signed by the author naming the ids to delete in e tags; the same callers and binding as /v1/community/publish. Events held here by that author are marked deleted at once (the row stays for moderation; every read hides it), deleted counts them; the deletion is stored when it deleted something held and is broadcast outbound in any case, since a note that only public relays hold is the author's to delete there. A stranger's deletion deletes nothing. 501 not_configured while WRITES_ENABLED is off (on since CP3, P60). Over MCP this is delete_community_event, with the same bearer binding (S5.10).

MCP tool
delete_community_event — see For agents
Auth
An operator credential as the bearer; every call is audited.

Request body

schema
  • event object required — A Nostr event exactly as signed (NIP-01); the server recomputes the id and verifies the signature.
    • id string required
    • pubkey string required
    • created_at integer required
    • kind integer required
    • tags array of array of string required
    • content string required
    • sig string required

Response 200

Nothing held was deleted (deleted: 0, stored: false) or the deletion was known already; broadcast still.

schema
  • id string required
  • pubkey string required
  • kind integer required
  • pow_bits integer required — Committed NIP-13 difficulty.
  • stored boolean required — The event row exists on this relay.
  • accepted_by array of string required — self when this relay holds it.
  • broadcast_to array of string required — Outbound relays the event is being sent to (best effort, asynchronous).
  • duplicate boolean required
  • deleted integer — Deletions only: events of the author marked deleted here.
  • _meta CommunityMeta required
    • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
    • endorsement boolean required — Always false.

Response 201

The deletion was stored (it deleted something held) and broadcast.

schema
  • id string required
  • pubkey string required
  • kind integer required
  • pow_bits integer required — Committed NIP-13 difficulty.
  • stored boolean required — The event row exists on this relay.
  • accepted_by array of string required — self when this relay holds it.
  • broadcast_to array of string required — Outbound relays the event is being sent to (best effort, asynchronous).
  • duplicate boolean required
  • deleted integer — Deletions only: events of the author marked deleted here.
  • _meta CommunityMeta required
    • notice string required — Always: Community content is indexed from Nostr and not endorsed by btcintel.
    • endorsement boolean required — Always false.

Errors

  • 400 — Malformed input (invalid_input).
  • 401 — Missing or invalid bearer (unauthorized).
  • 403 — The operator lacks the role or kind the action needs, or is switched off (forbidden).
  • 422 — The event was refused at the door (event_rejected): the message carries the relay's NIP-01 prefix — unbound: (not this caller's key), invalid: (shape, subject, window, size, signature), pow: (below the floor), blocked: (kind, banned, read-only).
  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s -X POST https://api.btcintel.io/v1/community/delete \
  -H 'Authorization: Bearer $BTCI_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"event":{"id":"…","pubkey":"…","created_at":10,"kind":10,"tags":[],"content":"…","sig":"…"}}' | jq

An operator credential: the ops bearer or a btci_ key with the ops:agent scope.

POST /v1/annotations/propose

Propose a Curated claim (t2 agents, t3 humans; a human reviews it)

Spec S5.1 FR-10 (P42, P5). A proposal names a research source that accepts community proposals (GET /v1/sources, community_proposals: true), a canonical subject, a label and, optionally, category or abuse words from the vocabulary (GET /v1/taxonomy/concepts), concept ids, an entity, a role, evidence entries and the Community event that led to it. It becomes a draft filed under the proposer's npub (a human's own key; a t2/t4 key's pubkey, one of its allowed_npubs, or its only one) with method: manual and the source's default confidence; a human curator approves or rejects it (S3.3), and an approved claim is published under the source, cited to a fetch of this proposal, with {"kind": "nostr_event", "value": <id>} in its evidence when a lead event was cited — the row stands on its own; the brand never seals the event (P5). Quota proposals_per_day per caller (t2 and t3 20, t4 100). 501 not_configured while WRITES_ENABLED is off (on since CP3, P60).

MCP tool
propose_annotation — see For agents
Auth
An operator credential as the bearer; every call is audited.

Request body

schema
  • source_id string required — A research source with community_proposals true.
  • subject object required
    • kind string required · one of "address", "tx", "block"
    • key string required — The address, txid or block hash; canonicalised (CC-3).
  • label string required · max length 200
  • category string — A DW-VA entity category word (GET /v1/taxonomy/concepts?scheme=category). · max length 100
  • abuse string — A DW-VA abuse word (scheme=abuse). · max length 100
  • concepts array of string
  • entity_id string · max length 100
  • role string · max length 100
  • evidence array of object
    • kind string required · one of "url", "nostr_event", "txid", "text"
    • value string required · max length 2048
    • note string · max length 2048
  • lead_event_id string — The Community event (64 hex or note1…) that led to the proposal; added to the evidence as nostr_event.
  • pubkey string — t2/t4 keys only: which of the key's allowed_npubs proposes (64 hex or npub1…).

Response 201

The draft; a human reviews it.

schema
  • draft_id integer required
  • status string required · one of "draft"
  • proposed_by string required — npub:<hex>, or key:<id> for a key without allowed npubs.
  • source_id string required
  • subject Subject required
    • kind string · one of "address", "script", "tx", "block", "outpoint", "pool", "descriptor", "pubkey"
    • key string — Canonical key (CC-3).
  • created_at string (date-time) required
  • note string

Errors

  • 400 — Malformed input (invalid_input).
  • 401 — Missing or invalid bearer (unauthorized).
  • 403 — The operator lacks the role or kind the action needs, or is switched off (forbidden).
  • 422 — The NIP-98 event was refused (nip98_invalid): wrong URL or method, stale, bad signature, wrong payload hash, or used before; the message names the reason.
  • 429 — quota_exceeded (spec S3.1 FR-4): the caller's tier ran out of requests for the minute or the day. Retry-After says when to try again; every rate-limited answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Tier. While the deployment runs in log-only mode the decision is logged instead and X-RateLimit-Policy: log-only is set.
  • 501 — The mempool engine is not enabled on this deployment (BITCOIN_ZMQ_SEQUENCE unset).

Example

curl -s -X POST https://api.btcintel.io/v1/annotations/propose \
  -H 'Authorization: Bearer $BTCI_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"source_id":"…","subject":{"kind":"address","key":"bc1qz654h5qcqzalv6ltpxsk4ksdcc3e20wkedqntgnarv3a0t2e2p7scr48pl"},"label":"…"}' | jq

An operator credential: the ops bearer or a btci_ key with the ops:agent scope.