> ## 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.

# Blockchain Data APIs for 200+ Networks

> Stream blockchain data from 200+ networks over HTTP and build TypeScript indexers.

export const QueryInterface = () => {
  const useCasesConfig = [{
    id: "ethereum-usdt",
    name: "Track USDT transfers on Ethereum",
    network: "ethereum-mainnet",
    payload: {
      type: "evm",
      fromBlock: 18000000,
      toBlock: 18000000,
      fields: {
        log: {
          address: true,
          topics: true,
          data: true,
          transactionHash: true
        }
      },
      logs: [{
        address: ["0xdAC17F958D2ee523a2206206994597C13D831ec7"],
        topic0: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
      }]
    }
  }, {
    id: "solana-token",
    name: "Query token transfers on Solana",
    network: "solana-mainnet",
    payload: {
      type: "solana",
      fromBlock: 180000000,
      toBlock: 180000000,
      fields: {
        instruction: {
          programId: true,
          data: true
        },
        block: {
          number: true,
          hash: true
        }
      },
      instructions: [{
        programId: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"]
      }]
    }
  }, {
    id: "base-mainnet",
    name: "Query recent blocks on Base",
    network: "base-mainnet",
    payload: {
      type: "evm",
      fromBlock: 10000000,
      toBlock: 10000010,
      fields: {
        block: {
          number: true,
          hash: true,
          timestamp: true,
          gasUsed: true
        }
      }
    }
  }, {
    id: "arbitrum-mainnet",
    name: "Track USDC transfers on Arbitrum",
    network: "arbitrum-one",
    payload: {
      type: "evm",
      fromBlock: 200000000,
      toBlock: 200000010,
      fields: {
        log: {
          address: true,
          topics: true,
          data: true,
          transactionHash: true
        }
      },
      logs: [{
        address: ["0xaf88d065e77c8cC2239327C5EDb3A432268e5831"],
        topic0: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
      }]
    }
  }, {
    id: "hyperliquid-fills",
    name: "Query BTC perp fills with PnL on Hyperliquid",
    network: "hyperliquid-fills",
    payload: {
      type: "hyperliquidFills",
      fromBlock: 900000000,
      toBlock: 900000030,
      fields: {
        block: {
          number: true,
          timestamp: true
        },
        fill: {
          user: true,
          coin: true,
          px: true,
          sz: true,
          side: true,
          dir: true,
          closedPnl: true,
          fee: true
        }
      },
      fills: [{
        coin: ["BTC"]
      }]
    }
  }, {
    id: "tron-usdt",
    name: "Track USDT (TRC-20) transfers on Tron",
    network: "tron-mainnet",
    payload: {
      type: "tron",
      fromBlock: 79257136,
      toBlock: 79257136,
      fields: {
        block: {
          number: true,
          timestamp: true
        },
        log: {
          address: true,
          topics: true,
          data: true
        }
      },
      logs: [{
        address: ["a614f803b6fd780986a42c78ec9c7f77e6ded13c"],
        topic0: ["ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
      }]
    }
  }, {
    id: "bitcoin-txns",
    name: "Query transactions on Bitcoin",
    network: "bitcoin-mainnet",
    payload: {
      type: "bitcoin",
      fromBlock: 250000,
      toBlock: 250000,
      fields: {
        block: {
          number: true,
          hash: true,
          timestamp: true
        },
        transaction: {
          txid: true,
          size: true,
          weight: true
        }
      },
      transactions: [{}]
    }
  }];
  const [useCase, setUseCase] = useState("ethereum-usdt");
  const [response, setResponse] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [viewMode, setViewMode] = useState("code");
  const [copied, setCopied] = useState(false);
  const generateCurlCommand = config => {
    const url = `https://portal.sqd.dev/datasets/${config.network}/stream`;
    const payload = JSON.stringify(config.payload, null, 2);
    return `curl --compressed -X POST '${url}' \\\n  -H 'Content-Type: application/json' \\\n  -d '${payload}'`;
  };
  useEffect(() => {
    setViewMode("code");
    setResponse("");
    setError(null);
  }, [useCase]);
  const handleRun = async () => {
    const selectedUseCase = useCasesConfig.find(uc => uc.id === useCase);
    if (!selectedUseCase) return;
    setViewMode("output");
    setLoading(true);
    setError(null);
    setResponse('');
    try {
      const url = `https://portal.sqd.dev/datasets/${selectedUseCase.network}/stream`;
      const doFetch = () => fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(selectedUseCase.payload)
      });
      let response = await doFetch();
      for (const retryDelay of [700, 1500, 3000]) {
        if (response.status < 500) break;
        await new Promise(resolve => setTimeout(resolve, retryDelay));
        response = await doFetch();
      }
      if (response.status === 503) {
        throw new Error('Portal is busy right now. Wait a few seconds and run the query again.');
      }
      if (!response.ok) {
        throw new Error(`API request failed: ${response.status} ${response.statusText}`);
      }
      const text = await response.text();
      if (text.trim()) {
        const lines = text.trim().split('\n');
        const parsedData = lines.map((line, index) => {
          try {
            return JSON.parse(line);
          } catch (e) {
            return {
              error: `Failed to parse line ${index + 1}`,
              raw: line
            };
          }
        });
        const formattedOutput = parsedData.map(obj => JSON.stringify(obj, null, 2)).join('\n\n');
        setResponse(formattedOutput);
      } else {
        setResponse('No data returned from API');
      }
    } catch (err) {
      setError(err.message || 'An error occurred while fetching data');
      setResponse('');
    } finally {
      setLoading(false);
    }
  };
  const NETWORK_LABELS = {
    "ethereum-usdt": "Ethereum",
    "solana-token": "Solana",
    "base-mainnet": "Base",
    "arbitrum-mainnet": "Arbitrum",
    "hyperliquid-fills": "Hyperliquid",
    "tron-usdt": "Tron",
    "bitcoin-txns": "Bitcoin"
  };
  const NETWORK_LOGOS = {
    "ethereum-usdt": "/images/chains/eth.png",
    "solana-token": "/images/chains/sol.png",
    "base-mainnet": "/images/chains/base.png",
    "arbitrum-mainnet": "/images/chains/arb.png",
    "hyperliquid-fills": "/images/chains/hl.jpg",
    "tron-usdt": "/images/chains/tron.png",
    "bitcoin-txns": "/images/chains/btc.png"
  };
  const NetworkLogo = ({id}) => {
    const src = NETWORK_LOGOS[id];
    if (!src) return null;
    return <img src={src} alt="" aria-hidden="true" loading="lazy" className="h-3.5 w-3.5 rounded-full object-cover" />;
  };
  const CurlTok = ({s}) => <>
    {s.split(/('[^']*')/).map((seg, i) => (/^'[^']*'$/).test(seg) ? <span key={i} style={{
    color: "var(--hl-str)"
  }}>{seg}</span> : seg.split(/(curl|--compressed|-X POST|-H|-d)/).map((t2, j) => t2 === "curl" ? <span key={`${i}-${j}`} style={{
    color: "var(--hl-bool)"
  }}>{t2}</span> : (/^(--compressed|-X POST|-H|-d)$/).test(t2) ? <span key={`${i}-${j}`} style={{
    color: "var(--hl-flag)"
  }}>{t2}</span> : <span key={`${i}-${j}`}>{t2}</span>))}
  </>;
  const JsonTok = ({s}) => <>
    {s.split(/("[^"]+"\s*:)/).map((seg, i) => (/^"[^"]+"\s*:$/).test(seg) ? <span key={i} style={{
    color: "var(--hl-key)"
  }}>{seg}</span> : seg.split(/("[^"]*")/).map((s2, j) => (/^"[^"]*"$/).test(s2) ? <span key={`${i}-${j}`} style={{
    color: "var(--hl-str)"
  }}>{s2}</span> : s2.split(/\b(true|false|null|-?\d+\.?\d*)\b/).map((s3, k) => (/^(true|false|null)$/).test(s3) ? <span key={`${i}-${j}-${k}`} style={{
    color: "var(--hl-bool)"
  }}>{s3}</span> : (/^-?\d+\.?\d*$/).test(s3) ? <span key={`${i}-${j}-${k}`} style={{
    color: "var(--hl-num)"
  }}>{s3}</span> : <span key={`${i}-${j}-${k}`}>{s3}</span>)))}
  </>;
  return <div className="not-prose w-full max-w-4xl mx-auto px-4 sm:px-6 my-6 sm:my-8">

      <div className="sqd-no-scrollbar mb-3 flex items-center gap-0.5 overflow-x-auto pb-1">
        <span className="sqd-pg-label mr-2 flex-shrink-0">Query</span>
        {useCasesConfig.map(uc => {
    const active = uc.id === useCase;
    return <button key={uc.id} type="button" onClick={() => setUseCase(uc.id)} aria-pressed={active} className="sqd-pg-net flex flex-shrink-0 items-center gap-1.5 px-2.5 py-1 whitespace-nowrap">
              <NetworkLogo id={uc.id} />
              {NETWORK_LABELS[uc.id]}
            </button>;
  })}
      </div>

      <div className="sqd-pg-panel overflow-hidden">
        <div className="sqd-pg-bar flex flex-wrap items-center gap-2 px-3 sm:px-4 py-2">
          <div className="flex items-center gap-1">
            <button type="button" onClick={() => setViewMode("code")} className={`sqd-pg-tab px-2.5 py-1 ${viewMode === "code" ? "sqd-pg-tab-active" : ""}`}>
              Request
            </button>
            <button type="button" onClick={() => setViewMode("output")} disabled={!response && !loading && !error} className={`sqd-pg-tab px-2.5 py-1 disabled:opacity-40 disabled:cursor-not-allowed ${viewMode === "output" ? "sqd-pg-tab-active" : ""}`}>
              Response
              {response ? <span className="inline-block w-1.5 h-1.5 rounded-full bg-emerald-400 ml-1.5 align-middle" /> : null}
            </button>
          </div>
          <div className="flex items-center gap-2 sm:gap-3 ml-auto">
            <button type="button" onClick={() => {
    const textToCopy = viewMode === "code" ? generateCurlCommand(useCasesConfig.find(uc => uc.id === useCase)) : response;
    navigator.clipboard.writeText(textToCopy);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  }} className="sqd-pg-dim text-[12px] transition-opacity hover:opacity-70" title={copied ? "Copied!" : "Copy to clipboard"}>
              {copied ? "Copied" : "Copy"}
            </button>
            <button onClick={handleRun} type="button" disabled={loading} className="sqd-btn-primary-docs flex items-center gap-1.5 px-3 sm:px-4 py-1.5 text-[13px] disabled:opacity-40 disabled:cursor-wait whitespace-nowrap focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 dark:focus:ring-offset-gray-950">
              {loading ? <>
                  <svg className="animate-spin h-3 w-3" fill="none" viewBox="0 0 24 24">
                    <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
                    <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                  </svg>
                  Running
                </> : "Run"}
            </button>
          </div>
        </div>
        <div className={`sqd-pg-code px-3 sm:px-4 py-4 ${viewMode === "output" ? "max-h-[440px] overflow-auto" : "overflow-x-auto"}`}>
          {loading ? <div className="sqd-pg-dim flex items-center justify-center py-10 text-[13px]">Streaming from Portal...</div> : viewMode === "code" ? <div key={`code-${useCase}`}>
              {generateCurlCommand(useCasesConfig.find(uc => uc.id === useCase)).trim().split('\n').map((line, i) => <div key={`curl-line-${i}`} className="sqd-pg-line">
                  <span className="sqd-pg-num">{i + 1}</span>
                  <span style={{
    whiteSpace: 'pre-wrap',
    wordBreak: 'break-word'
  }}>
                    {line.includes('curl') || line.match(/^\s*-[XHd]/) ? <CurlTok s={line} /> : <JsonTok s={line} />}
                  </span>
                </div>)}
            </div> : response ? <div key={`response-${useCase}-${response.length}`}>
              {response.trim().split('\n').map((line, i) => <div key={`response-line-${i}`} className="sqd-pg-line">
                  <span className="sqd-pg-num">{i + 1}</span>
                  <span style={{
    whiteSpace: 'pre-wrap',
    wordBreak: 'break-word'
  }}>
                    <JsonTok s={line} />
                  </span>
                </div>)}
            </div> : error ? <div className="py-4 text-[13px] text-red-600 dark:text-red-400">Error: {error}</div> : <div className="sqd-pg-dim text-center py-12 text-[13px]">
              Hit Run to stream live data from Portal
            </div>}
        </div>
        <div className="sqd-pg-bar-b flex flex-wrap items-center gap-x-3 gap-y-1 px-4 py-2">
          <div className="sqd-pg-dim flex items-center gap-2 min-w-0 text-[12px]">
            <NetworkLogo id={useCase} />
            <span className="flex-shrink-0">{NETWORK_LABELS[useCase]}</span>
            <span className="truncate">{useCasesConfig.find(uc => uc.id === useCase)?.network + "/stream"}</span>
          </div>
          <span className="sqd-pg-dim text-[12px] ml-auto flex-shrink-0">
            {useCasesConfig.find(uc => uc.id === useCase)?.name}
          </span>
        </div>
      </div>
    </div>;
};

