StableClarity Network Building in public — March 2026
01 Live

Basic 402 Gate

api.stable402.com/gate

What this demonstrates

The x402 basic gate is the simplest possible x402 implementation: a single endpoint that returns HTTP 402 Payment Required when called without a valid payment, and 200 OK with a payload after payment is verified by the Coinbase CDP facilitator.

The pattern establishes the core x402 V2 contract — a machine-readable PAYMENT-REQUIRED header encodes everything a client needs to construct and submit payment autonomously, with no accounts, API keys, or human intervention. This is what makes x402 suitable for AI agent commerce: an agent can receive a 402, parse the header, settle via USDC on Base Sepolia, and retry — all in a single code path.

The payment flow

  1. Request. Client sends GET https://api.stable402.com/gate with no payment header.
  2. 402 response. Worker returns HTTP 402 Payment Required with a PAYMENT-REQUIRED header containing a Base64-encoded JSON payload describing the payment requirements: network, asset, amount, recipient wallet, and facilitator metadata.
  3. Payment construction. An x402-aware client (SDK or agent) decodes the header, constructs a signed USDC transfer on Base Sepolia testnet (eip155:84532), and encodes it as a PAYMENT-SIGNATURE header.
  4. Facilitator verification. The Worker forwards the payment signature to the Coinbase CDP facilitator at https://api.cdp.coinbase.com/platform/v2/x402. The facilitator verifies the on-chain transaction and returns a settlement receipt.
  5. 200 response. Worker returns HTTP 200 OK with the payload and a PAYMENT-RESPONSE header containing the Base64-encoded settlement receipt.

PAYMENT-REQUIRED header

The header value is the Base64 encoding of this JSON object:

{
  "x402Version": 2,
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:84532",
      "maxAmountRequired": "1000",
      "resource": "https://api.stable402.com/gate",
      "description": "Access to the x402 basic gate reference endpoint. Returns a demonstration payload.",
      "mimeType": "application/json",
      "payTo": "0x22F637cF55217cb00252dDCF0c61FC4EfC12682c",
      "maxTimeoutSeconds": 60,
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "extra": {
        "name": "USDC",
        "version": "2"
      }
    }
  ]
}

Network eip155:84532 is Base Sepolia testnet. Asset 0x036CbD… is USDC on Base Sepolia. maxAmountRequired: "1000" is 1000 USDC base units — $0.001 USDC.

The Worker implementation

Full source at stable402/api/src/index.ts. Deployed via wrangler deploy to the api.stable402.com route.

import { verifyPayment } from '@x402/core';

const PAYMENT_REQUIRED_PAYLOAD = {
  x402Version: 2,
  accepts: [{
    scheme: "exact",
    network: "eip155:84532",
    maxAmountRequired: "1000",
    resource: "https://api.stable402.com/gate",
    description: "Access to the x402 basic gate reference endpoint.",
    mimeType: "application/json",
    payTo: env.WALLET_ADDRESS, // 0x22F637cF...12682c
    maxTimeoutSeconds: 60,
    asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    extra: { name: "USDC", version: "2" },
    extensions: {
      bazaar: {
        discoverable: true,
        outputSchema: {
          type: "object",
          properties: {
            message:       { type: "string" },
            endpoint:      { type: "string" },
            protocol:      { type: "string" },
            facilitator:   { type: "string" },
            network:       { type: "string" },
            timestamp:     { type: "string" },
            documentation: { type: "string" },
          }
        }
      }
    }
  }]
};

const CORS_HEADERS = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, PAYMENT-SIGNATURE',
};

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    // Handle CORS preflight
    if (request.method === 'OPTIONS') {
      return new Response(null, { status: 204, headers: CORS_HEADERS });
    }

    // Route: GET /gate
    if (url.pathname === '/gate' && request.method === 'GET') {
      return handleGate(request, env);
    }

    return new Response('Not found', { status: 404 });
  },
};

async function handleGate(request: Request, env: Env): Promise<Response> {
  const paymentSignature = request.headers.get('PAYMENT-SIGNATURE');

  // No payment header — return 402
  if (!paymentSignature) {
    const encoded = btoa(JSON.stringify(PAYMENT_REQUIRED_PAYLOAD));
    return new Response(null, {
      status: 402,
      headers: {
        ...CORS_HEADERS,
        'PAYMENT-REQUIRED': encoded,
        'Content-Type': 'application/json',
      },
    });
  }

  // Payment header present — verify with CDP facilitator
  try {
    const verifyResponse = await fetch(
      'https://api.cdp.coinbase.com/platform/v2/x402/verify',
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          paymentHeader: paymentSignature,
          paymentRequirements: PAYMENT_REQUIRED_PAYLOAD.accepts[0],
        }),
      }
    );

    if (!verifyResponse.ok) {
      return new Response(JSON.stringify({ error: 'Payment verification failed' }), {
        status: 402,
        headers: { ...CORS_HEADERS, 'Content-Type': 'application/json' },
      });
    }

    const settlement = await verifyResponse.json();
    const settlementEncoded = btoa(JSON.stringify(settlement));

    const payload = {
      message: 'Payment verified. Welcome to the x402 basic gate.',
      endpoint: 'api.stable402.com/gate',
      protocol: 'x402 V2',
      facilitator: 'Coinbase CDP',
      network: 'Base Sepolia (testnet)',
      timestamp: new Date().toISOString(),
      documentation: 'https://stable402.com/demos/gate',
    };

    return new Response(JSON.stringify(payload, null, 2), {
      status: 200,
      headers: {
        ...CORS_HEADERS,
        'Content-Type': 'application/json',
        'PAYMENT-RESPONSE': settlementEncoded,
      },
    });

  } catch (err) {
    return new Response(JSON.stringify({ error: 'Internal error during payment verification' }), {
      status: 500,
      headers: { ...CORS_HEADERS, 'Content-Type': 'application/json' },
    });
  }
}

interface Env {
  WALLET_ADDRESS: string;
}

Call the live endpoint

Send a request to api.stable402.com/gate and inspect the raw 402 response — no payment wallet required to see the protocol in action.