Skip to main content
Version: 0.9.1

Tables API

The Table API supports fetching large quantities of data. Tables can flexibly filter data of interest and let you pick the exact list of columns for a result. Tables have a much higher limit of 50,000 entries. However, binary data is not unpacked so we recommend you use our SDKs.

Generic Table Query​

GET /tables/{table_code}.{format}?{args}

Tables store data in tabular form as a set of columns. Each column has a specified type and each row has a unique uint64 row_id. Empty values are represented as JSON null or empty strings. Tables can grow extremely large, so it's good practice to use filters and the columns query argument to limit the result size. Table responses are automatically sorted by row_id. Use client-side sorting if a different sorting order is required.

Row Ids, uniqueness and comparisons​

Please don't treat row ids as globally unique, stable or comparable. Row ids are essentially table sequence numbers that are only unique within a particular version of a table. Lets use two scenarios to explain why that matters:

We use multiple independent indexer instances for scaling the TzPro API to support many concurrent users. Each indexer locally stores its own private database tables. On chain reorgs our indexers roll back history by removing side-chain operations and reverse-updating account balances. That means two different indexers instances may end up seeing two different chain reorg histories. When that happens, these instances will have different row ids for operations and likely also accounts in their individual databases.

The same can happen when we from time to time update the indexer and rebuild databases as result. In this case a previously observed chain reorg will be lost and the database will only contain data about the canonical chain. This means that even the same API instance can return different row ids for the same historic operations when on-chain history was built without knowledge of a reorgs.

As work-around you can use the combination of block height and operation positions op_l, op_n if your application requires a unique id other than a hash.

List of Tables​

EndpointTable Content
GET /tables/balancehistoric end-of-block balances for all accounts
GET /tables/chainrunning blockchain totals
GET /tables/supplyrunning supply totals
GET /tables/blockblocks (including orphans)
GET /tables/opoperations (only final)
GET /tables/accountmost recent account balances and state
GET /tables/contractsmart contracts state at creation
GET /tables/constantsmart contract global constants
GET /tables/flowbalance, freezer and delegation flows
GET /tables/rightsbaking and endorsing rights
GET /tables/snapshotbalances of active delegates & delegators at all snapshot blocks
GET /tables/incomeper-cycle statistics on baker income, efficiency, etc
GET /tables/gov_electionelection metadata (i.e. entire governance cycles)
GET /tables/gov_proposalindividual proposals
GET /tables/gov_votevoting period metadata
GET /tables/gov_ballotballots and proposal operations
GET /tables/bigmap_typesbigmap identity
GET /tables/bigmap_valuescurrently live bigmap values
GET /tables/bigmap_updateshistoric bigmap updates (including copy/alloc)

Query Arguments​

Tables support the following general query parameters.

ArgumentDescription
columns optionalComma separated list of column names to return. Bulk array results will be ordered accordingly. Default is all defined columns for a table.
limit optionalMaximum number of rows to return. Limited to 50,000, default 500.
cursor optionalId (row_id) of the latest result row returned by a previous call.
order optionalResult order either asc (default) or desc, sorted by row_id.

To paginate result sets larger than the maximum limit, include row_id into the list of columns and use the last value of row_id as cursor in your next call. This will automatically apply an extra filter row_id.gt=cursor for ascending and row_id.lt=cursor for descending order. You can of course also apply the relevant row_id filter directly, without using cursor.

Query Filters​

Filter Example

The example below filters blocks by time range from time.gte=2019-08-01 (inclusive) to time.lte=2019-08-31 (inclusive) and returns columns time and height. The same effect can be achieved with the range operator time.rg=2019-08-01,2019-08-31.

GET /tables/block.json?
columns=time,height&
time.gte=2018-08-01&
time.lte=2018-08-31&
limit=50000

JSON Result​

[
[1533081657000,42672],
[1533081717000,42673],
[1533081777000,42674],
[1533081837000,42675],
[1533081897000,42676],
[1533081957000,42677],
[1533082017000,42678],
[1533082152000,42679],
[1533082287000,42680],
[1533082347000,42681],
[1533082407000,42682],
// ...
]

To filter tables use filter expressions of the form <column>.<operator>=<arg>. Filters work on any combination of columns regardless of type. For arguments, type encoding rules of the column type apply. Filtering by multiple columns is similar to a logical AND between expressions. For simplicity and performance there are currently no OR expressions or more complex operators available. Comparison order for strings and binary is the lexicographical order over UTF8 (string) or ASCII (binary) alphabets.

OperatorSemantics
=, .eq=Equal. Matches rows where column values match exactly the filter value.
.ne=Not equal. Matches rows where column values do not match the filter value.
.gt=Greater than. matches columns whose value is strictly greater than the filter value.
.gte=Greater than or equal. matches columns whose value is greater than or equal to the filter value.
.lt=Less than. matches columns whose value is strictly smaller than the filter value.
.lte=Less than or equal. matches columns whose value is strictly smaller than or equal to the filter value.
.in=Inclusion in list. matches columns whose value is equal to one of the filter values. Multiple values must be separated by comma.
.nin=Not included in list. matches columns whose value is not equal to one of the filter values. Multiple values may be separated by comma.
.rg=Range. matches columns whose value is between the provided filter values, boundary inclusive. Requires exactly two values separated by comma. (This is similar to, but faster than using .gte= and .lte= in combination.)
.re=Regexp. matches columns whose value matches the regular expression. Can only be used on string-type columns (not enum or hash). Non-URL-safe characters must be properly escaped.