Skip to main content
LimitGuard implements the x402 V2 micropayment protocol for AI agent pay-per-use access. No subscription or API key required — agents pay per call in USDC.

Overview

x402 extends HTTP with a payment layer. The flow is simple:
1

Request without payment

Agent makes a normal API request.
2

Receive HTTP 402

Server returns payment requirements — chain, amount, recipient, contract address.
3

Build payment signature

Agent constructs an EIP-3009 TransferWithAuthorization signature.
4

Retry with X-PAYMENT header

Agent retries the same request with the base64-encoded payment header.
5

Receive response

Server verifies signature, processes the request, and returns the result.

Supported Networks

NetworkCAIP-2 Chain IDUSDC Contract
Base Mainneteip155:84530x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Base Sepoliaeip155:845320x036CbD53842c5426634e7929541eC2318f3dCF7e
Solana Mainnetsolana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Solana Devnetsolana:EtWTRABZaYq6iMfeYKouRu166VU2xqa14zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU

Step 1: Discover Payment Requirements

Make a request without payment to get the requirements:
curl -X POST https://api.limitguard.ai/v1/entity/check \
  -H "Content-Type: application/json" \
  -d '{"entity_name": "Acme Corp BV", "country": "NL"}'
HTTP 402 Response
{
  "x402Version": "2",
  "error": "Payment Required",
  "accepts": [
    {
      "chainId": "eip155:8453",
      "currency": "USDC",
      "contractAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "amount": "50000",
      "decimals": 6,
      "recipient": "0xFacilitatorAddress",
      "description": "LimitGuard API call (0.05 USDC)"
    },
    {
      "chainId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
      "currency": "USDC",
      "contractAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "amount": "50000",
      "decimals": 6,
      "recipient": "SolanaFacilitatorAddress",
      "description": "LimitGuard API call (0.05 USDC)"
    }
  ]
}

Step 2: Build EVM Payment (Base / EIP-3009)

import base64, json, secrets, time
from eth_account import Account
from eth_account.messages import encode_typed_data

def build_x402_payment(
    chain_id: str,          # e.g. "eip155:8453"
    amount: int,            # in USDC 6-decimal units
    sender_key: str,        # private key (hex)
    recipient: str,         # facilitator address
    usdc_address: str,      # USDC contract address
) -> str:
    sender = Account.from_key(sender_key).address
    chain_num = int(chain_id.split(":")[1])  # 8453

    nonce = "0x" + secrets.token_hex(32)
    now = int(time.time())

    # EIP-712 domain
    domain = {
        "name": "USD Coin",
        "version": "2",
        "chainId": chain_num,
        "verifyingContract": usdc_address,
    }

    # EIP-3009 TransferWithAuthorization
    message = {
        "from": sender,
        "to": recipient,
        "value": amount,
        "validAfter": now - 10,
        "validBefore": now + 300,
        "nonce": bytes.fromhex(nonce[2:]),
    }

    types = {
        "EIP712Domain": [
            {"name": "name", "type": "string"},
            {"name": "version", "type": "string"},
            {"name": "chainId", "type": "uint256"},
            {"name": "verifyingContract", "type": "address"},
        ],
        "TransferWithAuthorization": [
            {"name": "from", "type": "address"},
            {"name": "to", "type": "address"},
            {"name": "value", "type": "uint256"},
            {"name": "validAfter", "type": "uint256"},
            {"name": "validBefore", "type": "uint256"},
            {"name": "nonce", "type": "bytes32"},
        ],
    }

    signable = encode_typed_data(domain, types, "TransferWithAuthorization", message)
    signed = Account.sign_message(signable, private_key=sender_key)

    payload = {
        "chainId": chain_id,
        "amount": str(amount),
        "sender": sender,
        "recipient": recipient,
        "nonce": nonce,
        "signature": signed.signature.hex(),
        "validAfter": now - 10,
        "validBefore": now + 300,
    }

    return base64.b64encode(json.dumps(payload).encode()).decode()

Step 3: Make Paid Request

import httpx

x_payment = build_x402_payment(
    chain_id="eip155:8453",
    amount=50_000,           # $0.05 for /v1/entity/check (fresh)
    sender_key="0xYOUR_PRIVATE_KEY",
    recipient="0xFacilitatorFromThe402Response",
    usdc_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
)

response = httpx.post(
    "https://api.limitguard.ai/v1/entity/check",
    headers={"X-PAYMENT": x_payment, "Content-Type": "application/json"},
    json={"entity_name": "Acme Corp BV", "country": "NL"},
)
print(response.json())

Response Headers

On successful payment verification, these headers are included:
HeaderValueMeaning
X-Payment-VerifiedtruePayment accepted
X-Payment-Amount50000Amount verified (6-decimal USDC)
X-Payment-FallbacktrueCircuit breaker triggered (rare)

Replay Prevention

Each nonce can only be used once. Nonces are tracked in Redis with a 5-minute TTL. Reusing a nonce returns:
HTTP 402
{
  "error": "Nonce already used (replay detected)"
}

Quality Tiers with x402

Control cost via the X-Response-Quality header. The amount in X-PAYMENT must match or exceed the price for the selected tier:
Tier/v1/entity/check/v1/risk/score/v1/kyb/check
cached$0.01 (10,000)$0.005 (5,000)$0.25 (250,000)
fresh$0.05 (50,000)$0.01 (10,000)$1.25 (1,250,000)
enhanced$0.15 (150,000)$0.05 (50,000)$2.50 (2,500,000)
If the payment amount is insufficient for the requested tier, you’ll receive HTTP 402 with the correct amount.

Circuit Breaker Fallback

If the payment facilitator is unavailable (circuit breaker open), LimitGuard falls back to a verified wallet cache. Wallets that have previously completed verified payments are cached. The response includes X-Payment-Fallback: true when this path is used.

Discovery

AI agents can discover LimitGuard’s x402 payment requirements automatically:
curl https://api.limitguard.ai/.well-known/x402.json
Returns a Bazaar-compatible service listing with all endpoints, pricing, and accepted payment methods.

V1 Backward Compatibility

The older PAYMENT-SIGNATURE header (V1 format) is still accepted for backward compatibility. V2 (X-PAYMENT) is recommended for all new integrations.