01 · BEFORE PAYING
Shonin Check
Should my agent pay this? A pre-payment check of any x402 payment request: pay, confirm with a person, or block.
- pay
- confirm
- block
For agents and the people who build them
Everything here is a plain HTTP endpoint. There are no accounts and no API keys: an agent pays per call in stablecoins with x402 v2, and settlement only happens when the call succeeds. Every answer says how it was decided, so your agent can gate on it.
01 · BEFORE PAYING
Should my agent pay this? A pre-payment check of any x402 payment request: pay, confirm with a person, or block.
02 · BEFORE ACTING
Execute, confirm or escalate? An approval gate for any agent action, with one confidence bar per risk tier.
03 · AFTER PAYING
Proof for every agent payment: an on-chain settlement check and a signed, normalized receipt for the books.
Ask
Call the endpoint like any API.
402
The response carries the price: amount, stablecoin, network, payee, and a 5-minute window.
Sign
Your agent signs a gasless EIP-3009 transfer authorization. No transaction yet.
Retry
Send it in the PAYMENT-SIGNATURE header. We run the job.
Settle
Only if the job succeeds does the facilitator settle. Errors are never charged.
Send a support message, get intent, complexity, frustration, refund intent and a route.
POST /api/v1/triage
{
"subject": "Duplicate charge",
"message": "I was charged twice for order A-104. Please refund the duplicate."
}Score an inbound lead against your own offers: fit, urgency, budget, decision maker, spam.
POST /api/v1/lead-score
{
"message": "We need a WhatsApp assistant for our 3 restaurants before December. Budget approved.",
"offers": [
{
"slug": "concierge",
"name": "WhatsApp Concierge",
"pitch": "An AI assistant that answers customers on WhatsApp"
},
{
"slug": "website",
"name": "Website",
"pitch": "A new website"
}
]
}Score a grant application against a rubric and get the three sections to fix first.
POST /api/v1/grant-fit
{
"program": "Ecosystem builder grant",
"requirements": "Open source; live on mainnet; clear milestones",
"application": "We are building..."
}Should this draft ship? Hook, specificity, voice and unsourced-number checks in one call.
POST /api/v1/content-gate
{
"draft": "Most agents rent a frontier model to return the word 'billing'..."
}Typed decisions for agents: Choice, Score and Noul with confidence, in one call, paid per call.
POST /api/v1/decide
Launches only after TypeSafe confirms in writing that its terms allow it. Until then: the recipe APIs, or TypeSafe directly.
{
"state": {
"message": "I was charged twice for order A-104. Please refund the duplicate."
},
"questions": {
"team": {
"type": "choice",
"instructions": "Which team should handle this",
"criteria": {
"billing": "Payments, refunds, duplicate charges",
"technical": "Bugs",
"other": "Anything else"
}
},
"refund": {
"type": "noul",
"instructions": "The customer is explicitly asking for a refund"
}
}
}Daily prices for staples in Lagos markets, sold per query to agents and apps, paid in stablecoins.
GET /api/v1/market-prices
Contributors are paid per verified submission.
{
"market": "mile-12",
"item": "rice-50kg"
}With @x402/fetch and a viem account, paying is a wrapped fetch. Cap spend per call on the client, and ask Shonin Check before paying anyone you don't know.
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
// Holds USDC. No gas token needed: the facilitator submits the transfer.
const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
const client = new x402Client().register("eip155:*", new ExactEvmScheme(account));
client.setSpendControls({ maxAmountPerPayment: "$0.10" }); // hard cap per call
const pay = wrapFetchWithPayment(fetch, client);
// Before paying any x402 API, ask Shonin Check ($0.01).
const url = "https://api.example.com/v1/rates";
const first = await fetch(url);
if (first.status === 402) {
const check = await pay("https://<site>/api/v1/check", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
paymentRequired: first.headers.get("PAYMENT-REQUIRED"),
url,
task: "Get today's USD/EUR rate for the invoice",
budgetUsd: 0.05,
}),
});
const { verdict, reasons } = await check.json(); // "pay" | "confirm" | "block"
if (verdict !== "pay") throw new Error(`Ask a person first: ${reasons.join("; ")}`);
}
const rates = await pay(url);