x402.md
August 7, 2026 · View on GitHub
PubFi supports accountless x402 payment on explicitly enabled Registry v2 gateway routes. The caller uses a wallet authorization instead of creating a PubFi account or API key.
Environment And Availability Boundary
PubFi keeps Staging and Production payment networks separate:
| Environment | API origin | MCP origin | Permitted x402 network |
|---|---|---|---|
| Staging | https://api-stg.pubfi.ai | https://mcp-stg.pubfi.ai | Base Sepolia eip155:84532 |
| Production | https://api.pubfi.ai | https://mcp.pubfi.ai | Base mainnet eip155:8453, only when the exact route has x402 enabled |
This table is an environment policy. It does not prove that any route or offer is currently
available. Inspect GET /v1/capabilities on the selected API origin. Then inspect the exact
route's unsigned 402 challenge. The live catalog is the route authority, and the live challenge
is the payment-term authority.
Use a different dedicated wallet and private key for each environment. Never reuse a Staging wallet, private key, or payment authorization in Production, or the reverse.
The public Base Sepolia walkthrough is Staging-only. Select its resource from the current catalog:
<GET or POST> https://api-stg.pubfi.ai<exact ready Quantro-priced path>
The selected method must have operations[].billing.mode set to quantro_priced. Exact health
operations are free_health; they bypass x402 and are not payment examples.
The example client requires:
| Field | Example policy |
|---|---|
| x402 version | 2 |
| scheme | exact |
| network | eip155:84532 |
| asset | canonical Base Sepolia USDC |
| transfer method | EIP-3009 |
| financial value | none; testnet only |
See the Staging guide before you configure endpoints or credentials.
Historical Production Base Mainnet Example
The separate Production example is pinned to the route and payment boundary accepted on 2026-07-27:
| Field | Required value |
|---|---|
| HTTP resource | https://api.pubfi.ai/v1/gateway/quantro/health |
| MCP endpoint | https://mcp.pubfi.ai |
| Network | Base mainnet eip155:8453 |
| Asset | canonical Base USDC 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 |
| Amount | 1000 atomic units, or 0.001 USDC |
| Payee | 0x35764549c387f6befcbe6d03e6bfbd7ade4543b6 |
| Transfer method | EIP-3009 |
This is historical acceptance evidence, not a current payment example. Under schema v5, exact
health operations are free_health and bypass x402. Do not run the archived paid commands against
that route. For a current Production payment, select a ready non-health quantro_priced operation
from the complete Production catalog and validate its unsigned challenge with a separately reviewed
mainnet wallet policy.
See the Production Base mainnet example for the pinned HTTP and MCP commands.
The Production acceptance run completed on 2026-07-27 with the official x402 clients. The workflow link requires access to the source repository; the Base transactions below are public:
| Lane | Base transaction | Verified result |
|---|---|---|
| HTTP | 0xb011351c…cc594f | 200, PAYMENT-RESPONSE, signed receipt, exact replay |
| MCP | 0x25819c48…3f9934 | paid tool result, signed receipt, exact structured-content and payment-metadata replay |
Both requests used Base mainnet, canonical USDC, and the pinned 0.001 USDC offer. The test kept the buyer key and full payment evidence outside public output.
A bounded Quantro read-only acceptance confirmed one settled settlement and one signed receipt
for each lane. Exact replay reused the first settlement and receipt; it did not create a second
charge. The underlying Quantro records remain private.
Before You Pay In Staging
The numbered procedure below is Staging-only. A Production client must use the same selection and validation principles with a separate Base mainnet wallet policy; the pinned 2026-07-27 example is historical evidence only.
Prepare:
- an x402 V2 client;
- a dedicated Base Sepolia test wallet with test USDC;
- an independently approved expected PubFi payee;
- a maximum amount and authorization lifetime; and
- a secret manager or wallet that keeps the buyer private key outside prompts, source code, logs, issues, and CI output.
The public runnable example rejects payments above 0.01 test USDC and authorizations longer than 300 seconds.
1. Request The Resource Without Auth
export X402_RESOURCE_URL='https://api-stg.pubfi.ai<exact ready Quantro-priced path>'
curl --include \
"${X402_RESOURCE_URL}"
An eligible unpaid request returns:
- HTTP
402 Payment Required; - a
PAYMENT-REQUIREDheader; - the same payment requirements in the JSON response; and
Cache-Control: private, no-store.
The payment requirement contains the exact resource URL, amount, asset, network, payee, scheme, transfer method, and authorization timeout.
2. Validate Before Signing
Use an x402 V2 client and reject the challenge unless every field matches your wallet policy. At minimum, validate:
- the exact HTTPS resource;
- x402 version
2and schemeexact; - Base Sepolia network
eip155:84532; - canonical Base Sepolia USDC;
- EIP-3009;
- the expected PubFi payee;
- the maximum amount you authorize; and
- the maximum authorization lifetime.
Keep the buyer private key in a secret manager or wallet. Do not place it in a prompt, source file, shell history, log, issue, or CI output.
3. Send The Signed Request
The x402 client repeats the exact request with PAYMENT-SIGNATURE. Do not add Authorization or
X-PubFi-Api-Key to that request. The legacy header is not accepted as authentication, but its
presence still selects the credential lane. Supplying both payment modes is a conflict and PubFi
rejects it.
A successful settled response includes PAYMENT-RESPONSE. Treat the full payment signature,
payment payload, and payment response as sensitive payment evidence. Do not log them.
The unsigned challenge includes the official Signed Offers & Receipts offer-receipt extension
and its compact Ed25519 JWS Signed Offer. The settled PAYMENT-RESPONSE includes the extension's
Signed Receipt. The JWS kid points to PubFi's did:web verification method.
PubFi uses one active private signer. The did:web document can also publish up to eight retained
public verification keys. Only the active key signs new offers and receipts. Retained public keys
keep supported historical receipts verifiable after key rotation.
4. Replay Safely
If a connection is lost after signing, resend the exact same request with the exact same
PAYMENT-SIGNATURE. Do not create a second authorization first.
After settlement, exact replay returns the same bounded response bytes and the same
PAYMENT-RESPONSE, including the same signed receipt. It does not create a second provider call,
settlement, or wallet charge. A changed method, path, query, body, route, or payment binding is
rejected.
Public Runnable Examples
The public repository contains a no-secret challenge inspector and bounded, Staging-only paid HTTP and MCP examples:
sh examples/agents/x402-base-sepolia/show_challenge.sh
The paid examples use pinned official x402 clients. They require a buyer key supplied by the
caller's wallet or secret manager and an independently approved expected payTo address.
See the public x402 example for installation, HTTP, MCP, signed receipt, and exact replay commands.
The Staging acceptance run completed both official-client lanes with Signed Offer and Signed Receipt verification and exact replay. The workflow link requires access to the source repository.
An eligible Staging route can use the same accountless payment mode through MCP
pubfi.route.execute at https://mcp-stg.pubfi.ai. See
MCP Client Setup for the official MCP metadata flow.
The Production example uses the same protocol flow at the Production HTTP and MCP origins. It has a separate Base mainnet policy and does not accept the Staging network, asset, payee, or origins.
Verify The Offer And Receipt
Use a JWS and DID library that supports EdDSA and did:web.
- Read the offer JWS from
PaymentRequired.extensions["offer-receipt"].info.offers. - Require JWS algorithm
EdDSAand resolve the exactkidthrough itsdid:webdocument. - Require the DID document to authorize that Ed25519 verification method for assertions.
- Verify the compact JWS over its exact encoded payload bytes. Parse the payload as JSON only after signature verification, then require the payload bytes to match the JSON Canonicalization Scheme form.
- Check the signed offer fields against the live payment requirement: version, resource URL, scheme, network, asset, payee, amount, and expiry.
- After settlement, read and verify
SettlementResponse.extensions["offer-receipt"].info.receiptin the same way. - Check the signed receipt's version, network, resource URL, payer,
issuedAt, and optional transaction. Require an exact replay to return the same receipt.
The official receipt has a deliberately narrow payload. It does not by itself sign the amount,
asset, payee, request body, response body, route identity, or every internal settlement id. Validate
the Signed Offer, the HTTP PAYMENT-RESPONSE or MCP x402/payment-response, the Signed Receipt,
and the public transaction together when the transaction is available. Do not infer an account
balance or an internal ledger from the receipt.
The Signed Receipt is verifiable payment and execution evidence. It is not proof of a PubFi account balance, Credits balance, wallet top-up, or anonymous deposit.
issuedAt comes from Quantro's durable settledAt settlement time. It is the receipt issuance
time, not the earlier provider execution stage time. Exact replay reuses the durable receipt
instead of creating a new issuance time.
Operators should use Security And Public Data Boundary for signer and retained public-key configuration rules.
Billing Expectations
The x402 lane:
- creates no PubFi account;
- creates no API key;
- creates no Credits balance;
- creates no invoice or anonymous billing dashboard; and
- does not consume a registered account's allowance.
Signed receipts provide portable evidence. They do not create an account, a balance, or a wallet history service. SIWX and wallet-history lookup are not part of the current release.
The caller's USDC balance in the environment-specific wallet is the x402 payment balance. PubFi does not mirror it as Credits or an account balance. For this Staging walkthrough, the wallet balance remains visible through the wallet or Base Sepolia explorer.
Quantro is the common authority for settlement, receipt, purchase, and allocation facts. API-key and Credits execution selects the registered lane; x402 selects the wallet-payment lane. One request cannot debit both.
See Payment And Execution Modes for the boundary between x402, registered purchases, Credits, and API-key execution.
Failure Actions
| Result | Client action |
|---|---|
Unsigned 402 with PAYMENT-REQUIRED | Validate every term, then create at most one authorization. |
x402.invalid_payment or x402.claimed_payment_conflict | Stop. Do not reuse the authorization for a changed request. |
Paid retry returns 402 with a fresh payment requirement | Treat the submitted authorization as rejected. Validate every new term before deciding whether to sign again. |
| Lost connection after sending the signed request | Replay the exact same request and authorization. Do not sign again first. |
x402.provider_failure | Treat the request as failed. Do not assume it settled. |
x402.provider_timeout or x402.unavailable | Keep the original binding for recovery. Do not submit a second provider request blindly. |
See Registry Gateway Examples for the complete public error vocabulary.
Staging Paid Example Limits
Running both paid Staging examples creates two independent payments for the selected route: one through HTTP and one through MCP. Each payment can spend at most 0.01 test USDC. The total maximum is 0.02 test USDC.
The MCP replay check compares the returned structuredContent and
result._meta["x402/payment-response"]. It does not compare raw JSON-RPC response bytes.
When MCP payment processing fails with a replacement requirement, the error tool result keeps the
official PaymentRequired fields in structuredContent and adds an error message. Treat it as a
new challenge. It is not a settlement receipt.