List your API
Turn any backend API into a pay-per-call service on XDC. Agents discover it in the marketplace and pay in USDC per request — you receive USDC to your address, and never deal with gas or invoicing.
- 1
Make your endpoint x402-payable
Wrap your routes with x402 payment middleware. It returns 402 with the price until a valid X-PAYMENT header arrives, then verifies and settles the USDC payment through a facilitator and runs your handler.
import express from "express"; // x402 payment middleware (e.g. x402-express, or @xdctaskman/x402-server's // paymentMiddleware). It returns HTTP 402 until a valid X-PAYMENT arrives, // then verifies + settles the USDC payment via a facilitator and continues. import { paymentMiddleware } from "@xdctaskman/x402-server"; const app = express(); app.use(express.json()); app.use(paymentMiddleware({ payTo, // assigned to you at ingestion asset: USDC_XDC, // USDC on XDC (6 decimals) network: "xdc", // mainnet (chainId 50) facilitator, // verifies + settles; gas is sponsored routes: { "GET /forecast": { price: "0.01", capability: "weather.forecast" }, }, })); app.get("/forecast", (req, res) => res.json({ tempC: 21 })); app.listen(8402);Settlement uses EIP-3009, so a relayer pays the XDC gas — your callers (and you) never need native XDC. Don't set payTo yourself; it's assigned to you at ingestion and is stable.
- 2
Describe your service
Add a provider entry with your endpoints, prices (USDC), and capabilities. This is the curated catalog the marketplace serves.
{ "id": "acme-weather", "name": "Acme Weather", "description": "Weather forecasts over x402.", "mcpUrl": "https://acme-weather.example/mcp", "services": [ { "url": "https://acme-weather.example/forecast", "method": "GET", "priceUSDC": "0.01", "capability": "weather.forecast" } ], "tags": ["weather", "data"], "active": true }priceUSDC is a decimal string; capability is how agents filter (e.g. weather.forecast). Optionally expose an MCP endpoint (mcpUrl) so agents can discover your resources programmatically.
- 3
Submit to get listed
Add your service in the admin console (url, method, title, price, payTo, tags). Once saved it appears in the marketplace and is callable by any agent:
npx xdc-taskman call https://acme-weather.example/forecast
The facilitator (verify + settle)
Your API never touches the chain. The facilitator is the service your middleware calls to verify a signed USDC payment and settle it on-chain — and it pays the XDC gas. You point your middleware at a facilitator URL; that's the whole integration. No wallet, RPC, or gas on your side.
Agent
Signs a USDC payment and sends it in the X-PAYMENT header.
Your API
Returns 402, then calls the facilitator to verify + settle.
Facilitator
Settles on XDC and pays the gas; returns the tx hash.
On a paid request, your middleware makes two server-to-server calls:
- • POST https://xdc-mcp.vercel.app/api/facilitator/verify — is the signed payment valid (signature, balance, amount, not expired)? Nothing moves yet.
- • POST https://xdc-mcp.vercel.app/api/facilitator/settle — broadcast the EIP-3009 transferWithAuthorization; the facilitator pays gas and returns the tx hash.
Facilitator URL for XDC + USDC (this is what partners ask for):
https://xdc-mcp.vercel.app/api/facilitatorPoint your middleware at it:
app.use(paymentMiddleware(
payTo, // your USDC receiving address (XDC)
{ "GET /forecast": { price: "0.01", network: "xdc" } },
// ↓ the facilitator verifies + settles the payment and pays the gas
{ url: "https://xdc-mcp.vercel.app/api/facilitator" },
));Error: Facilitator does not support exact on xdc
The facilitator does support it — confirm with:
curl -s https://xdc-mcp.vercel.app/api/facilitator/supported
# → {"kinds":[{"scheme":"exact","network":"xdc","asset":"0xfA2958…8eb1","extra":{"decimals":6}}, …]}If that returns exact / xdc, the error is in your server config. With @x402/core it almost always means initialize() wasn't awaited before wrapping routes — the supported-kinds list is empty until it fetches /supported:
const server = new x402ResourceServer({
facilitator: { url: "https://xdc-mcp.vercel.app/api/facilitator" },
});
// ⚠️ REQUIRED before wrapping routes — fetches /supported from the facilitator.
await server.initialize();
createPaidWrappers(server); // now buildPaymentRequirements sees exact/xdc
startServer();Also check, in order:
- 1. await initialize() before createPaidWrappers / building requirements.
- 2. Facilitator URL is the XDC one (the default Coinbase/x402.org one serves Base, not XDC).
- 3. Network is exactly "xdc" (not xdc-mainnet, XDC, or 50); asset 0xfA2958…8eb1, 6 decimals.
Full step-by-step + troubleshooting: x402 integration guide (shareable — send it to your devs).
Your 402 response (checklist)
The most common onboarding bug is a non-spec-compliant 402 on a paid route — the client rejects it before paying. Your 402 body must include an accepts array where each entry has every field below. This is exactly what our demo endpoints return.
HTTP/1.1 402 Payment Required
Content-Type: application/json
{
"x402Version": 1,
"accepts": [
{
"scheme": "exact",
"network": "xdc",
"maxAmountRequired": "100",
"resource": "https://your-api.example/v1/assets",
"description": "Assets List",
"mimeType": "application/json",
"payTo": "0xYourReceivingAddress",
"asset": "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1",
"maxTimeoutSeconds": 60,
"extra": { "name": "USDC", "version": "2" }
}
]
}Diff your output against a known-good response:
curl -s https://xdctaskman-x402-server.vercel.app/x402/echo | jq .acceptsSymptom: client errors like maxAmountRequired: Required (received undefined) or resource: Required mean those fields are missing from your accepts entry. Free routes (no 402) won't show this — it's isolated to the paid route's payment config.
FAQ
Do I need a wallet, an RPC, or XDC for gas?
What network, asset, and decimals do I use?
What is the facilitator URL?
I get “Facilitator does not support exact on xdc”. Why?
How do I set payTo, and why must it match the marketplace?
Client says “maxAmountRequired: Required” / “resource: Required”.
My route never returns 402 (it's always free).
How do agents actually pay my API?
You get
- • USDC per call, settled on XDC
- • No gas to manage (sponsored via EIP-3009)
- • Agent-ready discovery (marketplace + MCP)
Reference
- • @xdctaskman/x402-server — Express + middleware + MCP
- • Wire format: x402 exact-evm, USDC (EIP-3009)
- • Agent side — how callers pay