Skip to main content

Structure

interface Response402 {
  x402Version: 1;
  accepts: PaymentRequirements[];
  error?: string;
  errorStage?: "parse" | "verify" | "settle";
}

Zod schema

import { z } from "zod";

export const Response402Schema = z.object({
  x402Version: z.literal(1),
  accepts: z.array(PaymentRequirementsSchema),
  error: z.string().optional(),
  errorStage: z.enum(["parse", "verify", "settle"]).optional(),
});

Multiple token options

{
  "x402Version": 1,
  "error": "Payment required - Choose a token",
  "accepts": [
    { "scheme": "exact", "network": "bsc", "asset": "0xUSDC", "maxAmountRequired": "1000000", "description": "USDC", "mimeType": "application/json", "payTo": "0xSeller", "maxTimeoutSeconds": 600 },
    { "scheme": "exact", "network": "bsc", "asset": "0xDAI", "maxAmountRequired": "1000000000000000000", "description": "DAI", "mimeType": "application/json", "payTo": "0xSeller", "maxTimeoutSeconds": 600 }
  ]
}

Error stage conventions

  • parse: parsing failed (Base64/JSON/Schema) → return 402
  • verify: signature verification failed (invalid/mismatch/expired) → return 402
  • settle: settlement failed (on-chain/network issues) → return 500

Return recommendations

  • Prefer a single, clear error field for better client display
  • accepts should contain at least one valid PaymentRequirements
  • For 500 errors, the server should log details and return a generic message

Example

{
  "x402Version": 1,
  "error": "Payment required",
  "accepts": [
    {
      "scheme": "exact",
      "network": "bsc",
      "maxAmountRequired": "1000000",
      "description": "Premium API access",
      "mimeType": "application/json",
      "payTo": "0xSeller",
      "maxTimeoutSeconds": 600,
      "asset": "0xUSDC",
      "paymentType": "permit"
    }
  ]
}