BlockVectra Tokens API

ERC-20/ERC-721/ERC-1155 transfers, holders, and metadata.

Operations 4

GET /{chain}/tokens/{token}/transfers List a token contract's transfers #
GET /{chain}/tokens/{token}/holders List a token's holders #
GET /{chain}/tokens/{token} Get token metadata #
POST /{chain}/tokens:batch Batch get token metadata #

Specifications

Schemas & Data

📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-freshness-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-token-transfer-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-address-transfer-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-tokens-batch-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-dex-swap-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-transaction-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-key-view-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-balance-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-plans-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-resets-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-identity-view-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-session-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-subscription-create-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-subscription-patch-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-remove-result-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-add-result-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-event-history-page-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-subscription-list-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-faucet-claim-accepted-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-faucet-claim-request-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-json-rpc-response-body-schema.json

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/blockvectra:blockvectra-tokens-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

blockvectra-tokens-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: BlockVectra Data Tokens API
  version: 0.1.3
  description: BlockVectra Data API — read-only REST endpoints over indexed data for each supported chain. The base URL is `https://api.blockvectra.com/v1/data`; supply your API key in the `x-api-key` header.
  contact:
    name: BlockVectra
servers:
- url: https://api.blockvectra.com/v1/data
  description: BlockVectra Data API
security:
- ApiKeyHeader: []
tags:
- name: Tokens
  description: ERC-20/ERC-721/ERC-1155 transfers, holders, and metadata.
