Streams API
The raw event firehose in chain order, a live tail over server-sent events, and the reorg history. Envelope and cursors are in REST conventions; most apps want the Index API instead.
Streams discovery
GET/v1/streamsLists the Streams routes, the event types and filters /v1/streams/events accepts, and the cursor format. Served ahead of Streams auth, so it never needs a credential.
Raw event firehose
GET/v1/streams/eventsCanonical chain events in chain order: block height, then transaction position, then event position. Pages are capped at the tip minus a 2-block reorg margin. With no cursor or from_height, the read starts 1000 blocks behind the tip. An empty filtered page still returns a next_cursor past to_height, so a consumer never stalls. Pages at or below tip.finalized_height are immutable: they carry an ETag and answer If-None-Match with 304.
Filters
stacks (default) is the existing Stacks feed, byte-identical to before. bitcoin serves Runes events (rune_etch, rune_mint, rune_transfer, rune_burn — see the RuneStreamsEvent schema) on their own cursor space: a bitcoin cursor only resumes with chain=bitcoin. Stacks-only filters (contract_id, sender, recipient, asset_identifier, filters, clock) 400 on chain=bitcoin; rune and address are bitcoin-only.
2 possible values
stacksbitcoinComma-separated event types to include. Default: all of them.
One event type, as an alias for types. Mutually exclusive with types; a set must use types.
11 possible values
stx_transferstx_mintstx_burnstx_lockft_transferft_mintft_burnnft_transfernft_mintnft_burnprintComma-separated event types to exclude, applied after types.
Contract principal, or a comma-separated set. Matches print events by the emitting contract and ft/nft events by the asset's contract. Other event types never match.
Principal, or a comma-separated set, matched against the payload's sender. Event types without a sender never match.
Principal, or a comma-separated set, matched against the payload's recipient.
Exact <contract>::<asset> match on the payload.
JSON object of up to 8 labelled filter groups: { "<label>": { types?, contractId?, sender?, recipient?, assetIdentifier? } }. Each value is a string or array of strings. Groups OR together, fields inside a group AND, and the flat filters above still apply to the whole scan. Each event lists the labels it matched in matched. Labels are letters, digits, - and _, 32 characters at most.
chain=bitcoin only. A RuneRef: an id (840000:3) or a name, spacers/case ignored (DOG•GO•TO•THE•MOON, dog.go.to.the.moon, doggotothemoon).
chain=bitcoin only. A mainnet address.
Range and paging
Events per page. Default 100. Values above 1000 are clamped to 1000.
<block_height>:<event_index> from a previous page's next_cursor. Resumes strictly after it. Mutually exclusive with from_cursor and from_height.
Same as cursor. 0:0 starts at genesis.
First block height to read. Mutually exclusive with a cursor. With neither, the read starts 1000 blocks behind the tip.
Last block height to read, inclusive. Always clamped to the tip minus a 2-block reorg margin, which is also the default.
Returns
A cursor envelope. events holds Streams event objects.
- 200A page of events, the cursor to resume from, the tip it was read against, and any reorgs that touched it
- 304Finalized page unchanged since the
ETagsent inIf-None-Match - 400A parameter, filter, cursor or body field was refused;
codesays which - 401This bind requires the instance token, and it was missing or wrong
- 429Rate limited on the hosted API (50/s per IP without a key, 10/s on a free key). Self-hosted instances do not throttle Streams. Retry after
Retry-Afterseconds - 503No canonical block indexed yet (
CHAIN_DATA_UNAVAILABLE). Wait for the indexer to ingest its first block
Tail the event firehose over SSE
GET/v1/streams/events/streamServer-sent events over the same read as /v1/streams/events, with the same parameters. The server polls every 1.5 seconds by default (STREAMS_SSE_POLL_MS) and writes one frame per event: id is the event's cursor and data is { "event": <StreamsEvent> }, or { "event", "sig", "key_id" } with an ed25519 signature over the event's JSON when the instance has a signing key. After 20 seconds with no events it writes event: ping with empty data; ignore it. With no cursor, from_cursor or from_height, the tail starts at the current tip minus the reorg margin. Last-Event-ID is not read; to resume after a disconnect, reconnect with from_cursor set to the last id you processed.
Filters
stacks (default) is the existing Stacks feed, byte-identical to before. bitcoin serves Runes events (rune_etch, rune_mint, rune_transfer, rune_burn — see the RuneStreamsEvent schema) on their own cursor space: a bitcoin cursor only resumes with chain=bitcoin. Stacks-only filters (contract_id, sender, recipient, asset_identifier, filters, clock) 400 on chain=bitcoin; rune and address are bitcoin-only.
2 possible values
stacksbitcoinComma-separated event types to include. Default: all of them.
One event type, as an alias for types. Mutually exclusive with types; a set must use types.
11 possible values
stx_transferstx_mintstx_burnstx_lockft_transferft_mintft_burnnft_transfernft_mintnft_burnprintComma-separated event types to exclude, applied after types.
Contract principal, or a comma-separated set. Matches print events by the emitting contract and ft/nft events by the asset's contract. Other event types never match.
Principal, or a comma-separated set, matched against the payload's sender. Event types without a sender never match.
Principal, or a comma-separated set, matched against the payload's recipient.
Exact <contract>::<asset> match on the payload.
JSON object of up to 8 labelled filter groups: { "<label>": { types?, contractId?, sender?, recipient?, assetIdentifier? } }. Each value is a string or array of strings. Groups OR together, fields inside a group AND, and the flat filters above still apply to the whole scan. Each event lists the labels it matched in matched. Labels are letters, digits, - and _, 32 characters at most.
chain=bitcoin only. A RuneRef: an id (840000:3) or a name, spacers/case ignored (DOG•GO•TO•THE•MOON, dog.go.to.the.moon, doggotothemoon).
chain=bitcoin only. A mainnet address.
Range and paging
Most events written per poll. Default 100. Values above 1000 are clamped to 1000.
<block_height>:<event_index> from a previous page's next_cursor. Resumes strictly after it. Mutually exclusive with from_cursor and from_height.
Same as cursor. 0:0 starts at genesis.
First block height to read. Mutually exclusive with a cursor. With neither, the read starts 1000 blocks behind the tip.
Last block height to read, inclusive. Always clamped to the tip minus a 2-block reorg margin, which is also the default.
Returns
text/event-stream
- 200An open
text/event-stream. Frames:id: <cursor>plusdata: {"event":{...}}per event, andevent: pingafter 20 seconds idle - 400An unknown query parameter. Other bad values close the stream without a frame
- 401This bind requires the instance token, and it was missing or wrong
- 429Rate limited on the hosted API (50/s per IP without a key, 10/s on a free key). Self-hosted instances do not throttle Streams. Retry after
Retry-Afterseconds
Chain reorg history
GET/v1/streams/reorgsReorgs the indexer recorded, oldest first. Page forward by passing next_since back as since.
Filters
stacks (default) is the existing Stacks feed, byte-identical to before. bitcoin serves Runes events (rune_etch, rune_mint, rune_transfer, rune_burn — see the RuneStreamsEvent schema) on their own cursor space: a bitcoin cursor only resumes with chain=bitcoin. Stacks-only filters (contract_id, sender, recipient, asset_identifier, filters, clock) 400 on chain=bitcoin; rune and address are bitcoin-only.
2 possible values
stacksbitcoinWhere to start. An ISO timestamp returns reorgs detected after it. A <block_height>:<event_index> cursor returns reorgs whose orphaned range ends at or after it. A next_since value (<detected_at>~<id>) resumes after the last reorg delivered.
Range and paging
Reorgs per page. Default 100. Values above 1000 are clamped to 1000.
Returns
A cursor envelope. reorgs holds Reorg objects.
- 200Reorgs, oldest first
- 400
sinceis missing or is not a timestamp, cursor ornext_sincevalue, orlimitis not a positive integer - 401This bind requires the instance token, and it was missing or wrong
- 429Rate limited on the hosted API (50/s per IP without a key, 10/s on a free key). Self-hosted instances do not throttle Streams. Retry after
Retry-Afterseconds
Canonical block by height
GET/v1/streams/canonical/{height}The canonical Stacks block at one height and the Bitcoin block it anchors to. Finalized heights are cached for good and answer If-None-Match with 304; the ETag is the block hash.
Path parameters
Block height (Stacks by default, Bitcoin with chain=bitcoin).
Query parameters
stacks (default) is the existing Stacks feed, byte-identical to before. bitcoin serves Runes events (rune_etch, rune_mint, rune_transfer, rune_burn — see the RuneStreamsEvent schema) on their own cursor space: a bitcoin cursor only resumes with chain=bitcoin. Stacks-only filters (contract_id, sender, recipient, asset_identifier, filters, clock) 400 on chain=bitcoin; rune and address are bitcoin-only.
2 possible values
stacksbitcoinReturns
The Streams canonical block object.
- 200The canonical block. chain=bitcoin returns a StreamsBitcoinCanonicalBlock (btc block hash, no burn-chain fields) instead.
- 304Block unchanged since the
ETagsent inIf-None-Match - 400
heightis not a non-negative integer - 401This bind requires the instance token, and it was missing or wrong
- 404No canonical block at that height yet
- 429Rate limited on the hosted API (50/s per IP without a key, 10/s on a free key). Self-hosted instances do not throttle Streams. Retry after
Retry-Afterseconds
Current chain tip
GET/v1/streams/tipThe newest canonical block this instance has indexed, the finality boundary, and how far back this caller can seek. Never cached.
Query parameters
stacks (default) is the existing Stacks feed, byte-identical to before. bitcoin serves Runes events (rune_etch, rune_mint, rune_transfer, rune_burn — see the RuneStreamsEvent schema) on their own cursor space: a bitcoin cursor only resumes with chain=bitcoin. Stacks-only filters (contract_id, sender, recipient, asset_identifier, filters, clock) 400 on chain=bitcoin; rune and address are bitcoin-only.
2 possible values
stacksbitcoinReturns
- 200The tip. chain=bitcoin returns a StreamsBitcoinTip (no burn-chain or retention fields) instead.
- 401This bind requires the instance token, and it was missing or wrong
- 429Rate limited on the hosted API (50/s per IP without a key, 10/s on a free key). Self-hosted instances do not throttle Streams. Retry after
Retry-Afterseconds - 503No canonical block indexed yet (
CHAIN_DATA_UNAVAILABLE). Wait for the indexer to ingest its first block
Catalog of the Streams routes and filters.
Returned by Streams discovery
One raw chain event. payload is the node's event body; its fields depend on event_type.
Returned by Raw event firehose
Attributes
<block_height>:<event_index>. Pass as cursor or from_cursor.
Stacks block the event landed in.
That block's hash.
Bitcoin block that block anchors to.
Transaction that emitted the event.
Its position in the block.
The event's position among the block's Streams events, from 0.
The event's type.
11 possible values
stx_transferstx_mintstx_burnstx_lockft_transferft_mintft_burnnft_transfernft_mintnft_burnprintEmitting contract for print, asset contract for ft/nft events, null otherwise.
The event body. Prints carry topic, value and contract_id; transfers carry sender, recipient, amount or value, and asset_identifier.
The block's timestamp.
Always true: the firehose serves the canonical chain only.
Labels from filters this event satisfied. Present only when the request used filters.
true when the block is at or below tip.finalized_height and can no longer reorg.
The Reorg object
ObjectA fork the indexer rolled back. Rows inside orphaned_range were replaced; undo anything you committed from them.
Returned by Chain reorg history
Attributes
Reorg id.
When the indexer saw the fork.
First block height the new fork replaced. Undo rows at or above it.
Index block hash of the abandoned tip.
Index block hash of the winning tip.
First and last cursor of the rows that were replaced.
Cursor of the new canonical tip.
The canonical Stacks block at a height.
Returned by Canonical block by height
The newest canonical block and how far back this caller can read.
Returned by Current chain tip
Attributes
Highest canonical Stacks block this instance has indexed.
That block's hash.
The Bitcoin block it anchors to.
Highest Stacks block whose Bitcoin anchor has 6 confirmations. Rows at or below it are immutable.
Seconds since the tip block was produced.
Always null — every account reads full history. Rows past the monthly allowance are a paid read, not a blocked one.
Always null — see oldest_seekable_height.