checkout402_
Get started

Concepts#

checkout402 has one object. Understanding it is most of understanding the product.

The Checkout#

A checkout is { price, payTo, what-you-get } — a URL with two faces.

Checkout  =  Offer  +  Payment  +  Fulfilment
Part What it means
Offer What's for sale, described well enough that an agent can decide before paying
Payment The price, the fee, and which rails you accept
Fulfilment What the buyer actually receives once money moves

There is no separate "product", "listing", or "catalogue" object. Deliberately: creating a checkout should not feel like creating a marketplace listing.

Two faces, one URL#

GET /c/chk_abc123 content-negotiates:

Accept You get
text/html A pay page — price, description, a wallet button
anything else HTTP 402 with accepts[], the fee split, and the offer card

Same object, same price, same ID. The buyer's client decides which face makes sense.

The offer card#

The optional metadata that makes an unpaid 402 genuinely useful. All fields are optional — creating a checkout stays fast — but each one raises the chance an agent completes the purchase.

Field Answers
title, description What is this? (required)
input_schema What do I provide?
output_schema What will I get back?
example_input, example_output Can I see it before paying?
freshness, coverage, source Is it suitable for my task?
constraints What are the limits?

These are commercial claims

freshness, coverage and source are assertions a buyer will rely on. If an agent fills them in on your behalf, it should propose them for your approval — not publish them as fact.

Fulfilment modes#

What happens after settlement. Money moves first, always.

Mode Behaviour Use when
inline Returns payload verbatim You're selling a key, a token, a fixed answer
relay Calls your origin_url, forwards the response You're putting an existing API behind a paywall
mcp Connects to your MCP server and calls one tool You're selling tools to agents
webhook Receipt only; you're notified async Fulfilment happens in your own system

You rarely name one. The mode is inferred from what you send: payload is inline, origin_url is relay, and naming an mcp_tool makes it mcp. Selling a whole MCP server is the one shape that cannot be inferred — a bare URL is always a relay — so it needs fulfillment: "mcp" explicitly.

Settle-before-deliver is not configurable

The ordering — verify, settle, then release — isn't a setting. The opposite ordering isn't representable in the code.

Packages#

calls: N sells N deliveries for one payment. One on-chain settlement, then a pk_… key that spends a counter — no signature, no gas, no confirmation wait on any call after the first.

Which modes relay and mcp. inline replays free bytes; webhook we don't deliver
Minimum price $1.00 when calls > 1. Single calls have no minimum
The key One per payment, not per checkout. Shown once, only the hash is kept
Expiry 30 days by default, package_ttl_days to change it

The entitlement hangs off the payment, so it outlives the listing: it keeps working after the checkout is paid, expired, or retired. Retiring stops new sales; it does not confiscate what people already bought.

Who pays when a call fails#

The seller's origin returns Charged
5xx, timeout, unreachable, 401/403/429 No — refunded
400, 404, 422 — the buyer's request was wrong Yes

A buyer-fault failure returns the origin's own status, not a 502, so it is actionable. Refunding it would make "does record X exist?" free whenever the answer is no — the seller's origin would absorb every probe and only hits would be paid for.

GET /c/{id}/usage itemises every call with counted and fault, free, so "was I charged for that one, and whose fault was it" is always answerable.

What you still owe#

A package is cash received against calls not yet served. c402 owed-calls and the liabilities block on /v1/analytics show unspent calls per checkout, and retiring a checkout tells you the same number rather than letting you forget it.

Two kinds of checkout#

A classic checkout settles atomically: the buyer's signature moves the money straight to the seller (and the fee, and a platform's cut) in one on-chain transaction. Final the moment it lands — that is most of the product.

An escrow checkout (esc_ ids, served at /e/{id}) holds the money in an on-chain contract first. Exactly two exits exist, fixed the moment the buyer pays: release to the seller, or refund to the buyer. By default it releases automatically after the settle window; the buyer can pause, approve early, or dispute — and a dispute nobody resolves refunds the buyer automatically, so funds can never be stranded. Goods still deliver at payment; escrow changes when the money becomes the seller's, not when the buyer gets the thing. Fee: 1% instead of 0.5%. Full model: Escrow.

