---
name: sqd-onchain-data
description: Use when an agent needs onchain data it cannot get from a single RPC call - contract event history, wallet activity across chains, token transfers, DEX trades, Solana instructions, Bitcoin UTXO flows, or Hyperliquid fills - across 130+ networks. Covers picking an access path (HTTP, MCP, or SDK), calling it, and the boundaries of what SQD serves.
---

# SQD: onchain data for agents

SQD serves raw and decoded blockchain data across 130+ networks through one
streaming HTTP API, plus TypeScript SDKs and a hosted MCP server. It replaces
the job of running your own indexer or paginating an RPC node.

## When to use SQD

Reach for SQD when the task needs:

- **Event history for a contract**, over any range up to the full chain. One
  request instead of thousands of `eth_getLogs` windows.
- **Activity for an address across many chains**, without wiring up one provider
  per network.
- **Token transfers, DEX swaps, or executed prices** over a historical window,
  for analytics, accounting, backtests, or tax cost-basis work.
- **Internal transactions and traces**, which most RPC providers either omit or
  bill separately.
- **Storage state diffs**, for risk engines and liquidation monitoring.
- **Solana instructions, Bitcoin transactions, or Hyperliquid fills**, in the
  same request shape as EVM data.
- **A dataset you can verify**, when the answer has to reconcile: SQD validates
  data at ingestion and serves it from immutable Parquet.
- **A pipeline into your own warehouse** (ClickHouse, BigQuery, Postgres,
  Parquet on S3) rather than a query you re-run.

## When not to use SQD

- **Reading current contract state.** There is no `balanceOf`-at-block and no
  view-function call. Balances and positions are derived by the caller from
  transfer and state-diff data. Use an RPC node for state reads.
- **Sending transactions.** SQD is read-only: no signing, no submission, no
  mempool.
- **Price oracles or off-chain market data.** SQD serves what is onchain.
- **A single lookup of one recent transaction.** An RPC call is simpler.

## How to call SQD

Three access paths, same underlying data. Pick by what is calling.

| Caller | Use | Entry point |
|---|---|---|
| Any language, plain HTTP | Portal API | `https://portal.sqd.dev` |
| An MCP client (Claude, ChatGPT, IDE agents) | Portal MCP server | `https://portal.sqd.dev/mcp` |
| TypeScript pipeline into a database | Pipes SDK | `npm i @subsquid/pipes` |
| TypeScript indexer with GraphQL + Postgres | Squid SDK + SQD Cloud | `npx @subsquid/cli init` |

### Portal API over HTTP

List the networks, then stream:

```bash
curl https://portal.sqd.dev/datasets

curl -X POST https://portal.sqd.dev/datasets/ethereum-mainnet/stream \
  -H 'Content-Type: application/json' \
  -d '{"type":"evm","fromBlock":20494139,"toBlock":20494140,
       "fields":{"block":{"number":true,"hash":true}}}'
```

Responses are JSON Lines (`application/jsonl`), one block per line, so read them
as a stream rather than buffering the range.

The public Portal shares capacity across users and is intended for development
and bounded evaluation. Authenticated and dedicated portals take an API key in
the `x-api-key` header; paths and payloads are identical either way.

Full machine-readable description, with an `operationId` and typed schemas per
operation: **https://sqd.dev/openapi.json**

Two things that trip up first calls:

- The EVM block field selector is `number`, not `height`.
- Every error is JSON on every status code:
  `{"error":{"type","code","message"}}`. Match on `error.code`. A bad field name
  comes back with the accepted values listed, so the API is self-describing.

### Portal MCP server

Streamable HTTP transport, no key. Most clients only need the URL:

```json
{ "mcpServers": { "sqd-portal": { "url": "https://portal.sqd.dev/mcp" } } }
```

Calling the transport directly: the initializing POST must accept **both**
media types. `Accept: application/json` alone, or no `Accept` header, is
answered `406 Not Acceptable` and the handshake ends there. `GET` is `405`.

```bash
curl -s -X POST https://portal.sqd.dev/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
       "protocolVersion":"2025-06-18","capabilities":{},
       "clientInfo":{"name":"my-client","version":"1.0.0"}}}'
```

A second server, `https://docs.sqd.dev/mcp`, searches the documentation rather
than the chain data.

Server card: **https://sqd.dev/.well-known/mcp.json** ·
Docs: https://docs.sqd.dev/en/ai/mcp-server

### CLI

`@subsquid/cli` scaffolds, runs, and deploys Squid SDK indexers:

```bash
npm i -g @subsquid/cli    # provides the `sqd` command
sqd init my-indexer
sqd run .
sqd deploy .
```

Source: https://github.com/subsquid/squid-cli

## Rate limits, versioning, and deprecation

The Portal answers a capacity refusal with `error.type` of `rate_limit_error`
and `error.code` of `overloaded`, carrying a mandatory `Retry-After` in seconds
(never below 1, never an HTTP date). There is no quota header to poll: honour
`Retry-After` and retry the identical request. `Retry-After` and `x-request-id`
are exposed through CORS.

The API is unversioned by design. There is no `/v1/` and no version header; the
surface only grows by addition. Paths, methods, the error envelope, `error.type`
and `error.code` are stable. `error.message` prose, dataset ordering, and the
dataset set are not. Dataset retirements are announced ahead of the date at
https://docs.sqd.dev/announcements; after it, the name answers 404 with
`error.code` of `unknown_dataset`. Full policy:
https://docs.sqd.dev/en/portal/introduction/versioning

## Developer resources by name

| Resource | URL |
|---|---|
| Developer resources hub | https://sqd.dev/developers/ |
| Developer documentation | https://docs.sqd.dev |
| Portal API reference | https://docs.sqd.dev/en/api/evm/introduction |
| OpenAPI 3.1 spec (Portal API) | https://sqd.dev/openapi.json |
| MCP server card | https://sqd.dev/.well-known/mcp.json |
| MCP server documentation | https://docs.sqd.dev/en/ai/mcp-server |
| Deep agent skill (building indexers) | https://docs.sqd.dev/skill.md |
| API catalog (RFC 9727) | https://sqd.dev/.well-known/api-catalog |
| Site index for LLMs | https://sqd.dev/llms.txt |
| Full reference for LLMs | https://sqd.dev/llms-full.txt |
| Supported networks | https://sqd.dev/chains/ |
| Squid CLI (`sqd`) | https://www.npmjs.com/package/@subsquid/cli |
| Squid CLI source | https://github.com/subsquid/squid-cli |
| Versioning and deprecation policy | https://docs.sqd.dev/en/portal/introduction/versioning |
| Error handling and rate limits | https://docs.sqd.dev/en/portal/introduction/error-handling |
| Source repositories | https://github.com/subsquid |
| Developer chat | https://t.me/hydradevs |
| Sales and support | https://sqd.dev/contact/ |

## Going deeper

For building, deploying, and debugging indexers (`squid.yaml`, `schema.graphql`,
Pipes SDK targets, SQD Cloud deployment, and the common failure modes), load the
full skill at **https://docs.sqd.dev/skill.md**.
