checkout402_
Reference

MCP tools#

JSON-RPC 2.0 over streamable HTTP at https://api.checkout402.com/mcp.

Authorization: Bearer c402_live_...

tools/list needs no auth — a host can see what's on offer before anyone connects. Everything that touches your account does.

Setup for Claude specifically: Connect Claude.


Seller tools#

create_checkout#

The one that matters. Same object as POST /v1/checkouts.

Argument
title required
price_usd required, decimal string
pay_to your payout wallet. Optional — omit it and your account's standing payout wallet for each chain is used
description
fulfillment inline | relay | mcp | webhook — inferred if omitted
payload / origin_url the goods, or your endpoint
origin_method, origin_auth_type, origin_auth_value, origin_auth_header how we reach your endpoint
mcp_tool mcp only — sell ONE named tool; omit to sell the whole server
schedule_interval_days, schedule_periods a series: the buyer signs schedule_periods payments, one every schedule_interval_days days, price_usd each
calls sell a package. relay and mcp only, minimum $1.00
expires_in_minutes
input_schema, output_schema offer card
example_input, example_output offer card
freshness, coverage, source, constraints offer card
content makes it a gated article — see Pay to Read

Returns the checkout including its url — the thing to share.

Mode is not an argument. With a c402_ key the key decides. Over an OAuth connection (Claude, and anything else without a key) it creates an unarmed checkout — every face rehearses, so an agent working through a repo can mint a dozen without any of them arriving able to take real money. go_live is the one deliberate step that arms one, and an agent should ask before calling it.

The result carries url and test_url — the same id with /test appended. The test face settles simulated forever, armed or not.

max_deliveries is still accepted as an old name for calls, but the schema no longer advertises it: two names for one number is a question with only one right answer.

reusable is not advertised either, and defaults to true. A checkout an agent creates is a published product — an API, a tool, a payload — and a product is not spent by its first buyer. One-shot is the invoice case: still reachable by passing reusable: false, but not a question worth stopping a create for, and not the axis a seller means when they say "single". That axis is calls — one call, or a package of them.

go_live#

Arm an unarmed checkout for real money. Takes checkout_id.

Arms in place — same id, same URL. Nothing new is minted: the link already shared is the one that now takes real payments. The URL in a script, a README or a colleague's terminal is safe for a different reason than before — the rehearsal address is the same checkout's /test face, which can never be armed, and the response says so: it returns the checkout (same id) plus a rehearsal block naming where rehearsals continue.

Idempotent: calling it twice returns the same checkout, unchanged the second time.

Offer-card fields are commercial claims

An agent should propose freshness, coverage and source for the seller to approve, never infer and publish them. A buyer relies on them.

get_content · update_content#

The mini CMS, for agents. get_content returns a gated article as the seller wrote it — paid body, teaser, the whole declaration (owner only). update_content edits it in place: payload is the article text, content replaces the whole declaration, so read first, change one field, send it all back. Same id, same URL; edits are live for the next read, including readers already holding passes. An ordinary checkout's payload is refused — goods a buyer was quoted stay frozen.

Fix the typo in the second paragraph of my latest article and tighten the teaser.

get_content_snippet#

Argument
checkout_id required, a cnt_ id

The block the seller pastes where the paid body used to be: the free teaser, Google's paywalled-content JSON-LD, and a plain link to the payable URL. Static HTML, so a crawler that never runs JavaScript still finds a price where the content is missing and can buy instead of leaving empty-handed.

Returns snippet, gate_url, teaser, jsonld and price_usd. Read-only: it creates nothing and costs nothing to call twice.

issue_content_grant#

Argument
checkout_id required, a cnt_ id
subject required, who it is for in your own terms
scope seller (default) or content
ttl_seconds capped at 31 days

Let a reader you have already authenticated read a gated article without paying: your subscribers, your staff, a comped reader. You decide who is entitled; this mints the pass.

list_mcp_tools#

Ask the seller's own MCP server which tools it advertises. {origin_url}, plus the same optional origin_auth_* fields, returns {origin_url, tools: [{name, description, input_schema}]}.

Call it before create_checkout with fulfillment: "mcp". Nothing is stored — it is not a catalogue. It exists because a guessed tool name creates a checkout that takes the money and then fails on a tool the server never had, and the only person who can discover that is a buyer who already paid.

Then either sell the whole server for one price and let the buyer name the tool at call time, or set mcp_tool to sell exactly one. The pin is checked on every call rather than by the payment signature, because a package key is a bearer token presented with unsigned query parameters.

list_checkouts · get_checkout#

Yours, and one in detail. get_checkout takes checkout_id.

list_receipts · get_receipt#

Payments received. A receipt carries the payer, the split, tx_hash and the delivery outcome.

create_webhook#

{url} → registration plus the signing secret, shown once.

Also on the server#

whoami (which account, test or live), get_analytics, get_payout_history, list_awaiting_fulfilment and mark_fulfilled (the webhook-mode pair), and get_embed_settings · set_embed_settings (the frame-origin allowlist, so standing up an embedding site never has to leave the MCP flow). tools/list is always the authority on what exists.


Schedule tools#

list_schedules (filter by checkout_id, status), get_schedule (every period with its date, window, status and receipt, plus paid_through and next_charge_at) and cancel_schedule (stop a series you sell; what settled stays settled). See the recurring guide.

