> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sqd.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Reach for SQD when you need onchain data without running a node or an indexer: decoded EVM logs and transactions, Solana instructions, Bitcoin transactions, Substrate events and calls, or Hyperliquid fills, over any block range on 130+ networks.
> To query directly, POST to https://portal.sqd.dev/datasets/{dataset}/stream. The full API is described at https://docs.sqd.dev/openapi.json, and responses to the stream endpoints are JSON Lines.
> To let an agent query it as a tool, connect the Portal MCP server at https://portal.sqd.dev/mcp.
> Every page on this site is available as Markdown by appending .md to its URL.

# Introduction

> Stream Solana blockchain data with SQD Portal and handle pagination, finality, and reorgs.

1. [POST your data request to `/stream`](./stream) or [`/finalized-stream`](./finalized-stream) and you shall receive a [JSON lines](https://jsonlines.org) stream:
   ```bash theme={"system"}
   curl https://portal.sqd.dev/datasets/solana-mainnet/stream \
     -X POST \
     -d '{
       "type": "solana",
       "fromBlock": 325000000,
       "toBlock": 325000001,
       "fields": {
         "block": {"number": true},
         "instruction": {"data": true}
       },
       "instructions": [
         {"programId": [
           "MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG"
         ]}
       ]
     }'
   ```
   outputs
   ```jsonl theme={"system"}
   {"header":{"number":325000000},"instructions":[{"data":"XJqfG9ATWCDLLmxbNnKxcQ6KRHveSXFyrM8JwmyievueP"}]}
   {"header":{"number":325000001}}
   ```
2. By default the Portal will only include blocks with data matching the request filters. However, the stream will always include the first and the last blocks of the block range it covered, even if they have no matching data.
3. The portal may end stream before it reaches `toBlock`. You can omit `toBlock` for open-ended streaming.
4. To get the rest of the data, the client must adjust the `fromBlock` field to the number of the last received block **plus one**. When streaming unfinalized data from `/stream`, they must also include `parentBlockHash` into the request.

## Handling forks on `/stream`

5. Chain forks / reorgs sometimes make some of the data from `/stream` obsolete. The portal will detect that using the `parentBlockHash` field of the request and respond with an HTTP 409 containing a sample of new consensus blocks. When that happens, the client must roll back any changes to its own state made due to orphan blocks' data, then send another `POST /stream` that starts from an earlier block to attempt to fetch the updated chain.
6. Post-rollback request must contain `parentBlockHash`. If the Portal detects that the block is still not in the updated chain, it'll return a 409 again. Be prepared to process several of these in a row.
7. To make state management easier for the client, Portal may return `X-Sqd-Finalized-Head-Number` and `X-Sqd-Finalized-Head-Hash` headers with each response from `/stream`. The block from these headers and blocks below it won't ever reorganize.
8. That doesn't mean that `X-Sqd-Finalized-Head-Number` is a non-decreasing value: Portals can be behind load balancers and the value may decrease when the load balancer switches to a lagging instance. The client should trust the guarantees provided by either instance and treat the highest block returned with these headers as a high water mark for finalized blocks.


## Related topics

- [Introduction](/en/api/evm/introduction.md)
- [Cross-relation Queries](/en/sdk/squid-sdk/tron/reference/openreader/api/cross-relation-field-queries.md)
- [Entity Queries](/en/sdk/squid-sdk/tron/reference/openreader/api/queries.md)
