Back
Developer Docs
Dashboard

x402 Protocol: Developer Documentation & Integration Guide

Version: 1.3.1 (Production Grade)
Host URL: https://api.tx4.xyz

[!TIP] Advanced Wire Schema: If you are building a custom client or server from scratch (without using our SDKs), please refer to the SPEC-WIRE-PROTOCOL.md for strict details on CAIP-2 mapping, Hybrid HTTP Headers, and the Extended SDK JSON payload structure.


1. Introduction to x402

The x402 protocol is an open standard designed to enable seamless, programmatic, and autonomous machine-to-machine microtransactions on Solana (SVM). Utilizing the standard HTTP 402 Payment Required status code, x402 allows AI agents and client applications to dynamically discover, pay for, and unlock digital assets (APIs, LLM tokens, files, datasets) without human-in-the-loop friction.

Why Solana (SVM) for Agentic Payments?

  • Sub-Cent Transaction Fees: Transactions cost a fraction of a cent, enabling low-value microtransactions.
  • Sub-Second Finality: Under 400ms slot times ensure instant state locks.
  • High Concurrency: State isolation via Account Locking allows massive parallel throughput.

2. Solana Network Configuration

Depending on the environment you are targeting, configure your client and server SDKs with the following values:

ParameterSolana Devnet (Testing)Solana Mainnet-Beta (Production)
RPC Endpointhttps://api.devnet.solana.comhttps://api.mainnet-beta.solana.com
USDC MintGh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJrEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Program ID53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi
Destination Wallet (DID)did:pkh:solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG:<WALLET_ADDRESS>did:pkh:solana:5eykt4UsFvXYtt2SEeUuXXw1D7M755HXbhm8:<WALLET_ADDRESS>
Facilitator API URLhttps://api.tx4.xyz (Devnet Mode)https://api.tx4.xyz (Mainnet Mode)

[!NOTE] Dynamic Environment Resolution: The client and server SDKs automatically resolve the correct network and USDC mint addresses dynamically by inspecting the Solana connection RPC endpoint URL. You do not need to manually swap mint addresses in your code.

Program ID Configuration: The Program ID is passed directly as an initialization argument to the X402Client or X402Server constructor, allowing a single package build to support both the Devnet sandbox and the Mainnet production deployment.


2. Architecture & Data Flow

Below is the standard integration flow mapping how the Client SDK, your Merchant Backend, the shared Facilitator API (api.tx4.xyz), and the Solana Blockchain interact:

sequenceDiagram
    autonumber
    actor Client as Client SDK (Browser/Agent)
    participant Merchant as Merchant Backend
    participant Fac as Facilitator (api.tx4.xyz)
    participant Chain as Solana Blockchain (USDC Escrow)

    Client->>Merchant: POST /buy (Request paid resource)
    Note over Merchant: Verification check fails<br/>(No payment recorded)
    Merchant-->>Client: HTTP 402 Payment Required<br/>(invoice_id, amount, destination_wallet)
    
    Note over Client: Client constructs & signs<br/>Solana InitializePayment transaction
    Client->>Merchant: POST /buy (with Transaction Payload & invoice_id)
    
    Merchant->>Fac: POST /verify (Stateless check)
    Fac-->>Merchant: 200 OK (isValid: true)
    
    Merchant->>Fac: POST /settle?async=true (Broadcast)
    Fac-->>Merchant: 200 OK (status: "pending", txSig)
    
    Note over Merchant: Instantly deliver content to Client!<br/>Latency is < 150ms
    Merchant-->>Client: 200 OK (Delivered Resource)
    
    Note over Fac: Background Job sweeps & monitors Solana RPC Pool
    Fac->>Chain: confirmTransaction
    Note over Chain: PDA Escrow Locked!

3. How Authentication Works

Every request made by a Client SDK to a Merchant server carries three automatic HTTP headers that prove who you are — without requiring a login, API key, or session cookie. This is the x402 authentication handshake.

X-X402-DID:        did:pkh:solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG:HN7cABFiw96SFFoM...
X-X402-Timestamp:  1780407476
X-X402-Signature:  3M2B7GfW9sJmKz... (Base58 Ed25519)

