Two services run on this website, each on a different x402 scheme. Both are called through x402, with no accounts, no API keys, and no manual approval step before your first request. This page assumes you're writing a Node or TypeScript client — a script or backend holding its own private key, not a browser wallet flow — and shows the client-side code for both.
What you need
- An EVM wallet — Optimism and Base are Ethereum layer-2 networks, so any Ethereum wallet works — or just a private key, for a script.
- A small amount of USDC (a dollar stablecoin) on Optimism or Base — a few cents covers many requests. No ETH needed: you pay no gas, the facilitator submits every transaction.
npm install @x402/evm @x402/fetch viem
The two live endpoints
| Endpoint | Scheme | Does | Price |
|---|---|---|---|
imagegen-agent.fretchen.eu/genimg | exact | Generates an image, mints it as an NFT | ~$0.07 / call |
llm-agent.fretchen.eu | batch-settlement | OpenAI-shaped chat completion | ~$0.003 / message |
Both are consumed on the site by the AI Image Generator and the AI Assistant — those are the UIs; the endpoints above are what your own code calls directly.
Which scheme, when
exact is one signature, one on-chain settlement, one result — the right shape for a single paid call. batch-settlement opens a USDC payment channel with one on-chain deposit, then every further message is an off-chain signed voucher against that channel — no transaction, no wallet prompt, until the channel is claimed later. Use it for many small calls to the same service, like a chat session.
TypeScript — exact scheme (image generation)
The official @x402/fetch SDK handles the 402 → sign → retry cycle for you:
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(`0x${PRIVATE_KEY}`);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
// Payment is handled automatically on the 402 response
const response = await fetchWithPayment(
"https://imagegen-agent.fretchen.eu/genimg",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt: "A futuristic cityscape" }),
}
);
const result = await response.json();
console.log("Image:", result.image_url);
console.log("NFT mint tx:", result.transaction_hash);Loading the live spec…
TypeScript — batch-settlement (chat)
Unlike exact, this needs one network picked up front — client.register(network, scheme) below — because the channel it opens is specific to one chain. registerExactEvmScheme above has no such call because it can act on whichever network the 402 response names.
batch-settlement has no registerExactEvmScheme-style helper — the scheme is constructed directly with a signer and a channel store. The first call opens the channel: a deposit sized to cover several messages, not just one, so it moves more than the per-message price. Every call after that signs an off-chain voucher and settles instantly — no deposit, no wallet prompt:
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { BatchSettlementEvmScheme, InMemoryClientChannelStorage }
from "@x402/evm/batch-settlement/client";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(`0x${PRIVATE_KEY}`);
// Minimal signer shape the scheme needs — an EVM account already satisfies it.
const signer = { address: account.address, signTypedData: (a) => account.signTypedData(a) };
// In-memory here; a browser client would persist this to localStorage so an
// open channel survives a page reload instead of opening a new one each visit.
const storage = new InMemoryClientChannelStorage();
const scheme = new BatchSettlementEvmScheme(signer, { storage });
const client = new x402Client();
client.register("eip155:8453", scheme); // Base, in CAIP-2 eip155:<chainId> form
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
// OpenAI chat-completions shape — model must be one the agent advertises
const response = await fetchWithPayment("https://llm-agent.fretchen.eu", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "mistral-large-latest",
messages: [{ role: "user", content: "Hello" }],
}),
});
const result = await response.json();
console.log(result.choices[0].message.content);Loading the live spec…
Loading the live spec…
The batch-settlement contract is deployed on Base (mainnet and Sepolia) and Optimism mainnet — not Optimism Sepolia. Check llm-agent.fretchen.eu/openapi.json for the live, authoritative list of what the agent actually accepts.
What's protected, what isn't
Each payment is individually signed via EIP-3009 (exact) or the batch-settlement channel's voucher scheme. Every authorization is bound to a specific amount, recipient, and expiration — the protocol never has blanket access to your funds. A batch-settlement channel escrows only what you deposit; a voucher can never claim more than that.
Unspent escrow is not gone: a batch-settlement channel is withdrawable after a delay (currently ~24 hours in this facilitator's deployment) if you stop using it. See x402_batch_settlement_buyer.ipynb below for the withdrawal mechanics.
Try it without writing code
Both endpoints have a runnable Deno notebook in the facilitator's notebooks/ directory — genimg_x402_buyer.ipynb (exact) and x402_batch_settlement_buyer.ipynb (batch-settlement) — or use the live UIs directly: AI Image Generator and AI Assistant.