Charge for an API call
without an account on either side.
Wrap a route, name a price. The caller pays per request in USDT and the money lands in your wallet — no signup, no subscription, no processor in between.
import { withX402Payment } from '@/lib/x402/middleware';
export const POST = withX402Payment(handler, "0.01");
- Protocol fee
- 0%
- Settles in
- USDT
- Accounts required
- none
How a paid request works
Four steps, all of them in lib/x402/middleware.ts. No
facilitator required, no account anywhere in the loop.
-
01
The request arrives without payment
Your handler is wrapped once. FeeLess intercepts before your code runs.
GET /api/data/weather?city=Istanbul -
02
FeeLess answers 402
The response carries the price, your address, the chain ID and the tokens you accept.
HTTP/1.1 402 Payment Required { "amount": "0.01", "currency": "USDT", "recipient": "0x…", "network": "4663" } -
03
The caller pays on chain
A real USDT transfer on BNB Chain. The caller retries with its transaction hash — not a promise to pay, but a receipt.
X-Payment: {"from":"0x…","amount":"0.01", "token":"USDT","chainId":"4663", "transactionHash":"0x13c8…"} -
04
FeeLess reads the receipt
It confirms the transfer landed, paid the right address, cleared the price, and has not been spent before. Only then does your handler run.
HTTP/1.1 200 OK x-payment-chain: BSC { "city": "Istanbul", "temperature": 22 }
The transaction hash is also the replay key: one transfer buys exactly one response. Reuse it and the request is rejected. What is still open is a shared store for that ledger, so replay protection holds across serverless instances — see the chain docs.
One wrapper on the handler you already wrote
Your route keeps its signature. The price is the second argument.
import { withX402Payment } from '@/lib/x402/middleware';
async function handler(req: NextRequest) {
// Your API logic here
const data = await processRequest(req);
return NextResponse.json({ data });
}
// Add payment requirement - that's it!
export const POST = withX402Payment(handler, "0.01");
// 1. Pay on BNB Chain
const hash = await USDT.transfer(recipient, amount);
// 2. Call again with the receipt
const response = await fetch('/api/your-endpoint', {
method: 'POST',
headers: {
'X-Payment': JSON.stringify({
transactionHash: hash, // proof, not a promise
amount, token: 'USDT', chainId: '4663'
})
},
body: JSON.stringify({ data })
});
Selling data about the assets the chain carries
Reading a tokenised equity on BNB Chain is permissionless. Moving one is not. So these endpoints sell data about them and settle in USDT — no securities held, no upstream key, and every answer checkable against the explorer.
/api/rwa/tokens
$0.02 USDT
Every BSC stock token, supply read live
/api/rwa/token
$0.01 USDT
One tokenised equity, by ticker
/api/rwa/holdings
$0.02 USDT
An address’s tokenised equity position
/api/chain/receipt
$0.02 USDT
Did this transaction actually pay me?
/api/chain/balance
$0.01 USDT
BNB and token balances for any address
/api/chain/token
$0.01 USDT
BEP-20 metadata, read live from chain 4663
/api/data/crypto
$0.015 USDT
Spot prices, no API key on your side
/api/tools/qrcode
$0.005 USDT
Half a cent a QR code