Integrate SAR in an afternoon.
This is a practical guide for a resource server or partner that delivers work or a paid resource and wants to emit a Settlement Attestation Receipt (SAR) as a byproduct. Payment rails prove value moved. SAR evidence rails record what was delivered, by whom, against what request, with what evidence, and under what authority boundary — as a structured receipt a payer or verifier can inspect and resolve later.
SAR does not replace your payment rail and does not gate your delivery. It gives you a portable, payload-bound receipt of what happened after delivery.
A delivery event in your service that emits a SAR payload, a receipt_id you can resolve through DefaultVerifier, and a receipt you can open in SAR Explorer — with the recorder and the deliverer kept as separate parties. No funds move through DefaultVerifier and none of your delivery logic is handed over.
A receipt for what was delivered, recorded after the fact.
A Settlement Attestation Receipt records delivery evidence after work or a resource has been delivered. It is a structured object — not a log line — that binds a delivered payload to the request it answered, names the acting_party that delivered it, and states the authority boundary under which it was recorded.
Three things it is deliberately not:
- Not a payment railIt does not replace how you get paid.Your payment rail proves value moved. SAR sits alongside it and records delivery evidence. The two are independent.
- Not a gateEmission never blocks delivery.A receipt is produced as a byproduct of delivery. If receipt emission fails, delivery still happened; you simply have weaker evidence of it.
- A structured receiptIt gives the payer or verifier something to inspect.Instead of trusting a 200 response and a private log, a third party can resolve the receipt by
receipt_id, recompute the payload binding, and read the authority boundary.
A 200 and a payment success are not evidence of delivery.
Two systems can both report success and still leave a gap that neither side can settle later:
What ordinary success leaves out
- An API can return 200 and still leave weak evidence of what content was delivered.
- A payment success proves value moved — not the delivery content, actor continuity, or authority boundaries around it.
- Logs are not portable receipts. They live in your infrastructure and require trusting your infrastructure to read them.
What a SAR receipt adds
- A payload binding — a digest of the delivered object a third party can recompute.
- A named acting_party and an explicit authority boundary for who did what.
- A receipt_id that resolves through a resolver you don't have to host, inspectable in Explorer.
Deliver first. Emit the receipt as a byproduct.
The integration seam is after your delivery logic runs. You add one step: emit a SAR payload describing what you just delivered, then submit it so DefaultVerifier can record and resolve it.
- Resource serverReceive request / payment contextYour service receives the request and whatever payment/settlement context your rail provides. Nothing about SAR changes this.
- Resource serverDeliver the resource or workYou deliver exactly as you do today. This is the load-bearing step and SAR never sits in front of it.
- Resource serverEmit the SAR payloadAs a byproduct, build a payload with: the request binding, delivery evidence (a payload hash), the
acting_party, the authority boundary, and an integrity block. - DefaultVerifierRecord and resolve the receiptDefaultVerifier records the receipt and makes it resolvable by
receipt_id. It records evidence — it does not deliver, move funds, authorize access, or control release.
The load-bearing property: recorder ≠ deliverer
The party that records the receipt (the verifier) and the party that delivered the resource (the acting_party) are kept as different roles inside the payload. The authority boundary states plainly that the verifier holds no execution authority and does not control release. Preserving that separation is what makes the receipt worth reading.
Pick how far you want receipts to reach.
You can adopt SAR at whatever depth fits. These postures are additive — most partners start at the first.
- Posture AReceipts as your recordEmit receipts purely for inspection and replay. When a delivery is later disputed or audited, you point at a resolvable receipt instead of a private log. Lowest-commitment starting point.
- Posture BReceipts as your gateA downstream system in your own control checks the recorded evidence before it continues its next step. The check is yours — DefaultVerifier records and resolves; it does not authorize or control that downstream release.
- Posture CReceipts as future trust historyOver time, receipts accumulate into a track record for an agent or resource server. This is a direction of travel, not a shipped scoring product — treat it as future work.
A real, abbreviated receipt — not a fictional schema.
Below is a minimal excerpt from the SAR-402 public_demo payload. Every field shown is a real field from the current demo receipt; fields have been removed for brevity, not invented. The JSON is valid — nothing has been added inside it that the receipt does not carry.
{
"receipt_id": "sha256:91e2ae85f03c7a8e7df10e8862895b99456cb13abc50b4e23ba84f1c15b3b8c9",
"receipt_type": "sar_402_settlement",
"receipt_context": "public_demo",
"created_at": "2026-06-23T17:01:58Z",
"agent_id": "agent:x402:eip155:84532:0xPAYER0000000000000000000000000000000002",
"receipt": {
"issuer": { "verifier": "DefaultVerifier" },
"authority_binding": {
"acting_party": "resource_server",
"verifier_has_execution_authority": false,
"verifier_controls_resource_release": false,
"resource_server_controls_delivery": true
},
"delivery": {
"evidence_digest": "sha256:ea24c8369b31816546e07644b3621831d2e8d780e527ccb0c9fd26471dd2a8c6"
},
"verification_mode": "record",
"verification_point": "post_delivery"
}
}
Fields omitted for brevity include the inner request/operation-binding block and other settlement metadata carried by the full receipt. agent_id is the payer-derived identity — not the deliverer; the deliverer is named by authority_binding.acting_party. For recomputation, work from the full published payload, not this excerpt — see the links section.
| Field | Value | What it records |
|---|---|---|
| authority_binding.acting_party | resource_server | The deliverer — the party that produced the resource. Not DefaultVerifier. |
| authority_binding.verifier_has_execution_authority | false | The verifier claims no execution authority. |
| authority_binding.verifier_controls_resource_release | false | The verifier does not control release. |
| authority_binding.resource_server_controls_delivery | true | The resource server controls delivery. |
| delivery.evidence_digest | sha256:… | The payload binding — a recomputable digest of the delivered object. |
| issuer.verifier | DefaultVerifier | The recorder. In Path A this is a self-asserted string; Path B binds it to a DefaultVerifier recording key. |
| verification_mode / verification_point | record / post_delivery | Post-hoc recording at the after-delivery seam — not gating. |
Resolving a receipt and recomputing its id are two different checks.
Depending on the fixture and path, the receipt_id may be computable from the original payload preimage: canonicalize the payload preimage using the derivation rule for that path (for the SAR-402 Path A demo: sorted_keys_compact_v0 applied to payload_without_integrity), SHA-256 the canonical bytes, and you get the receipt_id. That is the recomputability property — but it is a property of the payload file plus the derivation rule, not of every response body.
The resolver response verifies stable lookup. Resolving GET /v1/attest/receipt/{receipt_id} confirms that the id maps to a published, stable record.
The payload file plus the derivation rule verifies the digest. To reproduce a receipt_id, canonicalize the signed core of the original payload and hash it per the rule.
The resolver envelope is not necessarily the digest preimage. The resolver wraps the receipt in an envelope (receipt_id, receipt_type, receipt_context, created_at, agent_id, receipt). Do not assume that hashing a resolver response body reproduces the receipt_id — hash the canonicalized signed core from the payload, not the envelope.
Practical consequence: if you want to claim recomputability for your receipts, preserve the original payload preimage (or fixture) you derived the id from. Without it, you can still resolve the receipt, but a third party cannot independently re-derive the id.
Attribution over a receipt, without touching the receipt.
In Path A, issuer.verifier = "DefaultVerifier" is a self-asserted string. The recording wrapper (Path B) adds cryptographic recording attribution: DefaultVerifier signs a wrapper over the receipt so a third party can confirm DefaultVerifier — not the submitter alone — recorded it.
What the wrapper is
- Attribution over a receipt, verifiable against the published recording key (
defaultverifier-recording-ed25519-1). - It does not mutate the base receipt — the wrapped receipt and its
receipt_idare unchanged. - It can carry recording key identity and the authority boundary of the recording.
What the wrapper is not
- Not a claim about delivery, payment execution, access authorization, or release control.
- Not a change to the role separation — it attributes recording only.
- Not proof of legal payment finality or mainnet settlement.
The following wrapper fields are under discussion and are not required today. Treat them as a direction, not a contract:
• emitter_uri / an operator-row pointer identifying the emitting operator.
• authorization_basis expressed as a delegation id or policy reference.
• two independent wrappers over the same digest, for multi-party recording attribution.
PASS, FAIL, and INDETERMINATE.
A SAR verification resolves to one of three outcomes. The third one is a feature.
The signed core verifies and the checks the verifier could make succeeded. The receipt holds up to independent inspection.
A check the verifier could make did not hold — for example, a digest mismatch or a malformed signed core. The receipt is contradicted, not merely unproven.
The verifier could not reach a decision — for example, an input was absent or a spec was ambiguous. Not a PASS and not a FAIL.
Why INDETERMINATE is restraint, not failure
A system that only ever returns PASS or FAIL has to guess when it lacks the evidence to decide. INDETERMINATE lets the verifier say "I cannot honestly attest to this" instead of manufacturing a verdict. That restraint is what keeps a PASS meaningful — and it is why downstream systems should treat INDETERMINATE as "get more evidence," never as a silent pass.
The authority boundary, stated plainly.
Reading a SAR receipt correctly means reading the boundary. DefaultVerifier is a recorder and resolver of evidence — nothing in this integration hands it your delivery, your funds, or your access control.
DefaultVerifier does
- Records delivery evidence.
- Resolves receipts by
receipt_id. - Renders receipt and chain views for inspection.
- Preserves authority boundaries (recorder ≠ deliverer).
DefaultVerifier does not
- Execute resource delivery.
- Move or custody funds.
- Authorize access.
- Control release.
- Prove legal payment finality.
The afternoon, step by step.
- Decide the delivery event that creates a receipt — the seam right after your delivery logic succeeds.
- Define the request binding — how the receipt references the request/operation it answered.
- Define the payload / evidence hash — a canonical digest of the delivered object (sorted keys, compact separators, excluding the digest field itself).
- Identify the acting_party — the deliverer, i.e. your resource server. Keep it distinct from the recorder.
- Add authority boundary fields —
verifier_has_execution_authority = false,verifier_controls_resource_release = false,resource_server_controls_delivery = true. - Emit the SAR payload as a byproduct of delivery — never gating it.
- Submit / record with the verifier so the receipt is recorded and resolvable.
- Test resolver lookup —
GET /v1/attest/receipt/{receipt_id}returns your record. - Inspect in Explorer — open the receipt and confirm role separation and the payload binding read as expected.
- Preserve the fixture / preimage if you intend to claim recomputability of the
receipt_id.