Skip to main content

Chains and base URLs

Each chain has its own base URL. Every route hangs off it:
Each chain also has its own hostname (https://eth.api.bloklake.com/query); the two forms are equivalent. https://api.bloklake.com/query on its own does not pick a chain and returns 404. One API key works on every chain.

Row types

Bloklake stores three kinds of rows per chain: Transaction rows include the receipt (status, gasUsed, effectiveGasPrice, contractAddress, …), so you never need a separate receipts call.

A query

A query is a JSON body sent with POST:
  • Range: fromBlock–toBlock, both inclusive. Leave toBlock out to read up to the head.
  • Filters: logs and/or transactions, each a list of filter objects. Within one object every field must match (AND). A row matches if any object matches (OR).
  • Fields: which columns to return, per row type. You get only what you select, which keeps responses (and your bill) small.
Request body documents every key.

Two response formats

Arrow vs JSON explains when to use which.

Responses are pages

One response covers at most 50,000 blocks, about 8 MB of data and about maxObjects objects (default and maximum 100,000). It always ends on a block boundary: a block’s rows are never split across two responses. Every response tells you where to continue: next_block. Keep requesting from next_block until it passes the end of your range. This loop is the core of every Bloklake client; see Pagination.
Never assume a response covers the whole range you asked for. Read from_block, to_block and next_block from the response.

The head, finality and reorgs

archive_height is the newest block you can query. Blocks near the head can still be replaced by a reorg; finalized_block is the newest block that can’t. A response that ends above the finalized block carries to_block_hash so you can detect a reorg when you re-read the range. See Finality and reorgs.

Billing in one paragraph

You pay for the data Bloklake sends you: the bytes of the rows in each response (not headers or metadata), with a minimum of 10 KB per request. Errors and refused requests are free. Selecting fewer fields and using Arrow instead of JSON both make the same rows cheaper. See How billing works.

Rate limits in one paragraph

Each key has a requests-per-second limit (1 on pay-as-you-go, 10 on Standard) shared across all chains, and a limit on how many of its requests can be open at once. Over the limit you get 429 with Retry-After. See Rate limits.

Sets and prepared queries

If your filter has thousands of addresses, upload them once as a set and refer to it by id. If you run the same filter over and over with different ranges, reuse its prepared query id instead of resending the body. Both make requests smaller and faster. See Sets and Prepared queries.