{
  "openapi": "3.1.0",
  "info": {
    "title": "SQD Portal API",
    "version": "1.0.0",
    "summary": "Streaming HTTP access to decoded blockchain data across 130+ networks.",
    "description": "The SQD Portal serves raw and decoded onchain data (blocks, transactions, logs, traces,\nstate diffs, Solana instructions, Bitcoin transactions, Hyperliquid fills) over plain\nHTTP, one dataset per network. Responses to the stream endpoints are JSON Lines, so a\nclient reads them incrementally instead of buffering a whole range.\n\nThe public Portal at https://portal.sqd.dev shares capacity across users and is intended\nfor development and bounded evaluation. Authenticated and dedicated portals take an API\nkey in the `x-api-key` header; the paths and payloads are identical either way.\n\nEvery error, on every status code, is JSON: `{\"error\":{\"type\",\"code\",\"message\"}}`. Match on\n`error.code`, not on the message text.\n\n## Versioning\n\nThis API is deliberately unversioned. There is no `/v1/` path segment and no version request\nheader: every client talks to the same surface at https://portal.sqd.dev. That works because\nthe surface only grows by addition. New dataset types, new block and transaction fields, and\nnew datasets appear without changing what an existing request means, so there is never a\nsecond version to migrate to. `info.version` above tracks this description, not the API.\n\nWhat is stable, and safe to code against: endpoint paths and HTTP methods, the error envelope,\n`error.type` as a closed set of four values, an `error.code` value once published, and a field\nname in a selector once accepted. What is NOT stable: the prose in `error.message`, the order\nof datasets in `GET /datasets`, the set of datasets, and worker assignments in\n`GET /datasets/{dataset}/state`.\n\n## Deprecation\n\nEndpoints are not deprecated or sunset; the dataset catalogue is what changes. A dataset\nretirement is announced ahead of the date at https://docs.sqd.dev/announcements, naming the\naffected datasets and the date, and in the developer chat. Watch that page rather than polling:\nafter the date, a retired name answers 404 with `error.code` of `unknown_dataset`, which is the\nremoval signal, not a warning. Diff this document to detect any other change; every operation\ncarries a stable `operationId` for exactly that.\n\nThe SDKs version separately, as npm packages on semantic versioning. A breaking change lands in\na major release with a migration guide, and the Portal keeps serving older SDK versions.\n\n## Rate limits\n\nA capacity refusal answers `error.code` of `overloaded` with a mandatory `Retry-After` header,\nin seconds, never below 1. There is no quota or remaining-request header to poll: honour\n`Retry-After` and retry the identical request. Both `Retry-After` and `x-request-id` are\nexposed through CORS, so browser clients can read them.\n\nWhat the Portal does NOT serve: reconstructed contract state. There is no balance-at-block\nor `balanceOf` call. Balances are derived by the caller from transfer and state-diff data.",
    "contact": {
      "name": "SQD",
      "url": "https://sqd.dev/contact/"
    },
    "termsOfService": "https://sqd.dev/imprint/",
    "x-api-versioning": {
      "strategy": "none",
      "summary": "Unversioned by design: no URL path segment, no version header. The surface changes only by addition.",
      "policyUrl": "https://docs.sqd.dev/en/portal/introduction/versioning",
      "humanUrl": "https://sqd.dev/developers/#versioning"
    },
    "x-api-deprecation": {
      "channel": "https://docs.sqd.dev/announcements",
      "summary": "Dataset retirements are announced ahead of the date on the announcements page. Endpoints are not sunset. A retired dataset answers 404 with error.code unknown_dataset.",
      "signal": "error.code=unknown_dataset",
      "humanUrl": "https://sqd.dev/developers/#versioning"
    },
    "x-rate-limits": {
      "strategy": "retry-after",
      "summary": "No quota headers. A capacity refusal carries a mandatory Retry-After in seconds, never below 1, on 429 and 529.",
      "retryAfterHeader": "Retry-After",
      "policyUrl": "https://docs.sqd.dev/en/portal/introduction/error-handling",
      "humanUrl": "https://sqd.dev/developers/#rate-limits"
    }
  },
  "externalDocs": {
    "description": "SQD developer documentation",
    "url": "https://docs.sqd.dev/en/api/evm/introduction"
  },
  "servers": [
    {
      "url": "https://portal.sqd.dev",
      "description": "Public SQD Portal. Shared capacity, for development and bounded evaluation."
    },
    {
      "url": "https://{portal}",
      "description": "Authenticated or dedicated portal. Same paths and payloads as the public one.",
      "variables": {
        "portal": {
          "default": "portal.sqd.dev",
          "description": "Hostname of the dedicated portal issued to your organisation."
        }
      }
    }
  ],
  "tags": [
    {
      "name": "Datasets",
      "description": "Discover networks and inspect what a dataset currently holds."
    },
    {
      "name": "Streaming",
      "description": "Read matching blocks as JSON Lines."
    }
  ],
  "security": [
    {},
    {
      "portalApiKey": []
    }
  ],
  "paths": {
    "/datasets": {
      "get": {
        "operationId": "listDatasets",
        "summary": "List every available dataset",
        "description": "Returns one entry per supported network, with its canonical name, any aliases, and whether it carries real-time data. Start here: the `dataset` path parameter of every other operation comes from this list.",
        "tags": [
          "Datasets"
        ],
        "responses": {
          "200": {
            "description": "The datasets this portal serves.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Dataset"
                  }
                },
                "examples": {
                  "default": {
                    "summary": "Truncated live response",
                    "value": [
                      {
                        "dataset": "arbitrum-one",
                        "aliases": [],
                        "real_time": true
                      },
                      {
                        "dataset": "base-mainnet",
                        "aliases": [],
                        "real_time": true
                      }
                    ]
                  }
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal error.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/{dataset}/metadata": {
      "get": {
        "operationId": "getDatasetMetadata",
        "summary": "Describe one dataset",
        "description": "Returns the dataset name, aliases, whether it is real-time, and its `start_block`. A query with `fromBlock` below `start_block` is rejected with 400, so read this first when querying deep history.",
        "tags": [
          "Datasets"
        ],
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "Dataset name or alias, one per network (e.g. `ethereum-mainnet`, `solana-mainnet`, `base-mainnet`). Enumerate the current set with `listDatasets`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]*$",
              "examples": [
                "ethereum-mainnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Dataset metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetMetadata"
                },
                "examples": {
                  "default": {
                    "summary": "Live response for ethereum-mainnet",
                    "value": {
                      "dataset": "ethereum-mainnet",
                      "aliases": [],
                      "real_time": true,
                      "start_block": 0
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset. `error.code` is `unknown_dataset`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/{dataset}/head": {
      "get": {
        "operationId": "getDatasetHead",
        "summary": "Get the highest available block",
        "description": "Returns the number and hash of the highest block the dataset holds, real-time data included, or `null` when the dataset is empty. Use it to bound a query or to check how far ingestion has progressed.",
        "tags": [
          "Datasets"
        ],
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "Dataset name or alias, one per network (e.g. `ethereum-mainnet`, `solana-mainnet`, `base-mainnet`). Enumerate the current set with `listDatasets`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]*$",
              "examples": [
                "ethereum-mainnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Highest available block, or null.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlockHead"
                },
                "examples": {
                  "default": {
                    "summary": "Live response for ethereum-mainnet",
                    "value": {
                      "number": 25826425,
                      "hash": "0x252be3366c3493c60d065a0145f69936e3485a78e1ab02865ede976342dcdac0"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset. `error.code` is `unknown_dataset`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/{dataset}/finalized-head": {
      "get": {
        "operationId": "getDatasetFinalizedHead",
        "summary": "Get the highest finalized block",
        "description": "Same as `getDatasetHead`, restricted to finalized blocks. Anything at or below this height will not be reorganised, so it is the safe watermark for irreversible bookkeeping.",
        "tags": [
          "Datasets"
        ],
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "Dataset name or alias, one per network (e.g. `ethereum-mainnet`, `solana-mainnet`, `base-mainnet`). Enumerate the current set with `listDatasets`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]*$",
              "examples": [
                "ethereum-mainnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Highest finalized block, or null.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlockHead"
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset. `error.code` is `unknown_dataset`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/{dataset}/timestamps/{timestamp}/block": {
      "get": {
        "operationId": "resolveTimestampToBlock",
        "summary": "Resolve a Unix timestamp to a block number",
        "description": "Returns the first block at or after the given instant. Block numbers are not comparable\nacross networks, so this is how a caller lines up the same wall-clock window on several\nchains before querying each one. On Solana the same field carries a slot.\n\nThe timestamp is in **seconds**. Passing milliseconds does not error in an obvious way:\nthe value lands far beyond the chain head and comes back as a 404, so a client that\nforgets to divide sees \"not found\" rather than \"wrong unit\".",
        "tags": [
          "Datasets"
        ],
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "Dataset name or alias, one per network (e.g. `ethereum-mainnet`, `solana-mainnet`, `base-mainnet`). Enumerate the current set with `listDatasets`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]*$",
              "examples": [
                "ethereum-mainnet"
              ]
            }
          },
          {
            "name": "timestamp",
            "in": "path",
            "required": true,
            "description": "Unix timestamp in seconds, not milliseconds.",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0,
              "examples": [
                1748736000
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The first block at or after the timestamp.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimestampBlock"
                },
                "examples": {
                  "default": {
                    "summary": "2025-06-01 00:00:00 UTC on Base, from a live response",
                    "value": {
                      "block_number": 30973327
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The timestamp is not an integer. `error.code` is `malformed_request`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset (`unknown_dataset`), or the timestamp is beyond the highest block the dataset holds (`not_found`). A millisecond timestamp lands here.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/{dataset}/state": {
      "get": {
        "operationId": "getDatasetState",
        "summary": "Get stored block ranges per worker",
        "description": "Returns which block ranges each SQD Network worker currently holds, plus the highest seen block and the first gap. Intended for diagnostics and network status views. The response is large (tens of MB for a mature dataset); prefer `getDatasetMetadata` or `getDatasetHead` for routine checks.",
        "tags": [
          "Datasets"
        ],
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "Dataset name or alias, one per network (e.g. `ethereum-mainnet`, `solana-mainnet`, `base-mainnet`). Enumerate the current set with `listDatasets`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]*$",
              "examples": [
                "ethereum-mainnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stored ranges for the dataset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetState"
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset. `error.code` is `unknown_dataset`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/{dataset}/stream": {
      "post": {
        "operationId": "streamBlocks",
        "summary": "Stream blocks matching a query",
        "description": "Streams every block matching the query as JSON Lines (`application/jsonl`), one JSON object\nper line, including unfinalized blocks. Send `Content-Type: application/json`; optionally\n`Accept-Encoding: gzip` and `Content-Encoding: gzip`.\n\nThe response is open-ended when `toBlock` is omitted, so read it as a stream. Cross-check\n`X-Sqd-Finalized-Head-Number` to know which returned blocks are still reorg-able; on a 409,\nrestart from a block both sides agree on.",
        "tags": [
          "Streaming"
        ],
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "Dataset name or alias, one per network (e.g. `ethereum-mainnet`, `solana-mainnet`, `base-mainnet`). Enumerate the current set with `listDatasets`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]*$",
              "examples": [
                "ethereum-mainnet"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Block range, field selector, and item filters.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DataQuery"
              },
              "examples": {
                "evmBlockHeaders": {
                  "summary": "Two Ethereum block headers",
                  "value": {
                    "type": "evm",
                    "fromBlock": 20494139,
                    "toBlock": 20494140,
                    "fields": {
                      "block": {
                        "number": true,
                        "hash": true
                      }
                    }
                  }
                },
                "evmTransfers": {
                  "summary": "ERC-20 Transfer logs for one contract",
                  "value": {
                    "type": "evm",
                    "fromBlock": 20494139,
                    "toBlock": 20494200,
                    "fields": {
                      "log": {
                        "address": true,
                        "topics": true,
                        "data": true
                      },
                      "block": {
                        "number": true
                      }
                    },
                    "logs": [
                      {
                        "address": [
                          "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
                        ],
                        "topic0": [
                          "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
                        ]
                      }
                    ]
                  }
                },
                "solanaBlocks": {
                  "summary": "One Solana block header",
                  "value": {
                    "type": "solana",
                    "fromBlock": 317617480,
                    "toBlock": 317617480,
                    "fields": {
                      "block": {
                        "number": true,
                        "hash": true
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matching blocks as JSON Lines. Empty when a bounded range contains no match.",
            "headers": {
              "X-Sqd-Finalized-Head-Number": {
                "description": "Block number of the latest finalized block. Returned blocks may sit above, at, or below it.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              },
              "X-Sqd-Finalized-Head-Hash": {
                "description": "Hash of the latest finalized block. Every returned block belongs to the same chain as this block.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Sqd-Head-Number": {
                "description": "Block number of the highest block the dataset currently holds.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              }
            },
            "content": {
              "application/jsonl": {
                "schema": {
                  "$ref": "#/components/schemas/Block"
                },
                "examples": {
                  "default": {
                    "summary": "One line of a live response; the stream sends one such object per block",
                    "value": {
                      "header": {
                        "number": 20494139,
                        "hash": "0x3faa6ecbfc83a0c5d95a9728616295cfb17238edc897550fdc1330e3b8edf575"
                      }
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "The requested range sits entirely above the dataset height. The portal may hold the request for up to 5s first.",
            "headers": {
              "X-Sqd-Finalized-Head-Number": {
                "description": "Block number of the latest finalized block. Returned blocks may sit above, at, or below it.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              },
              "X-Sqd-Finalized-Head-Hash": {
                "description": "Hash of the latest finalized block. Every returned block belongs to the same chain as this block.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Sqd-Head-Number": {
                "description": "Block number of the highest block the dataset currently holds.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              }
            }
          },
          "400": {
            "description": "Malformed request: bad encoding, an invalid query, or a `fromBlock` below the dataset start block (see `getDatasetMetadata`). `error.message` names the offending field and lists the accepted values.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset. `error.code` is `unknown_dataset`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The requested range starts on an orphaned block. The body lists recent blocks on the current chain; restart the stream from the newest one your records agree with.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConflictResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Do not retry the identical request.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable: `error.type` is `availability_error` (`no_workers`, `retries_exhausted`, or `not_ready`). A later attempt can still succeed. Honour `Retry-After` when present, otherwise back off yourself.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/{dataset}/finalized-stream": {
      "post": {
        "operationId": "streamFinalizedBlocks",
        "summary": "Stream finalized blocks matching a query",
        "description": "Identical to `streamBlocks` in query shape and response format, restricted to finalized blocks. Nothing it returns can be reorganised, so no 409 handling is needed; it lags the chain head by the network finality delay.",
        "tags": [
          "Streaming"
        ],
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "Dataset name or alias, one per network (e.g. `ethereum-mainnet`, `solana-mainnet`, `base-mainnet`). Enumerate the current set with `listDatasets`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]*$",
              "examples": [
                "ethereum-mainnet"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Block range, field selector, and item filters.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DataQuery"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matching finalized blocks as JSON Lines.",
            "headers": {
              "X-Sqd-Finalized-Head-Number": {
                "description": "Block number of the latest finalized block. Returned blocks may sit above, at, or below it.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              },
              "X-Sqd-Finalized-Head-Hash": {
                "description": "Hash of the latest finalized block. Every returned block belongs to the same chain as this block.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Sqd-Head-Number": {
                "description": "Block number of the highest block the dataset currently holds.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              }
            },
            "content": {
              "application/jsonl": {
                "schema": {
                  "$ref": "#/components/schemas/Block"
                }
              }
            }
          },
          "204": {
            "description": "The requested range sits entirely above the finalized height.",
            "headers": {
              "X-Sqd-Finalized-Head-Number": {
                "description": "Block number of the latest finalized block. Returned blocks may sit above, at, or below it.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              },
              "X-Sqd-Finalized-Head-Hash": {
                "description": "Hash of the latest finalized block. Every returned block belongs to the same chain as this block.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Sqd-Head-Number": {
                "description": "Block number of the highest block the dataset currently holds.",
                "schema": {
                  "type": "integer",
                  "format": "int64"
                }
              }
            }
          },
          "400": {
            "description": "Malformed request: bad encoding, an invalid query, or a `fromBlock` below the dataset start block (see `getDatasetMetadata`). `error.message` names the offending field and lists the accepted values.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset. `error.code` is `unknown_dataset`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method for this path. `error.code` is `method_not_allowed`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The requested range starts on an orphaned block. The body lists recent blocks on the current chain; restart the stream from the newest one your records agree with.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConflictResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: a capacity refusal proxied from a data source. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Do not retry the identical request.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable: `error.type` is `availability_error` (`no_workers`, `retries_exhausted`, or `not_ready`). A later attempt can still succeed. Honour `Retry-After` when present, otherwise back off yourself.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "529": {
            "description": "The Portal is at capacity. `error.type` is `rate_limit_error` and `error.code` is `overloaded`. Wait the number of seconds in `Retry-After`, then retry the identical request.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "portalApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "API key for an authenticated or dedicated portal. The public Portal accepts requests without one. See https://docs.sqd.dev/en/portal/pricing for access options."
      }
    },
    "headers": {
      "RetryAfter": {
        "description": "Seconds to wait before retrying the identical request. Never an HTTP date, and never below 1. Mandatory on every `overloaded` response (429 and 529) and present on some `availability_error` responses. This is the whole throttle signal: the Portal publishes no quota or remaining-request header, so a client self-throttles by honouring this value rather than by tracking a budget. Exposed through CORS, so browser clients can read it.",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "examples": [
            10
          ]
        }
      },
      "RequestId": {
        "description": "Identifier for this request, on every response. Quote it when reporting a problem; it is also repeated in `error.request_id` on 5xx bodies. Exposed through CORS.",
        "required": false,
        "schema": {
          "type": "string",
          "examples": [
            "0198c3f1-0000-7000-8000-000000000000"
          ]
        }
      }
    },
    "schemas": {
      "Dataset": {
        "type": "object",
        "title": "Dataset",
        "description": "One network served by this portal.",
        "required": [
          "dataset",
          "aliases",
          "real_time"
        ],
        "properties": {
          "dataset": {
            "type": "string",
            "description": "Canonical dataset name, used in every path.",
            "examples": [
              "ethereum-mainnet"
            ]
          },
          "aliases": {
            "type": "array",
            "description": "Alternative names accepted in the same position.",
            "items": {
              "type": "string"
            }
          },
          "real_time": {
            "type": "boolean",
            "description": "Whether the dataset carries unfinalized, real-time blocks."
          }
        }
      },
      "DatasetMetadata": {
        "type": "object",
        "title": "DatasetMetadata",
        "required": [
          "dataset",
          "aliases",
          "real_time",
          "start_block"
        ],
        "properties": {
          "dataset": {
            "type": "string",
            "description": "Canonical dataset name."
          },
          "aliases": {
            "type": "array",
            "description": "Alternative names.",
            "items": {
              "type": "string"
            }
          },
          "real_time": {
            "type": "boolean",
            "description": "Whether real-time blocks are served."
          },
          "start_block": {
            "type": "integer",
            "format": "int64",
            "description": "Lowest block available. A `fromBlock` below this is a 400."
          }
        }
      },
      "DatasetState": {
        "type": "object",
        "title": "DatasetState",
        "description": "Which ranges each worker holds. Large; diagnostics only.",
        "required": [
          "worker_ranges",
          "highest_seen_block"
        ],
        "properties": {
          "worker_ranges": {
            "type": "object",
            "description": "Keyed by worker peer ID.",
            "additionalProperties": {
              "type": "object",
              "required": [
                "ranges"
              ],
              "properties": {
                "ranges": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "begin",
                      "end"
                    ],
                    "properties": {
                      "begin": {
                        "type": "integer",
                        "format": "int64",
                        "description": "First block, inclusive."
                      },
                      "end": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Last block, inclusive."
                      }
                    }
                  }
                }
              }
            }
          },
          "highest_seen_block": {
            "type": "integer",
            "format": "int64",
            "description": "Highest block number seen for this dataset."
          },
          "first_gap": {
            "type": "integer",
            "format": "int64",
            "description": "First block number with missing coverage, when one exists."
          }
        }
      },
      "BlockHead": {
        "type": [
          "object",
          "null"
        ],
        "title": "BlockHead",
        "description": "A block reference, or null when the dataset is empty.",
        "required": [
          "number",
          "hash"
        ],
        "properties": {
          "number": {
            "type": "integer",
            "format": "int64",
            "description": "Block number."
          },
          "hash": {
            "type": "string",
            "description": "Block hash."
          }
        }
      },
      "TimestampBlock": {
        "type": "object",
        "title": "TimestampBlock",
        "description": "The block a timestamp resolves to. On Solana `block_number` carries a slot.",
        "required": [
          "block_number"
        ],
        "properties": {
          "block_number": {
            "type": "integer",
            "format": "int64",
            "description": "Number of the first block at or after the requested instant."
          }
        }
      },
      "DataQuery": {
        "type": "object",
        "title": "DataQuery",
        "description": "What to read and which fields to return. `type` selects the chain family and must match\nthe dataset; the item filters below (`logs`, `transactions`, `traces`, `stateDiffs`) are the\nEVM set. Other families take their own item filters: Solana `instructions`, Bitcoin\n`transactions`, Hyperliquid `fills`, documented per chain in the SQD docs.\n\nUnknown keys are rejected with 400, and the error message lists what was accepted, so a\nclient can discover the exact per-chain shape from the API itself.",
        "required": [
          "type",
          "fromBlock"
        ],
        "additionalProperties": true,
        "properties": {
          "type": {
            "type": "string",
            "description": "Chain family of the dataset being queried.",
            "enum": [
              "evm",
              "solana",
              "substrate",
              "bitcoin",
              "fuel",
              "tron",
              "hyperliquidFills",
              "hyperliquidReplicaCmds"
            ],
            "examples": [
              "evm"
            ]
          },
          "fromBlock": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "First block to read, inclusive. Must be >= the dataset `start_block`."
          },
          "toBlock": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Last block to read, inclusive. Omit to stream until the dataset height, then keep following the chain."
          },
          "parentBlockHash": {
            "type": "string",
            "description": "Expected parent hash of the first requested block. When it disagrees with the chain, the request fails with 409 instead of returning orphaned data."
          },
          "includeAllBlocks": {
            "type": "boolean",
            "default": false,
            "description": "Return blocks in range even when nothing in them matches the filters."
          },
          "fields": {
            "type": "object",
            "description": "Field selector. Only requested fields are returned, which is what keeps responses small. The `block` selector below is the EVM set.",
            "additionalProperties": true,
            "properties": {
              "block": {
                "type": "object",
                "description": "EVM block header fields. Note `number`, not `height`.",
                "additionalProperties": false,
                "properties": {
                  "number": {
                    "type": "boolean",
                    "default": false
                  },
                  "hash": {
                    "type": "boolean",
                    "default": false
                  },
                  "parentHash": {
                    "type": "boolean",
                    "default": false
                  },
                  "timestamp": {
                    "type": "boolean",
                    "default": false
                  },
                  "transactionsRoot": {
                    "type": "boolean",
                    "default": false
                  },
                  "receiptsRoot": {
                    "type": "boolean",
                    "default": false
                  },
                  "stateRoot": {
                    "type": "boolean",
                    "default": false
                  },
                  "logsBloom": {
                    "type": "boolean",
                    "default": false
                  },
                  "sha3Uncles": {
                    "type": "boolean",
                    "default": false
                  },
                  "extraData": {
                    "type": "boolean",
                    "default": false
                  },
                  "miner": {
                    "type": "boolean",
                    "default": false
                  },
                  "nonce": {
                    "type": "boolean",
                    "default": false
                  },
                  "mixHash": {
                    "type": "boolean",
                    "default": false
                  },
                  "size": {
                    "type": "boolean",
                    "default": false
                  },
                  "gasLimit": {
                    "type": "boolean",
                    "default": false
                  },
                  "gasUsed": {
                    "type": "boolean",
                    "default": false
                  },
                  "difficulty": {
                    "type": "boolean",
                    "default": false
                  },
                  "totalDifficulty": {
                    "type": "boolean",
                    "default": false
                  },
                  "baseFeePerGas": {
                    "type": "boolean",
                    "default": false
                  },
                  "uncles": {
                    "type": "boolean",
                    "default": false
                  },
                  "withdrawals": {
                    "type": "boolean",
                    "default": false
                  },
                  "withdrawalsRoot": {
                    "type": "boolean",
                    "default": false
                  },
                  "blobGasUsed": {
                    "type": "boolean",
                    "default": false
                  },
                  "excessBlobGas": {
                    "type": "boolean",
                    "default": false
                  },
                  "parentBeaconBlockRoot": {
                    "type": "boolean",
                    "default": false
                  },
                  "requestsHash": {
                    "type": "boolean",
                    "default": false
                  },
                  "l1BlockNumber": {
                    "type": "boolean",
                    "default": false
                  },
                  "mainBlockGeneralGasLimit": {
                    "type": "boolean",
                    "default": false
                  },
                  "sharedGasLimit": {
                    "type": "boolean",
                    "default": false
                  },
                  "timestampMillisPart": {
                    "type": "boolean",
                    "default": false
                  }
                }
              }
            }
          },
          "logs": {
            "type": "array",
            "description": "EVM log filters. Entries are OR-ed; keys within an entry are AND-ed.",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "properties": {
                "address": {
                  "type": "array",
                  "description": "Contract addresses, lowercase hex.",
                  "items": {
                    "type": "string"
                  }
                },
                "topic0": {
                  "type": "array",
                  "description": "Event signature hashes.",
                  "items": {
                    "type": "string"
                  }
                },
                "topic1": {
                  "type": "array",
                  "description": "First indexed argument.",
                  "items": {
                    "type": "string"
                  }
                },
                "topic2": {
                  "type": "array",
                  "description": "Second indexed argument.",
                  "items": {
                    "type": "string"
                  }
                },
                "topic3": {
                  "type": "array",
                  "description": "Third indexed argument.",
                  "items": {
                    "type": "string"
                  }
                },
                "transaction": {
                  "type": "boolean",
                  "description": "Also return the transaction that produced each matching log."
                }
              }
            }
          },
          "transactions": {
            "type": "array",
            "description": "EVM transaction filters. Entries are OR-ed.",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "properties": {
                "from": {
                  "type": "array",
                  "description": "Sender addresses.",
                  "items": {
                    "type": "string"
                  }
                },
                "to": {
                  "type": "array",
                  "description": "Recipient addresses.",
                  "items": {
                    "type": "string"
                  }
                },
                "sighash": {
                  "type": "array",
                  "description": "Function selectors.",
                  "items": {
                    "type": "string"
                  }
                },
                "logs": {
                  "type": "boolean",
                  "description": "Also return the logs each match emitted."
                },
                "traces": {
                  "type": "boolean",
                  "description": "Also return the traces each match produced."
                }
              }
            }
          },
          "traces": {
            "type": "array",
            "description": "EVM trace filters, for internal calls and contract creations.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "stateDiffs": {
            "type": "array",
            "description": "EVM storage state-diff filters.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "Block": {
        "type": "object",
        "title": "Block",
        "description": "One line of a stream response. `header` always carries the requested header fields; the other keys appear only when the query asked for those item types.",
        "required": [
          "header"
        ],
        "additionalProperties": true,
        "properties": {
          "header": {
            "type": "object",
            "description": "The header fields named in `fields.block`.",
            "additionalProperties": true,
            "properties": {
              "number": {
                "type": "integer",
                "format": "int64",
                "description": "Block number."
              },
              "hash": {
                "type": "string",
                "description": "Block hash."
              }
            }
          },
          "logs": {
            "type": "array",
            "description": "Matching logs.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "transactions": {
            "type": "array",
            "description": "Matching transactions.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "traces": {
            "type": "array",
            "description": "Matching traces.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "stateDiffs": {
            "type": "array",
            "description": "Matching state diffs.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "instructions": {
            "type": "array",
            "description": "Matching Solana instructions.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "ConflictResponse": {
        "type": "object",
        "title": "ConflictResponse",
        "description": "Returned with 409. Lists recent blocks on the chain the portal is serving so the client can find a common ancestor and resume.",
        "additionalProperties": true,
        "properties": {
          "previousBlocks": {
            "type": "array",
            "description": "Recent blocks on the current chain, newest last.",
            "items": {
              "type": "object",
              "required": [
                "number",
                "hash"
              ],
              "properties": {
                "number": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Block number."
                },
                "hash": {
                  "type": "string",
                  "description": "Block hash."
                }
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "title": "ErrorResponse",
        "description": "The single error envelope, returned as JSON on every failing status code. Match on `error.code`; `error.message` is written for humans and may be reworded.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "description": "The error itself. Present on every failing response.",
            "required": [
              "type",
              "code",
              "message"
            ],
            "properties": {
              "type": {
                "type": "string",
                "description": "Error class.",
                "examples": [
                  "invalid_request_error"
                ]
              },
              "code": {
                "type": "string",
                "description": "Stable, machine-matchable identifier.",
                "examples": [
                  "unknown_dataset",
                  "malformed_request",
                  "method_not_allowed",
                  "not_found"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation."
              }
            }
          }
        },
        "examples": [
          {
            "error": {
              "type": "invalid_request_error",
              "code": "unknown_dataset",
              "message": "Unknown dataset: not-a-real-dataset"
            }
          }
        ]
      }
    }
  }
}