Base URL: https://x402.semanticpay.io
The facilitator verifies and settles x402 payments on behalf of sellers. It currently supports USDT0 on Plasma (eip155:9745) and Stable (eip155:988).
Validates a payment payload against the seller’s requirements. Called by the seller’s middleware before serving a paid resource.
Request body
| Field | Type | Description |
|---|
paymentPayload | object | The signed payment from the buyer (from the X-PAYMENT header) |
paymentRequirements | object | The seller’s price and token requirements |
Headers
| Header | Required | Description |
|---|
X-Event-Callback | No | URL to receive lifecycle events. The facilitator will POST verify_started and verify_completed (or verify_failed) events to this URL. |
{
"paymentPayload": {
"network": "eip155:9745",
"payload": "0x...",
"scheme": "exact"
},
"paymentRequirements": {
"network": "eip155:9745",
"maxAmountRequired": "1000000",
"asset": "0x0000000000000000000000000000000000000001",
"payTo": "0xSELLER",
"facilitator": "https://x402.semanticpay.io",
"scheme": "exact"
}
}
Response
If invalid, isValid is false and an invalidReason field explains why.
Settles a verified payment on-chain. Transfers USDT0 from the buyer to the seller via the facilitator’s account.
Request body
Same shape as /verify.
Headers
| Header | Required | Description |
|---|
X-Event-Callback | No | URL to receive lifecycle events. The facilitator will POST settle_started and settle_completed (or settle_failed) events to this URL. |
{
"paymentPayload": { ... },
"paymentRequirements": { ... }
}
Response (success)
{
"success": true,
"transaction": "0xabc123...",
"network": "eip155:9745"
}
Response (failure)
{
"success": false,
"errorReason": "Insufficient allowance",
"network": "eip155:9745"
}
Supported
Returns the payment schemes and networks this facilitator supports.
Response
{
"schemes": [
{
"scheme": "exact",
"network": "eip155:9745"
},
{
"scheme": "exact",
"network": "eip155:988"
}
]
}
Health check. Returns the facilitator’s address and supported networks.
Response
{
"status": "ok",
"facilitator": "0xFACILITATOR",
"networks": [
{
"name": "Plasma",
"network": "eip155:9745",
"chainId": 9745,
"usdt0": "0x0000000000000000000000000000000000000001"
},
{
"name": "Stable",
"network": "eip155:988",
"chainId": 988,
"usdt0": "0x..."
}
]
}
Lifecycle Events
The facilitator can push real-time lifecycle events to a callback URL during verification and settlement. This is useful for building UIs that visualize the payment flow as it happens.
How it works
Pass the X-Event-Callback header with a URL on your /verify and /settle requests. The facilitator will POST events to that URL at each stage of the process.
curl -X POST https://x402.semanticpay.io/verify \
-H "Content-Type: application/json" \
-H "X-Event-Callback: https://your-server.com/events" \
-d '{ "paymentPayload": { ... }, "paymentRequirements": { ... } }'
Events are fire-and-forget — they don’t block the verify/settle response. If the callback URL is unreachable, events are silently dropped.
Each event is a JSON POST with this shape:
{
"type": "verify_started",
"step": 6,
"title": "Payment Verification Started",
"description": "Facilitator is verifying the payment signature and requirements",
"details": { ... },
"actor": "facilitator",
"timestamp": 1708123456789
}
Event types
Verification events (sent during /verify):
| Type | Step | Description |
|---|
verify_started | 6 | Facilitator has begun verifying the payment signature and requirements |
verify_completed | 7 | Verification finished successfully. details.isValid indicates the result |
verify_failed | 7 | Verification threw an error. details.error contains the message |
Settlement events (sent during /settle):
| Type | Step | Description |
|---|
settle_started | 9 | Facilitator is broadcasting the receiveWithAuthorization transaction |
settle_completed | 10 | Transaction confirmed on-chain. details.transactionHash contains the tx hash |
settle_failed | 10 | Settlement threw an error. details.error contains the message |
Example: receiving events
Set up an endpoint on your server to receive the POSTed events:
app.post("/events", (req, res) => {
const { type, step, title, details } = req.body;
console.log(`[step ${step}] ${type}: ${title}`);
// Forward to SSE clients, WebSocket, etc.
res.json({ ok: true });
});
Then pass the URL when calling the facilitator:
const response = await fetch("https://x402.semanticpay.io/verify", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Event-Callback": "https://your-server.com/events",
},
body: JSON.stringify({ paymentPayload, paymentRequirements }),
});
If X-Event-Callback is not provided, no events are sent. The facilitator behaves identically — this is purely opt-in.
All endpoints return standard HTTP status codes.
| Status | Meaning |
|---|
200 | Success |
400 | Missing required fields (paymentPayload or paymentRequirements) |
429 | Too many requests — rate limit exceeded |
500 | Internal error — the response body contains an error string |
Last modified on February 17, 2026