Documentation

Everything you need to integrate x402-compliant AI-to-AI payments on Algorand.

Who is this for?

Algorand wallet holders

  • Have Pera or Defly installed
  • Sign in with your wallet
  • Create an agent via the dashboard
  • Fund it with ALGO + USDC from Pera
Sign in →

Developers / AI agents

  • Use the REST API directly
  • POST /api/agents/create → get mnemonic
  • Send 0.5 ALGO to activate
  • Use SDK or MCP in your code
Jump to quickstart →

New to Algorand?

  • Install Pera Wallet
  • Buy ALGO on Coinbase / Binance
  • Get USDC on Algorand
  • Then come back and sign in
Setup guide →

Overview

The @algo-wallet/x402-client SDK handles the full x402 payment handshake automatically. Your agent sends a request, receives a 402 with payment terms, and the SDK builds the Ed25519 proof and settles the payment on-chain — all in milliseconds, zero human approval.

Two-step flow:

1. POST /api/agent-action → 402 (payment terms)

2. Retry with X-PAYMENT header → 200 (confirmed)

Testnet vs Mainnet

NetworkUSDC ASA IDTollbaseUrl
Mainnet315667040.01 USDC (10,000 µUSDC)api.ai-agentic-wallet.com
Testnet104589410.01 USDC (10,000 µUSDC)api.ai-agentic-wallet.com

Testnet USDC is available from the Folks Finance testnet faucet. Your agent wallet needs ≥ 0.1 ALGO minimum balance and must be opted into the USDC ASA before paying.

Agent Onboarding

Agents are non-custodial. You generate your own keypair, the operator deploys a MandateContract with your spend limits, you register with the server, and fund the contract app account with ALGO (gas) and USDC (spending power). No rekeying. You hold the signing key forever.

Step 1 — Create the agent (deploys MandateContract)

typescript
const res = await fetch("https://api.ai-agentic-wallet.com/api/agents/create-mandate", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Portal-Key": YOUR_PORTAL_API_KEY,
  },
  body: JSON.stringify({
    agentId:      "my-agent-001",  // unique ID, alphanumeric + hyphens
    ownerAddress: "PERA_ADDR...",  // optional — links agent to your wallet identity
    platform:     "anthropic",    // optional: "openai" | "anthropic" | "custom"
  }),
});

const { agentId, address, mnemonic, mandateAppId, appAddress } = await res.json();
// address      → agent's Algorand signing address
// mnemonic     → 25-word signing key — save to ALGO_MNEMONIC in your .env
// mandateAppId → MandateContract application ID — save to MANDATE_APP_ID in your .env
// appAddress   → contract app account — fund this with ALGO + USDC

Step 2 — Save the signing key

The server discards the mnemonic immediately. Copy it into your application's environment:

bash
ALGO_MNEMONIC="word1 word2 ... word25"  # in your .env file

Step 3 — Fund the MandateContract app account with ALGO

Send at least 0.5 ALGO to appAddress (the MandateContract app account, not the agent signing address). The ALGO covers inner transaction gas. The server detects the deposit and opts the contract into USDC automatically.

typescript
// Poll until active (typically 10–30 seconds after deposit)
let agent;
do {
  await new Promise(r => setTimeout(r, 5000));
  const r = await fetch(`https://api.ai-agentic-wallet.com/api/agents/${agentId}`, {
    headers: { "X-Portal-Key": YOUR_PORTAL_API_KEY },
  });
  agent = await r.json();
} while (agent.status !== "active");

console.log("Agent active:", agent.address);

Step 4 — Deposit USDC to the contract app account

Send USDC (ASA 31566704 mainnet / 10458941 testnet) to appAddress — the MandateContract app account. The server detects USDC > 0 and sets the agent to active. USDC spending power lives in the contract, not the agent's signing address.

Install & Quick Start

bash
npm install @algo-wallet/x402-client algosdk
typescript
import { AlgoAgentClient } from "@algo-wallet/x402-client";
import algosdk from "algosdk";

const account = algosdk.mnemonicToSecretKey(process.env.ALGO_MNEMONIC!);

const client = new AlgoAgentClient({
  baseUrl:      "https://api.ai-agentic-wallet.com",
  privateKey:   account.sk,               // 64-byte Uint8Array
  mandateAppId: Number(process.env.MANDATE_APP_ID!),  // from register-mandate
});

const result = await client.executeTrade({
  senderAddress: account.addr.toString(),
  amount: 10000,  // micro-USDC (10000 = $0.01)
});

if (result.success) {
  console.log("Settled:", result.settlement.txnId);
  console.log("Round:", result.settlement.confirmedRound);
} else {
  console.error("Failed at stage:", result.failedStage, result.detail);
}

402 Handshake Flow

executeTrade() — mandate architecture

├─ POST /api/agent-action ← Initial request (no proof)

│   ↳ 402 Payment Required ← Server returns payTo + toll amount

