<!-- source: https://secondlayer.tools/docs/api-reference#list-stream-events -->

## Raw event firehose

`GET /v1/streams/events`

Canonical 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

| Name | Type | Description |
| --- | --- | --- |
| `chain` | enum | `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. Values: `stacks`, `bitcoin`. |
| `types` | array of enum | Comma-separated event types to include. Default: all of them. |
| `event_type` | enum | One event type, as an alias for `types`. Mutually exclusive with `types`; a set must use `types`. Values: `stx_transfer`, `stx_mint`, `stx_burn`, `stx_lock`, `ft_transfer`, `ft_mint`, `ft_burn`, `nft_transfer`, `nft_mint`, `nft_burn`, `print`. |
| `not_types` | array of enum | Comma-separated event types to exclude, applied after `types`. |
| `contract_id` | string | 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. |
| `sender` | string | Principal, or a comma-separated set, matched against the payload's `sender`. Event types without a sender never match. |
| `recipient` | string | Principal, or a comma-separated set, matched against the payload's `recipient`. |
| `asset_identifier` | string | Exact `<contract>::<asset>` match on the payload. |
| `filters` | string | 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. |
| `rune` | string | 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`). |
| `address` | string | chain=bitcoin only. A mainnet address. |

### Range and paging

| Name | Type | Description |
| --- | --- | --- |
| `limit` | integer · 1 to 1000 | Events per page. Default 100. Values above 1000 are clamped to 1000. |
| `cursor` | string | `<block_height>:<event_index>` from a previous page's `next_cursor`. Resumes strictly after it. Mutually exclusive with `from_cursor` and `from_height`. |
| `from_cursor` | string | Same as `cursor`. `0:0` starts at genesis. |
| `from_height` | integer | First block height to read. Mutually exclusive with a cursor. With neither, the read starts 1000 blocks behind the tip. |
| `to_height` | integer | 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 `StreamsEvent` objects.

### Responses

- `200` A page of events, the cursor to resume from, the tip it was read against, and any reorgs that touched it
- `304` Finalized page unchanged since the `ETag` sent in `If-None-Match`
- `400` A parameter, filter, cursor or body field was refused; `code` says which
- `401` This bind requires the instance token, and it was missing or wrong
- `429` Rate 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-After` seconds
- `503` No canonical block indexed yet (`CHAIN_DATA_UNAVAILABLE`). Wait for the indexer to ingest its first block

### Example

```bash
curl -G https://api.secondlayer.tools/v1/streams/events \
  -H "Authorization: Bearer $SECONDLAYER_API_KEY" \
  -d contract_id=SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token \
  -d asset_identifier=SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token::alex \
  -d filters={"alex":{"types":["ft_transfer"],"contractId":"SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token"},"stx":{"types":"stx_transfer"}}
```

```json
{
  "events": [
    {
      "cursor": "9048876:3",
      "block_height": 9048876,
      "block_hash": "0xba0676b375e8d5fc1495a02847cc3cc32b5f7c2113a5e73999d94ee8d75ebde4",
      "burn_block_height": 968284,
      "tx_id": "0xb9edea3443a9adb603d856bfed2d1e630146bed128b07aaaa259dc97e3eae2ba",
      "tx_index": 2,
      "event_index": 3,
      "event_type": "ft_transfer",
      "contract_id": "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token",
      "payload": {
        "amount": "416515709472",
        "sender": "SP3R4NKXMGW6YXA44X2ESZPKJNV25X4ZN7DPW0RXR",
        "recipient": "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.alex-vault",
        "asset_identifier": "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token::alex"
      },
      "ts": "2026-09-23T14:56:36.000Z",
      "canonical": true,
      "finalized": false
    }
  ],
  "next_cursor": "7960000:42",
  "tip": {
    "block_height": 9048690,
    "finalized_height": 9048457,
    "lag_seconds": 4,
    "source_block_height": 9048692
  },
  "reorgs": [
    {
      "id": "3f16c2c5-9551-4ae9-adb0-923668e5c65e",
      "detected_at": "2026-09-15T15:39:38.129Z",
      "fork_point_height": 8996511,
      "old_index_block_hash": "0x45ba0195071488eda13afa66d8ce8612558a739f781be5a032d96332797c4174",
      "new_index_block_hash": "0xa686ff58e7c5ccb26c850a7eaffa7e7274fcbc081c706344eb6f1e1446023df0",
      "orphaned_range": {
        "from": "8996511:0",
        "to": "8996512:2701"
      },
      "new_canonical_tip": "8996511:0"
    }
  ]
}
```
