{"suite":"x402 client conformance","free":true,"message":"Each case injects one documented failure so you can assert your client handles it. Nothing here settles, so nothing here charges.","usage":"GET https://soren.com/v1/conformance/{case}","cases":[{"case":"underpaid","url":"https://soren.com/v1/conformance/underpaid","title":"Payment authorised for less than the quoted amount","expect":"HTTP 402 with error \"underpaid\" and the correct requirements repeated.","client_should":"Re-read accepts[] and sign the full amount. Do not assume the shortfall is tolerated."},{"case":"overpaid","url":"https://soren.com/v1/conformance/overpaid","title":"Payment authorised for more than the quoted amount","expect":"HTTP 402 with error \"overpaid\". We do not silently keep the excess.","client_should":"Sign exactly the quoted amount. An overpayment is not change — nothing refunds it."},{"case":"expired","url":"https://soren.com/v1/conformance/expired","title":"A quote whose validity window has effectively closed","expect":"HTTP 402 whose accepts[].maxTimeoutSeconds is 1, in BOTH the body and the PAYMENT-REQUIRED header.","client_should":"Abandon the quote and request a fresh one rather than signing a stale authorization."},{"case":"replayed-nonce","url":"https://soren.com/v1/conformance/replayed-nonce","title":"An EIP-3009 authorization whose nonce was already used","expect":"HTTP 402 with error \"replay_rejected\".","client_should":"Generate a fresh nonce per attempt. Never re-sign an identical authorization after a failure."},{"case":"wrong-network","url":"https://soren.com/v1/conformance/wrong-network","title":"Requirements quoted on a different chain than you expect","expect":"HTTP 402 quoting a network that is NOT this deployment's active chain.","client_should":"Refuse to sign. Verify accepts[].network against the chain you intend to spend on — this is the check that stops a mainnet key signing a testnet quote, or worse."},{"case":"wrong-asset","url":"https://soren.com/v1/conformance/wrong-asset","title":"Requirements quoted in an unexpected token contract","expect":"HTTP 402 quoting an asset address that is not the USDC contract for the active chain.","client_should":"Refuse to sign. Verify accepts[].asset against a known token address, never trust it blindly."},{"case":"malformed-header","url":"https://soren.com/v1/conformance/malformed-header","title":"A 402 whose PAYMENT-REQUIRED header cannot be decoded","expect":"HTTP 402 with a valid body but a deliberately corrupt PAYMENT-REQUIRED header.","client_should":"Fall back to the body rather than failing outright — v1 servers send only a body. A client that treats a bad header as a fatal error cannot buy from half the ecosystem."},{"case":"settle-timeout","url":"https://soren.com/v1/conformance/settle-timeout","title":"Settlement broadcast but not confirmed inside the deadline","expect":"HTTP 402 with error \"settlement_pending\" AND a transaction hash. This is NOT a plain failure.","client_should":"Treat it as unresolved, not as refused. The transfer may still confirm, so do not re-sign the same authorization and do not assume you were not charged. Record the hash."},{"case":"double-402","url":"https://soren.com/v1/conformance/double-402","title":"A valid-looking payment still answered with 402","expect":"HTTP 402 returned even though a payment proof was presented.","client_should":"Give up after a bounded number of attempts. A client that retries a 402 forever will loop against a broken or hostile server — this is the case that produces runaway spend."}],"when_you_are_ready":{"message":"A real payment against a real endpoint, for $0.10:","url":"https://soren.com/v1/testpayment"},"docs":"https://soren.com/conformance"}