├─ Build MandateContract.pay() app call ← ARC-4 ApplicationCallTxn

├─ Sign with agent's own key ← real on-chain transaction

├─ Retry with X-PAYMENT: base64(signedTxn)

│   ↳ Server decodes + verifies factory provenance + submits

│   ↳ AVM enforces all caps atomically

└─ 200 + { jobId } ← delivered after sendRawTransaction acceptance (~730ms)

     ↳ Poll /api/jobs/:jobId for confirmed on-chain txnId (background ~3s)

Atomic endpoints (e.g. /api/weather): same X-PAYMENT flow — server commits payment before returning data. No separate /api/execute step.

Gas Headers

Every payment response includes gas status headers so your agent can monitor its own ALGO balance and alert before it runs dry.

bash
X-Agent-Gas-Status:    ok | low | critical
X-Agent-Gas-Remaining: 847   # estimated transactions remaining
StatusMeaningThreshold
okSufficient ALGO for many more transactions≥ 200,000 µALGO above MBR
lowRefuel soon — limited transactions remaining< 200,000 µALGO above MBR
criticalRefuel immediately — may fail soon< 50,000 µALGO above MBR

Use parseGasInfo() from the SDK to read these headers automatically:

typescript
import { AlgoAgentClient, parseGasInfo } from "@algo-wallet/x402-client";

const client = new AlgoAgentClient({
  baseUrl,
  privateKey:   account.sk,
  mandateAppId: Number(process.env.MANDATE_APP_ID),
});
const response = await client.fetch("/api/your-endpoint", { method: "POST", body: ... });
const gas = parseGasInfo(response);

if (gas?.status === "critical") {
  console.warn(`Gas critical — only ${gas.remaining} transactions remaining`);
  // trigger a refuel flow or alert your operator
}

API Reference

POST/api/agents/register-mandate

Register a non-custodial mandate agent. Provide your address and mandateAppId. The server stores the record — no on-chain ops, no rekeying. Requires X-Portal-Key header.

Parameters

agentIdstringrequiredUnique agent ID (alphanumeric + hyphens)
addressstringrequiredAgent Algorand address (58-char base32)
mandateAppIdnumberrequiredMandateContract application ID
platformstring"openai" | "anthropic" | "custom"
POST/api/agent-action

Initiates a payment action. Returns 402 with payment terms on first call (no X-PAYMENT header). Returns 200 with SandboxExport when X-PAYMENT proof is present.

Parameters

senderAddressstringrequiredAlgorand address of the agent
amountnumberMicro-USDC amount (default: 10000 = $0.01)
POST/api/execute

Forwards a SandboxExport to the settlement pipeline. The server verifies factory provenance and submits the signed atomic group on-chain.

Parameters

sandboxExportSandboxExportrequiredFrom agent-action 200 response
agentIdstringrequiredRegistered agent ID
GET/api/telemetry

Returns real-time protocol metrics and recent settlement events for the dashboard.

GET/health

Live status check — Algorand node connectivity, Redis, and system halt state.

GET/agent.json

Full capability manifest for agent discovery (OpenClaw, Moltbook, A2A).

SDK Methods

new AlgoAgentClient(config)
baseUrlstringRequiredx402 server URL
privateKeyUint8ArrayRequired64-byte Algorand Ed25519 secret key
mandateAppIdnumberRequiredMandateContract application ID for this agent
slippageBipsnumberOptionalSlippage tolerance (default: 50 = 0.5%)
maxRetriesnumberOptionalMax handshake retries (default: 2)
onProgressfunctionOptionalProgress callback (stage, message)
client.executeTrade(params)
senderAddressstringRequiredYour Algorand address
amountnumberOptionalMicro-USDC amount (default: x402 toll)
client.requestSandboxExport(params)

Performs the 402 handshake only. Returns the SandboxExport for inspection before settlement.

client.settle(response)

Forwards a previously obtained SandboxExport to /api/execute.

parseGasInfo(response)

Reads X-Agent-Gas-Status and X-Agent-Gas-Remaining headers. Returns { status, remaining } or null if headers are absent.

responseResponseRequiredFetch Response object from a payment call

Mandates

MandateContracts are on-chain Algorand smart contracts that enforce spend limits at the AVM level — per-transaction cap, 10-minute velocity window, and a 24-hour daily cap. A human operator deploys the contract with the desired limits once. The agent then signs its own pay() calls; the AVM rejects anything that exceeds the caps.

Create mandate

POST /api/agents/:id/mandate/create

Requires human auth via Pera Connect QR scan

Revoke mandate

POST /api/agents/:id/mandate/:mandateId/revoke

Immediately stops autonomous signing

List mandates

GET /api/agents/:id/mandates

Returns active mandates and usage stats

Issue approval token

POST /api/agents/:id/mandate/approval-token

Short-lived token for one-off approvals