You don't need to write any of this manually. The SDK constructs and signs these headers automatically on every outgoing request using your Solana keypair.

What Each Header Means:

  • X-X402-DID — Your decentralized identity, derived directly from your Solana wallet address. No account registration needed. (Note: Our standalone @tx4/did-resolver NPM package handles parsing this standard).
  • X-X402-Timestamp — The current Unix timestamp (seconds). The Merchant server rejects requests that are more than 30 seconds old to prevent replay attacks.
  • X-X402-Signature — An Ed25519 cryptographic signature over the URL and timestamp. Only your wallet can produce it.
  • X-X402-AP2-Mandate(Optional) Supports Google's Agent Protocol 2 authorization, allowing X402 to act as a bridge between Web2 AI capabilities and Web3 payments.

SIWS (Sign-In With Solana) Authentication

If you are building a Next.js Dashboard, you do not need to manually verify these headers for frontend login. The @tx4/x402-server SDK natively exposes generateSIWSMessage() and verifySIWSMessage() methods that comply with the EIP-4361 Solana standard to authenticate your users effortlessly.


4. The Payment Flow in Detail

Extended x402 Architecture

Our platform fully complies with the official Coinbase x402.org wire protocol standards while extending them with our custom fields (like destination_wallet and amount) to support Escrow functionality.

When a Merchant server returns 402 Payment Required, it injects a PAYMENT-REQUIRED HTTP Header (base64 encoded JSON) and also returns the body below:

{
  "version": 2,
  "accepts": [
    {
      "scheme": "exact",
      "network": "solana:5eykt4UsFvXYtt2SEeUuXXw1D7M755HXbhm8",
      "payTo": "HK2a...vWnQ",
      "price": "1.00",
      
      "destination_wallet": "did:pkh:solana:5eykt4UsFvXYtt2SEeUuXXw1D7M755HXbhm8:HK2a...vWnQ",
      "amount": 1000000,
      "invoice_id": "0x9f2c...e8a1",
      "x402Version": "1.2.1",
      "expires_at": 1780407506,
      "lock_timeout": 60
    }
  ]
}
FieldDescriptionType
schemePayment scheme. "exact" means a fixed one-time payment.Official
networkThe CAIP-2 network ID (solana:5eykt4Us... for Mainnet).Official
payToThe destination Solana address.Official
priceAmount requested formatted as a string decimal ("1.00").Official
destination_walletThe merchant's wallet as a secure DID.Extension
amountPrecise amount in micro-USDC (1000000 = 1.00 USDC).Extension
invoice_idUnique 32-byte ID for this payment session (PDA seed).Extension
expires_atUnix timestamp by which the payment must complete.Extension

The Client SDK automatically reads the PAYMENT-REQUIRED header (or falls back to the body), constructs the Solana initialize_payment transaction, asks your wallet to sign it, and then retries the original request providing the PAYMENT-SIGNATURE HTTP header. Your app code never sees this complexity.


5. Payment Schemes

exact — Fixed One-Time Payment

The client pays a fixed amount upfront. The merchant delivers the resource. Simple, trustless.

Best for: API calls, file downloads, one-time access, per-request AI inference.

batch-settlement — Pay Once, Use Many

The client commits a maximum balance (e.g. $10 USDC) at the start of a session. The merchant bills the exact usage (e.g. $2.30) at the end, and the remaining balance ($7.70) is automatically refunded to the client atomically via metered_claim.

Best for: LLM token streaming, metered API usage, long AI agent sessions.

upto — Capped Metered Payment

Similar to batch-settlement but simpler: the client authorizes "up to $X", and the merchant claims the actual amount. The remainder is refunded atomically.

Best for: Variable-cost AI jobs, batch data processing.


6. Integration Guide

A. Client Integration

We provide official client SDKs for TypeScript/JavaScript, Python, and Go. Each SDK wraps HTTP request handlers to intercept 402 Payment Required responses, sign the required Solana transaction using your wallet/keypair, and retry the request automatically.

A.1 TypeScript / JavaScript (@tx4/x402-client)

Install the client SDK in your frontend application:

bun add @tx4/x402-client @solana/web3.js

Initialize the client and wrap your fetch calls:

