Everything you need to integrate x402-compliant AI-to-AI payments on Algorand.
Algorand wallet holders
Developers / AI agents
New to Algorand?
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)
| Network | USDC ASA ID | Toll | baseUrl |
|---|---|---|---|
| Mainnet | 31566704 | 0.01 USDC (10,000 µUSDC) | api.ai-agentic-wallet.com |
| Testnet | 10458941 | 0.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.
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)
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 + USDCStep 2 — Save the signing key
The server discards the mnemonic immediately. Copy it into your application's environment:
ALGO_MNEMONIC="word1 word2 ... word25" # in your .env fileStep 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.
// 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.
npm install @algo-wallet/x402-client algosdkimport { 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);
}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.
Every payment response includes gas status headers so your agent can monitor its own ALGO balance and alert before it runs dry.
X-Agent-Gas-Status: ok | low | critical
X-Agent-Gas-Remaining: 847 # estimated transactions remaining| Status | Meaning | Threshold |
|---|---|---|
| ok | Sufficient ALGO for many more transactions | ≥ 200,000 µALGO above MBR |
| low | Refuel soon — limited transactions remaining | < 200,000 µALGO above MBR |
| critical | Refuel immediately — may fail soon | < 50,000 µALGO above MBR |
Use parseGasInfo() from the SDK to read these headers automatically:
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/agents/register-mandateRegister 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 IDplatformstring"openai" | "anthropic" | "custom"/api/agent-actionInitiates 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 agentamountnumberMicro-USDC amount (default: 10000 = $0.01)/api/executeForwards a SandboxExport to the settlement pipeline. The server verifies factory provenance and submits the signed atomic group on-chain.
Parameters
sandboxExportSandboxExportrequiredFrom agent-action 200 responseagentIdstringrequiredRegistered agent ID/api/telemetryReturns real-time protocol metrics and recent settlement events for the dashboard.
/healthLive status check — Algorand node connectivity, Redis, and system halt state.
/agent.jsonFull capability manifest for agent discovery (OpenClaw, Moltbook, A2A).
new AlgoAgentClient(config)baseUrlstringRequiredx402 server URLprivateKeyUint8ArrayRequired64-byte Algorand Ed25519 secret keymandateAppIdnumberRequiredMandateContract application ID for this agentslippageBipsnumberOptionalSlippage tolerance (default: 50 = 0.5%)maxRetriesnumberOptionalMax handshake retries (default: 2)onProgressfunctionOptionalProgress callback (stage, message)client.executeTrade(params)senderAddressstringRequiredYour Algorand addressamountnumberOptionalMicro-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 callMandateContracts 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/createRequires human auth via Pera Connect QR scan
Revoke mandate
POST /api/agents/:id/mandate/:mandateId/revokeImmediately stops autonomous signing
List mandates
GET /api/agents/:id/mandatesReturns active mandates and usage stats
Issue approval token
POST /api/agents/:id/mandate/approval-tokenShort-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.
| Limit | Value | Scope |
|---|---|---|
| Request rate | 100 req / min | Per IP (sliding window) |
| Burst cap | 5 executions / 10s | Per agent |
| Velocity cap | $50 USDC / 10 min | Per agent (configurable) |
| Nonce window | 60 seconds | Replay protection |
| 402 expiry | 5 minutes | Payment 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.
import type {
TradeParams,
TradeResult,
SettlementResult,
SettlementFailure,
SandboxExport,
PayJson,
} from "@algo-wallet/x402-client";| Status | Meaning | Action |
|---|---|---|
| 402 | Payment required | Complete the handshake — attach X-PAYMENT header |
| 401 | Replay detected | Generate a fresh toll transaction (new groupId) |
| 400 | Malformed request | Check body schema |
| 429 | Rate limited | Back off exponentially; retry after 60s |
| 500 | Internal error | Check detail field; retry after 30s |
| 502 | Pipeline failure | Check failedStage: validation / auth / sign / broadcast |
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
}
}
}The @algo-wallet/x402-cli lets you inspect agents, mandates, and transaction history directly from your terminal — no dashboard required.
npm install -g @algo-wallet/x402-cliOr run without installing: npx @algo-wallet/x402-cli <command>
| Command | Description |
|---|---|
| x402 health | Backend health — node, Redis, halt state |
| x402 balance --agent <id> | Live ALGO + USDC balance for an agent |
| x402 agents list | List all registered agents with status |
| x402 mandate list --agent <id> | List active mandates for an agent |
| x402 mandate list --agent <id> --all | Include revoked mandates |
| x402 history --agent <id> | Transaction history (last 20) |
| x402 history --agent <id> --limit 50 | Transaction history (custom limit) |
| x402 gas --agent <id> | Gas status — ALGO balance, tx remaining, low/critical flag |
# 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 50The @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.
npx @algo-wallet/x402-mcpAdd to Claude Desktop config:
// ~/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):
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 var | Required | Description |
|---|---|---|
| ALGO_MNEMONIC | Yes | 25-word mnemonic of your registered agent wallet |
| X402_AGENT_ID | Yes | Agent ID registered with the wallet router |
| X402_API_URL | No | API base URL (default: https://api.ai-agentic-wallet.com) |
| X402_PORTAL_KEY | No | Portal API key if your server requires portal auth |
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
| Metric | p50 | p95 | p99 |
|---|---|---|---|
| x402 handshake | 549ms | 1,273ms | 1,693ms |
| Settlement | 9,712ms | 14,193ms | 15,694ms |
| End-to-end | 10,737ms | 15,359ms | 16,899ms |
100/100 confirmed · 126.6 tx/min · peak 46 concurrent · $1.00 USDC settled · 2026-03-22