Skip to main content

Overview

x402 is a payment protocol for HTTP resources. aixyz has built-in x402 support — when a client requests a payment-gated endpoint, the server responds with HTTP 402 and payment requirements. The client includes a payment proof in the X-Payment header, and the server verifies it via a facilitator.

How It Works

  1. Client requests a gated endpoint (e.g., POST /agent)
  2. Server returns HTTP 402 with payment requirements (price, network, payTo address)
  3. Client constructs payment proof and retries with X-Payment header
  4. Server verifies payment via a facilitator and grants access

The accepts Export

Define payment requirements by exporting accepts from your agent or tool:
import type { Accepts } from "aixyz/accepts";

export const accepts: Accepts = {
  scheme: "exact",
  price: "$0.005",
};
This gates the endpoint behind a $0.005 exact payment.

With Overrides

export const accepts: Accepts = {
  scheme: "exact",
  price: "$0.005",
  network: "eip155:8453", // override config network
  payTo: "0x...", // override config payTo
};
Prices are USD strings: "$0.005", "$0.01", "$0.0001".

Per-Agent and Per-Tool Pricing

Agents and tools can each declare their own accepts export, enabling granular pricing:
// app/agent.ts — agent-level pricing (gates /agent)
export const accepts: Accepts = {
  scheme: "exact",
  price: "$0.01",
};

// app/tools/premium-search.ts — tool-level pricing (gates on /mcp)
export const accepts: Accepts = {
  scheme: "exact",
  price: "$0.001",
};
  • Agent accepts gates the A2A /agent endpoint
  • Tool accepts gates the tool on the MCP /mcp endpoint
  • Agents and tools without accepts are not registered on protocol endpoints

Multiple Payment Options

Accept payment across multiple networks by passing an array of payment entries. This lets clients pay on whichever network they prefer:
export const accepts: Accepts = [
  { scheme: "exact", price: "$0.005", network: "eip155:8453" }, // Base
  { scheme: "exact", price: "$0.005", network: "eip155:84532" }, // Base Sepolia
];
When using the array format, network is required on each entry so the server can register the correct payment scheme for each network. All referenced networks are automatically discovered and registered during server initialization — no manual configuration needed beyond the accepts export. This works for both agents and tools:
// app/agent.ts — multi-network agent pricing
export const accepts: Accepts = [
  { scheme: "exact", price: "$0.01", network: "eip155:8453" },
  { scheme: "exact", price: "$0.01", network: "eip155:1" },
];

// app/tools/premium-search.ts — multi-network tool pricing
export const accepts: Accepts = [
  { scheme: "exact", price: "$0.001", network: "eip155:8453" },
  { scheme: "exact", price: "$0.001", network: "eip155:1" },
];

Payment Networks

Configure the payment network in aixyz.config.ts:
NetworkCAIP-2 ID
Baseeip155:8453
Base Sepoliaeip155:84532
Ethereumeip155:1
Switch networks per environment:
x402: {
  payTo: "0x...",
  network: process.env.NODE_ENV === "production" ? "eip155:8453" : "eip155:84532",
},

Facilitators

Payment verification is handled by a facilitator service:
FacilitatorActivationURL
DefaultAlways availablehttps://x402.use-agently.com/facilitator
Coinbase CDPWhen CDP_API_KEY_ID is setAuto-configured
CustomSet X402_FACILITATOR_URLYour custom URL

Custom Facilitator

Create app/accepts.ts to provide a custom facilitator:
app/accepts.ts
import { HTTPFacilitatorClient } from "aixyz/accepts";

export const facilitator = new HTTPFacilitatorClient({
  url: process.env.X402_FACILITATOR_URL ?? "https://x402.use-agently.com/facilitator",
});
See the BYO Facilitator template for a working example.

Payer Identity and Sessions

Every verified x402 payment identifies the payer by their wallet address. SessionPlugin (auto-registered by the build pipeline) gives each payer isolated key-value storage accessible via getSession():
import { getSession } from "aixyz/app/plugins/session";

const session = getSession();
if (session) {
  await session.set("preference", "dark-mode");
  const payer = session.payer; // "0x1234..."
}
This works in both A2A agent handlers and MCP tool handlers. See SessionPlugin for the full API and custom store configuration.