Add gasless, per-request payments to any API endpoint on BNB in minutes.
Today, most x402-style payment flows depend on a single facilitator. If that server rate-limits you, censors you, or goes offline, your monetization stops.
We're removing that choke point on BNB.
The Fac exposes multiple independent facilitators. Alpha is live now. Beta and Gamma are coming online next. Facilitators will compete on fees, stake FAC to register, and can be slashed if they cheat.
Your endpoint can start charging per request — with no Stripe, no API keys, and no gas needed from the caller.
Your API doesn't return data for free. If the request isn't paid, you respond with 402 Payment Required and include:
// /api/alpha-feed
import { NextResponse } from "next/server";
export async function GET(req: Request) {
const paidProof = req.headers.get("x-paid-proof");
// Not paid yet → return a 402 invoice
if (!paidProof) {
return NextResponse.json({
price: "1 USDx",
asset: process.env.NEXT_PUBLIC_USDX_TOKEN_ADDRESS,
facilitators: [
{
name: "Alpha",
endpoint: "/api/facilitators/alpha",
fee: "0.5%",
address: "0x1437fE0f155b910dda7A80c64b57C1460793641F"
},
{
name: "Beta",
endpoint: "/api/facilitators/beta",
fee: "1.0%",
address: "0xBETA...TODO"
}
]
}, { status: 402 });
}
// Paid → return the protected data
return NextResponse.json({
alpha: "your private model output / feed / data product here"
}, { status: 200 });
}402 is the invoice. You're telling the client: "This endpoint costs 1 USDx. Here are facilitators who can settle it for you."
The client picks a facilitator (Alpha, Beta, …), gets it to pay, then retries with proof.
x-paid-proof is the receipt from the facilitator: settlement tx hash, block number, etc. That's what you check to decide if they're allowed in.
This is how you meter your API per request.
The client (or AI agent) calls your endpoint. If it gets 402, it will:
x-paid-proof.You don't have to write that flow manually. Use the SDK helper:
import { payAndRequest } from "@facora/sdk";
const result = await payAndRequest({
resourceUrl: "http://localhost:3000/api/alpha-feed"
});
console.log(result.data.alpha);
console.log("Settled tx:", result.settlement.txHash);Note: The @facora/sdk package is included in this repo under /sdk. You can vendor it into your own agent/client code, or treat it as a local package until we publish it to npm.
/api/alpha-feed.402 Payment Required./api/facilitators/alpha)./api/alpha-feed with x-paid-proof.The caller never broadcasts a transaction and never needs BNB.
// result:
{
data: {
alpha: string; // your protected response body
};
settlement: {
txHash: string;
blockNumber: number;
facilitator: string; // e.g. "Alpha"
amount: string; // e.g. "1.00 USDx"
proofHeader: string; // what went into x-paid-proof
};
}This is designed so you can log the tx, show it back to the user, or store it for audit.
• No Stripe.
• No API keys / account provisioning.
• No subscription tiers.
• You get paid per request in USDx on BNB.
• Every payment has an on-chain receipt (tx hash + block number).
• You can show "here's the tx that paid for this response," which is impossible to fake.
This is on-chain metering, not Web2 billing.
You get to decide when you unlock your data.
You wait until the facilitator actually settles on-chain and returns a real tx hash. You only serve 200 OK once funds are on-chain in your merchant wallet.
You verify the permit signature off-chain and trust a good facilitator to settle a few seconds later. You unlock instantly. This is useful for high-frequency AI agent workflows.
Both modes are supported. It's your call per endpoint.
These are required for the demo / testnet flow:
NEXT_PUBLIC_USDX_TOKEN_ADDRESS=0xcfFA309a5Fb3ac7419eBC8Ba4a6063Ff2a7585F5
MERCHANT_WALLET_ADDRESS=0x...your_merchant_address
BNB_TESTNET_RPC=https://data-seed-prebsc-1-s1.bnbchain.org:8545
FACILITATOR_ALPHA_PRIVATE_KEY=0x...your_facilitator_private_keySafe to expose. This is the USDx contract on BNB testnet. USDx is our permit-enabled settlement token (ERC20Permit, 6 decimals).
This MUST only live in server-side code (like /api/facilitators/alpha). Never load it in client components.
This is where the facilitator (Alpha, Beta, etc.) sends funds when it settles.
payAndRequest() on the client/agent side.And critically: Facilitators are not hardcoded forever. The server returns a list of possible facilitators (Alpha now, Beta/Gamma next). They'll compete on fee, stake FAC as a bond, and can be slashed if they lie about settlement.
That's how we remove the single point of failure in x402.