Skip to content

Agent Integration

The whole API is designed to be consumed by code without a human in the loop: no accounts, no consumer API keys, machine-readable discovery, one response shape, typed error codes.

Endpoint Returns
GET / API index: name, tagline, links to /services, /openapi.json, /health
GET /services Full catalog: 14 services with paths, prices, providers, input examples, output fields, guardrails, and current payment posture
GET /services/:slug One service, plus its input JSON Schema — enough to construct a valid request without reading docs
GET /openapi.json OpenAPI 3.1 document for all paid routes, generated from the catalog and Zod schemas
GET /health { status, db, time } — 200 when Postgres is reachable, 503 otherwise

The discovery website renders the same catalog for humans and serves an llms.txt index for agents.

Terminal window
# What can I buy?
curl http://localhost:3000/services
# How do I call token-risk? (includes inputSchema as JSON Schema)
curl http://localhost:3000/services/token-risk

Wrap fetch so the 402 → sign → retry loop is automatic. The signer is a normal EVM account holding USDC on the network named in the quote:

import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { wrapFetchWithPayment } from "@x402/fetch";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(
process.env.AGENT_PRIVATE_KEY as `0x${string}`
);
const client = new x402Client();
registerExactEvmScheme(client, { signer: account });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const response = await fetchWithPayment(
"http://localhost:3000/services/token-risk",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
chain: "ethereum",
tokenAddress: "0x6b175474e89094c44da98b954eedeac495271d0f",
}),
}
);
const result = await response.json();
// Settlement confirmation, if you want it:
const settlement = response.headers.get("payment-response");

Keep the private key in the agent’s own environment — it is never sent to the server. The signature authorizes exactly the quoted amount.

Every successful call returns:

{
"service": "token-risk",
"requestId": "9f2c…",
"cache": { "hit": false },
"providers": [
{ "name": "goplus", "status": "ok" },
{ "name": "honeypot-is", "status": "ok" },
{ "name": "dexscreener", "status": "ok" }
],
"warnings": [],
"data": { "": "service-specific payload" }
}
  • service — the catalog slug that served the request.
  • requestId — correlates with the X-Request-Id response header and server-side logs; include it when reporting problems.
  • cache.hittrue when served from the server’s TTL cache (some services cache 1–10 minutes; you still pay per request).
  • providers — per-provider attribution with status, so agents can weight trust in the data.
  • warnings — human/agent-readable degradation notes (e.g. an enrichment source failed, or a fallback source was used).
  • data — the service payload; field lists per service are in the Service Catalog.

Errors use a different envelope with stable codes — see Error Codes. A robust agent loop is: on 400 validation_error fix the input using details.issues; on 402 pay and retry; on 503 treat the service as temporarily unavailable; on 429/5xx back off and retry.