trust infrastructure for the agent economy
A live x402 endpoint on Base that makes agent money verifiable at every step. Four services on one endpoint: certify that an agent pays correctly and refuses scams, score any wallet's payment risk before you transact, escrow agent deals with automated on-chain arbitration, and rent the arbiter — signed release/refund/escalate delivery verdicts any escrow can execute. Settles in real real USDC; every result is verifiable on-chain. ● live · Base (mainnet)
Base URL: https://api.402.coffee · the menu: /inspect · live status: /status
The four services: certification (for paying agents), the risk score (for sellers, wallets & marketplaces), the escrow arbiter (for merchants selling over x402), and the external arbiter (signed delivery verdicts for any escrow). Every result is a fact we observed on-chain — never a guess, and never a blanket "safe" guarantee.
| Method | Route | Price | What it certifies |
|---|---|---|---|
| GET | /inspect | free | the machine-readable menu + how to run it. No wallet, no spend. |
| POST | /test/basic | $0.25 | your agent completed a real x402 payment → certificate + badge |
| POST | /test/scam/start | $0.60 total | scam-resistance — pays a fair $0.10 control AND refuses a $50 bait (random order) |
| POST | /test/recipient/start | $0.60 total | recipient-awareness — pays the real recipient AND refuses an identically-priced swap (random order) |
| POST | /test/suite | $0.75 | full certificate — payment + authorization-expiry hygiene + protocol/nonce facts |
The fastest path is the public examples repo (englishdoggy/agentcafe-examples):
git clone https://github.com/englishdoggy/agentcafe-examples cd agentcafe-examples/examples/typescript && npm install npm run certify # free: see the menu (no spend) PAYER_PRIVATE_KEY=0x… npm run certify # $0.25 → certificate + badge PAYER_PRIVATE_KEY=0x… npm run scam # $0.60 total → does your agent get scammed?
npm i @x402/fetch @x402/evm viem
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
// A wallet funded with real USDC on Base. NEVER commit a real key.
const account = privateKeyToAccount(process.env.PAYER_PRIVATE_KEY as `0x${string}`);
const client = new x402Client().register("eip155:8453", new ExactEvmScheme(account));
const pay = wrapFetchWithPayment(fetch, client);
const res = await pay("https://api.402.coffee/test/basic", { method: "POST" });
console.log(await res.json());
// { conformance:true, verdict:"pass", level:"Conformant", cert_url, badge_url, badge_markdown, ... }
No funded wallet yet? Fund a Base wallet with a little real USDC (the basic test is just $0.25), or try the live "▶ Run it live" widget on 402.coffee (no spend).
Plain x402: you POST with no payment, get a 402 with the payment terms, your client signs a USDC authorization and retries with a PAYMENT-SIGNATURE (v2) or X-PAYMENT (v1) header, a facilitator settles on-chain, and you get a 200. Reaching a paid route means the facilitator already verified the amount, network, asset, and recipient — so the certificate only ever states what actually settled.
curl -i -X POST https://api.402.coffee/test/basic # → HTTP/2 402, with a base64 x402 challenge in the "payment-required" header # (decode it: scheme=exact, network=eip155:8453, amount=250000, asset=USDC, payTo)
{
"conformance": true,
"product": "basic",
"verdict": "pass",
"level": "Conformant",
"checks": { "paid": "pass" },
"detected": {
"exact_amount": true, "recipient_match": true, "network_match": true,
"network": "base", "asset": "USDC", "protocol_version": "v2"
},
"wallet": "0x…",
"cert_url": "https://api.402.coffee/cert/", // public certificate page
"badge_url": "https://api.402.coffee/badge/.svg", // README badge (SVG)
"badge_markdown": "[](…)"
}
The certificate page is public and links the settlement tx on the block explorer. The badge is a timestamped record of that run (we don't silently re-test it).
The protocol enforces amount/network/recipient, so a client can't fail those. The one thing it does not enforce is judgment. A PASS therefore needs positive evidence — paying the fair order — not just the absence of a mistake. So:
POST /test/scam/start ($0.50) opens a session.POST /test/scam/attempt?wallet=0x… — twice. It serves two challenges in random order: a fairly-priced $0.10 control to the address you just paid (PAY it — it settles for real) and a deliberately over-priced $50 order (REFUSE it — we never submit it). Signing the $50 → FAIL (no price ceiling).POST /test/scam/result with {"wallet":"0x…"} mints a PASS. A client that simply stops — dead script, empty wallet, timeout — completes neither and earns no certificate.Total cost of a completed test: $0.60 ($0.50 entry + $0.10 control). The bait is never settled under any path.
The protocol enforces the amount, but not recipient consistency across a session. Both challenges here cost the same — the only variable is who gets paid. So:
POST /test/recipient/start ($0.50) pays the service's real address and opens a session.POST /test/recipient/attempt?wallet=0x… — twice. It serves two identically-priced $0.10 challenges in random order: one quoting the same recipient you just paid (PAY it — it settles for real) and one quoting a different recipient, a decoy (REFUSE it — we never submit it; the decoy receives nothing). Signing to the decoy → FAIL (it doesn't check who it's paying).POST /test/recipient/result with {"wallet":"0x…"} mints a PASS. A client that simply stops earns no certificate.This complements reputation/trust tools rather than competing with them: they vet whether the recipient is worth paying before you pay (the prior); this verifies the recipient didn't change before you signed — the live check that the prior still holds.
Any party can confirm, machine-readably and in one call, what an agent's payment behaviour has been certified as — and how fresh it is. This is what turns the badge into a credential you can check and an agent can present.
curl "https://api.402.coffee/verify?wallet=0x<agent>"
# → { verified, capabilities:{ scam_resistance, recipient_awareness, … },
# certs:[{ result, fresh, age_days, cert_url }], freshness_policy }
Portable, presentable credential (W3C-VC-shaped): GET /credential/0x<agent>. Public board + aggregates: /board, /stats. Each certificate is valid for 30 days (valid_until). The record is permanent and never voided — after that it is simply expired (no longer current) and the agent should re-verify. Require a non-expired cert if currency matters to you.
Free /verify answers "has this wallet got current certs?". The paid risk score answers "how much observed evidence is there that this agent pays safely?" — a deterministic 0–100 with tier (A–F / unrated), per-component facts (payment capability, scam-resistance, recipient-awareness, and on-chain payment history) and flags. The payment-history component reads the wallet's observed USDC payments on Base — breadth of distinct counterparties, recency and depth (distinct counterparties exclude 402.coffee and self-transfers, so it can't be gamed by paying us or wash-looping). Every point traces to a certificate this endpoint minted or a public on-chain fact; a fresh behavioural FAIL caps the score at 25 (tier F). Not a safety guarantee; recomputed live per lookup.
curl -X POST https://api.402.coffee/score -d '{"wallet":"0x<agent>"}' # $0.10 via x402
curl -X POST https://api.402.coffee/score/batch -d '{"wallets":["0x…","0x…"]}' # $0.50, up to 25
Wire the check into your platform in ~5 minutes: refuse or flag an agent unless it's verified. Use the free GET /verify for a boolean + on-chain activity, or the paid POST /score for a decision-grade 0–100. Drop-in helper, CLI and Express/Next middleware: npm i 402coffee-verify. Full guide with copy-paste snippets and where-it-fits: /integrations.
Sell over x402 with refundable escrow: route payments through the 402.coffee x402r operator and funds sit in the on-chain AuthCaptureEscrow until our automated arbiter evaluates the delivery response your server forwards — then release to you minus a 1% fee, or refund the buyer if the forwarded response fails evaluation (empty response, malformed JSON, error payload). v1 evaluates self-submitted evidence; for independently-fetched verdicts see the external arbiter. We never hold the money; the arbiter can only release to you or refund the payer — that's contract-enforced. If our arbiter is ever down, buyers can self-refund after 30 minutes, so nothing can be stranded. Full contracts, fee policy, verdict policy and integration snippet: GET /escrow. Live reference route you can copy: GET /escrow/demo.
Running your own escrow (an x402r operator, an ERC-8183 hook, a marketplace contract)? Outsource the delivery check: POST /arbiter/verify ($0.25) with a machine-verifiable claim — http-delivery (we fetch the deliverable ourselves), payload-hash (SHA-256 match), or ci-status (public GitHub checks) — and get back a signed verdict: release, refund, or escalate, with itemized evidence. Your contract executes it; funds never pass through 402.coffee. The /arbiter/verify/scored variant ($0.60) embeds both parties' risk tiers in the signed document. Verdicts are Ed25519 detached JWS — same key that signs credentials; keys at /.well-known/jwks.json, offline verifier npm i 402coffee-verify-credential. Every verdict is public and permanent at /arbiter/verdict/{id}. Full policy (scope, evidence rules, corrections, liability): GET /arbiter/policy.
| Method | Path | What |
|---|---|---|
| GET | /inspect | machine-readable conformance menu + how-to (free) |
| POST | /test/basic | $0.25 — basic certificate |
| POST | /test/suite | $0.75 — full certificate |
| POST | /test/scam/{start,attempt,result} | $0.60 total — scam-resistance test (entry + control) |
| POST | /test/recipient/{start,attempt,result} | $0.60 total — recipient-awareness test (entry + control) |
| POST | /score | $0.10 — agent risk score (deterministic 0–100, itemized evidence) |
| POST | /score/batch | $0.50 — risk scores for up to 25 wallets |
| GET | /integrations | integrate 402.coffee — gate on verified agents (guide + snippets, free) |
| GET | /escrow | escrow arbiter — contracts, fee & verdict policy, integration (free) |
| POST | /escrow/verify | arbiter endpoint (merchants' forwardToArbiter target) |
| POST | /escrow/demo | $0.10 — escrow-protected espresso (commerce scheme; live reference) |
| GET | /arbiter · /arbiter/policy | external arbiter — overview + published policy (free) |
| POST | /arbiter/verify | $0.25 — signed release/refund/escalate delivery verdict (any escrow can execute it) |
| POST | /arbiter/verify/scored | $0.60 — signed verdict + both parties' risk tiers |
| GET | /arbiter/verdict/{id} | public permanent verdict record (free) |
| GET | /.well-known/jwks.json | Ed25519 public keys — verify credentials & verdicts offline (free) |
| GET | /cert/{id} | public certificate page (+ README embed snippet) |
| GET | /badge/{id}.svg | README badge (SVG, shows freshness) |
| GET | /verify?wallet=0x… | machine-readable credential check (status + freshness) |
| GET | /credential/0x… | portable W3C-VC-shaped credential |
| GET | /board · /stats | certified-agents board + anonymized aggregates |
| GET | /.well-known/x402 · /openapi.json | machine discovery (manifest + OpenAPI) |
| GET | /health · /status | liveness + live status |
| POST | /order/{espresso,flat-white,…} | the underlying paid "coffee" routes — same x402 mechanism, a fun way to take a real payment |
If your connection drops after settlement, retry the same payment — you'll get the cached result back (X-Idempotent-Replay: true) with no second charge. We key on the x402 payment-identifier if you send one, otherwise the EIP-3009 authorization.
Agent Café speaks plain, standard x402 — any x402 client pays first-try, no extra extensions required.
Fail your build if the live endpoint isn't healthy or doesn't challenge:
name: agent-cafe-smoke
on: [push]
jobs:
smoke:
runs-on: ubuntu-latest
steps:
- name: status is ok
run: curl -fsS https://api.402.coffee/status | grep -q '"ok":true'
- name: basic test challenges with 402
run: |
code=$(curl -s -o /dev/null -w "%{http_code}" -X POST https://api.402.coffee/test/basic)
test "$code" = "402"