import { Connection, PublicKey } from "@solana/web3.js";
import { X402Client } from "@tx4/x402-client";
import { useWallet } from "@solana/wallet-adapter-react";

const connection = new Connection("https://api.devnet.solana.com");
const { wallet } = useWallet();

const x402Client = new X402Client({
  connection,
  clientWallet: wallet,
  programId: new PublicKey("53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi")
});

// Use standard fetch wrapped by x402Client
async function fetchPaidResource() {
  const response = await x402Client.fetch("https://your-merchant-backend.com/api/v1/resource", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ query: "Hello AI Agent" })
  });

  const data = await response.json();
  console.log("Unlocked content:", data);
}

A.2 Python (x402-sdk)

Install the Python client package:

pip install x402-sdk

Use the client helper with standard HTTP clients (e.g., httpx or requests):

from x402_sdk import X402Client
from solders.keypair import Keypair

# Initialize the x402 client
client_keypair = Keypair.from_base58_string("YourPrivateKeyBase58")
x402_client = X402Client(
    rpc_url="https://api.devnet.solana.com",
    client_keypair=client_keypair,
    program_id="53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi"
)

# Fetch paid resources dynamically (automatically intercepts and pays on 402)
async def fetch_resource():
    response = await x402_client.fetch(
        "https://your-merchant-backend.com/api/v1/resource",
        method="POST",
        json={"query": "Hello AI Agent"}
    )
    data = response.json()
    print("Unlocked content:", data)

A.3 Go (go-sdk)

Install the Go client package:

go get github.com/tx4xyz/x402-infra/packages/go-sdk

Wrap Go's native http.Client using the custom RoundTripper:

package main

import (
	"fmt"
	"io"
	"net/http"
	"github.com/gagliardetto/solana-go"
	"github.com/tx4xyz/x402-infra/packages/go-sdk/client"
)

func main() {
	clientKey, _ := solana.PrivateKeyFromBase58("YourPrivateKeyBase58")
	x402Client, _ := client.NewX402Client(
		"https://api.devnet.solana.com",
		clientKey,
		"53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi",
	)

	// Wrap Go's native HTTP client with our x402 RoundTripper (Only 1 line!)
	httpClient := &http.Client{
		Transport: client.NewX402RoundTripper(x402Client, http.DefaultTransport),
	}

	// Make standard HTTP requests; payment is negotiated automatically on 402 responses
	resp, _ := httpClient.Get("https://your-merchant-backend.com/api/v1/resource")
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println("Unlocked content:", string(body))
}

B. Merchant Server Integration (@tx4/x402-server)

Install the server SDK in your backend:

bun add @tx4/x402-server @solana/web3.js

Step 1: Intercept Unpaid Requests

Check if the request contains valid payment tokens. If not, issue a 402 Payment Required challenge:

import { Connection, PublicKey } from "@solana/web3.js";
import { X402Server } from "@tx4/x402-server";
import crypto from "crypto";

const connection = new Connection("https://api.devnet.solana.com");
const server = new X402Server({
  connection,
  serverWallet: new PublicKey("YourMerchantWalletPubkey"),
  programId: new PublicKey("53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi")
});

// Middleware/Handler
async function handleRequest(req, res) {
  const paymentSignatureHeader = req.headers["payment-signature"];

  if (!paymentSignatureHeader) {
    // Generate new random invoice ID
    const newInvoiceId = crypto.randomBytes(32).toString("hex");
    const requirements = server.getPaymentRequirements("exact", newInvoiceId, 100000); // 0.1 USDC (6 decimals)
    
    res.setHeader("PAYMENT-REQUIRED", Buffer.from(JSON.stringify(requirements)).toString("base64"));
    return res.status(402).json(requirements);
  }

  // Parse payment signature
  const signaturePayload = JSON.parse(Buffer.from(paymentSignatureHeader, "base64").toString("utf-8"));
  const paymentSignature = signaturePayload.payload.transaction;
  const invoiceId = signaturePayload.invoice_id;

  // Next step: verify & settle the payment
}

Step 2: Delegate Settlement to api.tx4.xyz

Forward the transaction payload to the Facilitator API for fast, zero-overhead confirmation:

const settleResponse = await fetch("https://api.tx4.xyz/settle?async=true", {
  method: "POST",
  headers: { 
    "Content-Type": "application/json",
    "PAYMENT-SIGNATURE": paymentSignatureHeader
  }
});

const result = await settleResponse.json();
if (result.success) {
  // Deliver content immediately!
  res.status(200).json({ resource: "Super Secret AI Data" });
} else {
  res.status(400).json({ error: "Payment settlement failed" });
}

4. Production Best Practices

🚀 Asynchronous Sweep/Claim Queue & Dynamic Time-Locks

When a user pays, their funds are locked in an Escrow PDA controlled by the program for a specific duration (lock_timeout).

The lock_timeout is fully dynamic. It is determined by the Merchant when issuing the 402 Payment Required challenge.

  • Light API Calls: 15 - 30 seconds.
  • Large File Downloads: 300 seconds (5 minutes).
  • Long AI/Streaming Sessions: 3600 seconds (1 hour).

To transfer those locked funds to your main merchant wallet, your server MUST submit a claimPayment transaction before this timeout expires. If you fail to claim in time, the funds can be refunded by the client.

[!IMPORTANT] Client Protection (Auto-Refund & Gas Auto-Freeze):

  1. Auto-Refund: If a user's transaction is locked on-chain but your server responds with an error (e.g., 500 Internal Server Error) or times out (RTO) up to 5 times, the Client SDK will automatically schedule a background sweeper. Once your lock_timeout expires, the SDK autonomously executes a triggerRefund transaction to return funds to the user.
  2. Auto-Freeze (Anti-DDoS Gas Protection): If a client experiences 3 consecutive auto-refunds against the same merchant, the SDK will automatically freeze transactions to that merchant for 15 minutes to prevent the user from wasting Solana gas fees on dead endpoints. (Note: The TS, Python, and Go SDKs all handle this auto-freeze logic automatically using their respective HTTP interceptors).
  3. Manual Unfreeze Override: Developers can forcefully reset a penalty using client.unfreezeMerchant(walletAddress) in TS/Py or client.UnfreezeMerchant(walletAddress) in Go.

Note on Lock Timeout: The global default lock_timeout is now 300 seconds (5 minutes) to accommodate heavy workloads like AI processing and video rendering. However, Merchants SHOULD configure a dynamic lock_timeout closely matching their expected compute time to provide a snappier refund experience for lightweight endpoints.

To run this at scale without blocking user requests or paying bloated transaction fees:

  1. Never Claim Synchronously: Do not claim the funds during the user's request thread. Rely on the Facilitator's instant success: true to serve the content immediately.
  2. Use Upstash QStash: Queue a delayed sweeper job to claim the funds immediately after the user's session ends, or run a background worker.
  3. Batch Claims: Sweep multiple settled PDAs in a single aggregated transaction, drastically saving on Solana priority fees and transaction costs.

Example queue worker:

import { X402Server } from "@tx4/x402-server";

// QStash Worker Endpoint triggered every hour
async function handleSweeperQueue(req, res) {
  const settledSessions = await db.query("SELECT invoice_id FROM payment_sessions WHERE status = 'LOCKED' LIMIT 10");
  
  for (const session of settledSessions) {
    try {
      const txSig = await server.settleExactSvmPayload({
        invoiceId: session.invoice_id,
        serverKeypair: merchantPrivateKeypair
      });
      await db.query("UPDATE payment_sessions SET status = 'CLAIMED' WHERE invoice_id = $1", [session.invoice_id]);
      console.log(`Successfully claimed invoice ${session.invoice_id}: ${txSig}`);
    } catch (e) {
      console.error(`Failed to claim ${session.invoice_id}:`, e);
    }
  }
  res.status(200).send("Sweeper completed");
}

⚡ Scaling the Facilitator

If hosting your own facilitator backend, ensure the following environment configurations are populated:

  • Helius / Validation Cloud API Keys: Provide a comma-separated list of keys (HELIUS_API_KEYS, VALIDATION_CLOUD_KEYS) for load-balancing and failover.
  • Neon PostgreSQL: Configure NEON_DATABASE_URL to enable serverless connection pooling and auto-scaling.
  • Upstash Redis: Configure UPSTASH_REDIS_REST_URL to enable unified distributed rate-limiting across serverless workers.

