create-typescript-x402-server

Creating x402 Payment-Protected Servers

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "create-typescript-x402-server" with this command: npx skills add algorand-devrel/algorand-agent-skills/algorand-devrel-algorand-agent-skills-create-typescript-x402-server

Creating x402 Payment-Protected Servers

Build TypeScript servers that gate API endpoints behind Algorand (AVM) payments using Express.js or Hono middleware.

Prerequisites

Before creating a payment-protected server:

  • Node.js 18+ installed

  • An Algorand address to receive payments (58-character address)

  • A facilitator -- either run your own or use https://facilitator.goplausible.xyz

  • TypeScript project initialized with tsconfig.json

Core Workflow: Middleware-Based Payment Gating

The server middleware intercepts requests to protected routes, checks for a valid X-PAYMENT header, and either returns 402 (pay first) or passes through to the route handler (payment verified).

Request → Middleware checks X-PAYMENT header ├── No header → Return 402 with PaymentRequirements ├── Has header → Forward to facilitator │ ├── verify() fails → Return 402 │ └── verify() passes → settle() → Pass to route handler └── Route not protected → Pass through

How to Proceed

Step 1: Install Dependencies

Express.js:

npm install @x402-avm/express @x402-avm/avm @x402-avm/core express npm install -D @types/express typescript

Hono:

npm install @x402-avm/hono @x402-avm/avm @x402-avm/core hono npm install -D typescript

Hono with Node.js server:

npm install @x402-avm/hono @x402-avm/avm @x402-avm/core hono @hono/node-server

With paywall UI (optional):

npm install @x402-avm/paywall

Step 2: Choose a Middleware Variant

There are three middleware variants, from simplest to most configurable:

Variant Use Case What It Creates

paymentMiddlewareFromConfig

Quick start, simple apps Creates x402ResourceServer internally

paymentMiddleware

Need custom server config Uses your x402ResourceServer instance

paymentMiddlewareFromHTTPServer

Need hooks (API key bypass, logging) Uses x402HTTPResourceServer with hooks

Step 3: Define Routes

Routes map HTTP method + path patterns to payment configuration:

import { ALGORAND_TESTNET_CAIP2 } from "@x402-avm/avm";

const routes = { "GET /api/weather": { accepts: { scheme: "exact", network: ALGORAND_TESTNET_CAIP2, payTo: "YOUR_ALGORAND_ADDRESS", price: "$0.01", }, description: "Weather data", }, "GET /api/premium/*": { accepts: { scheme: "exact", network: ALGORAND_TESTNET_CAIP2, payTo: "YOUR_ALGORAND_ADDRESS", price: "$0.10", }, description: "Premium API endpoints", }, };

Step 4: Apply Middleware (Express)

import express from "express"; import { paymentMiddleware, x402ResourceServer } from "@x402-avm/express"; import { registerExactAvmScheme } from "@x402-avm/avm/exact/server"; import { HTTPFacilitatorClient } from "@x402-avm/core/server";

const app = express();

const facilitatorClient = new HTTPFacilitatorClient({ url: process.env.FACILITATOR_URL || "https://facilitator.goplausible.xyz", }); const server = new x402ResourceServer(facilitatorClient); registerExactAvmScheme(server);

app.use(paymentMiddleware(routes, server));

app.get("/api/weather", (req, res) => { res.json({ temperature: 72, condition: "sunny" }); });

app.listen(4021);

Step 4 (Alternative): Apply Middleware (Hono)

import { Hono } from "hono"; import { paymentMiddleware, x402ResourceServer } from "@x402-avm/hono"; import { registerExactAvmScheme } from "@x402-avm/avm/exact/server"; import { HTTPFacilitatorClient } from "@x402-avm/core/server";

const app = new Hono();

const facilitatorClient = new HTTPFacilitatorClient({ url: process.env.FACILITATOR_URL || "https://facilitator.goplausible.xyz", }); const server = new x402ResourceServer(facilitatorClient); registerExactAvmScheme(server);

app.use(paymentMiddleware(routes, server));

app.get("/api/weather", (c) => { return c.json({ temperature: 72, condition: "sunny" }); });

export default app;

Step 5: Add a Facilitator Server (Optional)

If you need your own facilitator instead of the public one:

import express from "express"; import { x402Facilitator } from "@x402-avm/core/facilitator"; import { registerExactAvmScheme } from "@x402-avm/avm/exact/facilitator"; import { ALGORAND_TESTNET_CAIP2 } from "@x402-avm/avm"; import algosdk from "algosdk";

const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64"); const address = algosdk.encodeAddress(secretKey.slice(32)); const algodClient = new algosdk.Algodv2("", "https://testnet-api.algonode.cloud", "");

// Create signer implementing FacilitatorAvmSigner interface const signer = { /* ... see EXAMPLES.md for full implementation ... */ };

const facilitator = new x402Facilitator(); registerExactAvmScheme(facilitator, { signer, networks: ALGORAND_TESTNET_CAIP2 });

const app = express(); app.use(express.json()); app.post("/verify", async (req, res) => { /* ... / }); app.post("/settle", async (req, res) => { / ... / }); app.get("/supported", (req, res) => { / ... */ }); app.listen(4020);

Step 6: Set Environment Variables

Resource Server

AVM_ADDRESS=YOUR_ALGORAND_ADDRESS_HERE FACILITATOR_URL=https://facilitator.goplausible.xyz PORT=4021

Facilitator (if running your own)

AVM_PRIVATE_KEY=<base64-encoded-64-byte-key> ALGOD_SERVER=https://testnet-api.algonode.cloud ALGOD_TOKEN= FACILITATOR_PORT=4020

Important Rules / Guidelines

  • Register AVM scheme unconditionally -- always call registerExactAvmScheme(server) without environment variable guards

  • Public routes are unaffected -- only routes listed in the routes config object are protected

  • Route patterns support wildcards -- "GET /api/premium/*" matches all sub-paths

  • Method prefix is optional -- "/api/resource" matches all HTTP methods

  • Multi-network routes use arrays -- pass an array to accepts for cross-chain support

  • Facilitator URL is required -- the resource server must be able to reach a facilitator

  • Price strings use USD notation -- "$0.01" is resolved to the appropriate asset amount

Common Errors / Troubleshooting

Error Cause Solution

All routes return 402 Route patterns too broad Check route patterns match intended paths

402 but no accepts array AVM scheme not registered on server Call registerExactAvmScheme(server)

Facilitator unreachable Wrong URL or facilitator not running Check FACILITATOR_URL and facilitator status

paymentMiddleware is not a function

Wrong import Import from @x402-avm/express or @x402-avm/hono

CORS errors in browser Missing CORS middleware Add cors() middleware before payment middleware

Paywall not showing Missing mimeType: "text/html"

Set mimeType in route config for browser routes

Dynamic price error Price function throws Ensure price function handles all edge cases

500 on verify/settle Facilitator signer error Check facilitator logs, verify private key

References / Further Reading

  • REFERENCE.md - Detailed middleware API reference

  • EXAMPLES.md - Complete server code examples

  • @x402-avm/express on npm

  • @x402-avm/hono on npm

  • GoPlausible x402-avm Examples

  • GoPlausible x402-avm Documentation

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

implement-arc-standards

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

test-smart-contracts

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

use-algokit-cli

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

search-algorand-examples

No summary provided by upstream source.

Repository SourceNeeds Review