The happy path is easy. Everyone gets it right. What nobody can test is the rest — and the rest is where money goes missing.
Every case below is a failure we hit in our own production code.
The pending-settlement case exists because we treated a broadcast-but-unconfirmed
transfer as a flat refusal for a week. The malformed-header case exists
because one of our endpoints shipped a 402 with no
PAYMENT-REQUIRED header at all and was unpayable by every v2
client. These are not hypotheticals.
Nine cases, no payment, no signup:
GET https://soren.com/v1/conformance/{case}
They are free because they cannot honestly charge — a simulated failure settles nothing, and billing you for a fake error is the quickest way to make a test service worthless. Start at /v1/conformance for the machine-readable index.
| Case | What it injects | Your client should |
|---|---|---|
underpaid | Authorization below the quote | Re-read accepts[] and sign the full amount |
overpaid | Authorization above the quote | Sign exactly the quote — nothing refunds the excess |
expired | A one-second validity window, in body and header | Abandon it and request a fresh quote |
replayed-nonce | A nonce already used | Fresh nonce per attempt; never re-sign an identical authorization |
wrong-network | Requirements on a different chain | Refuse to sign — this is what stops a mainnet key signing a testnet quote |
wrong-asset | An unexpected token contract | Refuse to sign; check accepts[].asset against a known address |
malformed-header | Undecodable header, valid body | Fall back to the body — v1 servers send only a body |
settle-timeout | Broadcast but unconfirmed, with a tx hash | Treat as unresolved, not refused. Record the hash; do not re-sign |
double-402 | 402 forever, even when paid | Give up after a bounded number of attempts |
settle-timeout is the one almost nobody handles.
A settlement that was broadcast but has not confirmed is not a
refusal — the transfer may still land. A client that treats it as
failure and re-signs can pay twice; one that treats it as success can be
served nothing. The correct behaviour is to record the transaction hash and
resolve it out of band.
double-402 is the one that produces runaway
spend. A server that answers 402 no matter what you pay will drain a wallet
that retries without a bound. If your client does not stop, it has an
unbounded spend bug, and this is the cheapest place to find that out.
These settle real payments and do real work, which is why they are priced.
| Endpoint | What it does | Price |
|---|---|---|
/v1/echo-payment | Decodes your signed EIP-3009 authorization and hands it back field by field — payer, value, recipient, validity window, nonce. For when a signer keeps being rejected and “invalid” is all you get. | $0.02 |
/v1/paid-ping | A heartbeat that costs money, so it proves verification and settlement are alive — not merely that the server answers. | $0.01 |
/v1/roundtrip | The same, plus how long settlement actually took, server-side. For setting your timeouts from evidence. | $0.01 |
/v1/testpayment | A full successful payment, echoed back so you can assert against it. | $0.10 |
Measured on Base: verification and settlement together typically complete in one to three seconds. A client timeout under five seconds will produce false failures on a perfectly healthy network.