AI agents have a boring problem: they can't sign up for things. Every
interesting API sits behind an email verification, a credit-card form and an
API key — three things a headless agent can't do. I ran into this building my
own agents, so I ended up building an API the other way round, and this is the
20-line version of what it makes possible.
We'll build a working KYB (Know Your Business) agent in ~20 lines of
TypeScript. It verifies any French company — identity, officers, insolvency
alerts, filed financials, sanctions screening — and it pays for what it uses,
per call, in USDC. No account anywhere.
curl -i "https://api.sirenic.eu/v1/kyb/552032534"
You get HTTP 402 Payment Required
. The PAYMENT-REQUIRED
header is
base64 JSON: price ($0.15
→ 150000
atomic USDC units), the receiving
address, the official USDC contract and the network (Base). Nothing was
charged — quotes are free.
Create a throwaway wallet (MetaMask works), export the private key, and
fund it with a couple of dollars of USDC on Base (any exchange can
withdraw to Base). The exact
payment scheme uses signed authorizations,
so the client never pays gas — USDC is all the wallet needs. The whole
tutorial costs $0.15.
npm install @x402/fetch @x402/core @x402/evm viem tsx
export TEST_WALLET_KEY=0x...
js
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
const siren = process.argv[2] ?? "552032534";
const client = new x402Client();
registerExactEvmScheme(client, {
signer: privateKeyToAccount(process.env.TEST_WALLET_KEY as `0x${string}`),
});
const payingFetch = wrapFetchWithPayment(fetch, client);
const kyb = await (await payingFetch(
`https://api.sirenic.eu/v1/kyb/${siren}`,
)).json() as Record<string, any>;
console.log(`Company : ${kyb.identite.denomination} (${kyb.siren}) — ${kyb.identite.etat_administratif}`);
console.log(`Officers: ${kyb.identite.dirigeants?.length ?? 0} | VAT: ${kyb.tva_intracommunautaire}`);
console.log(`Alerts : ${kyb.alertes_bodacc.procedures_collectives?.length ?? "n/a"} insolvency proceedings`);
console.log(`Sanctions screening: ${kyb.criblage_sanctions.statut}`);
console.log(`Completeness: ${kyb.score_completude}/100`);
Run it:
$ npx tsx kyb-agent.ts 552032534
Company : DANONE (552032534) — actif
Officers: 13 | VAT: FR27552032534
Alerts : 0 insolvency proceedings
Sanctions screening: correspondances_a_verifier
Completeness: 100/100
That's the whole agent. wrapFetchWithPayment
intercepted the 402, signed
a $0.15 USDC authorization, retried, and the API released the response once
the settlement was confirmed on-chain.
The /v1/kyb/{siren}
endpoint consolidates six sources server-side:
registry identity and officers, BODACC legal announcements, filed accounts,
and a fuzzy sanctions screening of the company name and every officer
against the five official lists (UN, EU, OFAC, UK, French asset-freeze
register). Matches come back with a 0-100 confidence score and the matched
alias — never a bare yes/no, because "Emmanuel Macron vs. Emmanuel Sultani
Makenga" is exactly the kind of thing you want a human to look at.
Two production details worth stealing for your own paid APIs:
The same API is an MCP server — Claude and Cursor can use it directly:
claude mcp add --transport http sirenic https://api.sirenic.eu/mcp
Each tool takes an optional x_payment
parameter with the same quote/sign/
retry loop.
Data is official open data redistributed as published; responses carry
source and disclaimer fields. Screening output is a decision aid, not a
compliance opinion.