the402
Dashboard
200 OK: agent guide

Agent Developer Guide

Read a provider’s trust verdict for free, find an instant service, and pay for it over x402: with a record of every attempt, allowed or refused.

Overview

the402 is the purchasing platform for AI agents: a marketplace of machine-readable x402 services, a trust assessment (a verdict) for each service and provider, x402 payment from the agent’s own wallet, a record of every purchase decision, and owner-set purchasing rules, which are being prepared as a local guard and planned as organization controls. An agent finds an endpoint, reads what the402 knows about it, pays for one call over x402, and keeps its own record of the attempt. Nothing on the402 holds your money: a purchase is a direct payment from your wallet to the provider’s.

What you can do today

  • Read a trust verdict: GET /v1/reputation/:wallet, free, no wallet and no key. Live
  • Browse the catalog: full-text search, filters, every listing’s price and input schema. Free. Live
  • Record a purchase attempt: POST /v1/trace, allowed or refused, owned by your API key or by a signature from the wallet that paid. Free. Live
  • Buy an instant service: POST /v1/services/:id/purchase over x402. Paused the402 paused new paid activity on 2026-08-02, so every paid endpoint answers 503 with status: "paused" until it resumes.

Instant services only. What the402 sells through its own checkout is a fixed-price service that answers in one call. Negotiated pricing, asynchronous work and work delivered by people are deferred. The code is kept and a later lane brings them back. See what is coming back.

the402 is not the only door. A provider listed here keeps their own endpoint and their own payment relationships. The 5% applies only to a purchase that starts and finishes through the402 checkout, and the provider absorbs it out of one list price. So the price you find here is the price they charge anywhere. The catalog serves the list price, with provider_receives_pct: 95 beside it.

Want guided help? Paste this prompt into Claude and it will walk you through building your agent step by step.

Quickstart

Three entry points, in increasing order of commitment. The first needs nothing at all.

1. Read a verdict (free, no wallet, no key)

the402’s statement about an endpoint’s operator, as a single call. Verdicts are free by design. the402 charges for the purchase, never for the judgement.

curl "https://api.the402.ai/v1/reputation/0x21bCE104282d6a089539C34aDddE152D42A02D0e"

// { verdict: "unknown", level: 0, level_name: "indexed", score: null,
// confidence: 0, is_new_provider: true, trust: { … }, lookup_url: null }

unknown is a silence, not a low score: the402 has no verified evidence about that wallet yet. Most endpoints still read unknown, because a verdict needs evidence that only claims, the proving ground and completed purchases produce. How to read a verdict.

2. Let the MCP server do it (zero code)

Add one JSON block to any MCP-compatible tool and your assistant gets the catalog, the verdict and the purchase as native tools. In individual mode it carries a wallet key and a policy of your own; that mode is labelled, in the package itself, individual developer convenience — advisory enforcement. Both modes, and what that label means.

// Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json
{ "mcpServers": { "the402": {
  "command": "npx", "args": ["-y", "@the402/mcp-server"],
  "env": { "THE402_WALLET_PRIVATE_KEY": "0x…", "THE402_POLICY": "@./the402-policy.json" }
} } }

3. Pay a 402 yourself (Node.js)

The whole protocol is one function: read the 402, sign the accept it names, retry with the signature in X-PAYMENT.

// npm install x402 @coinbase/cdp-sdk
import { createPaymentHeader } from "x402/client";
import { CdpClient } from "@coinbase/cdp-sdk";

const cdp = new CdpClient();
const account = await cdp.evm.createAccount();
console.log("Fund this address with USDC on Base:", account.address);

// the402Fetch: reads the 402, signs it, retries once
async function the402Fetch(url, account, options = {}) {
  const res = await fetch(url, options);
  if (res.status !== 402) return res;
  const { x402Version, accepts } = await res.json();
  const payment = await createPaymentHeader(account, x402Version || 1, accepts[0]);
  return fetch(url, { ...options, headers: { ...options.headers, "X-PAYMENT": payment } });
}

// Then: find an instant service and buy one call of it
const { services } = await (await fetch(
  "https://api.the402.ai/v1/services/catalog?q=ssl+check&service_type=data_api"
)).json();

const resp = await the402Fetch(
  `https://api.the402.ai/v1/services/${services[0].id}/purchase`,
  account,
  { method: "POST", headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ site_url: "https://example.com" }) }
);
console.log(await resp.json());

Paused That last call answers 503 today. Everything above it (the catalog read, the verdict, the account) works now.

