Skip to main content

Overview

  • Add nanopayments as a settlement provider to your x402 facilitator so that sellers connected to your facilitator automatically gain access to gas-free, batched payments.
  • Use this guide if you operate an x402 facilitator service and want to offer Gateway settlement alongside your existing onchain settlement methods.
This guide is for infrastructure providers and payment processors running x402 facilitators.

Prerequisites

Before you begin, ensure you have:
  • An existing x402 facilitator service using @x402/core.
  • Node.js v18+ installed.
  • Familiarity with the x402 protocol and how facilitators verify and settle payments.

Steps

Step 1. Install the SDK

Install @circle-fin/x402-batching alongside its required peer dependencies:
npm install @circle-fin/x402-batching @x402/core viem

Step 2. Initialize the BatchFacilitatorClient

The BatchFacilitatorClient handles all communication with Circle Gateway, including verification, settlement, and supported-network discovery.
import { BatchFacilitatorClient } from "@circle-fin/x402-batching/server";

const gatewayClient = new BatchFacilitatorClient();

Step 3. Route payments by type

Your facilitator acts as a router. Use isBatchPayment() to detect Gateway payments and delegate them to the BatchFacilitatorClient. Route all other payments to your existing onchain logic. Gateway payments are identified by the extra metadata field: extra.name === "GatewayWalletBatched".
import { isBatchPayment } from "@circle-fin/x402-batching/server";

async function handleVerify(
  payload: PaymentPayload,
  requirements: PaymentRequirements,
) {
  if (isBatchPayment(requirements)) {
    return gatewayClient.verify(payload, requirements);
  }
  return existingOnChainHandler.verify(payload, requirements);
}

async function handleSettle(
  payload: PaymentPayload,
  requirements: PaymentRequirements,
) {
  if (isBatchPayment(requirements)) {
    return gatewayClient.settle(payload, requirements);
  }
  return existingOnChainHandler.settle(payload, requirements);
}

async function handleSupported() {
  const gateway = await gatewayClient.getSupported();
  const existing = await existingOnChainHandler.getSupported();

  return {
    kinds: [...existing.kinds, ...gateway.kinds],
    extensions: [...existing.extensions, ...gateway.extensions],
    signers: { ...existing.signers, ...gateway.signers },
  };
}
Gateway’s settle() endpoint is optimized for low latency and guarantees settlement. Use settle() directly rather than calling verify() followed by settle() in production flows.

Step 4. Wire up HTTP endpoints

Expose your routing logic through standard x402 facilitator endpoints:
app.post("/v1/x402/verify", async (req, res) => {
  const { paymentPayload, paymentRequirements } = req.body;
  const response = await handleVerify(paymentPayload, paymentRequirements);
  res.json(response);
});

app.post("/v1/x402/settle", async (req, res) => {
  const { paymentPayload, paymentRequirements } = req.body;
  const response = await handleSettle(paymentPayload, paymentRequirements);
  res.json(response);
});

Step 5. Connect sellers to your facilitator

Once your facilitator supports Gateway, sellers connect to it and automatically gain access to both standard and gas-free payment options.

Using x402ResourceServer

Sellers using x402ResourceServer connect to your facilitator with HTTPFacilitatorClient:
import { x402ResourceServer } from "@x402/core/server";
import { HTTPFacilitatorClient } from "@x402/core/server";

const server = new x402ResourceServer([
  new HTTPFacilitatorClient({ url: "https://your-facilitator-service.com" }),
]);

await server.initialize();

Using createGatewayMiddleware

Sellers using the Gateway middleware can route verification and settlement through your facilitator by setting facilitatorUrl:
import { createGatewayMiddleware } from "@circle-fin/x402-batching/server";

const gateway = createGatewayMiddleware({
  sellerAddress: "0xSELLER_ADDRESS",
  facilitatorUrl: "https://your-facilitator-service.com",
});

Alternative: Gas-free-only facilitator

If you are building a new facilitator that only needs to support gas-free payments (without standard onchain settlement), use BatchFacilitatorClient directly with x402ResourceServer:
npm install @x402/core @x402/express @x402/evm
import { x402ResourceServer } from "@x402/core/server";
import { BatchFacilitatorClient } from "@circle-fin/x402-batching/server";

const server = new x402ResourceServer([new BatchFacilitatorClient()]);

await server.initialize();

Using GatewayEvmScheme with x402ResourceServer

When using x402ResourceServer with BatchFacilitatorClient, register GatewayEvmScheme to ensure payment requirements include the metadata that Gateway clients need for EIP-712 signing. GatewayEvmScheme extends the standard ExactEvmScheme to:
  • Preserve extra metadata (verifyingContract, name, version) in payment requirements
  • Set maxTimeoutSeconds to 345600 (4 days) for batched settlement
  • Register USDC money parsers for all Gateway-supported networks
import { x402ResourceServer } from "@x402/express";
import {
  BatchFacilitatorClient,
  GatewayEvmScheme,
} from "@circle-fin/x402-batching/server";

const circleClient = new BatchFacilitatorClient();
const server = new x402ResourceServer([circleClient]);
server.register("eip155:*", new GatewayEvmScheme());
await server.initialize();
The base ExactEvmScheme discards the extra field from supported kinds when building payment requirements. Gateway clients require extra.verifyingContract to construct valid EIP-712 signatures. GatewayEvmScheme preserves this data.

See also