# Receipts and verification

Prove a payment happened, and tell a real settlement from a lookalike transfer.

Section: Understand x402
Source: https://www.roundhouse.studio/docs/x402/receipts-and-verification

---

Proving a payment happened takes three layers of evidence, from weakest to strongest. Keep them
distinct: only the third is proof.

## Layer 1: the receipt header

`X-PAYMENT-RESPONSE` on the successful response, base64 JSON:

```json
{ "success": true, "txHash": "0xabc123…", "networkId": "base", "payer": "0x…" }
```

This is the facilitator telling you what it did. Keep every one — it is your reconciliation key, and
without the `txHash` you cannot connect a request in your logs to a movement on-chain.

It is evidence, not proof: it is an assertion by a third party. Which is fine, because it names the
one thing that *is* checkable.

## Layer 2: the transaction

Look up the hash. A genuine `exact` settlement contains two logs from the token contract:

| Log | Says |
| --- | --- |
| `Transfer(from, to, value)` | The money moved |
| `AuthorizationUsed(authorizer, nonce)` | It moved via a signed EIP-3009 authorization |

The second one is what matters. A plain `transfer()` call produces only the first, so a transfer to
a known service wallet *looks* like a payment but proves nothing about consent or purpose.

```bash
# Anything that can read a receipt will do; this is the shape of the check.
cast receipt 0xabc123… --rpc-url https://mainnet.base.org
```

## Layer 3: the index

Roundhouse runs exactly this check on every candidate settlement and records the result as a
three-valued confidence, which is why [`/stats`](https://www.roundhouse.studio/stats) can lead with a *verified* population
rather than a blended total:

| `verified_x402` | Means |
| --- | --- |
| `true` | An `AuthorizationUsed` marker was found. On-chain proof. |
| `null` | Not examined. Usually a catalog-derived heuristic, and usually *probably not* x402 |
| `false` | Examined and **disproven** — a plain transfer that happened to land on a payTo |

Look up your own settlement:

```bash
curl -sL "https://www.roundhouse.studio/api/v0/entities/<your-wallet>/settlements?limit=10" | jq
```

> [!NOTE]
> Do not blend the three values and call the sum "verified volume". Per-entity
> rollups (`mv_entity_rollups`) currently do sum all three, which is stated
> plainly on the pages that use them. When a number needs to mean *proven*, filter
> on `verified_x402 = true` yourself.

## Two things that distort a naive reading

**Fee proxies.** Some routes send buyer → proxy → merchant inside one transaction: two `Transfer`
logs, one payment. An indexer that records the first leg has the proxy as the payee and the gross
amount as the price, and the merchant never appears. Roundhouse collapses the chain so `payee` is
the merchant, records the fee separately, and audits the correction. If a figure seems to belong to
an intermediary rather than a business, this is usually why.

**Unpriced tokens.** `amount_usd` is `NULL` when a token has no USD rate at that time — the index
refuses to guess a price. So a *count* and a *volume* are computed over different populations, and
every volume figure is a **floor**. `/stats` states the unpriced count for exactly this reason.

## Reconciling your own spend

The honest procedure, in order:

1. Log the `X-PAYMENT-RESPONSE` for every paid request, with your own request id.
2. Nightly, look up each `txHash` on-chain and confirm the `Transfer` amount and recipient match
   what you signed.
3. Cross-check the total against your wallet's outbound in the index:

```sql
select count(*) as settlements,
       sum(amount_usd) as usd,
       count(*) filter (where verified_x402) as proven
from settlements
where payer = lower('0xYourWallet')
  and block_time > now() - interval '30 days'
```

A mismatch in either direction is informative. Fewer rows in the index than in your logs means a
gap (check [`/status`](https://www.roundhouse.studio/status)); more means something else is paying from your address.

## Next steps

- [Errors](https://www.roundhouse.studio/docs/x402/errors) — when a payment does not settle
- [Coverage and confidence](https://www.roundhouse.studio/docs/data/coverage-and-confidence) — how much of the chain we see
- [The data model](https://www.roundhouse.studio/docs/data/data-model) — what a settlement row holds

---

Every page in these docs is available as markdown at its own URL plus `.md`.
Full index: https://www.roundhouse.studio/docs.md