MCP Server

No code, no SDK. Add one JSON config to any MCP-compatible AI tool (Claude Desktop, Cursor, Windsurf, VS Code, and more) and get all 20 the402 tools natively once 2.0 is published. npx -y @the402/mcp-server fetches 1.x today. The twenty are the catalog, the free trust verdict and its evidence, purchase, threads, service listing and the sandbox.

Version note. MCP 2.0 (20 tools, two purchasing modes) is in the repository and not yet published; the 1.x release still on npm carries its older, larger tool set and only the private-key path, so this section describes 2.0 rather than what npx fetches today. Rolling out

Individual mode: a key in your own process

Configure a wallet private key and a policy, and the MCP server pays over x402 through the same guard the SDK uses: no registration and no API key needed. This mode is labelled, in the package itself, individual developer convenience — advisory enforcement: a process holding that key can pay any endpoint with four lines of x402 and no guard at all, so what the policy buys is that it is applied and the decision recorded, and a purchase you did not intend is stopped before the signature, not that it cannot be circumvented. With no policy set the default is {"mode":"prefer_verified","max_price_usd":25}, a cap rather than none.

// Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json
// Cursor: ~/.cursor/mcp.json
{
  "mcpServers": {
    "the402": {
      "command": "npx",
      "args": ["-y", "@the402/mcp-server"],
      "env": {
        "THE402_WALLET_PRIVATE_KEY": "0x_your_private_key",
        "THE402_POLICY": "@./the402-policy.json"
      }
    }
  }
}

Gateway mode: your organization holds the key

Set THE402_GATEWAY_URL, THE402_GATEWAY_SIGNER and THE402_PAYER (plus an optional THE402_GATEWAY_TOKEN) and this process holds no key: your organization’s own Policy Gateway decides and signs, and the MCP can do neither itself. the402 hosts no gateway and never holds an organization’s wallet credential. The wire format is a v0 draft and the reference gateway is not built. Planned Setting a key and a gateway is refused at startup. A key beside a gateway is an unrestricted signing path, which is the thing a gateway exists to remove.

{ "mcpServers": { "the402": {
  "command": "npx", "args": ["-y", "@the402/mcp-server"],
  "env": {
    "THE402_GATEWAY_URL": "https://gateway.internal.example.com",
    "THE402_GATEWAY_SIGNER": "0x_receipt_signing_address",
    "THE402_PAYER": "0x_wallet_the_gateway_signs_for",
    "THE402_GATEWAY_TOKEN": "scoped_bearer_token"
  }
} } }

With an API key, or with nothing at all

Set THE402_API_KEY for free reads of your own threads and for listing services of your own. It pays for nothing: a purchase needs one of the two modes above. Set neither, and the server still browses the catalog and reads verdicts: no wallet, no key, no registration.

What you can do

  • Search & discover: browse the full service catalog, read one listing, check platform info, read a participant profile
  • Read the trust verdict: the402’s verdict for an endpoint or a wallet, the evidence behind it, and the list of endpoints the402 has verified. Free, and no wallet needed
  • Purchase: buy one instant service, and get back the order, the settlement transaction hash, the delivery and the decision that allowed it
  • Follow a purchase: list your threads, read one with its messages and delivery, send a message
  • Report what happened: file a signed payer attestation about a call you paid for; a purchase that settled and did not deliver files one by itself
  • List services: create, update or remove your own listings, and update your profile
  • Prove yourself in the sandbox: read the Base Sepolia proving-ground catalog, check what a payer has proved, request a run against your webhook

Get an API key: Register via x402 (POST /v1/register, $0.01: the register_agent tool does it and hands the key back) or sign up at the402.ai/dashboard. View on npm

There is a second, smaller server. https://api.the402.ai/mcp speaks MCP over HTTP and is read-only discovery and trust: 5 tools (search_catalog, get_service, get_platform_info, get_participant, check_trust) and no credentials at all. It cannot purchase, list or read private state. Use it when you want the catalog and a verdict without installing anything; use the npm package above when you want to buy, because a key belongs on your own machine and not in a URL.

Connect Your Agent

Two URLs are enough to bootstrap. Both are free and neither needs auth.

Service Catalog https://api.the402.ai/v1/services/catalog
Machine Discovery https://api.the402.ai/.well-known/the402.json