6. Facilitator API Reference

All endpoints are hosted at https://api.tx4.xyz.

GET /healthz

Returns the health status of the Facilitator service.

Response:

{
  "status": "ok",
  "network": "devnet",
  "version": "1.2.5",
  "rpc_pool_size": 2,
  "db": "neon"
}

GET /supported

Returns a list of supported payment schemes and blockchain networks.

Response:

{
  "schemes": ["exact"],
  "networks": ["solana-devnet"],
  "facilitator": "https://api.tx4.xyz",
  "program_id": "53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi"
}

POST /verify

Performs a stateless validation of a signed transaction payload. Does not submit the transaction to the blockchain.

Request Body:

{
  "paymentPayload": {
    "transaction": "<base64-encoded-serialized-transaction>"
  },
  "paymentRequirements": {
    "invoice_id": "0xabc123...",
    "amount": 100000,
    "destination_wallet": "did:pkh:solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG:YourWalletAddress"
  }
}

Response (Valid):

{
  "isValid": true,
  "payer": "ClientWalletPublicKey"
}

Response (Invalid):

{
  "isValid": false,
  "invalidReason": "x402:signature_invalid",
  "invalidMessage": "Transaction signature verification failed"
}

Rate Limit: 600 requests / 60 seconds per IP per merchant wallet.


POST /settle

Broadcasts the signed transaction to the Solana network. Supports optional async mode.

Query Parameters:

ParameterTypeDefaultDescription
asyncbooleanfalseIf true, returns immediately with status: pending without waiting for block confirmation

Request Body: Same format as /verify.

Response (Async, ?async=true):

{
  "success": true,
  "transaction": "5Kd7g...txSig",
  "status": "pending",
  "network": "solana-devnet",
  "payer": "ClientWalletPublicKey",
  "invoice_id": "0xabc123..."
}

Response (Sync, confirmed):

{
  "success": true,
  "transaction": "5Kd7g...txSig",
  "status": "confirmed",
  "network": "solana-devnet",
  "payer": "ClientWalletPublicKey"
}

Rate Limit: 60 requests / 60 seconds per IP per merchant wallet.

[!TIP] Webhook Notifications: Instead of polling the /sessions/:id endpoint or waiting for the synchronous response, you can set the MERCHANT_WEBHOOK_URL environment variable in your Facilitator configuration. Upon successful settlement, the Facilitator will automatically dispatch an asynchronous HTTP POST payload ({ invoice_id, amount, status: 'settled', transaction }) to your backend.


7. Error Codes Reference

Error CodeHTTP StatusDescription
x402:malformed_json400Request body is not valid JSON
x402:malformed_payload200Transaction payload cannot be deserialized
x402:signature_invalid200Transaction signature does not match payer
x402:invoice_already_settled200This invoice_id has already been claimed or refunded
x402:amount_mismatch200Transaction amount does not match payment requirements
x402:mint_invalid200Token mint address does not match expected USDC mint
x402:solana_rpc_unavailable200All RPC endpoints in the pool failed to respond
x402:unsupported_cluster400Requested blockchain network is not supported
rate_limit_exceeded429Too many requests; see X-RateLimit-Reset header

8. Self-Hosting the Facilitator

You can run your own private Facilitator instance instead of using the shared api.tx4.xyz endpoint.

Environment Variables

Create a .env file with the following variables:

# Solana Program
PROGRAM_ID=53A9U35YrRGxRrN2owf3efQ56rMGCjn8AJ4W99XviyGi
NETWORK=devnet  # or "mainnet"

# Helius RPC (supports multiple keys for load rotation)
HELIUS_API_KEY_DEVNET=your-devnet-helius-key
HELIUS_API_KEY_MAINNET=your-mainnet-helius-key
# Or comma-separated for multiple keys:
# HELIUS_API_KEYS=key1,key2,key3

# Validation Cloud RPC (optional, for failover)
VALIDATION_CLOUD_KEY_DEVNET=your-devnet-vc-key
VALIDATION_CLOUD_KEY_MAINNET=your-mainnet-vc-key

# Neon PostgreSQL (optional, falls back to SQLite)
NEON_DATABASE_URL=postgresql://user:pass@host/db?sslmode=require

