checkout402_
Guides

What can I sell?#

Anything you can hand over when someone pays for it.

Your existing subscriptions, API keys and enterprise contracts stay exactly as they are. This adds a new purchasing surface for ad-hoc agent demand — buyers who will never sign up, but will pay $0.10 right now.

Start here: three questions#

Every checkout is the same three answers. Nothing else is required.

Question Answers
1 Where do the goods come from? I have them · my server makes them · I will handle it
1b Is it something people READ? if so, see Sell an article below
2 How many people can buy? one · many
3 What does one purchase include? one call · a bunch of calls

The first answer picks your checkout type. The other two are settings on it.

Pick your type#

Sell an API — relay#

You have an endpoint. We put a paywall in front of it, call it after payment, and hand back what it returned. Your URL and your upstream key never reach the buyer. The most common type, and it can be sold in bulk.

Sell MCP tools — mcp#

You run an MCP server. Price one named tool, or the whole server. We speak the protocol properly, so a tool that fails inside an HTTP 200 is not billed as a success. Two genuinely different products; can be sold in bulk.

Sell stored data — inline#

A key, a licence, a fixed answer. You give us the bytes and we hand them over when someone pays. Nothing to host, nothing to keep running, and the schema buyers inspect is derived from your payload automatically.

Sell anything else — webhook#

Physical goods, human work, your own flow. We take the payment and tell you; you deliver and close it out. The escape hatch, and the most flexible.

Sell a file — also a face#

A PDF, a dataset, a clip. relay pointed at the file, plus a content declaration that says it is one — so it gets a pay page, a download disposition and a working Range, and the bytes stay on your server. Under 5 MB; above that, relay to your own signing endpoint instead.

Sell an article — a face, not a fifth mode#

An essay, a report, a page. The opening stays on your site; the rest is served from checkout402 only to someone who paid. Readers pay in the page they are reading and crawlers get a 402 with a price on it instead of your text.

Not a fifth mode: it is inline or relay plus a content declaration, answering at /x/{id} instead of /c/{id}. If your CMS is WordPress there is a plugin and you never touch any of this.

You rarely name a type

It is inferred from what you send. payload means stored data, a URL means an API, a URL plus a tool name means MCP. Only webhook has to be said out loud, because there is nothing to infer it from.

The four modes, side by side#

Every checkout ends in one of four fulfilment modes. The mode is the only thing that differs between selling an API call, stored data and a physical object — price, payout, receipts and the 402 are identical in all four.

Pick by where the thing lives:

inline relay mcp webhook
You supply at create payload — the bytes themselves origin_url (your API) origin_url (your MCP server), optional mcp_tool fulfillment: "webhook", nothing else
The buyer receives that payload, verbatim your endpoint's response body one tool result, as JSON nothing
When at payment at payment at payment later, from you, off-platform
Repeat deliveries by default unlimited 3 3 unlimited
Can be sold as a package no — refused at create yes yes no — refused at create
Delivery status recorded delivered, always delivered or failed delivered or failed pending until you close it
What can fail after payment nothing your origin your MCP server, or a bad tool name nothing — but nothing arrives either

You rarely name a mode. It is inferred from what you send:

You send You get
payload inline
origin_url relay
origin_url + mcp_tool mcp
fulfillment: "webhook" webhook

fulfillment is still accepted and still wins if you send it. But it is an implementation word, and you should not have to learn one to sell something.

Two shapes cannot be inferred, and both must say fulfillment out loud: webhook, because there is nothing else to go on, and a whole MCP server — an origin_url with no tool name is indistinguishable from a relay.

One of each:

c402 checkouts create --title "…" --price 0.10 --payload '{"key":"…"}'
c402 checkouts create --title "…" --price 0.10 --origin-url https://api.yourco.com/v1/x
c402 checkouts create --title "…" --price 0.10 --origin-url https://mcp.yourco.com/mcp \
  --mcp-tool search_companies
c402 checkouts create --title "…" --price 25.00 --fulfillment webhook

Create → What kind of thing is it? → A fixed payload · An API endpoint · An MCP server · Something you fulfil. The rest of the form changes to ask only for what that mode needs.

{"title": "…", "price_usd": "0.10", "payload": {"key": "…"}}
{"title": "…", "price_usd": "0.10", "origin_url": "https://api.yourco.com/v1/x"}
{"title": "…", "price_usd": "0.10", "origin_url": "https://mcp.yourco.com/mcp",
 "mcp_tool": "search_companies"}
{"title": "…", "price_usd": "25.00", "fulfillment": "webhook"}

How they actually differ#

inline stores your bytes and hands them back. Nothing is called, so nothing can fail after settlement and the delivery is always delivered. Buyers get unlimited re-fetches of the same payload, which is retry safety, not generosity — replaying costs nobody anything. That is also why it cannot be a package.

relay calls your endpoint after the money settles and forwards what it says, so the response can be different every time. The buyer's parameters are forwarded as your query string — mcp does the same, as tool arguments, and the other three ignore them. One payment buys 3 deliveries by default — not 1, because a buyer whose connection drops after paying must be able to re-fetch, and not unlimited, because each delivery spends your upstream quota. If your origin times out, is unreachable, returns a non-2xx, or exceeds the body cap, the buyer gets 502 with their receipt id and the delivery is recorded failed. They never see your host or your error text.

Three, not one, and not unlimited