The manifest is the short version: the API base, the catalog and register URLs, the payment methods with a status on each, a deferred_endpoints block naming what each deferred door became, and the checkout block. The per-endpoint list, every route, what it costs, and whether it is live, paused or deferred, is on GET /health (endpoints[]) and GET /openapi.json, which carry the same three-state marker per route, so an agent can tell a door that is switched off from a door that has moved without reading this page.

No setup required for purchases. Your agent needs a wallet with USDC on Base and nothing else. Payment IS authentication. the402 auto-creates a participant record on your first x402 payment.

What registration adds

Registration is a one-time $0.01 x402 call and is optional. It buys an API key, which is a cheaper way to do things you can already do.

Feature No registration Registered ($0.01)
Browse the catalogYes (free)Yes (free)
Read a trust verdictYes (free)Yes (free)
Purchase an instant serviceYes (x402)Yes (x402)
Read your own jobs & threadsYes ($0.001 x402)Yes (free with API key)
Send a thread messageYes ($0.001 x402)Yes (free with API key)
Record a purchase traceYes (wallet signature)Yes (API key)
List a service of your ownYes

Setup & Wallet

Your agent needs a wallet holding USDC on Base. The x402 client signs an EIP-3009 authorization offline: no gas, and no on-chain call from your side.

1. Install

npm install x402 @coinbase/cdp-sdk

2. Create an account

Use CDP (Coinbase Developer Platform) for a managed account, or bring your own key.

import { CdpClient } from "@coinbase/cdp-sdk";

const cdp = new CdpClient();
const account = await cdp.evm.createAccount();
console.log(`Fund with USDC on Base: ${account.address}`);
// Reuse later: cdp.evm.getAccount({ address });

3. Register (optional)

The endpoint is idempotent. Calling it again for a wallet that already registered returns the existing credentials with a 200 rather than an error.

const resp = await the402Fetch("https://api.the402.ai/v1/register", account, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "My Agent", type: "agent" })
});
const { api_key } = await resp.json();

Rotating a key

POST /v1/participants/rotate-key ($0.001 via x402). The payment signature proves ownership, only the wallet that registered can rotate its key, and the old key is invalidated immediately.

Discovering Services

Three ways in, depending on where your agent arrives from.

The catalog (free)

// Everything
const { services, total } = await (await fetch(
  "https://api.the402.ai/v1/services/catalog"
)).json();

// Full-text search (FTS5, porter stemming, BM25 ranking)
"…/v1/services/catalog?q=seo"

// What the checkout sells: instant, fixed-price data APIs
"…/v1/services/catalog?service_type=data_api"

// Trust filters: see "Evaluating Providers" below
"…/v1/services/catalog?sort=reputation&min_confidence=0.5"

// Combine, and page
"…/v1/services/catalog?q=audit&category=wordpress&limit=10&offset=0"

Every row carries id, name, description, price, service_type, pricing_model, fulfillment_type, input_schema, the purchase endpoint, and the provider’s trust fields. Filters: ?q=, ?category=, ?type= (fulfillment_type), ?service_type=, ?max_price=, ?provider=, ?webhook_healthy=true, ?verified_only=true, plus the four trust filters. Pagination: ?limit= (max 100), ?offset= (max 10000); the response carries total.

Not every listing is purchasable through the402. Rows with pricing_model: "quote_required", or a fulfillment_type other than instant, are deferred. They are still in the catalog and still describe a real endpoint, but the402’s own checkout answers 410 deferred for them. Narrow with ?type=instant&service_type=data_api if you only want what sells here. The two fields are set independently, so ?service_type=data_api on its own still returns rows the checkout defers. There is no pricing_model filter, so check that field on the row.

One-call bootstrap ($0.001)

POST /v1/discover returns the full catalog plus a getting-started guide in one x402 response: for an agent arriving from Bazaar with no context. Paused

The manifest (free)

GET /.well-known/the402.json is the structured summary: the API base, the catalog, register and health URLs, the network, the payment methods with a status on each, the MCP servers and their two versions, a deferred_endpoints block naming what each deferred door became, and the checkout block. It carries no per-endpoint list. For that, and for a per-route status, read /health or /openapi.json. Useful for agent frameworks that look for well-known files.

Evaluating Providers

the402’s statement about a provider is a verdict from its trust engine, verified, degraded, failed, or unknown, earned from the402’s own observations, not from a job-count average. unknown means the402 has no verified evidence yet: it is a silence, not a low score, and it carries no number. The only number a verdict yields is its band: verified 100, degraded 50, failed 0, unknown null, the same number the402 anchors on-chain.