<div className="max-w-5xl mx-auto px-6 pt-14 pb-20 sm:pt-20">
  <div className="text-center mb-14">
    <h1 className="text-3xl sm:text-4xl lg:text-5xl font-semibold text-gray-900 dark:text-gray-100 mb-4">
      SQD Documentation
    </h1>

    <p className="text-lg sm:text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto mb-8">
      Stream onchain data from 200+ networks through the Portal HTTP API.
      Build indexers with the Squid and Pipes TypeScript SDKs and deploy
      them on SQD Cloud.
    </p>

    <div className="flex flex-wrap justify-center gap-3">
      <a href="/en/portal/evm/quickstart" className="px-6 py-3 sqd-btn-primary-docs">
        Query with Portal
      </a>

      <a href="/en/sdk/overview" className="px-6 py-3 sqd-btn-secondary-docs">
        Build with the SDK
      </a>
    </div>
  </div>

  <QueryInterface />

  <p className="text-center text-gray-600 dark:text-gray-400 mt-6 mb-20">
    Live queries against Portal, no API key required. Follow the{" "}

    <a href="/en/portal/evm/quickstart" className="text-primary dark:text-primary-light font-medium">
      Portal quickstart
    </a>

    {" "}

    to run your own.
  </p>

  <h2 className="text-2xl sm:text-3xl font-bold text-center text-gray-900 dark:text-gray-100 mb-8">
    Products
  </h2>

  <CardGroup cols={4}>
    <Card title="Portal" icon="database" href="/en/portal/overview">
      HTTP API for raw blockchain data with arbitrary ranges, streaming, and
      finality handling
    </Card>

    <Card title="SDK" icon="code" href="/en/sdk/overview">
      TypeScript libraries for decoding, transforming, and persisting data to
      any database
    </Card>

    <Card title="Cloud" icon="cloud" href="/en/cloud/overview">
      Managed indexer hosting with monitoring, scaling, and zero DevOps
    </Card>

    <Card title="Network" icon="waypoints" href="/en/network/overview">
      Decentralized data lake behind Portal, with self-hosting options
    </Card>
  </CardGroup>

  <h2 className="text-2xl sm:text-3xl font-bold text-center text-gray-900 dark:text-gray-100 mt-16 mb-8">
    Get started
  </h2>

  <CardGroup cols={2}>
    <Card title="Query blockchain data" icon="bolt" href="/en/portal/evm/quickstart">
      Extract data in minutes with plain HTTP requests, no setup required
    </Card>

    <Card title="Build an indexer" icon="hammer" href="/en/sdk/pipes-sdk/evm/quickstart">
      Create a type-safe indexer and stream data to your own database
    </Card>

    <Card title="Deploy to production" icon="rocket" href="/en/cloud/overview">
      Ship your indexer to SQD Cloud with managed infrastructure and monitoring
    </Card>

    <Card title="Build with AI" icon="sparkles" href="/en/ai/ai-development">
      Use MCP servers, agent skills, and LLM-optimized docs to build with agents
    </Card>
  </CardGroup>

  <div className="text-center mt-16 text-gray-600 dark:text-gray-400">
    <p className="mb-2">
      Portal serves{" "}

      <a href="/en/data/all-networks" className="text-primary dark:text-primary-light font-medium">
        200+ networks
      </a>

      {" "}

      — Ethereum, Solana, Base, Arbitrum, Bitcoin, Hyperliquid, and more.
    </p>

    <p>
      Questions? Read the{" "}

      <a href="/en/other/faq" className="text-primary dark:text-primary-light font-medium">
        FAQ
      </a>

      , browse{" "}

      <a href="https://sqd.dev/customers" target="_blank" rel="noopener noreferrer" className="text-primary dark:text-primary-light font-medium">
        customer stories
      </a>

      , or{" "}

      <a href="https://t.me/subsquid" target="_blank" rel="noopener noreferrer" className="text-primary dark:text-primary-light font-medium">
        join our Telegram
      </a>

      .
    </p>
  </div>
</div>


## Related topics

- [Network, Portal and SDK FAQ](/en/other/faq.md)
- [Portal: Blockchain Data API](/en/portal/overview.md)
- [External APIs and IPFS](/en/sdk/squid-sdk/solana/guides/advanced/external-apis-ipfs.md)
- [SQD Network](/en/network/overview.md)
- [SQD Connector for Claude](/en/ai/claude-connector.md)
