GraphQL API

Auto-generated from your TOML config. Every table gets a query endpoint.

Endpoints

Enable the API with [api] port in TOML or --api-port on the CLI.

PathDescription
/GraphiQL IDE
/graphqlGraphQL endpoint
/healthLiveness probe
/readyReadiness (503 during backfill)
/metricsPrometheus metrics

Query shape

Each table is a root field named after the table. It returns a connection: the rows are under nodes and the paging state is under pageInfo.

graphql
{
  usdc_transfers(first: 10) {
    nodes {
      block_number
      tx_hash
      value
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
  _meta {
    block
  }
}

_meta.block is the last committed block, so you can tell how fresh the data is.

Filter operators

Filters go in the where argument as column or column_suffix. Which suffixes a column gets depends on its type:

SuffixMeaning
(none)Equal
_neNot equal
_inIn list
_not_inNot in list
_gtGreater than
_gteGreater than or equal
_ltLess than
_lteLess than or equal
_containsContains substring
_starts_withStarts with

Numeric values, including uint256 amounts, are passed as strings, for example value_gte: "1000000000". A column overridden in columns to a type other than text, numeric, bigint, integer, boolean, or bytea only gets equality, _in, and _not_in.

Filter composition

Filters at the same level in where are combined with AND. OR takes a list of filter objects, and each of those can nest its own OR.

graphql
{
  usdc_transfers(
    where: {
      OR: [
        { from_address: "0xAbc..." }
        { to_address: "0xAbc..." }
      ]
      value_gte: "1000000000"
    }
    orderBy: block_number
    orderDirection: DESC
    first: 50
  ) {
    nodes {
      block_number
      tx_hash
      from_address
      to_address
      value
      block_timestamp
    }
  }
}

Pagination

first defaults to 100 and is capped at 1000. Two pagination modes:

Cursor-based

graphql
{
  usdc_transfers(first: 100, after: "<endCursor from the previous page>") {
    nodes {
      block_number
      tx_hash
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Pass the previous page's pageInfo.endCursor as after and keep the same orderBy and orderDirection. Stop when hasNextPage is false. Best for large datasets and infinite scroll.

Offset-based

graphql
{
  usdc_transfers(first: 50, skip: 100) {
    nodes {
      block_number
      tx_hash
    }
  }
}

Use first and skip for simple page-based navigation.

Sorting

graphql
{
  usdc_transfers(
    orderBy: block_number
    orderDirection: ASC
    first: 10
  ) {
    nodes {
      block_number
      value
    }
  }
}

orderBy accepts any column name and defaults to id. orderDirection is ASC or DESC (uppercase) and defaults to DESC.