> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bloklake.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Query (Arrow)

> POST /query: run a query and receive the rows as Apache Arrow IPC streams.

```http theme={null}
POST https://api.bloklake.com/v1/chains/{chain}/query
Authorization: Bearer <key>
Content-Type: application/json
```

Returns the matching rows as Apache Arrow: one IPC stream per row type, back to back. This is the
endpoint to use for real workloads. The same body works on [`/query/json`](https://docs.bloklake.com/api-reference/query-json).

## Body

**fromBlock** `integer` (default: 0)

First block, inclusive.

**toBlock** `integer` (default: head)

Last block, inclusive. Above the head it's lowered to the head.

**logs** `object[]`

Log filters, combined with OR. Each object may set `address`, `topic0`–`topic3` (arrays of hex)
and `addressSet`, `topic0Set`–`topic3Set` (set ids); set fields are combined with AND.
`{}` matches every log. See [Filters](https://docs.bloklake.com/querying/filters.md).

**transactions** `object[]`

Transaction filters, combined with OR. Each object may set `from`, `to`, `sighash` (arrays of
hex), `fromSet`, `toSet` (set ids), `type` (array of transaction types, 0–255) and `status`
(`0` or `1`, the same on every object).

**fields** `object` *required*

Columns to return: `{"log": {…}, "transaction": {…}, "block": {…}}`, each `{"<name>": true}`.
See the field reference: [logs](https://docs.bloklake.com/api-reference/fields/logs.md),
[transactions](https://docs.bloklake.com/api-reference/fields/transactions.md), [blocks](https://docs.bloklake.com/api-reference/fields/blocks.md).

**joinTransactions** `boolean` (default: false)

Also return the transaction of every matched log. Needs a `logs` filter and transaction fields.

**maxObjects** `integer` (default: 100000)

Target number of rows per response; the response ends at the end of the block where it's
reached. Maximum 100,000.

**blockInterval** `integer`

Keep every n-th block in the blocks stream (needs block fields).

**blockOffset** `integer` (default: 0)

Phase for `blockInterval`, smaller than it.

**strictFields** `boolean` (default: false)

`400 invalid_query` when a selected field doesn't exist on this chain, instead of an all-null
column. See [Fields a chain doesn't have](https://docs.bloklake.com/querying/unavailable-fields.md#rejecting-them-instead).

**queryId** `string`

A [prepared query](https://docs.bloklake.com/querying/prepared-queries.md) id, instead of `logs`, `transactions`, `fields`,
`joinTransactions` and `blockInterval`. Only `fromBlock`, `toBlock`, `maxObjects` and
`strictFields` may accompany it.

## Example

```bash curl theme={null}
curl https://api.bloklake.com/v1/chains/eth/query \
  -H "Authorization: Bearer $BLOKLAKE_API_KEY" \
  -H 'content-type: application/json' \
  -d '{
    "fromBlock": 19426000,
    "toBlock": 19426009,
    "logs": [{"address": ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"],
              "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]}],
    "joinTransactions": true,
    "fields": {
      "log": {"blockNumber": true, "logIndex": true, "topic1": true, "topic2": true, "data": true},
      "transaction": {"hash": true, "from": true}
    }
  }' --output response.arrows
```

```python Python theme={null}
from bloklake_arrow import query  # the Arrow reader: /responses/reading-arrow

tables, meta = query({...})
tables["logs"], tables["transactions"]
```

## Response

`200`, `Content-Type: application/vnd.apache.arrow.stream`.

The body is one complete Arrow IPC stream per row type in the response, always in the order
**transactions, logs, blocks**, each with its own schema and end-of-stream marker. Read them one
after another from the same body. See [Reading Arrow](https://docs.bloklake.com/responses/reading-arrow.md).

Each stream's schema metadata:

**bl.row\_type** `string`

`transactions`, `logs` or `blocks`.

**bl.streams** `string`

All streams of the response, in order, comma-separated: `"transactions,logs"`.

**bl.from\_block** `string (integer)`

First block covered.

**bl.to\_block** `string (integer)`

Last block covered.

**bl.next\_block** `string (integer)`

`fromBlock` for the next page.

**bl.objects** `string (integer)`

Total rows in the response, across all streams. Check it against what you read.

**bl.archive\_height** `string (integer)`

The chain head at query time.

**bl.finalized\_block** `string (integer)`

The newest final block at query time. Absent before the first finalization.

**bl.to\_block\_hash** `string (hex)`

Hash of `to_block`; only present when `to_block` is above `bl.finalized_block`.

**bl.query\_id\_template** `string (hex)`

The prepared query id of this request's filter.

**bl.unavailable\_fields** `string`

Selected fields this chain doesn't have, as `<row type>.<column>`, comma-separated; `""` when
none.

The first schema is sent as soon as the query is planned, before any rows.

## Errors

Validation errors are returned before any data, as JSON: see [Errors](https://docs.bloklake.com/api-reference/errors.md). An
error after the response has started closes the connection; see
[Errors and retries](https://docs.bloklake.com/production/errors-and-retries.md#failures-in-the-middle-of-a-response).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.