Créer un serveur de paiement x402
Créez un serveur Express qui facture de l'USDC pour l'accès API en utilisant le protocole de paiement x402. Les appelants paient par requête en USDC sur Base — aucun compte, clés API ou abonnement requis. Votre service est automatiquement découvrable par d'autres agents via le x402 Bazaar.
Comment ça marche
x402 est un protocole de paiement natif HTTP. Quand un client accède à un endpoint protégé sans payer, le serveur retourne HTTP 402 avec les exigences de paiement. Le client signe un paiement USDC et réessaye avec un header de paiement. Le facilitateur vérifie et règle le paiement, et le serveur retourne la réponse. Les services s'enregistrent auprès du x402 Bazaar pour que d'autres agents puissent les découvrir et les payer automatiquement.
Vérifier que le portefeuille est initialisé et authentifié
npx awal@2.8.2 status
Si le portefeuille n'est pas authentifié, consultez la skill authenticate-wallet.
Étape 1 : Obtenir l'adresse de paiement
Exécutez ceci pour obtenir l'adresse du portefeuille qui recevra les paiements :
npx awal@2.8.2 address
Utilisez cette adresse comme valeur payTo.
Étape 2 : Configurer le projet
mkdir x402-server && cd x402-server
npm init -y
npm install express @x402/express @x402/core @x402/evm @x402/extensions
Créez index.js :
const express = require("express");
const { paymentMiddleware } = require("@x402/express");
const { x402ResourceServer, HTTPFacilitatorClient } = require("@x402/core/server");
const { ExactEvmScheme } = require("@x402/evm/exact/server");
const app = express();
app.use(express.json());
const PAY_TO = "<address from step 1>";
// Create facilitator client and x402 resource server
const facilitator = new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" });
const server = new x402ResourceServer(facilitator);
server.register("eip155:8453", new ExactEvmScheme());
// x402 payment middleware — protects routes below
app.use(
paymentMiddleware(
{
"GET /api/example": {
accepts: {
scheme: "exact",
price: "$0.01",
network: "eip155:8453",
payTo: PAY_TO,
},
description: "Description of what this endpoint returns",
mimeType: "application/json",
},
},
server,
),
);
// Protected endpoint
app.get("/api/example", (req, res) => {
res.json({ data: "This costs $0.01 per request" });
});
app.listen(3000, () => console.log("Server running on port 3000"));
Étape 3 : L'exécuter
node index.js
Testez avec curl — vous devriez obtenir une réponse 402 avec les exigences de paiement :
curl -i http://localhost:3000/api/example
Référence API
paymentMiddleware(routes, server)
Crée un middleware Express qui applique les paiements x402.
| Paramètre | Type | Description |
|---|---|---|
routes |
object | Configuration de route mappant les patterns de route à la config de paiement |
server |
x402ResourceServer | Instance de serveur de ressource x402 préconfigurée |
x402ResourceServer
Créé avec un client facilitateur. Enregistrez les schémas de paiement et les extensions avant de le transmettre au middleware.
const { x402ResourceServer, HTTPFacilitatorClient } = require("@x402/core/server");
const { ExactEvmScheme } = require("@x402/evm/exact/server");
const facilitator = new HTTPFacilitatorClient({ url: "https://x402.org" });
const server = new x402ResourceServer(facilitator);
server.register("eip155:8453", new ExactEvmScheme());
| Méthode | Description |
|---|---|
register(network, scheme) |
Enregistrer un schéma de paiement pour un identifiant de réseau CAIP-2 |
Configuration de route
Chaque clé de l'objet routes est "METHOD /path". La valeur est un objet de configuration :
{
"GET /api/data": {
accepts: {
scheme: "exact",
price: "$0.05",
network: "eip155:8453",
payTo: "0x...",
},
description: "Human-readable description of the endpoint",
mimeType: "application/json",
extensions: {
...declareDiscoveryExtension({
output: {
example: { result: "example response" },
schema: {
properties: {
result: { type: "string" },
},
},
},
}),
},
},
}
Champs de configuration Accepts
Le champ accepts peut être un objet unique ou un tableau (pour plusieurs options de paiement) :
| Champ | Type | Description |
|---|---|---|
scheme |
string | Schéma de paiement : "exact" |
price |
string | Prix en USDC (par exemple "$0.01", "$1.00") |
network |
string | Identifiant de réseau CAIP-2 (par exemple "eip155:8453") |
payTo |
string | Adresse Ethereum (0x...) pour recevoir les paiements USDC |
Champs au niveau de la route
| Champ | Type | Description |
|---|---|---|
accepts |
object ou array | Exigences de paiement (simple ou multiple) |
description |
string? | Ce que fait cet endpoint (affiché aux clients) |
mimeType |
string? | Type MIME de la réponse |
extensions |
object? | Configuration des extensions (par exemple, découverte Bazaar) |
Extension de découverte
La fonction declareDiscoveryExtension enregistre votre endpoint auprès du x402 Bazaar pour que d'autres agents puissent le découvrir :
const { declareDiscoveryExtension } = require("@x402/extensions/bazaar");
extensions: {
...declareDiscoveryExtension({
output: {
example: { /* example response body */ },
schema: {
properties: {
/* JSON schema of the response */
},
},
},
}),
}
| Champ | Type | Description |
|---|---|---|
output.example |
object | Exemple de corps de réponse pour l'endpoint |
output.schema |
object | Schéma JSON décrivant le format de réponse |
Réseaux supportés
| Réseau | Description |
|---|---|
eip155:8453 |
Base mainnet (USDC réel) |
eip155:84532 |
Base Sepolia testnet (USDC test) |
Patterns
Plusieurs endpoints avec des prix différents
app.use(
paymentMiddleware(
{
"GET /api/cheap": {
accepts: {
scheme: "exact",
price: "$0.001",
network: "eip155:8453",
payTo: PAY_TO,
},
description: "Inexpensive data lookup",
},
"GET /api/expensive": {
accepts: {
scheme: "exact",
price: "$1.00",
network: "eip155:8453",
payTo: PAY_TO,
},
description: "Premium data access",
},
"POST /api/query": {
accepts: {
scheme: "exact",
price: "$0.25",
network: "eip155:8453",
payTo: PAY_TO,
},
description: "Run a custom query",
},
},
server,
),
);
app.get("/api/cheap", (req, res) => { /* ... */ });
app.get("/api/expensive", (req, res) => { /* ... */ });
app.post("/api/query", (req, res) => { /* ... */ });
Routes avec wildcard
app.use(
paymentMiddleware(
{
"GET /api/*": {
accepts: {
scheme: "exact",
price: "$0.05",
network: "eip155:8453",
payTo: PAY_TO,
},
description: "API access",
},
},
server,
),
);
app.get("/api/users", (req, res) => { /* ... */ });
app.get("/api/posts", (req, res) => { /* ... */ });
Vérification de santé (sans paiement)
Enregistrez les endpoints gratuits avant le middleware de paiement :
app.get("/health", (req, res) => res.json({ status: "ok" }));
// Payment middleware only applies to routes registered after it
app.use(paymentMiddleware({ /* ... */ }, server));
app.get("/api/data", (req, res) => { /* ... */ });
POST avec corps et extension de découverte
app.use(
paymentMiddleware(
{
"POST /api/analyze": {
accepts: {
scheme: "exact",
price: "$0.10",
network: "eip155:8453",
payTo: PAY_TO,
},
description: "Analyze text sentiment",
mimeType: "application/json",
extensions: {
...declareDiscoveryExtension({
output: {
example: { sentiment: "positive", score: 0.95 },
schema: {
properties: {
sentiment: { type: "string" },
score: { type: "number" },
},
},
},
}),
},
},
},
server,
),
);
app.post("/api/analyze", (req, res) => {
const { text } = req.body;
// ... your logic
res.json({ sentiment: "positive", score: 0.95 });
});
Plusieurs options de paiement par endpoint
Acceptez les paiements sur plusieurs réseaux pour le même endpoint :
"GET /api/data": {
accepts: [
{
scheme: "exact",
price: "$0.01",
network: "eip155:8453",
payTo: EVM_ADDRESS,
},
{
scheme: "exact",
price: "$0.01",
network: "eip155:84532",
payTo: EVM_ADDRESS,
},
],
description: "Data endpoint accepting Base mainnet or testnet",
}
Utiliser le facilitateur CDP (authentifié)
Pour une utilisation en production avec le facilitateur Coinbase (supporte mainnet) :
npm install @coinbase/x402
const { facilitator } = require("@coinbase/x402");
const { HTTPFacilitatorClient } = require("@x402/core/server");
const facilitatorClient = new HTTPFacilitatorClient(facilitator);
const server = new x402ResourceServer(facilitatorClient);
server.register("eip155:8453", new ExactEvmScheme());
Cela nécessite les variables d'environnement CDP_API_KEY_ID et CDP_API_KEY_SECRET. Obtenez-les sur https://portal.cdp.coinbase.com.
Tester avec la skill pay-for-service
Une fois le serveur en cours d'exécution, utilisez la skill pay-for-service pour tester les paiements :
# Check the endpoint's payment requirements
npx awal@2.8.2 x402 details http://localhost:3000/api/example
# Make a paid request
npx awal@2.8.2 x402 pay http://localhost:3000/api/example
Directives tarifaires
| Cas d'usage | Prix suggéré |
|---|---|
| Simple data lookup | $0,001 - $0,01 |
| API proxy / enrichment | $0,01 - $0,10 |
| Compute-heavy query | $0,10 - $0,50 |
| AI inference | $0,05 - $1,00 |
Checklist
- [ ] Obtenir l'adresse du portefeuille avec
npx awal@2.8.2 address - [ ] Installer
express,@x402/express,@x402/core,@x402/evmet@x402/extensions - [ ] Créer
x402ResourceServeravec le client facilitateur et enregistrerExactEvmSchemepoureip155:8453 - [ ] Définir les routes avec les prix, descriptions et extensions de découverte (Bazaar s'enregistre automatiquement quand les routes le déclarent)
- [ ] Enregistrer le middleware de paiement avant les routes protégées
- [ ] Garder les endpoints de santé/statut avant le middleware de paiement
- [ ] Tester avec
curl(devrait obtenir 402) etnpx awal@2.8.2 x402 pay(devrait obtenir 200) - [ ] Annoncez votre service pour que d'autres agents puissent le trouver et l'utiliser