Escrow tools#

The whole lifecycle, without leaving MCP.

Tool
get_escrow · list_escrows One escrow's state; the dispute queue for an agent working it
escrow_action One buyer/seller action (release, pause, dispute…) — accountless: returns calldata, and the escrow contract authorises by msg.sender, so only the right wallet can use it
escrow_submit Broadcast a signed escrow action on our gas — the second half of the gasless pair, on BOTH chains: Solana takes the signed transaction, Base takes the EIP-712 {v, r, s, deadline}. A buyer never needs native currency to act
resolve_escrow Prepare an arbiter's ruling. Returns an unsigned transaction — the arbiter's own wallet signs, this connection is not that wallet
resolve_escrow_submit Broadcast a platform arbiter's signed Solana ruling on our gas
get_escrow_settings · set_escrow_settings Wraps GET/PUT /v1/account/escrow — the B2B2X setup an agent standing up a marketplace must be able to do from here: sub-seller escrow creates are refused until the platform's arbiter is named. arbiter="payouts" copies the payout wallets as arbiters (snapshot, not link); check_balances=true on the get reports whether they can rule today — EVM rulings cost gas

Spending tools#

The rail an agent buys with: a wallet checkout402 generates and holds the key to, so a connected agent can pay an x402 challenge without holding crypto. Real money moves, so a live connection is required; a test key is refused.

Tool
list_spending_wallets The addresses, so the agent can say where to send USDC. Never reads the chain
spending_wallet_balance {chain}. What the wallet holds now, read from the chain. Warns above $999: this is a float we hold the key to, not somewhere to keep money
pay_x402 {url, max_usd?, chain?, params?}. Pays any x402 URL, not only ours, and returns the goods. The account's limits are the ceiling; max_usd only lowers it for one call. A checkout's /test URL is a free rehearsal that needs no funds
spending_budget {chain}. What the account holder allows: per purchase, per day, and what is left today. Read it before promising a purchase
spending_wallet_events {chain}. What happened, newest first: created, spent (amount, URL, tx), revealed, flagged, revoked, with who did it. Carries no secret

Two tools are deliberately absent. There is no create tool: minting a custodial wallet is done by a person at the dashboard. There is no reveal tool, ever: an MCP connection is exactly the credential that spends, and the credential that spends must not be the credential that exfiltrates. Getting money out is the dashboard's Reveal private key, and nothing else. See the spending wallets guide.


Buyer tools#

Buyer tools need no account and no key — a buyer holds a wallet, not one of our credentials. quote_checkout, pay_test_checkout, report_checkout and the buyer-side escrow actions all run unauthenticated; where an on-chain action results, the escrow contract authorises by msg.sender, so the tool reveals nothing and produces a transaction only the right wallet can use.

quote_checkout#

Read any checkout's price and offer card without paying. Takes a checkout URL or id; returns the total, the fee, and what you'd be buying.

Use it before deciding. It spends nothing. A …/test URL is quoted as the rehearsal face — testnet rails, simulated settlement — and either way the answer names where the rehearsal lives.

report_checkout#

Say a checkout failed you — the agent-native half of the abuse/failure channel. Buyers here are overwhelmingly agents with no account and no inbox; this is their recourse, and reports reach the seller's dashboard and checkout402's own review.

pay_test_checkout#

Rehearse any checkout end to end — on its test face, always. Whatever URL you pass (live face, /test face, armed or not), the payment settles simulated on /c/{id}/test: no funds, no key, no signature. Exists so an agent can prove the whole loop — challenge, settle, receipt, goods — before real money is involved. Rehearsals never consume the sale.

URLs on any of the three faces are accepted — /c/, /e/ and /x/ — because all three are addresses we publish. Rehearsing a gated article also returns grant, grant_scope and grant_expires_in: the pass is the product there, so a rehearsal that returned only the body would not be rehearsing the thing being sold.

There is no pay_live_checkout tool

Deliberate. Live spending happens through a client the buyer controls — pay402, with its required max_usd ceiling — not through a tool an agent can call in a loop.


Calling it directly#

curl -X POST https://api.checkout402.com/mcp \
  -H "content-type: application/json" \
  -H "Authorization: Bearer $C402_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"create_checkout","arguments":{
         "title":"Financials","price_usd":"0.10","pay_to":"0x..."}}}'

The transport is a plain JSON-RPC POST: one request object in, one JSON object back. There is no SSE stream, no GET /mcp and no session header, so the accept header changes nothing and a bare curl is a complete client.

Notifications are the exception — notifications/* messages carry no id and get an empty 202 rather than a result.


OAuth#

For hosts that connect on a user's behalf:

Endpoint
/.well-known/oauth-protected-resource Which server guards /mcp
/.well-known/oauth-authorization-server Registration, authorize, token
POST /oauth/register Dynamic client registration — nothing to pre-arrange
GET /oauth/authorize Consent screen
POST /oauth/token Code → token, PKCE required
POST /oauth/token with grant_type=refresh_token A fresh access token and a fresh refresh token; the old refresh token is spent. A connection that is used at all never has to be redone; one idle for six months does

Every tool here is a thin wrapper over the REST API in the API reference. Nothing is reachable through MCP that isn't reachable with curl.