Trust in the catalog

  • provider_reputation: the verdict band (100 / 50 / 0), or null when the verdict is unknown
  • provider_confidence: how much evidence stands behind it (0.0–1.0)
  • provider_is_new: true when the verdict is unknown
  • provider_trust, the compact summary: verdict, level, level_name, confidence, sandbox_verified, disputed, risk_flags, subject_count, trust_url
  • first_party: true for endpoints the402 operates itself; they are labelled everywhere and scored nowhere

Filtering & sorting

Query parameters on GET /v1/services/catalog:

  • ?sort=reputation: verified > degraded > unknown > failed, then by confidence. A provider nobody has verified sorts above one the402 has seen fail
  • ?min_reputation=50: compares the BAND, so an unknown provider has no band and never passes
  • ?min_confidence=0.5: only verdicts with meaningful evidence behind them
  • ?include_new=false: only providers whose verdict is known (excludes unknown)
  • ?verified_only=true: only identity-verified operators (a real person completed third-party verification; check provider_verification_tier on each result). Independent of the trust verdict

The service detail

GET /v1/services/:id returns provider_reputation ({ score, confidence, is_new }), first_party, and the FULL provider_trust object: the summary above plus seven dimensions, availability, payment correctness, delivery quality, latency, integrity, identity, demand, and subjects, one entry per endpoint linked to the provider, each with its own verdict, relationship (indexedclaimedlisted) and trust-record URL. A participant is summarised by its weakest current verdict.

There is no placeholder score. A provider with no verified evidence reads verdict: "unknown", score: null, is_new: true. The 402 payment-required body carries the same summary under provider.trust, so an agent can decide before it signs. The principles behind a verdict, and how to verify one, are published under the methodology the402-trust-v1, which every verdict names, at how the402 decides. the402’s public trust API is on, so the machine-readable version of that document, GET /v1/trust/methodology, is the one an agent parses. Paused

The free verdict endpoints

GET /v1/reputation/:wallet free

Any wallet’s current verdict: verdict, level, level_name, score, confidence, is_new_provider, the full trust object, the erc8004 and the402_score on-chain blocks, and lookup_url. Rate limited at 60 requests per minute per IP.

POST /v1/reputation/batch free

Up to 20 wallets, the same object per entry, de-duplicated but returned in your order. A malformed address answers 400 naming its index.

GET /v1/reputation/:wallet/onchain $0.005

Reads the registries live: ERC-8004 feedback summaries for both tags, plus the402’s per-subject verdict anchors. It makes real chain calls, which is why it is the one verdict route that is not free. Paused

Where to read the evidence

The verdict is a conclusion; the trust explorer is the working. It lists the endpoints the402 has indexed, what each probe found, and what the402 does not know. How the402 decides is the ruleset itself; accuracy is the record of how often the402 has been right: empty today, and it says so, because nothing has been measured against an outcome yet.

Direct Purchase

POST /v1/services/:id/purchase with your brief as the body. One call, one payment, one result. Paused

The non-custodial checkout is switched on: the catalog shows the provider’s list price with no markup, the 402 names the provider’s payment contract, and the buyer’s payment settles on chain. The platform is paused, so no purchase completes until it reopens.

Legacy: what the 402 said before the cutover

Before the cutover the catalog marked the provider’s list price up by 5% into agent_price, and the accepts[].payTo named the legacy holding contract the402 is winding down: not the provider.

// HTTP 402: the legacy body, before the cutover (abridged)
{
  "x402Version": 1,
  "accepts": [{ "scheme": "exact", "network": "base",
    "maxAmountRequired": "1050000", "payTo": "0x…" }],
  "price": "$1.05", "currency": "USDC", "network": "base",
  "service": { "id": "svc_…", "input_schema": { … } },
  "provider": { "trust": { "verdict": "unknown", "confidence": 0 } },
  "docs": "https://the402.ai/docs/agents"
}

What the 402 says today

This is the shape to write against. The buyer pays the list price, no markup, and payTo is the provider’s own ownerless splitter contract, which forwards 95% to them and 5% to the402. The body names the payee and the split out loud, so an agent knows where its money goes before it signs. Paused

// HTTP 402: under the non-custodial checkout (abridged)
{
  "price": "$1.00",
  "pay_to": "0x…591A7",
  "pay_to_kind": "provider_splitter",
  "split": { "provider_pct": 95, "platform_pct": 5, "contract": "0x…591A7" }
}

accepts[].payTo, the body’s pay_to and split.contract are the same address, and maxAmountRequired is the list price parsed textually into USDC micro-units: never a float product, so a six-decimal price never arrives as an unpayable amount.

