> ## 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.

# Request body

> Every key of a query, what it does, and the rules the server enforces.

A query is a JSON object sent as the body of `POST /query` or `POST /query/json`.

```jsonc theme={null}
{
  "fromBlock": 19426000,        // inclusive; default 0
  "toBlock": 19426099,          // inclusive; default = the chain head
  "maxObjects": 100000,         // optional page size target; default and maximum 100,000
  "logs": [ { /* filter */ } ],          // which logs; omit = no logs
  "transactions": [ { /* filter */ } ],  // which transactions; omit = no transactions
  "joinTransactions": true,     // optional: also return each matched log's transaction
  "blockInterval": 10,          // optional: every 10th block in the blocks stream…
  "blockOffset": 3,             // …starting at number ≡ 3 (mod 10)
  "strictFields": true,         // optional: 400 on fields this chain doesn't have
  "fields": {
    "log": { "blockNumber": true, "address": true },
    "transaction": { "hash": true },
    "block": { "number": true, "timestamp": true }
  }
}
```

## Keys

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

First block of the range, inclusive.

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

Last block of the range, inclusive. A value above the head is lowered to the head, without
an error. Leave it out to read up to the head.

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

How many objects (blocks + transactions + logs) a response should hold before it stops. A
target, not a hard cap: a response ends at the first block where the count reaches it, with
that block included whole. Values above 100,000 are lowered to 100,000. See
[Pagination](https://docs.bloklake.com/querying/pagination.md).

**logs** `object[]`

Log filters. A log is returned if it matches **any** object in the list. See
[Filters](https://docs.bloklake.com/querying/filters.md).

**transactions** `object[]`

Transaction filters. A transaction is returned if it matches **any** object in the list.

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

Add the transaction of every matched log to the `transactions` stream. See
[Joining logs to transactions](https://docs.bloklake.com/querying/join-transactions.md).

**blockInterval** `integer`

Keep only blocks whose number is `≡ blockOffset (mod blockInterval)` in the blocks stream.
Needs block fields. See [Sampling blocks](https://docs.bloklake.com/guides/sampling-blocks.md).

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

Offset for `blockInterval`; must be smaller than it.

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

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

**fields** `object` *required*

Columns to return, per row type: `log`, `transaction`, `block` (singular). Each is an object
of `"<fieldName>": true`. See [Fields](https://docs.bloklake.com/querying/fields.md).

**queryId** `string`

Instead of the filters and fields: the id of a [prepared query](https://docs.bloklake.com/querying/prepared-queries.md).
Only `fromBlock`, `toBlock`, `maxObjects` and `strictFields` may accompany it.

## Which row types come back

| You send | You get |
| - | - |
| `logs` filter + `fields.log` | the matching logs |
| `transactions` filter + `fields.transaction` | the matching transactions |
| `logs` filter + `joinTransactions` + `fields.transaction` | the matched logs' transactions (plus any `transactions` matches) |
| `fields.block` with no `logs`/`transactions` filter | every block in the range |
| `fields.block` with a `logs` or `transactions` filter | only the blocks that contain a match |

`logs` absent or `[]` means "don't query logs at all" (no rows, no cost). `[{}]` means "every
log in the range". The same goes for `transactions`.

## Rules

The server validates the whole request before it reads any data, and answers `400 invalid_query`
with a message that names the problem:

| Mistake | Message |
| - | - |
| `fromBlock` greater than `toBlock` | `fromBlock (5) is greater than toBlock (1)` |
| Unknown key in a filter | `unknown key "addr" in logs[0]` |
| Unknown field name | `unknown field "adress" in fields.log` |
| A filter with no fields selected for its row type | `no fields selected for logs` |
| A hex value of the wrong length | `logs[0].address[0]: value "0x1234" has 4 hex chars, expected 40 (20 bytes)` |
| `joinTransactions` without transaction fields | `joinTransactions needs transaction fields selected` |
| `blockInterval` without block fields | `blockInterval applies to the blocks stream; select block fields` |
| A `type` value outside 0–255 | `transactions[0].type[0] must be an integer from 0 to 255, got 300` |
| Different `status` values across transaction filters | `transactions[].status must be the same on every transaction object` |
| A `traces` key | `traces are not supported in v1` |
| `strictFields` and a field this chain doesn't have | `strictFields: this chain has no values for transactions.mint (GET /v1/schema lists the fields it has)` |
| No field selected at all | `invalid_query` |

Unknown keys are always errors, never silently ignored. A typo can't quietly give you fewer
columns or a broader filter than you meant.

## Range behavior

* **`toBlock` past the head** is lowered to the head. The response's `to_block` says what you
  actually got.
* **`fromBlock` past the head** returns no rows (not an error) and `next_block` equal to your
  `fromBlock`, so a client waiting for a new block simply repeats the request.
* **Wide ranges** are not refused. A response covers at most 50,000 blocks; `next_block` points
  to where the next page starts.

> [!WARNING]
>
> Always read the effective range from the response (`from_block`, `to_block`, `next_block`),
> never from what you sent. Near the head, the range you asked for and the range you got differ.


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