Skip to main content

Type

interface PaymentRequirements {
  scheme: "exact";
  network: string;
  maxAmountRequired: string;
  resource: string;
  description: string;
  mimeType: string;
  payTo: string;
  maxTimeoutSeconds: number;
  asset: string;
  paymentType?: "eip3009" | "permit" | "permit2";
  outputSchema?: Record<string, unknown>;
  extra?: Record<string, unknown>;
}

Field highlights

  • scheme: always "exact"
  • network: kebab-case network name (e.g., bsc, base-sepolia)
  • maxAmountRequired: maximum amount to pay (wei)
  • payTo: merchant address (EIP-7702)
  • asset: token contract address
  • maxTimeoutSeconds: signature validity window (anti-replay)

Example

{
  "scheme": "exact",
  "network": "bsc",
  "maxAmountRequired": "1000000",
  "resource": "https://api.example.com/premium",
  "description": "Premium API access",
  "mimeType": "application/json",
  "payTo": "0xSeller",
  "maxTimeoutSeconds": 600,
  "asset": "0xUSDC",
  "paymentType": "permit"
}

Zod schema

import { z } from "zod";

export const PaymentRequirementsSchema = z.object({
  scheme: z.literal("exact"),
  network: z.string(), // e.g. "bsc", "bsc-testnet", "base-sepolia"
  maxAmountRequired: z.string().refine(
    (v) => Number.isInteger(Number(v)) && Number(v) >= 0
  ),
  resource: z.string().url(),
  description: z.string(),
  mimeType: z.string(),
  outputSchema: z.record(z.any()).optional(),
  payTo: z.string(), // EVM 0x... or SVM
  maxTimeoutSeconds: z.number().int().positive(),
  asset: z.string(), // token address (EVM/SVM)
  paymentType: z.enum(["eip3009", "permit", "permit2"]).optional(),
  extra: z.record(z.any()).optional(),
});

Supported networks

type Network =
  | "bsc" | "bsc-testnet"
  | "ethereum" | "sepolia"
  | "base" | "base-sepolia"
  | "polygon" | "arbitrum" | "optimism";

Validation highlights

  • scheme must be "exact"
  • network must match client/chain config
  • BigInt(payment.value) <= BigInt(maxAmountRequired)
  • resource is a valid URL and matches the protected resource
  • payTo equals the merchant recipient address (EIP-7702 recommended)
  • Timeout: deadline/validBefore <= now + maxTimeoutSeconds
  • If paymentType is specified, the client must use that type

Common scenarios

  • Fixed-price API: create and cache requirements at startup, reuse to reduce overhead
  • Dynamic pricing: compute maxAmountRequired/description from request context
  • Multiple token options: return multiple accepts for client selection (see 402)

Combined with 402

{
  "x402Version": 1,
  "accepts": [
    { "scheme": "exact", "network": "bsc", "asset": "0xUSDC", "maxAmountRequired": "1000000", "description": "Pay with USDC", "mimeType": "application/json", "payTo": "0xSeller", "maxTimeoutSeconds": 600 },
    { "scheme": "exact", "network": "bsc", "asset": "0xDAI", "maxAmountRequired": "1000000000000000000", "description": "Pay with DAI", "mimeType": "application/json", "payTo": "0xSeller", "maxTimeoutSeconds": 600 }
  ]
}