402xAgent
402xAgent é a verificação que um agente faz antes de pagar qualquer endpoint x402. Ele testa o 402 do endpoint sem pagar e retorna um veredito de pagar / pular / rechecar com um motivo. Cada verificação deixa um recibo público. Ele nunca paga o alvo.
Servidor MCP hospedado
npx add-mcp 'https://api.402xagent.com/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
x402-spotcheck: verifique antes de pagar
Uma proteção para clientes e roteadores x402. Logo antes de seu cliente assinar, ele avalia o 402 que o vendedor enviou: são termos USDC válidos na Base e eles correspondem à sua listagem (preço, destinatário, rede)? Um skip bloqueia o pagamento, com um código de motivo. Qualquer outra coisa, incluindo desconhecido, timeout ou erro, permite que o pagamento seja feito.
- Local por padrão (1.0.0). Ele avalia o 402 que seu cliente já recebeu com spotcheck-rules (MIT, incluído como
x402-spotcheck/rules). Não faz chamadas de rede, não precisa de serviço e não tem dependências. - Desconhecido significa pagar. Um
skipbloqueia apenas com um código de motivo de rules.json:price_mismatch,pay_to_mismatch,network_mismatch,asset_not_usdc,bad_challenge(local), além denetwork_unsupported,ssrf_blocked,ambiguous(serviço). Um destinatário sem pontuação ou histórico nunca é recusado. - Sem rastreamento. Por padrão, não envia id de cliente, ref ou cabeçalhos. O modo local não envia nada.
- Somente Base por padrão. Requisitos em outras redes passam sem alteração. Solana é opcional com
solana: true. - O serviço 402xAgent é opcional (
mode: "service"). Seu timeout é um prazo rígido (timeoutMs, padrão 1500 ms) e falha aberto por padrão.onUnavailable: "block"é honrado exatamente, em timeout e em qualquer erro. - Ele nunca vê suas chaves.
npm i github:withgrokbot/x402-spotcheck#v1.0.0
Em uma linha
@x402/fetch:
const pay = wrapFetchWithPayment(spotCheckFetch(fetch, { expected: (url) => myListing.get(url) }), client);
Hook de cliente x402 (onBeforePaymentCreation, x402-foundation/x402 @x402/core 2.x; registre seu limite de gastos primeiro):
client.onBeforePaymentCreation(mySpendingCap).onBeforePaymentCreation(spotCheckBeforePaymentHook({ expected: (url) => myListing.get(url) }));
three.ws mcp-bridge (buildSpendingCapHook em mcp-bridge/src/x402-axios-client.js; o limite é executado primeiro):
client.onBeforePaymentCreation(threeWsSpendingCapThenSpotCheck(buildSpendingCapHook));
@x402/axios: wrapAxiosWithPayment(spotCheckAxios(axios.create(), opts), client).
expected(url, intent) retorna sua listagem { price, payTo, network } ou nada. Sem uma listagem, ele verifica os próprios termos: um valor legível, um endereço de destinatário válido e USDC canônico.
Promessa de semver
O comportamento do veredito (o que paga, o que pula e por quê) muda apenas em uma versão principal. Lançamentos menores e de correção podem adicionar opções (desativadas por padrão), corrigir falhas ou melhorar a documentação. Eles nunca transformam um pay em um skip. Fixe exatamente:
npm i github:withgrokbot/x402-spotcheck#v1.0.0 # package.json: "x402-spotcheck": "github:withgrokbot/x402-spotcheck#v1.0.0"
npm i github:withgrokbot/spotcheck-rules#v1.0.0 # the rules alone
Migrando de 0.x
Instalações 0.x fixadas em uma tag não são afetadas. Para manter o comportamento 0.5, fixe github:withgrokbot/x402-spotcheck#v0.5.0. Para obtê-lo na 1.0.0:
spotCheckFetch(fetch, { mode: "service", ref: "via-x402-spotcheck", onRecheck: "block", solana: true, timeoutMs: 15000 });
O que mudou na 1.0.0: o modo local é o padrão (0.x sempre chamava 402xAgent); recheck, um skip sem código conhecido e uma incompatibilidade de hash de termos do nível gratuito que as regras locais não conseguem nomear agora pagam; nenhum ref é enviado por padrão; requisitos fora da Base passam, a menos que solana: true; o timeout do serviço é de 1,5 s e um prazo rígido (era 15 s); e uma verificação com falha é lembrada por 10 s, para que a nova tentativa assinada não espere uma segunda vez (unavailableTtlMs). Termos do nível pago ainda são aplicados, com códigos de motivo.
Kit de teste (vitest e node:test)
Qualquer integração que chame uma verificação pré-pagamento pode provar quatro coisas: com o sinalizador desativado, não faz chamadas; um timeout permite o pagamento; uma resposta {} permite; um skip bloqueia.
import { test } from "node:test"; // or: import { it as test } from "vitest";
import { spotcheckContract } from "x402-spotcheck/testkit";
spotcheckContract(test, ({ enabled, fetch, timeoutMs }) => (enabled ? myHook({ fetch, timeoutMs }) : undefined));
build retorna um hook x402 onBeforePaymentCreation e deve usar o fetch que recebe.
Tudo abaixo descreve o modo de serviço opcional (mode: "service"), onde 402xAgent testa o alvo diretamente.
Um caso real de /v1/skips
Nosso rastreamento semanal autocontrolado de listas x402 públicas (CDP Bazaar, PayAI Bazaar, awesome-x402) publica toda listagem cujo 402 ao vivo discorda da listagem em /v1/skips. O recibo b5e13e8271 é um deles:
| listagem (CDP Bazaar) | 402 ao vivo (rastreamento de 2026-10-07 21:27 UTC) | |
|---|---|---|
| url | https://topagentx402.vercel.app/api/send-token | mesma |
| preço | $0.001 | $0.001 |
| rede | eip155:84532 (Base Sepolia, dinheiro de teste) | eip155:8453 (Base mainnet, USDC real) |
| pay_to | 0xb1f6…Ec74 | 0xb1f6…Ec74 |
Um roteador que escolhesse este endpoint da listagem pensaria que está pagando tokens de testnet. Um cliente x402 configurado com eip155:* assinaria USDC real de mainnet. Com a proteção, 402xAgent compara o 402 ao vivo com a listagem e responde:
{ "verdict": "skip", "reason": "network_mismatch", "expected_network": "eip155:84532", "network": "eip155:8453", "expected_source": "listing" }
Então pay(...) lança SpotCheckBlockedError e nada é assinado na rede. (No nível gratuito, o motivo vem em palavras simples: "listed $0.001, asks for a different network than expected, details locked".)
O que é verificado
402xAgent testa o alvo uma vez (seguro contra SSRF, GET, ou POST para requisições POST) e nunca paga a ele. O veredito:
pay: o 402 é analisado, pede o USDC canônico em uma mainnet suportada, e seu preço, rede e pay-to correspondem ao esperado.skip: sem paywall (sem termos 402), preço, rede ou pay-to diferente da listagem, testnet ou rede não suportada, token diferente de USDC canônico ou 402 ilegível.recheck: apenas casos transitórios (timeout, erro de rede, 5xx) efree_trial_active(o alvo envia cabeçalhosx-free-trial). Bloqueado por padrão (onRecheck).
402xAgent reutiliza um teste por URL por 5 minutos, então duas verificações seguidas concordam.
"Esperado" significa sua própria listagem quando você passa expected, caso contrário, a listagem do nosso rastreamento (500 endpoints, atualizados semanalmente) quando temos a URL:
spotCheckFetch(fetch, {
mode: "service",
expected: (url, intent) => myCatalog.get(url), // { price: 0.01, payTo: "0x…", network: "eip155:8453" }
});
Etapa de pagamento: assine apenas o pagamento aprovado
Desde 0.2.0, um veredito pay vem com o pagamento exato que 402xAgent aprovou. Ele é retirado do 402 ao vivo do alvo e verificado contra a listagem:
"payment": { "scheme": "exact", "network": "eip155:8453", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "asset_is_usdc": true, "amount_atomic": "1000", "amount_usd": 0.001, "pay_to": "0xf567Cfe0FDb87A1D6Ca330e3f30f0D3DA0F7cb98" }
Essa é a resposta ao vivo para https://api.402rates.com/v1/ping. O nível gratuito recebe payment_terms_sha256 em vez dos termos: um sha256 de network|asset|amount_atomic|pay_to, com a rede em minúsculas, ativo EVM e pay_to em minúsculas, e mint e pay_to Solana mantidos como estão (base58 é sensível a maiúsculas/minúsculas; desde 0.5.0, correspondendo ao Worker).
A proteção aplica esses termos antes que seu cliente x402 possa assinar qualquer coisa:
skipsignifica sem assinatura e sem gasto. O 402 nunca chega ao cliente;SpotCheckBlockedErroré lançado.- O 402 é reduzido aos requisitos que se encaixam. Rede, ativo e
pay_todevem ser idênticos, e o valor deve ser igual ou inferior ao aprovado; no nível gratuito, o hash dos termos deve corresponder. Se nada se encaixar, lançarefused to sign: pay_to differs (402 0x…, approved 0x…), ounetwork differs,asset differs,amount above approved. - Uma última verificação antes de enviar. Se um
PAYMENT-SIGNATUREassinado ainda não se encaixar, lançarefused to send: ….
try {
await pay(url);
} catch (e) {
if (e instanceof SpotCheckBlockedError) console.log(e.reason, e.receiptUrl); // show as the abort reason
}
Toda verificação ao vivo deixa um recibo público gratuito com a URL da listagem, os termos 402 ao vivo, veredito, motivo e hora, ex. sc-96e5586bcffcfab8. O recibo mais recente para qualquer URL está em /v1/receipts/by-url?url=<endpoint>. A mensagem de erro termina com — receipt: <url>.
Agentes que assinam pagamentos diretamente podem chamar assertApprovedPayment(await checkBeforePay(url), requirement) primeiro.
Custo
Você recebe 1 verificação gratuita por cliente por dia UTC. Depois disso, uma verificação custa um décimo do preço cotado do alvo, mínimo $0,01, teto $0,25, em USDC na Base via x402. Passe payFetch para pagar verificações com seu próprio cliente x402, limitado por maxCheckUsd (padrão $0,05):
const pay = wrapFetchWithPayment(spotCheckFetch(fetch, { mode: "service", payFetch: wrapFetchWithPayment(fetch, client) }), client);
Se você não passar payFetch e a verificação gratuita for usada, a proteção considera 402xAgent indisponível. Isso falha aberto por padrão (onUnavailable: "allow"), então uma interrupção ou falta de orçamento nunca impede seus pagamentos.
Primeiro roteador: 1.000 verificações gratuitas. Damos ao primeiro roteador ou framework de agente que integrar um id de cliente 1.000 verificações completas (detalhe do nível pago, sem pagamento). Abra uma issue neste repositório para solicitar uma.
Roteadores: solicite um id de cliente de roteador e as verificações custam $0,001 cada. Elas são cobradas como um pagamento x402 de $0,01 por pacote de 10 verificações, e as outras 9 são pré-pagas nesse id. Um nível de roteador é necessário porque o facilitador cobra cerca de $0,002 por liquidação, então um pagamento de $0,001 por verificação não cobriria.
Verifique um resultado do Bazaar antes de pagar (verificação paga)
402xagent.com/bazaar mostra uma verificação gratuita diária dos principais resultados do CDP Bazaar. Isso é um instantâneo. Antes de seu agente pagar um, execute sua própria verificação contra o que o Bazaar lista, depois reobtenha o 402 ao vivo e assine apenas se ainda se encaixar. Com payFetch, a verificação é do nível pago (termos aprovados completos; mesmo preço acima, limitado por maxCheckUsd):
import { checkBeforePay, assertApprovedPayment } from "x402-spotcheck";
// 1. Pick a Bazaar result (public discovery API, no key needed)
const q = new URLSearchParams({ query: "weather forecast", limit: "20" });
const { resources } = await (await fetch("https://api.cdp.coinbase.com/platform/v2/x402/discovery/search?" + q)).json();
const r = resources[0];
const listed = r.accepts.find((a) => a.network === "eip155:8453") || r.accepts[0];
const method = r.extensions?.bazaar?.info?.input?.method || "GET";
// 2. Check it against the listing (paid: payFetch pays the check, up to maxCheckUsd)
const decision = await checkBeforePay(r.resource, {
mode: "service",
method,
price: Number(listed.amount) / 1e6, // USDC has 6 decimals
payTo: listed.payTo,
network: listed.network,
payFetch: wrapFetchWithPayment(fetch, client),
maxCheckUsd: 0.05,
});
if (!decision.allowed) throw new Error(`skip: ${decision.reason}`); // no signature, no spend
// 3. Re-fetch the live 402 right before paying and sign only a requirement that matches the approved terms
const live = await fetch(r.resource, { method });
if (live.status !== 402) throw new Error(`no live 402 (HTTP ${live.status}); recheck later`);
const pr = live.headers.get("payment-required"); // x402 v2 header, else v1 body
const { accepts } = pr ? JSON.parse(atob(pr)) : await live.json();
const requirement = accepts.find((a) => a.network === decision.approved?.payment?.network) || accepts[0];
await assertApprovedPayment(decision, requirement); // throws "refused to sign: ..." if terms changed since the check
// ...now pay with your x402 client
Opções
| opção | padrão | |
|---|---|---|
mode | "local" | "service" consulta 402xAgent (opcional) |
expected(url, intent) | nenhum | sua listagem { price, payTo, network } |
solana | false | avaliar também Solana mainnet; caso contrário, não-Base passa |
tolerance | 0.01 | tolerância de preço local |
onDecision(d) | nenhum | registrar ou medir cada decisão (erros nele são ignorados) |
timeoutMs | 1500 | serviço: prazo rígido para uma verificação |
onUnavailable | "allow" | serviço: "block" para falhar fechado em timeout ou erro |
onRecheck | "allow" | serviço: "block" para recusar em reavaliação |
client, ref | não enviados | serviço: atribuição opcional |
payFetch, maxCheckUsd | nenhum, 0.05 | serviço: pagar o próprio preço de 402xAgent |
autoPayCheck | desativado | serviço: auto-pagamento limitado da taxa de verificação (abaixo) |
cacheTtlMs | 300000 | serviço: cache de veredito |
endpoint | https://api.402xagent.com/v1/products/endpoint-spot-check | serviço: URL de verificação; hosts anteriores ainda funcionam (LEGACY_ENDPOINT) |
Erros: SpotCheckBlockedError tem decision (veredito, motivo, termos aprovados), reason e receiptUrl (o recibo público dessa verificação, quando o Worker retorna um).
Agentes e MCP
Servidor MCP remoto (gratuito, Streamable HTTP): https://api.402xagent.com/mcp, ferramenta endpoint_spot_check. Adicione-o ao seu cliente MCP e coloque uma linha nas instruções do agente:
Antes de pagar qualquer endpoint x402, chame
endpoint_spot_checkcom seuurl(maisclaimed_price,pay_to,networkda listagem, se você os tiver). Pague apenas severdictforpay.
Função simples, para qualquer ferramenta de framework de agente:
import { checkBeforePay } from "x402-spotcheck";
const d = await checkBeforePay(url, { accepts, price: 0.01, network: "eip155:8453" }); // local; add mode: "service" to ask 402xAgent
if (!d.allowed) return `not paying: ${d.verdict} (${d.reason})`;
Há mais exemplos em examples/: Python, uma configuração MCP e uma ferramenta estilo LangChain.
Testes
npm test executa testes unitários sem rede: o contrato 1.0.0 (padrão local, timeout, desconhecido = pagar, sem rastreamento, somente Base, hooks com um cliente @x402/core real, o kit de teste), incluindo os casos da etapa de pagamento: correspondência, pay_to/rede/ativo diferente, valor acima do aprovado, um 402 misto reduzido a um requisito, um hash do nível gratuito e skip. npm i && npm run test:integration executa o @x402/fetch, @x402/axios e @x402/evm reais (2.28) contra um vendedor simulado, assinando localmente com uma chave descartável. Ele conta cada payload que o cliente cria, para provar que um pagamento recusado ou pulado nunca é assinado. (Os pacotes v1 x402-fetch e x402-axios atualmente falham ao instalar do npm porque sua dependência x402@^1.2.1 não pode ser encontrada, então são cobertos apenas pelo caminho X-PAYMENT dos testes unitários.) O teste de integração verifica que um cabeçalho de pagamento bloqueado nunca sai do processo.
MIT. Feito por @withgrokbot. O serviço 402xAgent e o rastreamento vivem em withgrokbot/verified-catalog.
Auto-pagar a verificação (opcional, modo de serviço)
Quando a verificação gratuita é usada, autoPayCheck paga a taxa do 402xAgent com o mesmo cliente x402, antes de pagar o vendedor:
const pay = wrapFetchWithPayment(spotCheckFetch(fetch, {
mode: "service",
autoPayCheck: { wrapFetch: (f) => wrapFetchWithPayment(f, client), maxPerCheck: 0.05, dailyCap: 1 },
}), client);
Só paga quando todas estas condições forem verdadeiras: a taxa é de no máximo maxPerCheck; a taxa mais o gasto de hoje (UTC, por instância) é de no máximo dailyCap; a taxa é de no máximo 25% do preço do alvo (maxFraction pode definir um limite menor, não maior); a taxa é exatamente 1/10 do preço em USDC do alvo ($0,01 a $0,25); e o 402 pede x402 v2 exact USDC na Base para o pay_to documentado do 402xAgent. A taxa é sempre paga na Base, inclusive para alvos na Solana, então o cliente precisa de um signatário EVM registrado. Seu wrapper de fetch pode assinar apenas esse único pagamento, uma vez. Para compartilhar o total diário entre reinicializações, passe spendStore: { get(day), add(day, atomic) }. Se qualquer regra falhar ou qualquer erro ocorrer, a verificação conta como indisponível, o mesmo que sem ela. Com autoPayCheck definido, payFetch não é usado para a taxa. Sem autoPayCheck, nada muda.