Payments
There are three ways to pay. All land in the same ledger: the payment becomes an escrow hold, the signed verification report decides, and the hold either pays the seller or goes back to whoever paid.
| Rail | Account | Who funds it | Lands in the ledger as |
|---|---|---|---|
| Credits | Yes | A person, by card through Stripe | A hold from the principal's credits, under the agent's mandate |
| x402 | No | The agent's own USDC wallet | A hold keyed to the payer wallet |
| MPP session | No | One deposit through a Stripe or Tempo MPP client | One session hold, drawn down by signed vouchers, settled once at close |
Each offer document (/offers/{id}) lists the rails that can buy it in its payment block, so an agent can choose before it asks. Credits are always on; x402 and MPP show only when the operator has switched them on, and never for subscriptions.
Credits
One credit is 1.00 US dollar. A person buys credits by card (Pricing), connects an agent, and the agent buys under its mandate with purchase_artifact or POST /v1/orders and a Bearer token. Subscriptions are paid from credits only.
x402: buy without an account, in USDC
x402 is an open payment protocol over HTTP status 402. An agent with a USDC wallet asks to buy, gets a quote, signs a transfer authorization, and retries. ContextFile verifies and settles the transfer through an x402 facilitator and holds the money in escrow like any other order.
x402 is off until the operator switches it on, and runs on a test network until legal review of stablecoin payments is done. A listing page says whether it is on.
1. Ask to buy, get a 402 quote
Send the purchase with no Authorization header:
POST https://mcp.contextfile.ai/v1/orders
Content-Type: application/json
{ "listing_id": "<listing id>", "formats": ["md"] }
The answer is 402 Payment Required with the x402 payment requirements:
{
"x402Version": 1,
"error": "payment_required",
"accepts": [{
"scheme": "exact",
"network": "base-sepolia",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"maxAmountRequired": "4000000",
"payTo": "0x...",
"resource": "https://mcp.contextfile.ai/v1/orders",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USDC",
"version": "2",
"quote_id": "q1....",
"quote_expires_at": "2026-11-01T14:07:11.000Z",
"listing_id": "<listing id>",
"formats": ["md"],
"price_cents": 400,
"escrow": "hold_and_settle",
"floor": 0.9
}
}]
}
maxAmountRequired is the live price of the basket in USDC base units (6 decimals, so 4000000 is 4 USDC). The figures here are Example values. The price always comes from the live listing, never a fixed number. The quote expires after maxTimeoutSeconds (Example: 5 minutes).
2. Pay with an X-PAYMENT header
Sign an EIP-3009 transfer authorization for exactly maxAmountRequired to payTo, and send the same request with the base64 payment payload in X-PAYMENT. Send the quote_id back in the body (or in an X-ContextFile-Quote header) so the quote's expiry and price hold:
POST https://mcp.contextfile.ai/v1/orders
Content-Type: application/json
X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLC4uLn0=
{ "listing_id": "<listing id>", "formats": ["md"], "quote_id": "q1...." }
A client that does not send the quote id pays the live price at that moment; its authorization's validBefore bounds the wait.
The payment is refused, and nothing is settled, when:
- the quote has expired (
quote_expired, with a fresh quote inaccepts), - the authorization is for more than the maximum (
amount_above_max) or less than the price (amount_below_price), - the price changed since the quote (
price_changed), - the facilitator does not verify the signature or the wallet's funds (
payment_invalid).
Every refusal is a 402 with new requirements, so the agent can pay again.
3. The payment lands as a hold
HTTP/1.1 201 Created
X-PAYMENT-RESPONSE: eyJzdWNjZXNzIjp0cnVlLCJ0cmFuc2FjdGlvbiI6IjB4Li4uIn0=
{
"order_id": "<order id>",
"state": "held",
"escrow_cents": 400,
"payment": { "rail": "x402", "payer": "0x...", "network": "base-sepolia", "tx": "0x..." },
"order_token": "x4o....",
"status_url": "https://mcp.contextfile.ai/v1/x402/orders/<order id>",
"download_url": "https://mcp.contextfile.ai/v1/x402/orders/<order id>/download",
"settles_on": "report_floor_check"
}
Keep order_token. It is the wallet's proof of the order: the paid request carried an authorization only the wallet could sign, and the token is bound to that order and that payer. Send it as X-ContextFile-Order-Token to read the order or download it. Another wallet's token does not open this order.
4. Release or refund
The signed report decides, exactly as for credits:
- The report meets the floor: the hold settles. The seller accrues
(T - c) / 2and ContextFile keeps the rest, the same formula as every order. The escrow.release receipt carriespayment: { rail: "x402", network, tx }, the transfer that funded it, and is anchored in the daily receipt tree like every receipt. - The report misses the floor: ContextFile sends the whole amount back to the paying wallet, and the hold returns to zero. A refund that fails on chain is retried; if retries run out it is recorded for manual action and still shows as owed.
GET https://mcp.contextfile.ai/v1/x402/orders/<order id>
X-ContextFile-Order-Token: x4o....
answers the state, the payment, any refund (pending, sent with its transaction, or failed), and the signed receipt once the escrow released.
GET https://mcp.contextfile.ai/v1/x402/orders/<order id>/download
X-ContextFile-Order-Token: x4o....
answers the artifact the same way download_artifact does, with artifact_digest and report_digest. A refunded order no longer downloads.
Pay per call with x402
A listing with a per-call price answers one question per call from its verified edition. Send the question to POST /v1/listings/{listing_id}/calls with no Authorization header and you get a 402 whose quote has extra.quote_kind set to per_call and the per-call price as the maximum. Retry with X-PAYMENT and the quote_id. An answered call settles the transfer, then holds and releases it through the same escrow as a purchase; the response carries the cited answer, charged_cents, order_id and the transfer. A question the edition does not cover answers no_answer and the authorization is never submitted, so nothing is charged. A per-call order never downloads the artifact. With a Bearer token the same path pays from credits, capped by the agent's mandate (MCP: commerce_buy with action: "call").
What x402 does not cover
- Subscriptions: a wallet cannot be billed each cycle without a mandate, so living artifacts are paid from credits.
- Sellers are paid out as today. USDC comes in; seller payouts do not change.
- Agents that also hold a ContextFile account pay with credits when they send a Bearer token. A request with a token is always the credit purchase.
MPP sessions
Deposit once, pay for many calls, settle once.
MPP (the Machine Payments Protocol from Stripe and Tempo) suits an agent that will make many paid calls in a row. It deposits once, then pays for each call with a signed voucher instead of a new payment. ContextFile holds the deposit as one session hold, turns each voucher into an ordinary escrowed order, and settles the whole session in one transfer when it closes.
MPP is off until the operator switches it on, and runs on a test network until legal review is done. A listing page and the offer document say whether it is on.
1. Open a session on a deposit
Make the deposit with your MPP client, then open a session with its reference and the Ed25519 public key that will sign your vouchers (raw 32 bytes, base64url):
POST https://mcp.contextfile.ai/v1/mpp/sessions
Content-Type: application/json
{ "deposit_ref": "0x...", "voucher_key": "<base64url Ed25519 public key>" }
ContextFile asks the MPP rail to confirm the deposit, who made it and how much landed, and answers:
{
"session_id": "<session id>",
"session_token": "mps....",
"state": "open",
"deposit_cents": 2000,
"cumulative_cents": 0,
"expires_at": "2026-11-02T12:00:00.000Z",
"calls_url": "https://mcp.contextfile.ai/v1/mpp/sessions/<session id>/calls",
"close_url": "https://mcp.contextfile.ai/v1/mpp/sessions/<session id>/close"
}
One deposit opens one session; sending the same open again returns the same session. The figures are Example values, as are the deposit limits (Example: 1 to 500 credits' worth) and the session lifetime (Example: 24 hours).
2. Pay for each call with a voucher
A voucher states the running total you authorize for the session, in cents, and the listing this call buys. Sign the exact string
cf-mpp-voucher-v1|<session id>|<cumulative_cents>|<listing id>
with your voucher key, and send it with the session token:
POST https://mcp.contextfile.ai/v1/mpp/sessions/<session id>/calls
Content-Type: application/json
X-ContextFile-Session-Token: mps....
{ "listing_id": "<listing id>", "formats": ["md"],
"voucher": { "cumulative_cents": 400, "signature": "<base64url>" } }
The total must rise by exactly the price of this call (the offer document has it). The call answers 201 with the order, the draw, the new total and what is left of the deposit. The order is held in escrow and settles on the signed report like any other.
A voucher is refused, and nothing is drawn, when its total does not rise over the last accepted one (voucher_not_increasing, which is what a replayed voucher gets), when it rises by a different amount than the price (voucher_amount_mismatch), when it goes past the deposit (voucher_over_deposit), or when the signature does not verify under the session's key (voucher_invalid). The specific reason is in mpp_code.
3. Close and settle once
POST https://mcp.contextfile.ai/v1/mpp/sessions/<session id>/close
X-ContextFile-Session-Token: mps....
Closing stops new vouchers. While any call's order still waits for its report, the answer is 202 with outcome: "waiting" and the session settles on its own as soon as the last order settles. Then one settlement runs on the rail:
- calls whose report met the floor are claimed from the deposit. The seller accrues
(T - c) / 2for each, the same formula as every order; - calls whose report missed the floor, failed-format surcharges, and the part of the deposit you never drew go back to you in the same transfer.
GET /v1/mpp/sessions/<session id> shows every draw, its order's state and, once settled, the settlement transaction with what was claimed and what was returned. A session that reaches its expiry closes the same way. Closing twice changes nothing.
Download what a call bought with GET /v1/mpp/sessions/<session id>/orders/<order id>/download and the session token.
Catalog channels
The same offer documents feed two catalog formats, rendered on request so a price change shows in the next response:
/.well-known/ucpis a UCP (Universal Commerce Protocol) business profile. It names ContextFile's REST and MCP services, lists the live offers under theai.contextfile.offerscapability, and lists the payment handlers that are on./feeds/acp.jsonis an ACP (Agentic Commerce Protocol) product feed, one product per one-off offer at its live price in cents. It is for discovery: OpenAI approves in-app checkout only for physical goods today, so buying happens on the rails above.
Both are checked in CI against the published UCP and ACP schemas.
Receipts and checks
Receipts verify offline against /.well-known/receipt-keys.json, and /receipts/{id}/proof shows a receipt's place in its day's anchored tree. The full API is in the API reference.
Version 2, updated 2026-11-01.