paths:
  /{chain}/tokens/{token}/transfers:
    get:
      tags:
      - Tokens
      summary: List a token contract's transfers
      description: 'Keyset-paginated list of token transfers for a specific token contract by `?standard=` (`erc20`, `erc721`, or `erc1155`), ordered by recency descending. The window''s lower bound is computed per dataset (the token transfers of that standard), not from the chain''s start alone: it is above `GET /chains` `coverage.from_block` only when that dataset has a recorded build coverage starting higher. A window entirely before it is `422 no_coverage`; one that starts before it, or has no `from_block`, is served as far as it goes with `meta.coverage = "partial"`. Limitation: during an *ascending* backfill the hole between the backfilled tail and the live start is not detected (the dataset''s start is its lowest covered block), so a window inside that hole is still `200` with an empty list.'
      operationId: getTokenTransfers
      parameters:
      - $ref: '#/components/parameters/ChainParam'
      - $ref: '#/components/parameters/TokenPath'
      - name: standard
        in: query
        required: true
        description: Transfer standard to query (`erc20`, `erc721`, or `erc1155`).
        schema:
          type: string
          enum:
          - erc20
          - erc721
          - erc1155
      - name: from_block
        in: query
        required: false
        description: Optional lower bound (inclusive), non-negative integer. An explicit value above `as_of_block` is a hard `409 not_indexed_yet` (`from_block > to_block` is 400).
        schema:
          type: integer
          minimum: 0
      - name: to_block
        in: query
        required: false
        description: Optional upper bound (inclusive), non-negative integer. Absent defaults to `as_of_block`, the newest fully written block (never an error); an explicit value above `as_of_block` is a hard `409 not_indexed_yet` — there is no `clamp` escape for this endpoint. `meta.finalized_block` is a marker and never bounds the window.
        schema:
          type: integer
          minimum: 0
      - $ref: '#/components/parameters/Limit'
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: This token's transfers, newest first.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenTransferListEnvelope'
        '400':
          description: '`error.code = "bad_request"`: invalid `{token}`; missing `standard`; `standard` not one of `erc20`/`erc721`/`erc1155`; `from_block`/`to_block` not a non-negative integer; `from_block > to_block`; invalid `limit`; or an invalid `cursor`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '401':
          $ref: '#/components/responses/GatewayUnauthorized'
        '402':
          $ref: '#/components/responses/GatewayPaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: '`error.code = "not_indexed_yet"`: an explicit `to_block` or `from_block` is above `as_of_block`. On a chain with no indexed block at all it is the same code without `indexed_through` (see "Errors").'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '422':
          $ref: '#/components/responses/NoCoverage'
        '429':
          $ref: '#/components/responses/GatewayRateLimited'
        '503':
          $ref: '#/components/responses/Unavailable'
  /{chain}/tokens/{token}/holders:
    get:
      tags:
      - Tokens
      summary: List a token's holders
      description: 'Keyset-paginated list of token holders for an ERC-20 token, ordered by `balance DESC, holder DESC`. `meta.coverage` is always `"full"`: a truncated page simply carries a `next_cursor`.

        **Snapshot freshness**: holders come from the same materialized ERC-20 balance snapshot, refreshed every 6 hours (with up to 30 minutes of random delay), so the newest rows can be about 6.5 hours old plus the refresh run itself. `as_of_block` here is the service''s current indexed head, not the block height of the snapshot; read the snapshot time from `meta.refreshed_at`, and treat the data as stale when `refreshed_at` is `null`.'
      operationId: getTokenHolders
      parameters:
      - $ref: '#/components/parameters/ChainParam'
      - $ref: '#/components/parameters/TokenPath'
      - $ref: '#/components/parameters/Limit'
      - name: sort
        in: query
        required: false
        description: 'Sort order. Supported values: `balance`. Omitting it also sorts by balance.'
        schema:
          type: string
          enum:
          - balance
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: This token's holders, largest balance first.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenHolderListEnvelope'
        '400':
          description: '`error.code = "bad_request"`: invalid `{token}`; `sort` present and not `balance`; invalid `limit`; or an invalid `cursor`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
              example:
                error:
                  code: bad_request
                  message: 'invalid sort ''foo'': supported values: balance'
        '401':
          $ref: '#/components/responses/GatewayUnauthorized'
        '402':
          $ref: '#/components/responses/GatewayPaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/NotIndexedYetEmptyChain'
        '422':
          $ref: '#/components/responses/NoCoverage'
        '429':
          $ref: '#/components/responses/GatewayRateLimited'
        '503':
          $ref: '#/components/responses/Unavailable'
  /{chain}/tokens/{token}:
    get:
      tags:
      - Tokens
      summary: Get token metadata
      description: Fetch token metadata (symbol, name, decimals, total supply) by contract address.
      operationId: getTokenMeta
      parameters:
      - $ref: '#/components/parameters/ChainParam'
      - $ref: '#/components/parameters/TokenPath'
      responses:
        '200':
          description: Token metadata.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenEnvelope'
        '400':
          description: '`error.code = "bad_request"`: invalid `{token}`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '401':
          $ref: '#/components/responses/GatewayUnauthorized'
        '402':
          $ref: '#/components/responses/GatewayPaymentRequired'
        '404':
          description: '`error.code = "not_found"`: either `{chain}` is unknown or not public, or metadata for `{token}` was not found.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '409':
          $ref: '#/components/responses/NotIndexedYetEmptyChain'
        '422':
          $ref: '#/components/responses/NoCoverage'
        '429':
          $ref: '#/components/responses/GatewayRateLimited'
        '503':
          $ref: '#/components/responses/Unavailable'
  /{chain}/tokens:batch:
    post:
      tags:
      - Tokens
      summary: Batch get token metadata
      description: Batch retrieve token metadata for up to 100 addresses. Unknown addresses do not trigger an error; they are listed in `missing` instead. Duplicate addresses in the request are deduplicated in both `tokens` and `missing`, each in first-occurrence request order.
      operationId: postTokensBatch
      parameters:
      - $ref: '#/components/parameters/ChainParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokensBatchRequest'
            example:
              addresses:
              - '0x1111111111111111111111111111111111111111'
              - '0x2222222222222222222222222222222222222222'
      responses:
        '200':
          description: Found tokens plus the list of addresses that were not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokensBatchEnvelope'
        '400':
          description: '`error.code = "bad_request"`: the body is not valid JSON matching `{"addresses": [...]}`; `addresses` has more than 100 entries; or any entry is not a valid 20-byte address (the request fails on the first invalid address it walks to, not a batched report of every invalid one).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
              examples:
                invalid_json:
                  value:
                    error:
                      code: bad_request
                      message: request body is not valid JSON (line 1, column 4)
                missing_addresses:
                  value:
                    error:
                      code: bad_request
                      message: missing required field `addresses`
        '401':
          $ref: '#/components/responses/GatewayUnauthorized'
        '402':
          $ref: '#/components/responses/GatewayPaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/NotIndexedYetEmptyChain'
        '422':
          $ref: '#/components/responses/NoCoverage'
        '429':
          $ref: '#/components/responses/GatewayRateLimited'
        '503':
          $ref: '#/components/responses/Unavailable'
