This page documents the public API of the @circle-fin/x402-batching package,
which provides buyer and seller integrations for Circle Gateway nanopayments.
npm install @circle-fin/x402-batching
Buyer APIs
GatewayClient
import { GatewayClient } from "@circle-fin/x402-batching/client";
The primary client for buyers. Handles deposits, gasless payments, withdrawals,
and balance queries.
Constructor
new GatewayClient(config: GatewayClientConfig)
| Parameter | Type | Required | Description |
|---|
config.chain | SupportedChainName | Yes | Blockchain to connect to (for example, 'arcTestnet', 'baseSepolia') |
config.privateKey | Hex | Yes | Private key for signing ('0x...') |
config.rpcUrl | string | No | Custom RPC URL (overrides the default for the chain) |
Properties
| Property | Type | Description |
|---|
address | Address | The account’s wallet address |
chainName | string | Human-readable chain name |
domain | number | Gateway domain identifier |
publicClient | PublicClient | viem public client instance |
walletClient | WalletClient | viem wallet client instance |
deposit(amount, options?)
Deposits USDC from your wallet into the Gateway Wallet contract. This is an
onchain transaction that requires gas.
| Parameter | Type | Required | Description |
|---|
amount | string | Yes | Amount in decimal USDC (for example, '10.5') |
options.approveAmount | string | No | ERC-20 approval amount (defaults to amount) |
Returns Promise<DepositResult>:
interface DepositResult {
approvalTxHash?: Hex;
depositTxHash: Hex;
amount: bigint;
formattedAmount: string;
}
pay<T>(url, options?)
Pays for an x402-protected resource. Handles the full 402 negotiation flow
automatically: sends the request, receives payment requirements, signs the
authorization, and retries with the payment header.
| Parameter | Type | Required | Description |
|---|
url | string | Yes | URL of the x402-protected resource |
options | RequestInit | No | Standard fetch options (method, body, headers) |
Returns Promise<PayResult<T>>:
interface PayResult<T> {
data: T;
amount: bigint;
formattedAmount: string;
transaction: string;
status: number;
}
withdraw(amount, options?)
Withdraws USDC from Gateway to your wallet. Supports same-chain (instant) and
crosschain withdrawals.
| Parameter | Type | Required | Description |
|---|
amount | string | Yes | Amount in decimal USDC |
options.chain | SupportedChainName | No | Destination blockchain (defaults to same chain) |
options.recipient | Address | No | Recipient address (defaults to your address) |
Returns Promise<WithdrawResult>:
interface WithdrawResult {
mintTxHash: Hex;
amount: bigint;
formattedAmount: string;
sourceChain: string;
destinationChain: string;
recipient: Address;
}
getBalances(address?)
Returns both the wallet’s USDC balance and the Gateway balance.
| Parameter | Type | Required | Description |
|---|
address | Address | No | Address to query (defaults to the client’s address) |
Returns Promise<Balances>:
interface Balances {
wallet: { balance: bigint; formatted: string };
gateway: GatewayBalance;
}
interface GatewayBalance {
total: bigint;
available: bigint;
withdrawing: bigint;
withdrawable: bigint;
formattedTotal: string;
formattedAvailable: string;
}
supports(url)
Checks whether a URL supports Gateway batching before attempting payment.
| Parameter | Type | Required | Description |
|---|
url | string | Yes | URL to check |
Returns Promise<SupportsResult>:
interface SupportsResult {
supported: boolean;
requirements?: Record<string, unknown>;
error?: string;
}
BatchEvmScheme
import { BatchEvmScheme } from "@circle-fin/x402-batching/client";
A SchemeNetworkClient implementation for Circle Gateway batched payments. Use
this when integrating with an existing x402Client instance or building a
custom payment flow.
Constructor
new BatchEvmScheme(signer: BatchEvmSigner)
| Parameter | Type | Required | Description |
|---|
signer | BatchEvmSigner | Yes | Object with address and signTypedData function |
createPaymentPayload(x402Version, paymentRequirements)
Creates a signed payment payload by constructing and signing an EIP-3009
TransferWithAuthorization message.
| Parameter | Type | Required | Description |
|---|
x402Version | number | Yes | x402 protocol version (use 2) |
paymentRequirements | PaymentRequirements | Yes | Requirements from the 402 response |
Returns Promise<PaymentPayload>.
CompositeEvmScheme
import { CompositeEvmScheme } from "@circle-fin/x402-batching/client";
Routes payment requests between Gateway batched payments and standard onchain
payments. Use this when your client needs to support both payment methods
simultaneously.
Constructor
new CompositeEvmScheme(batchScheme: BatchEvmScheme, fallbackScheme: SchemeNetworkClient)
| Parameter | Type | Required | Description |
|---|
batchScheme | BatchEvmScheme | Yes | Handles Gateway batched payments |
fallbackScheme | SchemeNetworkClient | Yes | Handles standard onchain payments (must use the 'exact' scheme) |
Behavior
- If the payment requirements include
extra.name === "GatewayWalletBatched",
delegates to batchScheme.
- Otherwise, delegates to
fallbackScheme.
Usage
import { ExactEvmScheme } from "@x402/evm/exact/client";
import {
CompositeEvmScheme,
BatchEvmScheme,
} from "@circle-fin/x402-batching/client";
const composite = new CompositeEvmScheme(
new BatchEvmScheme(signer),
new ExactEvmScheme(signer),
);
client.register("eip155:*", composite);
registerBatchScheme
import { registerBatchScheme } from "@circle-fin/x402-batching/client";
Helper that registers a BatchEvmScheme with an x402Client:
registerBatchScheme(client, { signer: account });
Seller APIs
createGatewayMiddleware
import { createGatewayMiddleware } from "@circle-fin/x402-batching/server";
Creates Express-compatible middleware that handles x402 payment negotiation,
verification, and settlement.
Configuration
createGatewayMiddleware(config: GatewayMiddlewareConfig)
| Parameter | Type | Required | Description |
|---|
config.sellerAddress | string | Yes | Your wallet address for receiving payments |
config.networks | string | string[] | No | Networks to accept (defaults to all supported) |
config.facilitatorUrl | string | No | Custom facilitator URL for verify/settle. Routes through this facilitator instead of Circle Gateway directly. |
config.description | string | No | Resource description included in 402 responses |
require(price)
Returns Express middleware that requires payment for the route.
| Parameter | Type | Description |
|---|
price | string | Price in USD (for example, '$0.01' or '0.01') |
The middleware attaches payment information to req.payment:
interface PaymentInfo {
verified: boolean;
payer: string;
amount: string;
network: string;
transaction?: string;
}
BatchFacilitatorClient
import { BatchFacilitatorClient } from "@circle-fin/x402-batching/server";
A FacilitatorClient implementation that communicates with Circle Gateway’s
x402 endpoints. Use this for custom server frameworks or when you need
fine-grained control over verification and settlement.
Constructor
new BatchFacilitatorClient(config?: BatchFacilitatorConfig)
verify(payload, requirements)
Verifies a payment signature through the Gateway API.
| Parameter | Type | Description |
|---|
payload | PaymentPayload | The payment payload from the client |
requirements | PaymentRequirements | The payment requirements you declared |
Returns Promise<VerifyResponse>:
interface VerifyResponse {
isValid: boolean;
invalidReason?: string;
payer?: string;
}
settle(payload, requirements)
Submits a payment for batched settlement through the Gateway API. This is the
recommended method for production flows because it has low latency and
guarantees settlement.
| Parameter | Type | Description |
|---|
payload | PaymentPayload | The payment payload from the client |
requirements | PaymentRequirements | The payment requirements you declared |
Returns Promise<SettleResponse>:
interface SettleResponse {
success: boolean;
errorReason?: string;
payer?: string;
transaction: string;
}
getSupported()
Fetches the payment kinds (networks and contract addresses) supported by
Gateway.
Returns Promise<SupportedResponse>:
interface SupportedResponse {
kinds: Array<{
x402Version: number;
scheme: string;
network: string;
extra?: { verifyingContract?: string };
}>;
}
GatewayEvmScheme
import { GatewayEvmScheme } from "@circle-fin/x402-batching/server";
Server-side EVM scheme that extends ExactEvmScheme with Gateway-specific
behavior. Required when using x402ResourceServer with
BatchFacilitatorClient.
Constructor
No parameters required. On construction, it automatically registers USDC money
parsers for all Gateway-supported networks.
Key behaviors
enhancePaymentRequirements(): Merges extra metadata
(verifyingContract, name, version) from supported kinds into payment
requirements. Sets maxTimeoutSeconds to 345600 (4 days) for batched
settlement.
- USDC money parsers: Automatically converts dollar amounts to USDC atomic
units (6 decimals) for all supported networks using the USDC addresses from
CHAIN_CONFIGS.
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.
Usage
import { x402ResourceServer } from "@x402/express";
import {
BatchFacilitatorClient,
GatewayEvmScheme,
} from "@circle-fin/x402-batching/server";
const server = new x402ResourceServer([new BatchFacilitatorClient()]);
server.register("eip155:*", new GatewayEvmScheme());
await server.initialize();
Utilities
supportsBatching
import { supportsBatching } from "@circle-fin/x402-batching";
Checks whether a PaymentRequirements object supports Gateway batched
settlement. Returns true if the requirements include the
GatewayWalletBatched scheme.
isBatchPayment
import { isBatchPayment } from "@circle-fin/x402-batching/server";
Server-side alias for supportsBatching. Use this in facilitator routing logic
to determine whether a payment should be routed to Gateway.
getVerifyingContract
import { getVerifyingContract } from "@circle-fin/x402-batching";
Extracts the Gateway Wallet contract address from a PaymentRequirements
object.
Constants
import {
CIRCLE_BATCHING_NAME,
CIRCLE_BATCHING_VERSION,
CIRCLE_BATCHING_SCHEME,
} from "@circle-fin/x402-batching";
| Constant | Value | Description |
|---|
CIRCLE_BATCHING_NAME | 'GatewayWalletBatched' | EIP-712 domain name used for batch payment signatures |
CIRCLE_BATCHING_VERSION | '1' | EIP-712 domain version |
CIRCLE_BATCHING_SCHEME | 'exact' | x402 payment scheme identifier |
Chain configuration
import {
CHAIN_CONFIGS,
GATEWAY_DOMAINS,
} from "@circle-fin/x402-batching/client";
CHAIN_CONFIGS: Full configuration (USDC address, Gateway Wallet address, RPC
URL) for all supported blockchains.
GATEWAY_DOMAINS: Domain IDs for EIP-712 signing, keyed by chain name.
Error reference
Gateway API error codes
These are the errorReason (settle) and invalidReason (verify) values
returned by the Gateway API:
| Error code | Cause | Recovery |
|---|
unsupported_scheme | Scheme is not exact | Only the exact scheme is supported |
unsupported_network | Network not supported for batching | Use a supported network |
unsupported_asset | Token address not recognized on this blockchain | Use the correct USDC address for the network |
invalid_payload | Malformed payment payload | Check EIP-712 signature fields |
address_mismatch | Authorization to address does not match payTo | Ensure the payment is addressed to the correct seller |
amount_mismatch | Authorization value does not match required amount | Ensure the signed amount matches the price |
invalid_signature | EIP-3009 signature verification failed | Re-sign the payment and check the signing key matches from |
authorization_not_yet_valid | Authorization validAfter is in the future | Wait until the authorization becomes valid |
authorization_expired | Authorization validBefore has passed | Create a new payment with a future expiry |
authorization_validity_too_short | Validity window is shorter than 3 days | Set validBefore to at least 3 days in the future |
self_transfer | from and to are the same address | Buyer and seller must be different addresses |
insufficient_balance | Buyer’s Gateway balance is too low | Deposit more USDC before paying |
nonce_already_used | Payment nonce was already submitted | Create a new payment (each payment needs a unique nonce) |
unsupported_domain | Gateway domain not configured for this blockchain | Check network configuration |
wallet_not_found | Gateway Wallet contract not found on this blockchain | Verify contract addresses for the network |
unexpected_error | Infrastructure error (HTTP 500) | Retry the request and contact support if the error persists |
GatewayClient errors
All errors are thrown as standard Error objects with descriptive messages.
| Error message | Cause | Recovery |
|---|
Unsupported chain: {chain} | Invalid SupportedChainName passed to the constructor | Use a valid chain name from the chain configuration table |
Request failed with status {N} | Non-402, non-2xx response from the server | Check server status and URL |
Missing PAYMENT-REQUIRED header in 402 response | Server returned 402 without the required header | Verify the server uses x402 v2 |
No payment options in 402 response | Empty accepts array in the 402 response | The server may not have configured payment options |
No Gateway batching option available | Server does not support Gateway batching | Use supports() to check first; the server may only accept onchain |
Payment failed: {reason} | Server rejected the payment | Check the Gateway API error code in the message |
Insufficient USDC balance | Wallet USDC balance is less than the deposit amount | Get more USDC from the faucet or transfer from another wallet |
Approval transaction failed: {txHash} | USDC approval transaction reverted onchain | Check gas, wallet balance, and network status |
Deposit transaction failed: {txHash} | Deposit transaction reverted onchain | Check gas and contract state |
Insufficient available balance | Gateway balance is too low for the withdrawal | Deposit more or reduce the amount |
Unsupported destination chain: {chain} | Invalid chain name for crosschain withdrawal | Use a valid SupportedChainName |
Middleware errors
| Error message | Cause | Recovery |
|---|
Invalid price: {price} | Price string could not be parsed | Use format '$0.01' or '0.01' |
No payment networks available | No supported networks found (503 response) | Check Gateway API connectivity |
Payment verification failed | Verify returned isValid: false | Check the Gateway API error code in the response body reason field |
Payment settlement failed | Settle returned success: false | Check the Gateway API error code in the response body reason field |
BatchFacilitatorClient errors
| Error message | Cause | Recovery |
|---|
Circle Gateway verify failed ({status}): {details} | Verify endpoint returned an unexpected response | Check payload format and API status |
Circle Gateway settle failed ({status}): {details} | Settle endpoint returned an unexpected response | Retry the request and contact support if the error persists |
Circle Gateway settle returned empty response ({status}) | Empty body from settle endpoint | Retry the request |
Circle Gateway getSupported failed ({status}): {details} | Cannot fetch supported networks | Check API connectivity and URL |
BatchEvmScheme errors
| Error message | Cause | Recovery |
|---|
BatchEvmScheme: unsupported network format "{network}" | Network string is not in eip155:<chainId> format | Use CAIP-2 format (for example, eip155:5042002) |
BatchEvmScheme can only handle Circle batching options | Payment requirements missing extra.name="GatewayWalletBatched" | Use this scheme only for Gateway payments |
Circle batching option missing extra.verifyingContract | Payment requirements missing the Gateway Wallet address | Ensure the server includes verifyingContract in extra |