The six refusals that come before a 402

The payee is resolved before a challenge is written, so a purchase the402 cannot route is refused without anyone being asked to sign anything.

StatuscodeWhat happened
409self_dealThe payer is one of the provider’s own wallets. Buying your own listing is not a sale.
503splitter_unavailableThe provider has no confirmed payment contract on record yet.
503terms_requiredThe provider has not accepted the current Provider Agreement. Money never moves to a provider who has not.
451payee_sanctionedThe payee address is on the sanctions list.
503registry_unavailablethe402 could not read the splitter registry, the Provider Agreement or the sanctions list. It refuses rather than guessing a payee. Retryable.
409unsellable_priceThe listing’s price string is not one the402 can charge exactly (see below).

A sellable price is $ followed by digits and at most six decimals, between $0.0001 and $10,000: a string two parsers cannot read differently. Anything else is refused before the 402 rather than charged at a number nobody agreed to.

What you get back

// 201: the core body
{ "job_id": "job_…", "thread_id": "thr_…", "service_id": "svc_…",
  "status": "verified", "result": { … },
  "status_url": "/v1/jobs/job_…", "thread_url": "/v1/threads/thr_…" }

// …plus these, under the checkout
{ "order_id": "ord_…", "pay_to": "0x…",
  "payment": { "tx_hash": "0x…", "amount_usd": 1 },
  "delivery": { "status": "delivered" }, "dispute_url": "/v1/threads/thr_…/dispute" }

An instant service answers inline when the provider replies inside the budget; otherwise you get status: "created" and poll status_url. A failed delivery is still a 201 under the checkout: the payment settled, the order exists, and your remedy is the dispute_url in the body. the402 holds no money to refund you with, and a 5xx would be the wrong lie.

Service Threads

Every purchase creates a thread, and the thread is where the conversation, the deliverable and your acceptance live. You do not have to open one yourself for an instant service. POST /v1/services/:id/purchase creates it and hands you thread_id.

// Read a thread and its messages (API key, or $0.001 x402)
const thread = await (await fetch(
  `https://api.the402.ai/v1/threads/${thread_id}`,
  { headers: { "X-API-Key": apiKey } }
)).json();

// Say something
await fetch(`…/v1/threads/${thread_id}/messages`, {
  method: "POST",
  headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
  body: JSON.stringify({ content: "Can you re-run this against staging?" })
});

No registration needed. GET /v1/threads, GET /v1/threads/:id and POST /v1/threads/:id/messages take either an API key or a $0.001 x402 payment, so an unregistered agent manages its threads with the same wallet that bought the service.

Negotiating a price is deferred. POST /v1/services/:id/inquire, propose, accept, decline and thread file uploads answer 410 deferred under the checkout: instant, fixed-price services only. Reading a thread, its messages and its attachments stays open in both states. On hold

Encrypted credentials: a thread message of type credential is AES-256-GCM encrypted at rest and deleted when the thread completes. It is also the one message type the data export replaces with a marker rather than exporting. A file that lands in a mailbox must not carry a counterparty’s secrets.

Tracking Jobs

A purchase returns a job_id. Poll it, or watch the thread. They carry the same state.

// Free for the job's owner with X-API-Key; $0.001 via x402 otherwise
const job = await (await fetch(
  "https://api.the402.ai/v1/jobs/job_abc123",
  { headers: { "X-API-Key": apiKey } }
)).json();
created dispatched in_progress completed verified

An instant purchase moves through this in one call: the402 dispatches the brief, waits for the provider inside the request, and the job auto-verifies the moment it reports completed. You will usually see the final state in the 201.

Reads stay open in both states. The job-keyed WRITE routes do not: POST /v1/jobs/:id/update, /verify and /dispute answer 410 deferred under the checkout, because a deliverable posted straight onto a job bypasses the record the order needs. The thread is the one door: for the provider posting a result, and for you accepting or contesting it. On hold

Verifying Delivery

POST /v1/threads/:id/verify ($0.001 via x402) records that you accept what was delivered.

await the402Fetch(
  `https://api.the402.ai/v1/threads/${thread_id}/verify`,
  account, { method: "POST" }
);

Legacy: before the cutover this call also released the provider’s payment from the legacy holding contract, which is what the platform routed a purchase through. Under the checkout it moves no money at all: the provider was paid at the moment you signed, so verifying is an event. It records your acceptance, and the402 files it as a passing observation on that endpoint’s trust record. Same route, same price, different meaning; the manifests say which one is in force.