components:
  schemas:
    AddressInput:
      type: string
      description: 20-byte address. `0x`/`0X` prefix optional; either hex digit case is accepted.
      pattern: ^(0[xX])?[0-9a-fA-F]{40}$
      example: '0xAbCdEf0123456789aBcDeF0123456789aBCDEF01'
    TokensBatchEnvelope:
      type: object
      required:
      - data
      - meta
      properties:
        data:
          type: object
          required:
          - tokens
          - missing
          properties:
            tokens:
              type: array
              items:
                $ref: '#/components/schemas/Token'
            missing:
              type: array
              description: Canonical (`0x`-lowercase) addresses from the request with no matching metadata, first-occurrence request order, deduplicated.
              items:
                $ref: '#/components/schemas/Address'
        meta:
          $ref: '#/components/schemas/Meta'
    TokensBatchRequest:
      type: object
      required:
      - addresses
      properties:
        addresses:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/AddressInput'
    Erc721Transfer:
      type: object
      required:
      - token
      - standard
      - from
      - to
      - token_id
      - block_number
      - block_timestamp
      - tx_hash
      - tx_index
      - log_index
      properties:
        token:
          $ref: '#/components/schemas/Address'
        standard:
          type: string
          const: erc721
        from:
          $ref: '#/components/schemas/Address'
        to:
          $ref: '#/components/schemas/Address'
        token_id:
          $ref: '#/components/schemas/UInt256String'
        block_number:
          type: integer
          format: int64
        block_timestamp:
          $ref: '#/components/schemas/Timestamp'
        tx_hash:
          $ref: '#/components/schemas/Hash32'
        tx_index:
          type: integer
        log_index:
          type: integer
    TokenHolder:
      type: object
      required:
      - token
      - holder
      - balance
      properties:
        token:
          $ref: '#/components/schemas/Address'
        holder:
          $ref: '#/components/schemas/Address'
        balance:
          $ref: '#/components/schemas/UInt256String'
    Erc1155Transfer:
      type: object
      required:
      - token
      - standard
      - operator
      - from
      - to
      - token_id
      - value
      - block_number
      - block_timestamp
      - tx_hash
      - tx_index
      - log_index
      - batch_index
      properties:
        token:
          $ref: '#/components/schemas/Address'
        standard:
          type: string
          const: erc1155
        operator:
          $ref: '#/components/schemas/Address'
        from:
          $ref: '#/components/schemas/Address'
        to:
          $ref: '#/components/schemas/Address'
        token_id:
          $ref: '#/components/schemas/UInt256String'
        value:
          $ref: '#/components/schemas/UInt256String'
        block_number:
          type: integer
          format: int64
        block_timestamp:
          $ref: '#/components/schemas/Timestamp'
        tx_hash:
          $ref: '#/components/schemas/Hash32'
        tx_index:
          type: integer
        log_index:
          type: integer
        batch_index:
          type: integer
    Meta:
      type: object
      description: Metadata present on every success response.
      required:
      - chain
      - chain_slug
      - chain_external_id
      - as_of_block
      - safe_block
      - finalized_block
      - coverage
      - refreshed_at
      properties:
        chain:
          type: string
          description: Chain identifier; the value of the `{chain}` path parameter.
          example: robinhood_mainnet
        chain_slug:
          type: string
          description: Canonical uppercase chain slug; `chain` is always its lowercase form.
          example: ROBINHOOD_MAINNET
        chain_external_id:
          type: string
          description: CAIP-2 formatted external chain identifier (`eip155:{chain_id}`).
          example: eip155:4663
        as_of_block:
          type: integer
          format: int64
          description: 'The newest fully written block (the `blocks` table''s maximum height); the only serving bound for block-scoped endpoints. For snapshot endpoints (balances, holders, nfts, dex prices, stocks) it is the service''s current indexed head, not the block height of the snapshot: read the snapshot time from `meta.refreshed_at`, and treat the data as stale when `refreshed_at` is `null`.'
        safe_block:
          type:
          - integer
          - 'null'
          format: int64
          description: 'A marker only: the node''s consensus `safe` block. Always present; `null` while no value is known (the node has no such tag, or the indexer has not read one yet). Only grows, never below `finalized_block`, and may be above or below `as_of_block`. It never truncates, rejects or bounds a response; see Finality in the API description.'
        finalized_block:
          type:
          - integer
          - 'null'
          format: int64
          description: 'A marker only: the node''s consensus `finalized` block. Always present; `null` while no value is known (the node has no such tag, or the indexer has not read one yet). Only grows, and may be above or below `as_of_block`. It never truncates, rejects or bounds a response; see Finality in the API description.'
        coverage:
          type: string
          enum:
          - full
          - partial
          description: '`"partial"` appears only from `GET /{chain}/addresses/{address}/transactions` and `GET /{chain}/addresses/{address}/transfers`, when `clamp=true` narrowed the served window, and from those two, `GET /{chain}/tokens/{token}/transfers` and `GET /{chain}/dex/swaps` when the block window starts before the lower bound of the dataset the endpoint reads -- the chain''s first indexed block, or higher while that dataset is still being backfilled (see Coverage in the API description and each endpoint''s window description). Every other endpoint reports `"full"`.'
        refreshed_at:
          description: 'When the data behind this response was last updated (UTC): the timestamp of `as_of_block` for block-based endpoints, the latest snapshot time for snapshot endpoints, and the last update time for token metadata and status. `null` means the snapshot''s update time is currently unknown: treat the data as stale; it never means "just refreshed".'
          oneOf:
          - $ref: '#/components/schemas/Timestamp'
          - type: 'null'
    TokenTransferListEnvelope:
      type: object
      required:
      - data
      - meta
      description: '`next_cursor` is present only when the page returned exactly `limit` rows (optimistic pagination: it may turn out to be the last page anyway).'
      properties:
        data:
          type: array
          items:
            oneOf:
            - $ref: '#/components/schemas/Erc20Transfer'
            - $ref: '#/components/schemas/Erc721Transfer'
            - $ref: '#/components/schemas/Erc1155Transfer'
        next_cursor:
          type: string
          description: Opaque pagination token from the previous response's `next_cursor`; pass it back unchanged.
        meta:
          $ref: '#/components/schemas/Meta'
    ErrorBody:
      type: object
      description: The only shape any non-2xx response ever takes. `code` and `message` are always present; `indexed_through` is present only on `error.code = "not_indexed_yet"` on a chain with an indexed block, and absent (never `null`) otherwise. No other field is ever added.
      required:
      - error
      additionalProperties: false
      properties:
        error:
          type: object
          required:
          - code
          - message
          additionalProperties: false
          properties:
            code:
              type: string
              description: Stable machine-readable identifier; see each operation for the exact set of values it can return.
            message:
              type: string
              description: Free-form English text for logs/debugging. Do not pattern-match on it.
            indexed_through:
              type: integer
              format: int64
              description: 'Highest indexed block on this chain. Present only when `code = "not_indexed_yet"` and the chain has at least one indexed block; absent when it has none at all (an absent value is not `0`: block 0 indexed is `indexed_through: 0`).'
            data:
              type: object
              description: Optional structured error details.
              additionalProperties: true
    Token:
      type: object
      required:
      - address
      - standard
      - name
      - symbol
      - decimals
      - total_supply
      - first_seen_block
      - metadata_updated_at
      - metadata_block
      - metadata_status
      - metadata_issues
      properties:
        address:
          $ref: '#/components/schemas/Address'
        standard:
          type: string
          enum:
          - erc20
          - erc721
          - unknown
        name:
          oneOf:
          - type: string
          - type: 'null'
        symbol:
          oneOf:
          - type: string
          - type: 'null'
        decimals:
          oneOf:
          - type: integer
            minimum: 0
            maximum: 255
          - type: 'null'
        total_supply:
          oneOf:
          - $ref: '#/components/schemas/UInt256String'
          - type: 'null'
          description: Raw on-chain integer, no `decimals` scaling applied server-side.
        first_seen_block:
          type: integer
          format: int64
        metadata_updated_at:
          $ref: '#/components/schemas/Timestamp'
          description: When this token's metadata was last updated (UTC).
        metadata_block:
          type: integer
          format: int64
          description: Block height at which this token's metadata was read.
        metadata_status:
          type: string
          enum:
          - ok
          - partial
          - unavailable
          description: Overall status of the token metadata.
        metadata_issues:
          type: object
          description: Issues encountered while fetching individual metadata fields. Key is the field name; value is the issue category.
          properties:
            name:
              type: string
              enum:
              - reverted
              - no_data
              - invalid_encoding
              - temporarily_unavailable
            symbol:
              type: string
              enum:
              - reverted
              - no_data
              - invalid_encoding
              - temporarily_unavailable
            decimals:
              type: string
              enum:
              - reverted
              - no_data
              - invalid_encoding
              - temporarily_unavailable
            total_supply:
              type: string
              enum:
              - reverted
              - no_data
              - invalid_encoding
              - temporarily_unavailable
          additionalProperties: false
    Timestamp:
      type: string
      format: date-time
      description: '`YYYY-MM-DDTHH:MM:SSZ`, UTC, second precision.'
      example: 2026-09-26 05:41:07+00:00
    Address:
      type: string
      description: 20-byte address, canonical form always `0x` + 40 lowercase hex digits.
      pattern: ^0x[0-9a-f]{40}$
    TokenEnvelope:
      type: object
      required:
      - data
      - meta
      properties:
        data:
          $ref: '#/components/schemas/Token'
        meta:
          $ref: '#/components/schemas/Meta'
    TokenHolderListEnvelope:
      type: object
      required:
      - data
      - meta
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/TokenHolder'
        next_cursor:
          type: string
          description: Opaque pagination token from the previous response's `next_cursor`; pass it back unchanged.
        meta:
          $ref: '#/components/schemas/Meta'
    Erc20Transfer:
      type: object
      required:
      - token
      - standard
      - from
      - to
      - amount
      - block_number
      - block_timestamp
      - tx_hash
      - tx_index
      - log_index
      properties:
        token:
          $ref: '#/components/schemas/Address'
        standard:
          type: string
          const: erc20
        from:
          $ref: '#/components/schemas/Address'
        to:
          $ref: '#/components/schemas/Address'
        amount:
          $ref: '#/components/schemas/UInt256String'
        block_number:
          type: integer
          format: int64
        block_timestamp:
          $ref: '#/components/schemas/Timestamp'
        tx_hash:
          $ref: '#/components/schemas/Hash32'
        tx_index:
          type: integer
        log_index:
          type: integer
    Hash32:
      type: string
      description: 32-byte hash/topic, canonical form always `0x` + 64 lowercase hex digits.
      pattern: ^0x[0-9a-f]{64}$
    UInt256String:
      type: string
      description: Non-negative integer that may exceed 2^53, rendered as a plain decimal string — never a JSON number, never scientific or hex notation.
      pattern: ^[0-9]+$
      example: '9007199254740993'
  responses:
    GatewayPaymentRequired:
      description: 'Payment required: the paid balance or the free grant is exhausted. The response body is `{"error":{"code":"insufficient_balance"}}`. Rejected requests are not billed.'
    Unavailable:
      description: '`error.code = "unavailable"`: the service is temporarily unavailable, timed out, busy on this chain (no query slot freed up in time, see `limits.max_concurrent_queries` in `GET /chains`), or shutting down (see "Errors" above). Always carries an HTTP `Retry-After` header (seconds); wait at least that long before retrying.'
      headers:
        Retry-After:
          required: true
          schema:
            type: integer
            minimum: 1
          description: Seconds to wait before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error:
              code: unavailable
              message: service temporarily unavailable, please retry
    GatewayRateLimited:
      description: Rate limited. `{"error":{"code":"rate_limited"}}` when the key CU rate limit is exceeded (the response includes `Retry-After`) or the account call rate limit is exceeded (no `Retry-After`). `{"error":{"code":"cost_exceeds_burst"}}` when a single request exceeds the key burst capacity; split the request, retrying as sent never succeeds. Rejected requests are not billed.
    NotFound:
      description: '`error.code = "not_found"`: the target object was not found, or `{chain}` is not a registered or public chain (returns HTTP 404 with `error.code = "not_found"`, not billed).'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          examples:
            unknown_chain:
              summary: Unknown or not-public chain
              value:
                error:
                  code: not_found
                  message: unknown chain
            object_not_found:
              summary: Resource not found
              value:
                error:
                  code: not_found
                  message: block not found
          example:
            error:
              code: not_found
              message: unknown chain
    NoCoverage:
      description: '`error.code = "no_coverage"`: no data here, which is permanent except while a dataset is being backfilled (a windowed endpoint''s lower bound can move down as the backfill proceeds, so retry later). Either the chain does not have this endpoint''s capability, or the requested block (or whole block window) is before the chain''s first covered block (`coverage.from_block`) -- for the windowed endpoints, the lower bound of the dataset they read, which is that block or higher while the dataset is still being backfilled -- or the capability needs history from genesis (`balances`, `holders`, `nfts`) and `coverage.from_block` is not `0` yet or the indexed blocks have holes, or (traces) the block falls in a permanent trace coverage gap. A block window entirely before the lower bound is reported as this `422` even when its `to_block` is also above `as_of_block`. See Coverage in the API description (the history start in examples is a placeholder; read `GET /chains` `coverage.from_block` at runtime).'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          examples:
            capability:
              value:
                error:
                  code: no_coverage
                  message: chain 'eth_mainnet' does not support balances
            before_history:
              summary: the start is live -- read `GET /chains` `coverage.from_block` at runtime
              value:
                error:
                  code: no_coverage
                  message: block 1 is before indexed history start <from_block> on chain 'eth_mainnet'
            history_not_at_genesis:
              summary: balances, holders and nfts need history from genesis
              value:
                error:
                  code: no_coverage
                  message: 'chain ''eth_mainnet'' does not serve balances yet: it needs history from genesis and indexed history starts at block <from_block>'
    GatewayUnauthorized:
      description: 'HTTP 401: a missing API key returns missing_api_key; an unknown, disabled, or revoked key returns the same invalid_api_key error envelope. error.code and error.data.reason contain the reason. Rejected requests are not billed.'
      content:
        application/json:
          examples:
            missing_api_key:
              value:
                error:
                  code: missing_api_key
                  message: 'missing API key: send it in the x-api-key header'
                  data:
                    reason: missing_api_key
                    docs_url: https://docs.blockvectra.com/en/errors/#missing_api_key
                    retryable: false
            invalid_api_key:
              value:
                error:
                  code: invalid_api_key
                  message: 'invalid API key: it is unknown, disabled or revoked; check the key in the console'
                  data:
                    reason: invalid_api_key
                    docs_url: https://docs.blockvectra.com/en/errors/#invalid_api_key
                    retryable: false
    NotIndexedYetEmptyChain:
      description: 'After the operation passes its earlier routing, capability, parameter and permit checks and reaches the indexed-head check, `error.code = "not_indexed_yet"` without `indexed_through`: the chain has no indexed block at all yet (`GET /chains` `coverage.has_data = false`), so there is no head to answer against (see "Errors" above). Transient: retry later. A missing capability (including `traces`) is checked before the empty head and returns `422 no_coverage` instead.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error:
              code: not_indexed_yet
              message: 'chain ''hyperevm_mainnet'' has no indexed data yet: no block has been indexed'
  parameters:
    TokenPath:
      name: token
      in: path
      required: true
      description: 20-byte token contract address, `0x` optional, either case.
      schema:
        $ref: '#/components/schemas/AddressInput'
    ChainParam:
      name: chain
      in: path
      required: true
      description: 'Chain identifier: the `chain` value of an entry in `GET /chains` (for example `robinhood_mainnet`), which lists every value this API accepts, i.e. the exact lowercase form of that entry''s `chain_slug`. Matching is exact and case-sensitive; other spellings, aliases and numeric chain IDs are not accepted and return `404 not_found` (unknown or not-public chain). What the chain serves differs per chain: see that entry''s `features` and `coverage`.'
      schema:
        type: string
        pattern: ^[a-z][a-z0-9]*(_[a-z0-9]+)+$
      examples:
        robinhood_mainnet:
          value: robinhood_mainnet
        eth_mainnet:
          value: eth_mainnet
    Cursor:
      name: cursor
      in: query
      required: false
      description: Opaque pagination token from the previous response's `next_cursor`; pass it back unchanged.
      schema:
        type: string
    Limit:
      name: limit
      in: query
      required: false
      description: Page size. Absent defaults to 50. `0` or a non-integer value is `400 bad_request`. A value above 500 is clamped to 500, not rejected.
      schema:
        type: integer
        minimum: 1
        default: 50
        maximum: 500
  securitySchemes:
    ApiKeyHeader:
      type: apiKey
      in: header
      name: x-api-key
      description: Your BlockVectra API key.