Charge for your API in USDC, per request, with no accounts and no signup. A facilitator running at facilitator.fretchen.eu verifies each payment and settles it on-chain, so your server never has to touch a blockchain directly. I run it, but as the whole protocol is open and permissionless you can use it too.
- 0.01 USDC flat per settlement — no percentage, no minimum, no monthly fee.
- Optimism and Base, mainnet and testnet. Other chains on request.
- Open source and self-hostable — no lock-in. If this facilitator goes away, the code and your integration both still work.
What you'll need
- A server you can run code on, and an endpoint worth charging for.
- An EVM wallet — Optimism and Base are Ethereum layer-2 networks, so any Ethereum wallet works. This address receives the payments.
- A little ETH on that network, for one transaction: the approval below. Nothing after that.
- About 1 USDC of allowance for fees — USDC is a dollar stablecoin, pegged 1:1 to the US dollar. That covers roughly 100 settlements.
- To rehearse on testnet: testnet ETH and a buyer holding testnet USDC — see below.
The buyer pays no gas — they sign, they do not transact. The facilitator pays the gas to settle. You pay gas exactly once, for the approval below.
Quick start
Three things happen on your server: you quote a price, you verify, and you settle. The resource is delivered in between — after the payment is known good, before it is taken.
1. Return a 402 with your price
When a request arrives without payment, answer 402 and say what you want. Set scheme to exact — x402's word for how the money moves; this one settles one authorized amount, once, per request. Set network to eip155:10 (Optimism, in the standard eip155:<chainId> form), payTo to your wallet, and amount in USDC units — 6 decimals, so 100000 is $0.10.
{
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "eip155:10",
"amount": "70000",
"asset": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"payTo": "0xYourSellerAddress",
"maxTimeoutSeconds": 60,
"extra": { "name": "USD Coin", "version": "2" }
}],
"facilitatorUrl": "https://facilitator.fretchen.eu"
}2. Approve the facilitator for the fee
The fee is collected after settlement with ERC-20 transferFrom, so the facilitator needs an allowance. Keep it small — about 1 USDC, roughly 100 settlements. The spender is a hot settlement wallet, and a large standing allowance is a standing risk. Every /verify response tells you how many settlements you have left, so you can top up before it runs out.
Connect your wallet to check and manage your USDC approval for the facilitator.
3. Verify, deliver, settle
paymentPayload is the decoded PAYMENT-SIGNATURE header from the buyer; paymentRequirements is the same object you put in accepts[0] above.
// 1. Verify — before you spend anything on the resource
const verifyRes = await fetch("https://facilitator.fretchen.eu/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ paymentPayload, paymentRequirements })
});
// /verify answers 200 even when the payment is bad. Check isValid, not the status code.
const { isValid, invalidReason } = await verifyRes.json();
if (!isValid) return new Response(invalidReason, { status: 402 });
// 2. Deliver the resource
const result = await generateYourResource(request);
// 3. Settle — the money moves here
const settleRes = await fetch("https://facilitator.fretchen.eu/settle", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ paymentPayload, paymentRequirements })
});
const { success, transaction } = await settleRes.json();
return new Response(JSON.stringify(result), { status: 200 });That is the whole integration.
Try it on testnet first
Rehearse the full flow on OP Sepolia before any real money is involved. The facilitator treats testnet exactly like mainnet — including the fee and the approval — so a testnet run exercises the same code path you will ship. Pick the testnet in the approval widget above.
You will need testnet ETH to send the approval — get some from the Superchain faucet. Your test buyer needs testnet USDC to pay you with — Circle's faucet covers both OP Sepolia and Base Sepolia.
Three values change:
{
"network": "eip155:11155420",
"asset": "0x5fd84259d66Cd46123540766Be93DFE6D43130D7",
"extra": { "name": "USDC", "version": "2" }
}On testnet the USDC contract's EIP-712 domain name is USDC, not USD Coin. The signature is bound to that name, so if you change only the network and the asset, every payment fails verification — and it fails after your server has already done the expensive work. Both testnets use USDC; both mainnets use USD Coin.
The exact scheme documented here works on all four networks. Batch-settlement, if you go beyond exact later, is not deployed on OP Sepolia — use Base Sepolia to rehearse that one.
Fee model
0.01 USDC per settlement, flat, taken after the payment succeeds — no percentage, no minimum. On a $0.07 request that is about 14%; on a $1 request, 1%. Card processors start around $0.30 per transaction, so they can't price a seven-cent request at all — a flat fee can.
The amount and the facilitator's address are advertised in /supported under facilitatorFees, so a client can read them rather than trust this page.
API reference
Three endpoints at facilitator.fretchen.eu. Both POST endpoints take the same body: paymentPayload and paymentRequirements. The only scheme supported is exact, with USDC, via EIP-3009 transferWithAuthorization: the buyer signs an authorization for one specific amount, recipient and expiry, and pays no gas — the facilitator submits the transaction. Nothing here ever holds your buyer's funds or gets blanket access to them.
Loading the live spec…
POST /verify
Checks the signature, the balance, the recipient and the expiry — off-chain, so it costs nothing. Call it before you deliver. Note that a rejected payment still comes back as HTTP 200 — branch on isValid, not the status code.
Loading the live spec…
POST /settle
Submits the payment on-chain via EIP-3009 transferWithAuthorization. Call it after the resource is delivered. The on-chain hash comes back as transaction.
Loading the live spec…
GET /supported
Networks, schemes and fees the facilitator currently accepts.
Loading the live spec…
Supported networks
| Network | Chain ID | USDC address | EIP-712 name |
|---|---|---|---|
| Optimism | eip155:10 | 0x0b2C…Ff85 | USD Coin |
| Base | eip155:8453 | 0x8335…2913 | USD Coin |
| OP Sepolia | eip155:11155420 | 0x5fd8…30D7 | USDC |
| Base Sepolia | eip155:84532 | 0x036C…CF7e | USDC |
For the other side of the same exchange — what your buyers sign and how they call you — see x402 for buyers.