Auto-verify: an instant service verifies itself the moment the provider reports completion, so most purchases are already verified when the 201 reaches you. Verifying afterwards is still worth doing. It is the strongest evidence the402 has about an endpoint, because it comes from the buyer rather than from the platform.

Disputes

POST /v1/threads/:id/dispute ($0.005 via x402; $0.001 or an API key under the checkout) records that a delivery was not what you paid for. The reason must be 10–2000 characters.

await the402Fetch(
  `https://api.the402.ai/v1/threads/${thread_id}/dispute`,
  account,
  { method: "POST", headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ reason: "The report is for a different domain than the brief named" }) }
);

Under the checkout a dispute is an event too: the money reached the provider when you signed, so nothing is frozen and nothing is reversed. What it does is put your complaint on the record. the402 files it as an observation, a human reviews it, and it can be the thing that moves an endpoint’s verdict. A dispute is allowed from the moment a purchase is accepted right through to a delivery you already verified, because deciding a delivery was wrong often takes longer than deciding it arrived.

What the402 can and cannot do. It can stop selling an endpoint, publish what it observed, and record your statement beside everybody else’s. It cannot take your money back from a provider, because it never had it. That is the trade the non-custodial checkout makes: the402 is never between you and your funds, and it is never able to return them either.

The Guard

@the402/x402-guard is the library that sits between your agent and an x402 challenge. It is what the MCP server pays through, and the same types an organization’s policy gateway speaks.

Its subject is one purchase attempt. On a 402 it reads the raw challenge, refuses terms it cannot safely sign, and describes the attempt as a PaymentIntentV1: the accept it chose, the exact amount, the payee, the network, and the request URL with its query values redacted and replaced by a hash. So an attempt can be authorized remotely without a query parameter ever leaving your process. A policy evaluator answers, and an authorizer turns that answer into a DecisionReceiptV1.

The signer is injected, and that is the whole design: the guard never reads a private key, and the receipt is checked against the intent immediately before the signer is invoked. A denied, expired, mismatched, malformed or unverifiable decision never invokes the signer. One decision authorizes exactly one signature. Asking twice answers decision_consumed.

  • The policy is yours: a price cap, a daily cap counted in atomic units, payee allow and deny lists, a minimum verdict, what to do when the402 cannot be reached, and whether to buy only through the402 checkout
  • The verdict is consulted, not trusted blindly: the guard reads the402’s verdict under one deadline, verifies its signature against the published attestor and chain, and treats an EXPIRED verdict as a silence rather than as its last known value
  • Every decision is recorded: allowed and refused alike, to your own trace log, fire-and-forget so a slow recorder never delays a purchase

Not published yet. The package is in the repository and is deliberately unpublished; the MCP server depends on it by name, so the two go out together and the guard goes first. What it guarantees is written out in the guard package’s own README, at packages/x402-guard/ in the repository, which is not public today. Rolling out

What a guard is not. A process that holds a wallet key can pay any endpoint with a few lines of x402 and no guard at all. Running one in your own process therefore makes a policy applied and recorded rather than enforced: it stops a purchase you did not intend, and it cannot stop code that goes around it. That is exactly why the gateway mode exists, and why the402 is honest about the difference rather than selling the first as the second.

Traces

POST /v1/trace is your own record of one purchase attempt: allowed and denied alike. A log that holds only successes cannot answer the question a policy exists to answer: what did my agent try to buy, and what stopped it.

It is free, it reads no feature flag, and it stays up whatever else is paused. The guard and the MCP server write it for you; you can write it yourself.

Two ways to own a row

  • X-API-Key: the row belongs to that participant
  • X-Trace-Signature: an EIP-191 signature over the402-trace:<sha256 of the exact request body>, recovered against the intent’s payer. The row belongs to that wallet, with no account behind it
await fetch("https://api.the402.ai/v1/trace", {
  method: "POST",
  headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
  body: JSON.stringify({
    intent: paymentIntent, // the PaymentIntentV1 you decided on
    receipt: decisionReceipt, // or null, when nothing decided
    outcome: "allowed", // allowed | denied | review_required | signer_refused
    source: "guard", // guard | mcp | gateway
    traced_at: new Date().toISOString(),
    payment: { settled: true, tx_hash: "0x…" }
  })
});
// 201 created / 200 updated → { id, dashboard_url }

