OpenZeppelin Relayer - x402 Facilitator plugin
relayer-plugin-x402-facilitator is an early-stage TypeScript project in the AI payments / x402 ecosystem. It currently has 3 GitHub stars and 2 forks.
OpenZeppelin Relayer plugin that implements the x402 facilitator API so you can serve x402 payments directly from a Relayer instance. Works with the Coinbase x402 ecosystem (e.g., @x402/express) and exposes the expected /verify, /settle, and /supported endpoints under the Relayer plugin router.
This version supports x402 v2 specification. For x402 v1 support, please use a previous version of this plugin (check git history for v1-compatible releases).
# inside your relayer repo
pnpm add @openzeppelin/relayer-plugin-x402-facilitator
For local development of the plugin itself:
pnpm install
pnpm build
plugins/x402/index.ts
export { handler } from "@openzeppelin/relayer-plugin-x402-facilitator";
config.json (adjust path to your wrapper location or to the provided example file if you copied it, e.g., examples/x402-facilitator/handler.ts):{
"plugins": [
{
"id": "x402",
"path": "plugins/x402/index.ts",
"emit_logs": false,
"emit_traces": false,
"raw_response": true,
"forward_logs": true,
"allow_get_invocation": true,
"timeout": 30,
"config": {
"networks": [
{
"network": "stellar:testnet",
"type": "stellar",
"relayer_id": "stellar-example",
"assets": [
"CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"
]
}
]
}
}
]
}
Each object in config.networks:
network: x402 network identifier (e.g., stellar:testnet)type: "stellar" (current support)relayer_id: ID of the Relayer account to use for this networkassets: list of allowed assets (issuer addresses for Stellar)channel_service_api_url / channel_service_api_key (optional): enable channel service acceleration for Stellarchannel_service_fund_relayer_address (optional): on-chain signer address of the channel service fund relayer, used in /supported response and security checksRoutes are called through the Relayer plugin call endpoint: POST /api/v1/plugins/{plugin_id}/call{route}.
/ or ``: info/verify: x402 v2 verify/settle: x402 v2 settle/supported: discovery of supported payment kinds (returns v2 format)This plugin implements the x402 v2 specification, which includes:
accepted field instead of top-level scheme and networkamount instead of maxAmountRequired, removed resource/description/mimeType (moved to top-level PaymentRequired)kinds, signers, and extensions fieldsThe /supported endpoint returns data in the following v2 format:
{
"kinds": [
{
"x402Version": 2,
"scheme": "exact",
"network": "stellar:testnet",
"extra": {
"areFeesSponsored": true
}
}
],
"signers": {
"stellar:testnet": ["G-RELAYER-ADDRESS"]
},
"extensions": []
}
Point the facilitator to your Relayer plugin URL and pass the Relayer API key via createAuthHeaders.
STELLAR_ADDRESS=
FACILITATOR_URL=http://localhost:8080/api/v1/plugins/x402/call
import { config } from "dotenv";
import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { ExactStellarScheme } from "@x402/stellar/exact/server";
import { HTTPFacilitatorClient } from "@x402/core/server";
config();
const stellarAddress = process.env.STELLAR_ADDRESS as string | undefined;
// Validate stellar address is provided
if (!stellarAddress) {
console.error("❌ STELLAR_ADDRESS is required");
process.exit(1);
}
const facilitatorUrl = process.env.FACILITATOR_URL;
if (!facilitatorUrl) {
console.error("❌ FACILITATOR_URL environment variable is required");
process.exit(1);
}
const facilitatorClient = new HTTPFacilitatorClient({
url: facilitatorUrl,
createAuthHeaders: async () => ({
// Use your Relayer API key for the plugin
verify: { Authorization: "Bearer RELAYER_API_KEY" },
settle: { Authorization: "Bearer RELAYER_API_KEY" },
supported: { Authorization: "Bearer RELAYER_API_KEY" },
}),
});
const app = express();
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "stellar:testnet",
payTo: stellarAddress,
},
],
description: "Weather data",
mimeType: "application/json",
},
},
new x402ResourceServer(facilitatorClient).register(
"stellar:testnet",
new ExactStellarScheme(),
),
),
);
app.get("/weather", (req, res) => {
res.send({
report: {
weather: "sunny",
temperature: 70,
},
});
});
app.listen(4021, () => {
console.log(`Server listening at http://localhost:${4021}`);
});
Authorization: Bearer <RELAYER_API_KEY> to each endpoint.POST /api/v1/plugins/x402/call/verifyPOST /api/v1/plugins/x402/call/settlePOST /api/v1/plugins/x402/call/supported (or GET if allow_get_invocation is enabled)For high-throughput x402 payment settlement, you can connect the plugin with the OpenZeppelin Stellar Channels Service. The Channels service provides managed infrastructure for parallel transaction submission on Stellar, handling fee management and sequence number coordination automatically.
Benefits:
Add channel_service_api_url and channel_service_api_key to your network config:
{
"config": {
"networks": [
{
"network": "stellar:testnet",
"type": "stellar",
"relayer_id": "stellar-example",
"assets": ["CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"],
"channel_service_api_url": "https://channels.openzeppelin.com/testnet",
"channel_service_api_key": "YOUR_CHANNELS_API_KEY",
"channel_service_fund_relayer_address": "G..."
}
]
}
}
Key fields:
channel_service_api_url: The URL of the Channels service. Use https://channels.openzeppelin.com/testnet for testnet or the appropriate endpoint for your environment.channel_service_api_key: Your API key for the Channels service.channel_service_fund_relayer_address (optional): The on-chain signer address of the Channels service fund relayer. When set, the /supported endpoint reports this address instead of the RPC relayer address, and verify security checks also protect this address from being used as a transfer source.When these fields are present, the plugin routes settlement through the Channels service instead of submitting transactions directly via the relayer. The plugin sends the Soroban function XDR and authorization entries to the Channels service, which handles transaction building, simulation, and submission using its pool of channel accounts.
Note: This is only needed if the relayer address needs to hold tokens like USDC. If the relayer is only used for transaction submission and does not receive or hold the asset, no trustline is required.
Before a Stellar account can hold or receive tokens like USDC, it must establish a trustline to the token's contract. You can create a trustline using Stellar Laboratory to build a Change Trust transaction, then submit the XDR via the relayer:
POST /api/v1/relayers/{relayer-id}/transactions
{
"params": {
"network": "testnet",
"transaction_xdr": "<XDR_VALUE>"
}
}
pnpm test
pnpm lint
pnpm build
AGPL-3.0
Production-ready x402 facilitator server.
Rust SDK for the x402 payment protocol.
Accept payments from AI agents. Open-source. Your data, your domain, your rules. Free forever.
A production-ready payment settlement service for the x402 protocol. Built with Elysia and Node.js, it verifies cryptographic payment signatures and settles transactions on-chain for EVM, SVM (Solana), and Starknet networks.
Golang implementation of an x402 payment facilitator
x402 payment facilitator — verifies and settles EIP-3009 USDC micropayments on Base, Arbitrum, and Ethereum.