Integrate

Three ways in, depending on which side you are on

Recourse is additive. A seller keeps its existing x402 flow and changes where the money settles; a buyer keeps its existing client and gains somewhere to appeal. Neither has to adopt the whole protocol to get something out of it.

01

Call the adjudicator

Any agent buying from any x402 seller

The lowest-commitment entry point, and it needs no contracts at all. Send the SLA you agreed to and the response you got, and find out whether it honoured the terms — using the same code that runs inside the enclave. Agreeing with your own validator is worth nothing; agreeing with the adjudicator is what gets you refunded.

POST /v1/adjudicate          # 0.01 HBAR via x402
{
  "sla": { … },
  "response": { "body": "<raw bytes>",
                "contentType": "application/json" }
}

→ { "verdict": "REJECT",
    "reasonCode": 4,
    "failedClause": { "index": 4, "op": "numeric.lte",
                      "path": "$.spreadBps",
                      "note": "spread within 50bps" } }
02

Sell under an SLA

Anyone running an x402-gated service

Publish what you promise, quote its hash in the 402, and point payTo at the escrow instead of your own account. Sign a hash of each response before you send it. In exchange, a buyer that disputes has to bring your signature, so you can never be accused of sending something you did not.

// in the 402
{
  "accepts": [{ "payTo": "0.0.10380390", … }],
  "recourse": { "paymentId": "0x…",
                "slaHash":   "0x…",
                "slaUrl":    "https://…/sla" }
}

// with the 200
X-Recourse-Response-Hash: 0x…
X-Recourse-Receipt:       0x…   // sig over paymentId ‖ keccak(body)
03

Buy with a refund path

Agents making unattended purchases

Settle into the escrow, bind the deposit to the terms, then check the response before you use it. If it fails, dispute with a bond and the verdict settles itself. The check is the point: a human notices a bad response and stops buying, and an agent making a thousand calls an hour does not.

const offer  = await fetch(url);            // 402 + slaHash
const sla    = await verifySlaHash(offer);  // refuse a mismatch
await settle(offer.accepts[0]);             // into escrow
await bind(paymentId, seller, amount, slaHash, window);

const res = await fetch(url, { headers: payment });
const judgement = adjudicate(sla, evidence(res));

if (judgement.verdict === REJECT) {
  await dispute(paymentId, responseHash, sellerSig, bond);
}

Deployments

Testnet only

The contracts are unaudited and hold testnet value. Two limits worth knowing before you build on this: a seller could misstate its own serving time, since nothing on-chain attests a clock — the buyer comparing it against local time on receipt is the defence. And the adjudicator judges against a published SLA, so it has no opinion on whether data is true, only on whether it broke a promise. A seller that promises nothing cannot be held to anything, which is itself a useful signal when choosing who to buy from.