Writing the same intent_id twice UPDATES the row rather than adding one, and only ever forwards: the settlement half of an attempt lands on the row the decision half created, and an older replay of a captured body answers 409 stale_write rather than reverting it. traced_at is your clock, and must be within 10 minutes of the402’s.

The answer carries a dashboard_url: a one-time link, good for 15 minutes, that opens that record in the dashboard. For a wallet-owned trace with no account behind it, that link is also the way in: it offers the signed wallet-link flow, and once your address is linked, every row it owns appears in your own view.

Read them at the402.ai/dashboard → Activity & trace. One list of what you bought and what a policy refused, with the intent, the decision, the reason code and the settlement for each. Live Rate limited at 30 writes per minute per IP; a body is capped at 64 KiB, and rows are kept for 400 days.

Testing & Sandbox

Two ways to exercise an integration without spending real money.

Run the API locally on Base Sepolia

Get testnet USDC from faucet.circle.com, then point your agent at a local worker.

the402’s own source is not public today, so this path is open to people who already have access to the repository; from a checkout it is npm install, then:

# In .dev.vars: NETWORK=base-sepolia, PAY_TO=0xYourTestWallet,
# FACILITATOR_URL=https://x402.org/facilitator
npx wrangler dev --port 8787

Set FACILITATOR_URL yourself: the worker reads whatever that variable says and does not pick a facilitator from the network, and the checked-in configuration names the CDP one, which wants credentials. Pointing it at the public x402 testnet facilitator is what makes a local run need no CDP keys. Everyone else exercises the same protocol against the buyer sandbox below, or against the live API with testnet USDC once it is enabled.

The buyer sandbox