A repeat delivery of relay or mcp calls the seller again, so an unlimited default would let one payment spend their upstream quota forever — replaying a settled X-PAYMENT re-enters fulfilment. Three is a retry allowance for a buyer whose connection drops, not a package: a package key is only minted when you set calls. inline and webhook stay unlimited because repeating them costs nobody anything.

Selling a package? Three things to know

Entitlements expire after 30 days by default (package_ttl_days), the terms are shown to the buyer in the 402 before they pay, and a failure that is your origin's fault is refunded to them automatically while a bad request on their side is not. c402 owed-calls shows what you still owe holders — see Packages.

Selling files was retired

There used to be a fifth mode that handed out disposable download links. Bandwidth scales with file size while the fee scales with price, so it only ever paid for itself at prices nobody was charging. To sell a file now, put the link behind your own endpoint and use relay, or hand it over directly with inline. The implementation is kept under parked/file-downloads/.

mcp connects to your MCP server as a client and calls one tool. Two products live here: omit mcp_tool and one price buys any tool, with the buyer naming it at call time; set it and the checkout buys that tool, enforced on every call. origin_method is forced to POST.

webhook returns the buyer nothing at payment time and is the only mode where the sale stays open after the money moves. It sits at pending until you close it with c402 fulfilled. Use it for anything you cannot return over HTTP in the moment; do not use it as "how I get notified", because every paid checkout fires checkout.paid to your registered endpoints regardless of mode.

A package call that fails is refunded — the first one is not

Calls spent with a package key are handed back when your origin fails. The delivery included in the original purchase is not: it is claimed before your origin is called, and a failure there returns a 502 without restoring it.

Describe it well enough to sell#

A bare title and price will get you some sales. An offer card gets you more, because an agent can tell whether your data fits its task before spending.

c402 checkouts create \
  --title "Swiss company financials" --price 0.10 --pay-to 0x... \
  --fulfillment relay --origin-url https://api.yourco.com/v1/financials \
  --input-schema  '{"company_uid": "string"}' \
  --output-schema '{"company_name": "string", "revenue": "number", "employees": "number"}' \
  --example-input '{"company_uid": "CHE-123.456.789"}' \
  --freshness "updated daily" \
  --coverage "all 26 cantons" \
  --source "Zefix commercial register"

Schemas and examples accept @file.json — real ones outgrow a shell argument:

c402 checkouts create --output-schema @schema.json --example-output @sample.json ...

Only publish claims you can stand behind

freshness, coverage and source are commercial assertions. A buyer will rely on them, and an agent reading your card can't tell an aspiration from a fact.

Pricing#

Set the price you want. The fee is added on top and shown separately, so the buyer sees both numbers and you receive exactly what you asked for.

The fee is 0.5% of the price plus a fixed $0.01. The fixed part is what one on-chain settlement costs to land, and it costs the same whether the sale is $0.01 or $1,000.

You set Fee Buyer pays You receive
$0.10 $0.0105 $0.1105 $0.10
$1.00 $0.0150 $1.0150 $1.00
$49.00 $0.2550 $49.2550 $49.00

Sub-cent prices work — there is no minimum on a single call. But the fixed part is charged per payment, so selling calls for less than a cent each means selling a package, where one settlement covers many calls.

Offering buyer protection#

Selling something expensive, transferable, or trust-heavy (a repo, a domain, a physical thing)? Offer escrow: add "escrow_offer": "optional" to your create and the checkout advertises a protected twin the buyer can choose at pay time — or create with POST /v1/escrow-checkouts to make protection the only face. You get paid when the escrow releases (automatically after the settle window unless the buyer disputes); the fee is 1% instead of 0.5% and the buyer pays it. How escrow works.

Getting paid#

Money lands in pay_to on-chain, in the same transaction that takes the fee. There's no balance, no payout schedule, and no withdrawal request, because checkout402 never holds it.

Check your payout address character by character

pay_to is validated as a real address for a supported chain, so a typo that mangles the format is rejected. But a well-formed and wrong address is indistinguishable from a correct one, and on-chain payments cannot be reversed. Nothing can save you from a valid address that isn't yours.

Checking it once beats checking it every time: set a payout wallet on your account and pay_to becomes optional, so there is one address to get right instead of one per checkout.

Your payout address decides which rails you're offered

An address belongs to one chain family. An EVM 0x… wallet is offered Base; a Solana pubkey is offered Solana. A checkout is never advertised on a rail its payout address could not receive on.

Build unarmed, then go live#

c402 keys create --name dev --mode test     # test keys can't move real money
c402 checkouts create --test ...            # unarmed: settles with a synthetic receipt

When it works end to end, arm it in place — same id, same URL:

c402 checkouts go-live chk_abc123

Nothing else changes, and rehearsal doesn't stop: every checkout keeps a test face at /c/{id}/test that settles with no money, forever, and can never be armed. Scripts point there; buyers get the bare URL.

Selling many endpoints#

Don't create sixty checkouts by hand. Point Claude at your API and let it read your routes and docs — see Connect Claude.

Or loop the CLI, since every command speaks JSON:

jq -c '.[]' products.json | while read -r p; do
  c402 checkouts create --json \
    --title    "$(jq -r .title <<<"$p")" \
    --price    "$(jq -r .price <<<"$p")" \
    --origin-url "$(jq -r .url <<<"$p")" \
    --fulfillment relay --pay-to "$PAYOUT"
done

Knowing when you've been paid#

Poll GET /v1/checkouts, or register a webhook and be told — see Webhooks.