# Read the Offer Evidence Record

The versioned, protocol-independent record a check produces: what was requested, what was offered, when, signed how, anchored where.

Canonical: https://402signal.com/developers/evidence-record

## The Offer Evidence Record, version 1

A versioned, protocol-independent description of the evidence a check produces for one offer: what was requested, what was offered, when, observed by whom, signed how and anchored where. Short name `offer_evidence_record_v1`. It documents what is issued today (the v4 exact x402 binding and the v5 group-offer observation) and reserves fields for what is not yet issued (MPP bindings, agent mandates). It introduces no new wire format, key, signer or on-chain transaction.

A score is an opinion about an endpoint computed from public inputs. A record is a signed statement, made by a third party at a specific second, that a specific request received a specific offer, bound to the payment the buyer then made. Everything below exists to make the record verifiable by someone who does not trust 402Signal.

### Seven parts

 | Part | Content | Today's field

 | Request | The exact seller request: complete HTTPS URL with its query, method, hash of the body bytes. No redirects, no normalization. | `decision_binding.request.url`, `.method`, `.body_sha256`

 | Offer | The whole challenge the seller returned, hashed: every option in order with price, recipient, asset, network, timeout, facilitator data and supported extensions; plus which option the check selected. | `decision_binding.quote_sha256`, `.selected_index`; the observed challenge in the reveal

 | Rules | The buyer's rules as submitted. Evidence of what was asked, not of human approval. | `request_json` in the reveal

 | Decision | The winner, the compared candidates with exclusion reasons, the selected payment, the scoring model. | `routing_evidence_json` in the reveal

 | Time | When the challenge was received and when the observation stops being usable for signing. Never extended by retries, replay or approval. | `decision_binding.observed_at`, `.expires_at`

 | Signature | A commitment to the private evidence in a public leaf; the leaf in an append-only Merkle log; an Ed25519-signed checkpoint; an inclusion proof from leaf to checkpoint. | `pq_trust.transparency.receipt`

 | Anchor | Cumulative checkpoints written to Algorand MainNet in a transaction authorized with Falcon-1024, so a later rewrite of log history becomes detectable. | Public trust descriptor and [the log viewer](/transparency) 

### Commitment

```
leaf_commitment = SHA256("402signal.route_decision.v4" || 0x00 || canonical(evidence) || salt_32_bytes)
evidence = { evidence_version, binding, request_json, routing_evidence_json }
```

`canonical` is the RFC 8785 subset the verifiers implement: null, booleans, Unicode strings, arrays, objects and safe integers only; floats, duplicate keys, lone surrogates and unsafe integers are rejected. The two JSON strings keep their exact bytes. The public leaf carries only the leaf type, a minute-rounded timestamp, a nonce and the commitment; the reveal stays with the buyer. Nothing copies seller response bodies, payment headers, wallet keys, authorizations or signatures into the record.

### Protocol profiles

 | Profile | Offer content | Status

 | x402-exact-v2 | An x402 v2 PaymentRequired envelope with exact options on Base, Solana, Algorand or an observed EVM network. | Issued today as the v4 binding.

 | x402-group-offer-v1 | One exact HTTPS GET API observed under buyer limits with a codec auto-detected from the live challenge. | Issued today (v5).

 | mpp-charge-v1 | A WWW-Authenticate: Payment challenge classified as a charge: method, intent, amount, recipient, network. | Observed and returned as terms; no signed binding yet.

 | mpp-session-v1, mpp-subscription-v1 | Session and subscription terms: unit price, suggested deposit, period. | Observed as terms, never as a fixed price; no binding.

 | mandate-ref-v1 | Reserved: a reference to an agent mandate (AP2 cart or payment mandate, Visa Trusted Agent Protocol assertion, Mastercard verifiable intent) so one record carries both the offer and the authority the agent acted under. | Reserved; nothing issued.

Adding a profile changes the offer part only; the commitment scheme and the verifiers do not change.

### Verification

- Recompute the commitment from the reveal and compare it with the leaf.
- Check the inclusion proof from the leaf to the checkpoint and the checkpoint's Ed25519 signature under a key you pinned yourself, never one that arrived in the same response.
- Compare `decision_binding` in the response with the authenticated binding inside the evidence.
- Compare `request_json` with the request the buyer actually made.
- Before signing a payment, compare the seller's current challenge with the bound quote hash and refuse when the terms differ or `expires_at` has passed.

Implementations: `verifyReceipt` and `withVerifiedRoute` in `@402signal/route-guard`, the `signal402` Python package, and [the browser verifier](/verify). All three agree on the conformance fixture in CI.

### Versioning and limits

`evidence_version` and the leaf type version the commitment. Historical leaves keep their original verification semantics; new profiles and reserved fields are additive; a change to the commitment scheme or the signature is a new leaf type and a new version of this document. The record proves that a specific request received a specific offer at a specific time and what the check decided. It does not prove delivery, output quality, seller identity or intent, legality, or that a human approved the submitted rules; it cannot recover a deleted private record or observe purchases that bypassed the check; the Falcon anchor protects the checkpoint history, not the seller payment.

[The Trust page](/trust) · [Investigate with a retained record](/developers/evidence) · [The proposed x402 extension](https://github.com/402signalhq/402signal/blob/main/docs/proposals/offer-evidence-extension.md)