# Upstash Redis (optional, falls back to in-memory rate limiting)
UPSTASH_REDIS_REST_URL=https://your-upstash-url.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-upstash-token

# Optional: Asynchronous Webhook Dispatcher
MERCHANT_WEBHOOK_URL="https://your-backend.com/webhooks/x402"

# Server
PORT=8080

Running the Service

# Clone and install
git clone https://github.com/tx4xyz/x402-infra.git
cd x402-infra/apps/facilitator

# Run database migration (only needed once)
bun run src/migrate.ts

# Start the server
bun run src/index.ts

Deploy to Fly.io

fly launch --name my-x402-facilitator
fly secrets set NEON_DATABASE_URL="..." HELIUS_API_KEYS="..." UPSTASH_REDIS_REST_URL="..."
fly deploy

After deployment, point a custom CNAME record to your Fly.io app URL (e.g., api.your-domain.com).

Deploy to Cloudflare Workers

The reference Facilitator is designed to be deployable to Cloudflare Workers for zero-latency global edge hosting. Create a wrangler.toml:

# wrangler.toml
name = "x402-facilitator"
main = "src/index.ts"
compatibility_date = "2026-06-01"

[vars]
NETWORK = "mainnet"

# Set secrets with: wrangler secret put <NAME>
# HELIUS_API_KEYS
# VALIDATION_CLOUD_KEYS
# NEON_DATABASE_URL
# UPSTASH_REDIS_REST_URL
# UPSTASH_REDIS_REST_TOKEN

Then deploy:

wrangler deploy --env production

To rollback if needed:

wrangler rollback --message "revert: faulty deploy"

10. Security Notes for Merchants

Replay Attack Protection

The X-X402-Timestamp header is validated on every request. Requests with a timestamp older than 30 seconds are automatically rejected. This prevents attackers from capturing and reusing a valid signed request.

Cross-Network Protection

The DID in X-X402-DID embeds the Solana cluster ID. A Server SDK configured for Mainnet will automatically reject any request signed with a Devnet key, preventing cross-chain replay attacks.

Trustless Settlement

The Facilitator (api.tx4.xyz) never holds your private key. The client signs the Solana transaction locally in their wallet, and the signed transaction is simply forwarded for broadcast. If the Facilitator were compromised, it could not steal funds — it can only delay or drop broadcasts.

On-Chain Refund Safety

If your Merchant backend crashes after a user pays but before you claim the funds, the user's money is safe. After the lock_timeout (default 60 seconds), the on-chain program allows the user to reclaim their USDC permissionlessly without any action from you.


11. Frequently Asked Questions

Q: Is the shared api.tx4.xyz facilitator trusted?
A: The Facilitator does not hold any private keys and cannot move funds. It only broadcasts pre-signed transactions from users. The security model is trustless by design.

Q: What happens if the Facilitator goes down after a user pays?
A: The user's signed transaction is encoded in the payment payload. Your server can re-submit the settlement to any compatible Facilitator endpoint, or broadcast the transaction directly to any Solana RPC node.

Q: Can I run my own Facilitator?
A: Yes. See Section 8 (Self-Hosting). Running your own Facilitator gives you full control over RPC providers, rate limits, and database backends.

Q: Can I accept payments in tokens other than USDC?
A: The current exact scheme supports USDC only. Support for additional SPL tokens is planned in a future release.

Q: What is the minimum / maximum payment amount?
A: There is no protocol-level minimum or maximum. The practical range is 1 micro-USDC (1) up to the client's wallet balance. USDC uses 6 decimal places, so 1000000 = 1.00 USDC.

Q: How do I handle refunds?
A: Solana x402 has built-in automatic refunds. If your Merchant server does not call claimPayment before the lock_timeout expires, the on-chain program allows the user to reclaim their funds permissionlessly.

Q: Is x402 compatible with other chains (EVM, Ethereum)?
A: The x402 protocol standard supports multiple chains. This SDK targets Solana (SVM). EVM-compatible implementations exist separately and use different payment payloads.

Q: How do I test without real USDC?
A: Set NETWORK=devnet and use the Devnet USDC mint (Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr). You can mint free test USDC on Solana Devnet via the Solana CLI or the Circle Developer faucet.