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{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

Table Content
GET /tables/balance
historic end-of-block balances for all accounts
GET /tables/chain
running blockchain totals
GET /tables/supply
running supply totals
GET /tables/block
blocks (including orphans)
GET /tables/op
operations (only final)
GET /tables/account
most recent account balances and state
GET /tables/contract
smart contracts state at creation
GET /tables/constant
smart contract global constants
GET /tables/flow
balance, freezer and delegation flows
GET /tables/rights
baking and endorsing rights
GET /tables/snapshot
balances of active delegates & delegators at all snapshot blocks
GET /tables/income
per-cycle statistics on baker income, efficiency, etc
GET /tables/election
election metadata (i.e. entire governance cycles)
GET /tables/proposal
individual proposals
GET /tables/vote
voting period metadata
GET /tables/ballot
ballots and proposal operations
GET /tables/bigmaps
bigmap allocations
GET /tables/bigmap_values
currently live bigmap values
GET /tables/bigmap_updates
historic bigmap updates (including copy/alloc)

Query Arguments

Tables support the following general query parameters.
columns optional
Comma separated list of column names to return. Bulk array results will be ordered accordingly. Default is all defined columns for a table.
limit optional
Maximum number of rows to return. Limited to 50,000, default 500.
cursor optional
Id (row_id) of the latest result row returned by a previous call.
order optional
Result 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 for ascending and 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.
curl ",height&time.gte=2018-08-01&time.lte=2018-08-31&limit=50000"

JSON Result

// ...
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.
=, .eq=
Equal. Matches rows where column values match exactly the filter value.
Not equal. Matches rows where column values do not match the filter value.
Greater than. matches columns whose value is strictly greater than the filter value.
Greater than or equal. matches columns whose value is greater than or equal to the filter value.
Less than. matches columns whose value is strictly smaller than the filter value.
Less than or equal. matches columns whose value is strictly smaller than or equal to the filter value.
Inclusion in list. matches columns whose value is equal to one of the filter values. Multiple values must be separated by comma.
Not included in list. matches columns whose value is not equal to one of the filter values. Multiple values may be separated by comma.
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.)
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.