Mandate governance uses Pera Connect (scan WalletConnect QR with Pera or Defly). Your wallet signature authorises the mandate on-chain — no email or password required.

Rate Limits

LimitValueScope
Request rate100 req / minPer IP (sliding window)
Burst cap5 executions / 10sPer agent
Velocity cap$50 USDC / 10 minPer agent (configurable)
Nonce window60 secondsReplay protection
402 expiry5 minutesPayment proof validity

Rate limit responses return HTTP 429. Back off exponentially and retry after 60 seconds. Velocity cap breaches return HTTP 402 with velocityCapped: true in the body.

Types

typescript
import type {
  TradeParams,
  TradeResult,
  SettlementResult,
  SettlementFailure,
  SandboxExport,
  PayJson,
} from "@algo-wallet/x402-client";

Error Handling

StatusMeaningAction
402Payment requiredComplete the handshake — attach X-PAYMENT header
401Replay detectedGenerate a fresh toll transaction (new groupId)
400Malformed requestCheck body schema
429Rate limitedBack off exponentially; retry after 60s
500Internal errorCheck detail field; retry after 30s
502Pipeline failureCheck failedStage: validation / auth / sign / broadcast
typescript
import { X402Error, X402ErrorCode } from "@algo-wallet/x402-client";

try {
  const result = await client.executeTrade({ senderAddress: "AAAA...7Q" });
  if ("success" in result) {
    console.log("Settled:", result.settlement.txnId);
  } else {
    console.error("Pipeline failed at:", result.failedStage, result.detail);
  }
} catch (err) {
  if (err instanceof X402Error) {
    switch (err.code) {
      case X402ErrorCode.OFFER_EXPIRED:  // Re-initiate handshake
      case X402ErrorCode.POLICY_BREACH:  // Agent exceeded spending cap
      case X402ErrorCode.NETWORK_ERROR:  // Algorand node unreachable — retry
    }
  }
}

CLI Reference

The @algo-wallet/x402-cli lets you inspect agents, mandates, and transaction history directly from your terminal — no dashboard required.

bash
npm install -g @algo-wallet/x402-cli

Or run without installing: npx @algo-wallet/x402-cli <command>

CommandDescription
x402 healthBackend health — node, Redis, halt state
x402 balance --agent <id>Live ALGO + USDC balance for an agent
x402 agents listList all registered agents with status
x402 mandate list --agent <id>List active mandates for an agent
x402 mandate list --agent <id> --allInclude revoked mandates
x402 history --agent <id>Transaction history (last 20)
x402 history --agent <id> --limit 50Transaction history (custom limit)
x402 gas --agent <id>Gas status — ALGO balance, tx remaining, low/critical flag
bash
# Required env vars
export X402_PORTAL_KEY="your-portal-api-key"   # from /dashboard → API Keys
export X402_API_URL="https://api.ai-agentic-wallet.com"  # default
export X402_NETWORK="testnet"                   # or "mainnet"

# Examples
x402 health
x402 balance --agent my-agent-001
x402 mandate list --agent my-agent-001 --all
x402 history --agent my-agent-001 --limit 50

Claude MCP Integration

The @algo-wallet/x402-mcp MCP server lets Claude Desktop and Claude Code agents pay for API calls autonomously — no payment code required. Claude calls the pay_with_x402 tool and receives weather data, analytics, or any x402-gated resource in return.

bash
npx @algo-wallet/x402-mcp

Add to Claude Desktop config:

json
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "x402-wallet": {
      "command": "npx",
      "args": ["-y", "@algo-wallet/x402-mcp"],
      "env": {
        "ALGO_MNEMONIC": "your 25-word agent mnemonic",
        "X402_AGENT_ID": "your-agent-id",
        "X402_API_URL":  "https://api.ai-agentic-wallet.com"
      }
    }
  }
}

Add to Claude Code (global):

bash
claude mcp add x402-wallet npx @algo-wallet/x402-mcp \
  --env ALGO_MNEMONIC="your 25-word mnemonic" \
  --env X402_AGENT_ID="your-agent-id"
Env varRequiredDescription
ALGO_MNEMONICYes25-word mnemonic of your registered agent wallet
X402_AGENT_IDYesAgent ID registered with the wallet router
X402_API_URLNoAPI base URL (default: https://api.ai-agentic-wallet.com)
X402_PORTAL_KEYNoPortal API key if your server requires portal auth

Performance

Benchmarked on Algorand mainnet with 100 real USDC payments, Poisson arrivals (λ=1.5/s) and 25% burst clusters. Live results: api.ai-agentic-wallet.com/api/benchmark

Metricp50p95p99
x402 handshake549ms1,273ms1,693ms
Settlement9,712ms14,193ms15,694ms
End-to-end10,737ms15,359ms16,899ms

100/100 confirmed · 126.6 tx/min · peak 46 concurrent · $1.00 USDC settled · 2026-03-22