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

# Joining logs to transactions

> Get the transaction behind every matched log in the same request.

Logs don't carry their transaction's sender, input or gas. With `joinTransactions`, the
response also contains the transaction of every matched log:

```json theme={null}
{
  "fromBlock": 19426000,
  "toBlock": 19426009,
  "logs": [{
    "address": ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "joinTransactions": true,
  "fields": {
    "log": {"blockNumber": true, "transactionIndex": true, "logIndex": true, "topic1": true, "topic2": true, "data": true},
    "transaction": {"blockNumber": true, "transactionIndex": true, "from": true, "to": true, "sighash": true, "gasUsed": true, "effectiveGasPrice": true}
  }
}
```

The response has a `transactions` stream (52 rows here) and a `logs` stream (72 rows). Several
logs can belong to one transaction, which appears once.

## Rules

* It needs at least one `logs` filter object and at least one `fields.transaction` field
  (`400` otherwise).
* If you also send `transactions` filters, the transactions stream is the **union**: the
  filter's matches plus the matched logs' transactions, each once.
* Transactions come back in the usual `(block_number, transaction_index)` order.
* Joined transactions count toward `maxObjects` and are billed like any other row.
* A `transactions[].status` filter, if present, applies to the joined transactions too. A
  `transactions[].type` filter doesn't: it only narrows its own object's matches.

## Joining in your client

Match rows on `(block_number, transaction_index)`. Select those two fields on both row types:

```python theme={null}
import polars as pl

logs = pl.from_arrow(tables["logs"])
txs = pl.from_arrow(tables["transactions"])
joined = logs.join(txs, on=["block_number", "transaction_index"], how="left", suffix="_tx")
```

You can also join on `transaction_hash` (log) = `hash` (transaction), but hashes are 32 bytes
each; two integers are smaller and faster.

## The other direction

Matching a transaction does **not** pull in its logs. To get a transaction's logs, filter logs
too (for example on the contract it called) and join client-side on
`(block_number, transaction_index)`.


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