x402 Whitepaper: Agent Payment Verification
Ontario Protocol is pre-payment verification and discovery infrastructure for x402-paid endpoints. This document describes how endpoint metadata, HTTP 402 challenges, signed readiness reports, can-pay policy, service discovery, and settlement evidence fit together before an agent spends.
Fastest path from architecture to a real signal
If you are evaluating whether an agent should trust or pay an x402 endpoint, do not start with a payment. Run the free readiness verifier, run the can-pay policy check, then move to the smallest paid proof only when your policy returns allow.
1. The shape of the problem
Autonomous AI agents need three things that classic SaaS does not give them:
- Per-call settlement. Agents transact in micropayments — cents and fractions of cents — and only when they actually need a capability. Subscriptions and API keys are unfit for purpose.
- Auto-discovery. Agents do not read landing pages. They consume manifests. Anything an agent needs to know about a service must be machine-readable and reachable in one HTTP round-trip.
- Verifiable trust. When an agent decides whether to trust another agent, it cannot rely on hand-waved testimonials. It needs a structured signal it can audit on-chain.
x402 covers (1) and (2). EAS covers (3). Ontario Protocol stitches them together and operates the marketplace on top.
2. Stack overview
+--------------------------------------------------------------------+
| Agents (LangChain, CrewAI, Anthropic MCP clients, OpenAI, custom) |
+----------------+---------------------------------------------------+
| HTTP (x402)
v
+--------------------------------------------------------------------+
| Ontario Protocol — Flask app |
| - x402_server.py (HTTP 402 middleware) |
| - agent_discovery.py (.well-known + /discover + /listings) |
| - agent_trust_scanner.py(paid trust scan) |
| - reputation_eas.py (EAS attestations on Base) |
| - proxy_facilitator.py (1.5% take-rate wrapper) |
| - take_rate_ledger.py (append-only SQLite) |
| - treasury.py (public dashboard) |
+----+----------------------+----------------------+-----------------+
| | |
v v v
Coinbase Facilitator EAS contract on Base Base RPC
(verify + settle) (0x4200...0021) (basescan.org)
|
v
USDC ERC-20 (0x8335...0913)
3. The x402 flow
Every paid endpoint follows the canonical x402 dance:
- Client makes the call without payment.
- Server returns
HTTP 402with a base64-encodedPAYMENT-REQUIREDheader. The decoded payload describes the asset, the amount, the network, the receiver, and a nonce. - Client signs an EIP-3009
transferWithAuthorizationmessage and base64-encodes the result into aPAYMENT-SIGNATUREheader. - Server forwards the signed payload to a facilitator (Coinbase by default) for
verify+settle. On success, the facilitator submits the on-chain transaction; on failure the server returnsHTTP 402again with the failure reason. - Server returns
HTTP 200with the actual response, plus a base64PAYMENT-RESPONSEheader containing{success, transaction, network, payer}.
All of this is implemented in x402_server.py as a Flask
decorator. Adding a new paid endpoint is one decorator and one view function.
4. Discovery
Agents discover Ontario through three surfaces, all served as JSON:
| URL | Purpose |
|---|---|
/.well-known/x402.json | Standardised manifest. The default place an agent looks. |
/discover | Flat catalog with filtering. ?category=trust etc. |
/listings | Content-negotiated: HTML for humans, JSON for agents. |
The same data is also rendered into listings_out/coinbase-bazaar.yaml
and listings_out/mcp-server.json for syndication via the
Coinbase Bazaar registry and the MCP server registry respectively.
5. Trust scans & reputation
agent_trust_scanner.py performs a deterministic, side-effect-free
scan of an agent's surface area:
- Agent card at
/.well-known/agent.json— reachable, well-formed? - x402 manifest at
/.well-known/x402.json— present, well-formed? - OpenAPI schema at
/.well-known/openapi.jsonor/openapi.json? - Schema.org structured data on the homepage?
- HTTPS on the canonical URL?
- robots.txt: is AI consumption allowed or disallowed?
The trust score is the unweighted percentage of positive signals that
fired. It is intentionally simple — there are no hidden weights — so
consumers can re-derive the same number from signals alone.
Each scan is recorded as an attestation through
reputation_eas.py. When EAS_SIGNER_PRIVATE_KEY
and EAS_SCHEMA_UID are configured, the attestation is
submitted on-chain to the Base EAS contract at
0x4200000000000000000000000000000000000021; otherwise it is
stored in the local SQLite mirror only and labelled onchain: false.
6. Proxy facilitator & take rate
proxy_facilitator.py wraps Coinbase's hosted facilitator.
Its verify() is a pure pass-through. Its settle():
- Forwards the call to Coinbase, on Base mainnet, settling USDC.
- Looks up the resource against
agent_discoveryto detect whether the listing is first-party or third-party. - Computes a 1.5% (150 bps) take rate on third-party gross.
- Writes one append-only row to
take_rate_ledger.pyregardless of outcome — failures included for audit reconciliation.
treasury.py reads the ledger and exposes it at
/treasury (HTML) and
/api/treasury/stats (JSON).
Provider sweeps are deliberately manual at Tier 3; the ledger
surfaces the amount owed to each provider so payouts are auditable.
7. Why USDC on Base
- USDC is the dominant agent-payable asset (regulated, redeemable, multi-chain).
- Base offers ~$0.01 transactions, mature tooling, and the Coinbase facilitator runs on it natively.
- EIP-3009 (
transferWithAuthorization) gives signed-payment UX without per-tx approvals. - EAS is deployed on Base mainnet, which keeps reputation writes cheap.
8. Failure modes & mitigations
-
Coinbase facilitator outage —
x402_facilitator_client.pyreturns a fallbacksupported()response and degrades clearly. Settlements fail closed; no payment is recorded as successful unless we have a transaction hash. -
Coinbase TOS may forbid proxy mode. The proxy is
opt-in via
X402_USE_PROXY=1. With it off, payments go directly to Coinbase and Tier 3 take-rate is dormant. Tiers 1+2 keep working unchanged. -
Replay attacks. Each
PaymentRequiredcarries a fresh nonce inextraand avalidUntiltimestamp. Nonce uniqueness is enforced by the facilitator; if Ontario ever runs its own settlement, the same field will be validated locally. - Trust-score gaming. The score is mechanical and public. Agents that can game it can do so in seconds, but the signals it surfaces are still useful as raw inputs to a richer decision policy.
9. What's next
- Vertical specialisation in agent-trust data: behavioural scans, history-aware reputation, cross-agent attestations.
- Multi-network: support for Optimism, Arbitrum, Solana once the x402 facilitator ecosystem matures off Coinbase.
- A first-class browse UI for the marketplace separate from
/listings, including reputation-aware ordering. - A formal MCP server registry submission once the ecosystem agrees on a shared registry shape.
Source code lives in the same repository as this site. Nothing on this page is hand-typed marketing — every number on the homepage and the treasury page is sourced from the live ledger or live counters.