A plain checkout can also offer protection (escrow_offer: "optional"): both faces exist and the buyer chooses at pay time by which URL they sign.

Payments and receipts#

Every payment attempt writes a CheckoutPayment row with its own pay_… id, addressable at /r/pay_….

A receipt carries the payer, the seller, the exact split, the network, the transaction hash, and the delivery outcome. Two faces again: JSON for agents, HTML for humans.

The X-PAYMENT-RECEIPT header returns it inline on the paying request, so an agent gets its receipt in the same round trip as the goods.

Retrying is safe

Re-presenting the same X-PAYMENT redelivers the goods and never charges twice. A dropped connection after settlement is the worst failure in payments — the buyer has paid and has nothing — so the same signed authorization is idempotent by design.

Single-shot vs reusable#

Behaviour
reusable: true Many payments, stays open. A payment link or a metered endpoint. What an agent creates by default — a published product is not spent by its first buyer.
reusable: false One payment, then status: paid. An invoice to a particular buyer. The CLI and dashboard still default to this; pass it explicitly over MCP.

Not to be confused with calls, which is the axis sellers usually mean by "single": one call per payment, or a package of many. reusable is about how many buyers the URL serves; calls is about how much one buyer gets.

The test face#

Every checkout carries a rehearsal address: /c/{id}/test. Same product, same origin call, but settlement is simulated — synthetic 0xtest_… hash, test_mode: true stamped on the payment and the receipt, no funds anywhere. /pay and /prepare exist on both faces, so a whole client can point at the test face unchanged.

Which face settles simulated is decided by the path and the armed state, never by the payment payload. A test payload presented to an armed live face is refused, not quietly simulated. And a rehearsal never flips the checkout's status — it cannot consume a single-shot or pollute the sale.

The faces cross-link inside the 402: a live face carries endpoint.rehearsal.test_url; a test face says in words that it settles without real money, and names live_url — or says the seller has not gone live yet.

Origin-backed rehearsals (relay and mcp) are budgeted: 25 test deliveries per checkout per day by default, test_delivery_daily_cap on create to change it. Past the cap is a 429 pointing at the live URL. Inline and webhook rehearsals call nothing, so they are unmetered.

Build unarmed, then go live#

test_mode: true on a checkout means not armed. Checkouts created over an OAuth connection — Claude, or any agent without a c402_ key — and by c402_test_ keys start unarmed: the bare URL rehearses too, so nothing an agent makes for you can take real money until you say so.

Arming is its own step, in place:

c402 checkouts go-live chk_abc123

Same id, same URL, idempotent. The link you already shared is the one that now takes real money — and the address that rehearses differs from it by a path segment that says which is which, because /test can never be armed. Scripts belong on the test face; buyers get the bare URL. One URL per product, always.

The dashboard has the same button under Manage → Go live, with the price and title in front of you while you decide.

The fee#

0.5% of the price, plus $0.01. Visible in the 402 before anyone pays, and split out on-chain in the same transaction that pays you.

Your price     $0.10
Fee            $0.0105     (0.5% of $0.10 = $0.0005, plus the $0.01 fixed part)
Buyer pays     $0.1105
You receive    $0.10       — always your full price

The fixed $0.01 is one on-chain settlement, not margin — it costs real money to land a transaction, and it costs the same whether the sale is $0.01 or $1,000. That is also why packages exist: a package settles once and serves many calls, so a $1 package of 1,000 calls pays the fixed part once instead of a thousand times. Selling calls for less than a cent each is a package, not a cheaper single call.

Single calls have no minimum price, deliberately. A cheap one is how a buyer tries your API before committing — $0.015 to find out, rather than $1.015.

On Base the split runs through an immutable splitter contract. On Solana there's no contract at all — the split is two SPL transfers inside the buyer's own transaction. Either way, checkout402 never holds the money.

Identity#

Who How Why
Buyers Nothing. The payment is the login. No signup is the entire point
Sellers (human) Magic link → session cookie No password to leak
Sellers (agent) Wallet signature → automation key Agents have keys, not inboxes

A signed wallet challenge is a verified identity here — bring-your-own-wallet is the product thesis, and the signature proves control of the payout address.