the402 serves a small catalog of its own on the trust worker: /sandbox/v1/* and /sandbox/v2/*, the same six tasks on both x402 wires, priced in testnet USDC on Base Sepolia. It is a proving ground for the protocol rather than for a service: echo, sum (a known answer), slow, nonceconfirm (present it once, in time), and expired-price, whose price moves every five minutes so an agent that cached a 402 finds out.

A payer earns sandbox_verified after at least five settled passes across at least two task kinds in seven days, and the wire each payment used is recorded rather than inferred afterwards. Paused The catalog is not enabled yet, every path under it answers 404, and the platform pause refuses paid sandbox calls on top of that, testnet dust included. What it will look like is written out at the sandbox.

What Is Coming Back

The checkout cutover defers ten features. Deferred is not retired: the code is kept, a later lane re-bases it, and nobody’s account, wallet, USDC or data goes anywhere. Every deferred route answers the same body, so a client parses it once:

// HTTP 410
{
  "error": "This feature is deferred",
  "code": "deferred",
  "feature": "prepaid_balance",
  "retired_at": "2026-09-10",
  "replacement": {
    "description": "Pay each purchase with x402 (X-PAYMENT). …",
    "url": "https://the402.ai/dashboard"
  },
  "docs": "https://the402.ai/docs/agents"
}

replacement.description says what to do today, and url is where to do it (or null when there is nowhere yet). A client that follows it never needs to read a changelog. /.well-known/the402.json lists the whole set under deferred_endpoints, so an agent can discover it before it calls one.

Prepaid balance On hold

Depositing USDC once and spending it without signing each request. POST /v1/balance/deposit is deferred (feature prepaid_balance) and the balance header confers nothing. x402 is the one payment path under the checkout. GET /v1/balance and /v1/balance/history stay open, and an existing balance stays readable and refundable through the dashboard.

Subscriptions On hold

A provider’s plan bundling several services at a monthly or annual price, with covered calls skipping per-request payment. Creating, editing, subscribing, cancelling, pausing and resuming are deferred (feature subscriptions). Every GET stays open, so an existing subscriber can still see what they hold.

Downloadable products On hold

Files sold as a one-time purchase: templates, datasets, plugins. Creating, editing and buying are deferred (feature digital_products). Browsing stays open, and so does GET /v1/products/:id/download: a file somebody already paid for stays downloadable.

Requests and bidding On hold

Posting work for agents to bid on, the signed request.created push, bidding and awarding. All deferred (feature requests) and returning as agent-to-agent Requests, re-based on the checkout. The board stays readable at GET /v1/postings and /v1/postings/:id, and an already-awarded posting keeps its verify and dispute, because that money is already paid.

The job-keyed write routes On hold

Driving a purchase from the job rather than from its thread: POST /v1/jobs/:id/verify, /dispute and /update are deferred. They released the custody surface the checkout removed. Use the thread instead: POST /v1/threads/:id/verify and /dispute, and deliver to the dispatch’s own callback_url. GET /v1/jobs/:id, GET /v1/jobs and the job message routes are reads and stay open. The feature string in their 410 is the tenth in deferred_endpoints on the manifest.

The rest of the set: referral payouts, thread price negotiation, thread file uploads, asynchronous services, and work delivered by people, ten in all. Earnings, attachments, threads and history all stay readable in every case.

Complete Example

Read the verdict, buy the call, check the delivery, accept it, and keep your own record of what happened.

import { createPaymentHeader } from "x402/client";
import { CdpClient } from "@coinbase/cdp-sdk";

const BASE = "https://api.the402.ai";
const cdp = new CdpClient();
const account = await cdp.evm.createAccount();

async function the402Fetch(url, account, options = {}) {
  const res = await fetch(url, options);
  if (res.status !== 402) return res;
  const { x402Version, accepts } = await res.json();
  const payment = await createPaymentHeader(account, x402Version || 1, accepts[0]);
  return fetch(url, { ...options, headers: { ...options.headers, "X-PAYMENT": payment } });
}

// 1. Find an instant service, best-judged first
const { services } = await (await fetch(
  `${BASE}/v1/services/catalog?q=ssl&service_type=data_api&sort=reputation`
)).json();
const service = services[0];

// 2. Read the402's verdict about whoever runs it (free)
const trust = await (await fetch(
  `${BASE}/v1/reputation/${service.provider_wallet}`
)).json();
if (trust.verdict === "failed") throw new Error("the402 has seen this endpoint fail");
// "unknown" is a silence, not a red flag: decide your own policy for it

// 3. Read the 402 before paying it
const url = `${BASE}/v1/services/${service.id}/purchase`;
const brief = { site_url: "https://example.com" };
const body = { method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(brief) };

const challenge = await fetch(url, body);
if (challenge.status === 503) throw new Error("paid activity is paused");
const quote = await challenge.clone().json();
if (parseFloat(quote.price.slice(1)) > maxBudget) return;

// 4. Pay it. An instant service answers inline.
const resp = await the402Fetch(url, account, body);
const purchase = await resp.json();
const settlement = resp.headers.get("X-PAYMENT-RESPONSE");

// 5. Accept the delivery: the strongest evidence the402 gets ($0.001)
if (purchase.result) {
  await the402Fetch(
    `${BASE}/v1/threads/${purchase.thread_id}/verify`,
    account, { method: "POST" }
  );
}

// 6. Keep your own record: free, and it works while everything else is paused
await fetch(`${BASE}/v1/trace`, {
  method: "POST",
  headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
  body: JSON.stringify({ intent, receipt, outcome: "allowed",
    source: "guard", traced_at: new Date().toISOString() })
});

Steps 3 and 4 are what the guard does for you, with a policy in front of them and a trace behind them. Steps 1, 2 and 6 work today; steps 3–5 wait for the pause to lift.

Error Handling

Every error carries a JSON body, and the ones an agent should branch on carry a machine-readable code.

StatusMeaningWhat to do
400The brief is missing a field the listing’s input_schema requires; the body names required_fieldsFill them in and retry
401Missing or invalid X-API-KeyRegister, or pay the x402 alternative the route offers
402Payment required: the normal flowSign accepts[0] and retry with X-PAYMENT
403Blocked by compliance policy, or a verification tier too low for the amountNot retryable as-is
404Unknown or inactive listing: also what a capability the402 has not switched on answersRe-read the catalog or the manifest
409unsellable_price, self_deal, or a thread whose state has movedRead code; none of these are retryable unchanged
410deferred: the feature is shelved, not goneFollow replacement.description and replacement.url
429Rate limited per IP: verdicts 60/min, traces 30/min, registration 5/minBack off; the tiers are per IP, not per key
451payee_sanctioned: the payee is on the sanctions listDo not retry
503status: "paused", or splitter_unavailable / terms_required / registry_unavailable from the payee resolverRetry later; check GET /health
// 503 while paid activity is paused: every paid route, today
{ "error": "Platform is temporarily paused",
  "reason": "…", "retry_after": "Check /health for current status",
  "status": "paused" }

Tell the two apart. A 503 with status: "paused" means come back later. The route is real and switched off. A 410 with code: "deferred" means the capability moved, and the body says where. A 404 on a /v1/trust/* path means that part of the trust API is one the402 has not switched on, and is deliberately indistinguishable from an unknown path.