๐ค๐ต Agentic Payment Service for Open Agent Skills Ecosystem.
agentic-payments-bot is an early-stage TypeScript project in the AI payments / x402 ecosystem, focused on ap2, blockchain, clawdbot, compliance. It currently has 0 GitHub stars and 0 forks, and sits alongside related tools like agentic-payments-bot, sardis, x402-payments-mcp, awesome-molt-ecosystem, piprail, deadline-validator.
A tri-protocol (x402 + AP2 + MPP) agentic payment service for Open Agent Skills Ecosystem (including OpenClaw, Claude Code, Codex, Junie, OpenCode, GitHub Copilot, Gemini CLI, etc.), with web3 & web2 gateway support, EIP-3009 signed stablecoin authorizations (Viem), AWS KMS key management, policy engine compliance, audit trail, and human-in-the-loop confirmation.
agentic-payments-bot is a payment serivce/gateway/bot/agent/assistant with support for and providing of X402, AP2, and MPP server and client, and providing an Open Agent Skills Ecosystem compliant skill, that enables AI agents to autonomously initiate, validate, and execute payments across both blockchain (web3) and traditional (web2) payment rails.
| Capability | Details |
|---|---|
| Triple protocol support | x402 (HTTP 402 + onchain settlement), AP2 (Google's mandate-based agent payments), and MPP (Machine Payments Protocol โ rail-agnostic quote โ invoice โ settle โ receipt lifecycle with content-addressed invoices and signed receipts) |
| Dual role: server + client | Acts as a payment gateway (accepts payments from external agents via x402/AP2/MPP server endpoints) and as a payment client (makes payments to external services via all backends) |
| Web3 transactions | Ethereum, Base, Polygon via Viem โ native ETH and ERC-20 (USDC, etc.) |
| EIP-3009 signing | Full x402 client payment flow: EIP-712 TransferWithAuthorization signed via Viem with a private key decrypted through the configured KMS backend โ the key never leaves the KMS trust boundary |
| Web2 gateways | Stripe, PayPal, Visa Direct, Mastercard Send, Google Pay, Apple Pay |
| Protocol gateways | x402 remote resource payment, AP2 remote mandate submission, MPP remote invoice payment โ paying any service that supports these protocols |
| Key management | Pluggable KMS providers: AWS KMS, OS Keyring (KDE Wallet / GNOME Keyring / macOS Keychain / Windows Credential Manager), D-Bus Secret Service, GnuPG, Local AES-256-GCM |
| Policy engine | Per-tx limits, daily/weekly/monthly aggregates, time-of-day, blacklist/whitelist, currency restrictions |
| Human-in-the-loop | Automatic escalation on policy violations via CLI prompt, chat prompt, or web API |
| Audit trail | Every action logged to SQLite audit_log table + Winston (stdout/stderr/file) |
| Three interfaces | OpenClaw (or other agent) chat, CLI (agentic-payments-bot), REST web API |
| Fully configurable | Single YAML file controls all behavior |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Agent Payments Skill โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโ SERVER SIDE (Accept Payments) โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ External Agents โโโบ x402 Paywall Middleware (HTTP 402 flow) โ โ
โ โ AP2 Mandate Endpoints (mandate lifecycle) โ โ
โ โ MPP Endpoints (quote โ invoice โ settle โ โโโบ Paymentโ โ
โ โ receipt) Execution โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ Chat UI โ โ CLI (term) โ โ Web API โ โ
โ โโโโโโโฌโโโโโโ โโโโโโโโโฌโโโโโโโโ โโโโโโฌโโโโโโ โ
โ โ โ โ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Protocol Router โ โ
โ โ (AI output parser โ PaymentIntent โ routing) โ โ
โ โโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโ โ
โ โ โ โ โ โ โ
โ โโโโโโผโโโโ โโโโโโผโโโโ โโโโโผโโโโโ โโโโโผโโโโโ โโโโโผโโโโโ โ
โ โ web3 โ โ web2 โ โ x402 โ โ ap2 โ โ mpp โ โ
โ โ(Viem) โ โ(Stripe โ โ(remote โ โ(remote โ โ(remote โ โ
โ โ โ โPayPal โ โresourceโ โmandate โ โinvoice โ โ
โ โ โ โVisa MC โ โclient) โ โclient) โ โclient) โ โ
โ โ โ โGPay โ โ โ โ โ โ โ โ
โ โ โ โAPay) โ โ โ โ โ โ โ โ
โ โโโโโโฌโโโโ โโโโโฌโโโโโ โโโโโฌโโโโโ โโโโโฌโโโโโ โโโโโฌโโโโโ โ
โ โ โ โ โ โ โ
โ โโโโโโผโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโผโโโโโ โ
โ โ Policy Engine โ โ
โ โ (compliance checks before execution) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โข Single tx limit โข Blacklist โ โ โ
โ โ โ โข Daily/Weekly/Mo โข Whitelist โ โ โ
โ โ โ โข Time-of-day โข Currency โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ (violation?) โโโบ Human Confirm โ โ
โ โโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โ โ Payment Execution โ โ KMS Provider โ โ
โ โ โโโโโโโโโโ โโโโโโโโโโ โโโโโโโโโโ โโโโโโโโ โ โ โโโโโโโโโโโโโ โ โ
โ โ โ Viem โ โ Stripe โ โ Visa โ โ x402 โ โ โ โ AWS KMS โ โ โ
โ โ โ(ETH/ โ โ PayPal โ โ MC โ โ AP2 โ โ โ โ OS Keyringโ โ โ
โ โ โ ERC20/ โ โ GPay โ โ โ โ MPP โ โ โ โ D-Bus SS โ โ โ
โ โ โ EIP- โ โ APay โ โ โ โ โ โโโโ โ GnuPG โ โ โ
โ โ โ 3009) โ โ โ โ โ โ โ โ โ โ Local AES โ โ โ
โ โ โโโโโโโโโโ โโโโโโโโโโ โโโโโโโโโโ โโโโโโโโ โ โ โโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ SQLite โ โ
โ โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ โ
โ โ โencrypted_keysโ โtransac- โ โaudit_log โ โ โ
โ โ โ โ โtions โ โ โ โ โ
โ โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
agentic-payments-bot/
โโโ SKILL.md # Open Agent Skills Ecosystem compliant skill definition (YAML frontmatter + markdown)
โโโ package.json # npm package manifest
โโโ tsconfig.json # TypeScript compiler config
โโโ .env.example # Environment variable template
โโโ .gitignore
โโโ config/
โ โโโ default.yaml # Master YAML configuration
โโโ src/
โ โโโ index.ts # Main entry point / orchestrator
โ โโโ cli.ts # CLI interface (Commander.js)
โ โโโ web-api.ts # REST API (Express) โ includes x402/AP2 server endpoints
โ โโโ config/
โ โ โโโ loader.ts # YAML config loader + Zod validation
โ โโโ protocols/
โ โ โโโ router.ts # Protocol router + AI output parser
โ โ โโโ x402/
โ โ โ โโโ client.ts # x402 HTTP 402 client (paying for resources)
โ โ โ โโโ eip3009.ts # EIP-3009 TransferWithAuthorization signer (EIP-712 via Viem)
โ โ โ โโโ server.ts # x402 paywall middleware & settlement (accepting payments)
โ โ โโโ ap2/
โ โ โ โโโ client.ts # AP2 mandate-based client (submitting mandates)
โ โ โ โโโ server.ts # AP2 mandate lifecycle server (processing mandates)
โ โ โโโ mpp/
โ โ โโโ types.ts # MPP shared types (Quote, Invoice, SettleRequest, Receipt)
โ โ โโโ client.ts # MPP client (quote โ invoice โ settle โ receipt)
โ โ โโโ server.ts # MPP server (content-addressed invoices, signed receipts, rail dispatch)
โ โโโ payments/
โ โ โโโ web3/
โ โ โ โโโ ethereum.ts # Viem-based ETH/ERC-20 tx producer
โ โ โโโ web2/
โ โ โโโ gateways.ts # Stripe, PayPal, Visa, MasterCard, Google Pay, Apple Pay
โ โโโ kms/
โ โ โโโ provider.ts # KmsProvider interface (shared contract)
โ โ โโโ factory.ts # Provider factory (selects backend from config)
โ โ โโโ aws-kms.ts # Public API: encryptAndStore / retrieveAndDecrypt
โ โ โโโ aws-kms-provider.ts # AWS KMS provider implementation
โ โ โโโ os-keyring-provider.ts # OS Keyring via @aspect-build/keytar
โ โ โโโ dbus-secret-service-provider.ts # Linux D-Bus Secret Service (dbus-next)
โ โ โโโ gpg-provider.ts # GnuPG encryption for headless Linux
โ โ โโโ local-aes-provider.ts # Local AES-256-GCM (fallback / dry-run)
โ โโโ dry-run/
โ โ โโโ crypto.ts # Local AES-256-GCM encryption (no KMS)
โ โ โโโ stubs.ts # Gateway stub responses (success/failure/random)
โ โ โโโ wallet.ts # Viem key generation + local encrypt/store
โ โโโ db/
โ โ โโโ sqlite.ts # SQLite init + migrations
โ โ โโโ key-store.ts # Encrypted key CRUD
โ โ โโโ transactions.ts # Transaction records + aggregates
โ โ โโโ audit.ts # Audit trail read/write
โ โโโ policy/
โ โ โโโ engine.ts # Policy rule evaluator
โ โ โโโ feedback.ts # Human confirmation (CLI/chat/API)
โ โโโ logging/
โ โโโ logger.ts # Winston multi-transport logger
โโโ data/ # (created at runtime)
โ โโโ payments.db # SQLite database
โโโ logs/ # (created at runtime)
โโโ payment-skill.log # File log output
User/Agent input
โ
โผ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ
โ Parse AI Output โโโโโโบโ Validate JSON Schema โ
โ (regex + JSON) โ โ (Zod PaymentIntent) โ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Protocol Router โ
โ (detect gateway: โ
โ web3/web2/x402/ โ
โ ap2/mpp) โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Create Transaction โ
โ Record (SQLite) โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโ
โ Policy Engine โโโโ rules from YAML
โ โข limits check โโโโ aggregates from SQLite
โ โข blacklist/whitelist โ
โ โข time restrictions โ
โโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ
โโโโโโโโโดโโโโโโโโโ
โ violations? โ
โโโโโฌโโโโโโโโโฌโโโโ
yes โ โ no
โผ โ
โโโโโโโโโโโโโโโโโ โ
โ Human Confirm โ โ
โ (CLI/Chat/API)โ โ
โโโโโโโโโฌโโโโโโโโ โ
reject โ confirm โ
โผ โ โโโโโโโโโ
REJECT โ โ
โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Decrypt Keys (KMS) โ
โโโโโโโโโโโฌโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโ
โ โ โ
โโโโโโโโโโผโโโโโโโ โโโโโโโโผโโโโโโโ โโโโโโโโโผโโโโโโโโ
โ web3 (Viem) โ โ web2 โ โ Protocol โ
โ ETH / ERC-20 โ โ Stripe โ โ Clients โ
โ โ โ PayPal โ โ โ
โ Direct chain โ โ Visa / MC โ โ x402: discoverโ
โ transactions โ โ GPay / APay โ โ โ sign EIP- โ
โ โ โ โ โ 3009 (KMS key)โ
โ โ โ โ โ โ pay โ
โ โ โ โ โ โ get resourceโ
โ โ โ โ โ โ
โ โ โ โ โ AP2: mandate โ
โ โ โ โ โ โ sign โ cred โ
โ โ โ โ โ โ submit โ
โ โ โ โ โ โ
โ โ โ โ โ MPP: quote โ
โ โ โ โ โ โ invoice โ
โ โ โ โ โ โ settle(rail)โ
โ โ โ โ โ โ receipt โ
โโโโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โโโโโโโโโฌโโโโโโโโ
โ โ โ
โโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโผโโโโโโโโโโโโ
โ Update Transaction โ
โ + Audit Log โ
โโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ External Agent Request โ
โโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโ
โ โ โ
x402 path โ โ AP2 path โ MPP path
โโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GET /x402/premium/data โ โ POST /ap2/mandates โ โ POST /mpp/quote โ
โ (any paywall route) โ โ (accept mandate) โ โ (issue quote) โ
โโโโโโโโโโโโโฌโโโโโโโโโโโโโ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ โ โ
โโโโโโโโดโโโโโโโ โผ โผ
โ X-PAYMENT โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ header? โ โ POST /ap2/sign-mandate โ โ POST /mpp/invoice โ
โโโโฌโโโโโโโฌโโโโ โ (credential provider) โ โ (content-addressed, โ
no โ โ yes โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ โ signed invoice) โ
โผ โ โ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโ โผ โ
โ HTTP 402 โโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โผ
โ + payment โโ โ POST /ap2/payment-credentialsโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ requirem. โโ โ (issue scoped tokens) โ โ POST /mpp/settle โ
โ in X-PAY- โโ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโ โ (rail: x402 / stripe / โ
โ MENT hdr โโ โ โ paypal / card / crypto) โ
โโโโโโโโโโโโโโโ โผ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โผ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโ โ POST /ap2/process-payment โ โผ
โ Validate payload: โ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โข auth fields โ โ โ GET /mpp/receipt/:id โ
โ โข EIP-3009 signed โ โ โ (signed receipt) โ
โ authorization โ โ โโโโโโโโโโโโโโฌโโโโโโโโโโโโ
โ โข amount โฅ required โ โ โ
โ โข time bounds โ โ โ
โ โข payTo matches โ โ โ
โโโโโโโโโโโโฌโโโโโโโโโโโ โ โ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Submit to on-chain โ โ Route to internal backend: โ โ Settle on chosen rail: โ
โ facilitator for โ โ โข stripe โข paypal โข card โ โ โข x402 โ facilitator โ
โ settlement โ โ โข crypto (Viem ETH/ERC-20) โ โ โข stripe/paypal/card โ
โโโโโโโโโโโโฌโโโโโโโโโโโ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ โ โข crypto (tx reference) โ
โ โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโ
โผ โผ โ
โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ HTTP 200 โ โ Return AP2PaymentResult: โ โผ
โ + resource data โ โ { mandate_id, status, โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ + X-PAYMENT-RESPONSEโ โ transaction_id, receipt } โ โ Return MPPReceipt: โ
โ (settlement proof)โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ โ { receipt_id, status, โ
โโโโโโโโโโโโฌโโโโโโโโโโโ โ โ rail_reference, sig } โ
โ โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโผโโโโโโโโโโโ
โ Audit Log (SQLite โ
โ + Winston) โ
โโโโโโโโโโโโโโโโโโโโโโโ
A quick start guide with Docker and Docker Compose.
Quick start (dry-run, no credentials needed):
# Build and start both services
DRY_RUN=true docker compose up --build -d
# Start everything (first run auto-configures OpenClaw + installs skill)
docker compose up -d
# Or explicitly run skill installation first
docker compose --profile setup run --rm install-skill
docker compose up -d
# Check the payment API health
curl http://localhost:3402/api/v1/health
# Run the demo via the CLI helper
DRY_RUN=true docker compose run --rm cli demo
# Run CLI commands
docker compose run --rm --profile cli cli demo --stub-mode success
# Quick dry-run test
DRY_RUN=true docker compose up -d
# Check logs
docker compose logs -f agentic-payments-bot
# View audit log
DRY_RUN=true docker compose run --rm cli audit --limit 30
# Store a key via CLI
DRY_RUN=true docker compose run --rm cli keys list
Production (with real credentials):
# Create a .env file with your secrets
cat > .env <<EOF
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
AWS_KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/...
LLM_PROVIDER=anthropic
LLM_API_KEY=sk-ant-...
OPENCLAW_GATEWAY_TOKEN=your-gateway-token
EOF
# Start
docker compose up --build -d
# Tail logs
docker compose logs -f agentic-payments-bot
# Stop
docker compose down
Pair OpenClaw with a messaging channel (e.g. Telegram):
# Run the OpenClaw CLI inside the running container
docker compose exec agentic-payments-bot openclaw pairing approve telegram
| Container | Service | Port | Description |
|---|---|---|---|
agentic-payments-bot |
Payment Bot Web API (npm run web) |
3402 |
REST API for payments, parsing, confirmations, audit |
agentic-payments-bot |
OpenClaw Gateway (openclaw gateway) |
18789 |
Agent gateway (Telegram, Slack, WhatsApp, etc.) |
agentic-payments-bot |
OpenClaw Bridge (openclaw) |
18790 |
Internal bridge for multi-channel routing |
agentic-payments-bot |
CLI (on-demand) (npm run cli) |
โ | Runs agentic-payments-bot CLI commands against the shared SQLite DB |
Both services share the same SQLite database and encrypted key store through Docker volumes [1]. The payment skill is auto-registered as an OpenClaw skill via the symlink into ~/.openclaw/skills/ [2], so the agent discovers it at startup through the standard skill loading mechanism.
x402 is an open payment protocol built by Coinbase that revives the HTTP
402 Payment Required status code for internet-native stablecoin payments. It is stateless,
HTTP-native, and developer-friendly.
The skill implements x402 in both directions โ as a client (paying for resources) and as a server (accepting payments from external agents).
When the skill needs to pay for an x402-protected resource (e.g., a premium API endpoint):
GET request to a resource URL. If 402 is returned, the
response body (or X-PAYMENT header) contains payment details: scheme, network, amount,
payTo, asset, and maxTimeoutSeconds.transferWithAuthorization using the wallet's
private key (decrypted from KMS) via Viem. The signed payload is Base64-encoded and sent as
the X-PAYMENT header on a retried GET request.200 OK response is returned with the resource and an X-PAYMENT-RESPONSE
header containing the settlement receipt (including txHash).Trigger: Set gateway: "x402" in the PaymentIntent, or use a URL as the recipient with
protocol: "x402". The protocol router will automatically detect this and route to the x402
client.
When the skill acts as a payment provider that accepts x402 payments from external agents:
x402Paywall Express middleware. When an agent
requests a resource without an X-PAYMENT header, the server responds with HTTP 402 and
includes payment requirements in the X-PAYMENT response header (Base64-encoded JSON).X-PAYMENT request header containing a
signed payment payload, the middleware validates the authorization fields (amount, recipient,
time bounds) and submits the payload to the on-chain facilitator for settlement.X-PAYMENT-RESPONSE
header with the settlement receipt and passes the request through to the actual resource
handler.Server endpoints:
| Endpoint | Method | Description |
|---|---|---|
/api/v1/x402/premium/data |
GET | Example paywall-protected resource |
/api/v1/x402/pricing |
GET | List all registered x402-priced resources |
/api/v1/x402/verify |
POST | Verify a settlement transaction hash |
Supported networks: Ethereum Mainnet, Base, Polygon (configurable).
Supported assets: USDC (default), any ERC-20 with known contract addresses.
Reference: x402 GitHub ยท x402 Docs ยท ERC-8004 Spec
AP2 is Google's open protocol for AI agent-driven payments. It uses cryptographically signed Mandates โ verifiable credentials that capture user intent and constraints โ to enable agents to transact on behalf of humans.
The skill implements AP2 in both directions โ as a client (submitting mandates to external services) and as a server (accepting and processing mandates from external agents).
AP2 Mandate Types:
| Mandate | Purpose |
|---|---|
| IntentMandate | Captures the user's initial intent (e.g., "buy running shoes under $100") with a max spend ceiling. Signed by the user. |
| CartMandate | Locks a specific cart of items and price. Created after the agent finds products. |
| PaymentMandate | Authorizes actual payment execution. Contains payment method reference and final amount. |
When the skill needs to pay an external AP2-compliant service:
PaymentIntent, the skill constructs an AP2 mandate with intent
details, amount constraints, validity window, and delegator info.Trigger: Set gateway: "ap2" in the PaymentIntent, or use a URL as the recipient with
protocol: "ap2". The protocol router will automatically detect this and route to the AP2
client.
When the skill acts as a payment provider that accepts AP2 mandates from external agents:
POST a mandate to /api/v1/ap2/mandates. The server
validates the mandate structure, constraints, and expiry./api/v1/ap2/sign-mandate
(credential provider role)./api/v1/ap2/payment-credentials./api/v1/ap2/process-payment. The server routes the payment to the appropriate internal
backend (Stripe, PayPal, Viem, etc.) and returns the result.Server endpoints:
| Endpoint | Method | Description |
|---|---|---|
/api/v1/ap2/mandates |
POST | Accept a new mandate from an agent |
/api/v1/ap2/mandates |
GET | List all mandates |
/api/v1/ap2/mandates/:id |
GET | Get mandate status |
/api/v1/ap2/sign-mandate |
POST | Sign a mandate (credential provider) |
/api/v1/ap2/payment-credentials |
POST | Issue tokenized payment credentials |
/api/v1/ap2/process-payment |
POST | Execute mandate against internal payment backends |
Supported payment methods: Card (Visa/MC via gateway), PayPal, Stripe, Crypto (transparently routed through the appropriate web2/web3 backend).
Reference: AP2 Specification ยท Google Announcement
MPP (Machine Payments Protocol) is a HTTP-native, rail-agnostic payment protocol designed for autonomous agents. It composes on top of existing rails (x402 on-chain authorizations, Stripe/PayPal fiat, card tokens, raw crypto tx hashes) via a uniform quote โ invoice โ settle โ receipt lifecycle with content-addressed invoices and signed receipts.
The skill implements MPP in both directions โ as a client (paying any MPP endpoint) and as a server (exposing paywall resources via MPP to external agents).
| Step | Endpoint | Who calls | Purpose |
|---|---|---|---|
| 1 โ Quote | POST /mpp/quote |
Client (agent) | Ask the merchant what it costs and which rails are accepted |
| 2 โ Invoice | POST /mpp/invoice |
Client (agent) | Receive a content-addressed, signed invoice binding the quote |
| 3 โ Settle | POST /mpp/settle |
Client (agent) | Pay via the chosen rail (x402 EIP-3009 auth, Stripe token, etc.) |
| 4 โ Receipt | GET /mpp/receipt/:id |
Client (agent) | Fetch (or verify) the signed settlement receipt |
Invoice IDs are sha256(canonicalize(body)) which makes them tamper-evident
and safe to pin or cache.
Agent Merchant (this service)
โ โ
โโโ POST /mpp/quote โโโโโโโโโโโโโโโโโโโโโโโโโโโบโ
โโโโ 200 MPPQuote (price, accepted_rails) โโโโโโ
โ โ
โโโ POST /mpp/invoice {quote_id} โโโโโโโโโโโโโโบโ
โโโโ 201 MPPInvoice (rail, pay_to, signature) โ
โ โ
โ [build rail-specific payload: โ
โ โข x402 โ EIP-3009 TransferWithAuth โ
โ โข stripe โ payment-method token โ
โ โข crypto โ tx hash ] โ
โ โ
โโโ POST /mpp/settle {invoice_id, rail, ...} โโบโ
โ โโโ [settle on rail]
โโโโ 200 MPPReceipt (status, rail_reference) โโโ
โ โ
โโโ GET /mpp/receipt/:invoice_id โโโโโโโโโโโโโโบโ
โโโโ 200 MPPReceipt (signed) โโโโโโโโโโโโโโโโโโโ
When the skill needs to pay an external MPP-compliant service:
POST /mpp/quote with the intent's amount, currency, and
description. The merchant returns MPPQuote listing accepted rails,
pay-to address (for on-chain rails), and expiry.POST /mpp/invoice with the quote_id. The merchant issues
an MPPInvoice with rail, amount, network, asset, pay_to, and a
content-addressed invoice_id.rail: "x402", the client decrypts the wallet private key through the
configured KMS backend (AWS KMS / OS Keyring / D-Bus / GPG / Local AES) and
signs an EIP-3009 TransferWithAuthorization via Viem. For fiat rails, a
tokenized payment method is attached.POST /mpp/settle with the rail payload.MPPReceipt; the client stores
the receipt_id and rail_reference (tx hash, payment intent id, etc.)
as the transaction's settlement proof.Trigger: set gateway: "mpp" in the PaymentIntent, or use an MPP URL as
the recipient with protocol: "mpp". The protocol router auto-detects both.
Example intent:
{
"protocol": "mpp",
"action": "pay",
"amount": "1.00",
"currency": "USDC",
"recipient": "https://merchant.example.com/mpp",
"network": "base",
"gateway": "mpp",
"description": "Pay 1 USDC via MPP",
"metadata": {
"payment_method_type": "x402"
}
}
In dry-run mode, the MPP client flow is fully stubbed โ no real HTTP requests or on-chain transactions are made.
Four endpoints implement the full MPP lifecycle. Every issued invoice is
content-addressed (invoice_id = sha256(canonical_body)) and every receipt
is signed with the server's MPP signing secret (protocols.mpp.signing_secret
in config, or MPP_SIGNING_SECRET env var).
Server endpoints:
| Endpoint | Method | Description |
|---|---|---|
/api/v1/mpp/quote |
POST | Issue a quote (price + accepted rails) |
/api/v1/mpp/invoice |
POST | Issue a content-addressed signed invoice from a quote |
/api/v1/mpp/settle |
POST | Settle an invoice via the chosen rail |
/api/v1/mpp/receipt/:invoiceId |
GET | Fetch the signed receipt |
/api/v1/mpp/invoices/:invoiceId |
GET | Fetch the invoice + status |
/api/v1/mpp/invoices |
GET | List issued invoices (admin/debug) |
The rail field on an invoice tells the server how to settle it. Each
rail has a well-defined payload shape:
| Rail | payload shape |
Underlying backend |
|---|---|---|
x402 |
{ "x402Payload": { ...X402PaymentPayload } } |
Submitted to the x402 facilitator (EIP-3009 on-chain settlement) |
stripe |
{ "token": "tok_...", "token_provider": "stripe" } |
Routed through executeWeb2Payment("stripe", ...) |
paypal |
{ "token": "tok_...", "token_provider": "paypal" } |
Routed through executeWeb2Payment("paypal", ...) |
card |
{ "token": "tok_...", "token_provider": "stripe" } |
Same as stripe (generic card via Stripe) |
crypto |
{ "txHash": "0x...", "network": "base" } |
Client-broadcast on-chain tx; server records the reference |
Security note: the settle endpoint always re-checks invoice expiry, rail match, and single-use semantics before touching any rail. The facilitator URL, Stripe/PayPal keys, and MPP signing secret are loaded through the pluggable KMS backend โ nothing is logged in plaintext.
The protocol router (src/protocols/router.ts) is the entry point for all payment requests. It:
PaymentIntent from free-form AI text using multiple
strategies:```json ... ```)``` ... ```)"protocol" fieldgateway field (if provided): viem, stripe, paypal, visa, mastercard,
googlepay, applepay, x402, ap2, or mpphttp:// or https://):protocol: "x402" + URL recipient โ x402 remote resource paymentprotocol: "ap2" + URL recipient โ AP2 remote mandate submissionprotocol: "mpp" + URL recipient โ MPP remote invoice paymentRouting matrix:
Key distinction: The
protocolfield (x402/ap2/mpp) is a metadata tag classifying the payment's flavour โ it does NOT determine execution. Thegatewayfield is the routing key that selects the execution backend.
| Gateway Value | Payment Type | Description |
|---|---|---|
viem |
web3 |
Direct ETH/ERC-20 transfer via Viem |
stripe |
web2 |
Stripe Payment Intents |
paypal |
web2 |
PayPal Orders API |
visa |
web2 |
Visa Direct Push Payments |
mastercard |
web2 |
Mastercard Send API |
googlepay |
web2 |
Google Pay token processing |
applepay |
web2 |
Apple Pay token processing |
x402 |
x402 |
Outbound x402 client โ discover โ sign โ pay โ access an external x402-protected resource |
ap2 |
ap2 |
Outbound AP2 client โ create mandate โ sign โ get credentials โ submit to external AP2 service |
mpp |
mpp |
Outbound MPP client โ quote โ invoice โ settle โ receipt against an external MPP endpoint |
Auto-detection when gateway is omitted:
recipient + protocol: "x402" โ gateway x402recipient + protocol: "ap2" โ gateway ap2recipient + protocol: "mpp" โ gateway mppUSDC, USDT, ETH, WETH, DAI) or protocol: "x402" โ gateway viemstripeServer-side endpoints (/api/v1/x402/*, /api/v1/ap2/*, /api/v1/mpp/*) are independent
infrastructure โ they allow external agents to pay this service via x402
paywalls or AP2 mandates or MPP invoices. They are not related to the protocol/gateway fields
in the payment intent JSON.
The Viem-based transaction producer (src/payments/web3/ethereum.ts) supports:
| Operation | Function | Details |
|---|---|---|
| Send ETH | sendEth() |
Native ETH transfer on any supported EVM chain |
| Send ERC-20 | sendErc20() |
Token transfer (USDC, USDT, DAI, etc.) using transfer() ABI |
| Wait for confirmation | waitForConfirmation() |
Polls for on-chain receipt |
Supported chains (configurable via YAML):
| Chain | Chain ID | Default RPC |
|---|---|---|
| Ethereum Mainnet | 1 | https://mainnet.infura.io/v3/... |
| Base | 8453 | https://mainnet.base.org |
| Polygon | 137 | https://polygon-rpc.com |
Well-known USDC addresses are built-in per chain. Custom token addresses can be passed directly.
Uses the official Stripe Node.js SDK.
PaymentIntent via stripe.paymentIntents.create()Uses PayPal's REST Checkout API v2.
POST /v2/checkout/ordersUses Visa Direct Push Funds Transfer API.
POST /visadirect/fundstransfer/v1/pushfundstransactionsUses Mastercard Send Transfer API.
POST /send/v1/partners/transfers/paymentUses the Google Pay API for server-side payment token processing.
metadata.paymentTokenPAN_ONLY and CRYPTOGRAM_3DS authentication methodsTEST and PRODUCTIONRequired metadata fields:
| Field | Required | Description |
|---|---|---|
paymentToken |
โ | Encrypted payment token from the Google Pay JS API client |
countryCode |
โ | ISO 3166-1 alpha-2 country code (default: US) |
Uses the Apple Pay API for server-side merchant validation and payment token processing.
metadata.paymentTokenmetadata.validationURL is provided)Required metadata fields:
| Field | Required | Description |
|---|---|---|
paymentToken |
โ | Encrypted payment token from the Apple Pay JS API client |
validationURL |
โ | Apple's merchant validation URL (for session validation step) |
The x402 client (src/protocols/x402/client.ts) is integrated as a payment backend alongside
Viem, Stripe, PayPal, etc. When the protocol router determines the payment should go through x402
(e.g., the recipient is a URL of an x402-protected resource), the orchestrator invokes the full
x402 client flow:
GET the resource URL. If 402 is returned, parse payment requirements from
the X-PAYMENT header or response body.GET the resource with the signed X-PAYMENT header.X-PAYMENT-RESPONSE.Trigger: Set gateway: "x402" in the PaymentIntent, or use a URL as the recipient with
protocol: "x402".
Example intent:
{
"protocol": "x402",
"action": "pay",
"amount": "1.00",
"currency": "USDC",
"recipient": "https://api.example.com/premium/data",
"network": "base",
"gateway": "x402"
}
In dry-run mode, the x402 client flow is fully stubbed โ no real HTTP requests or on-chain transactions are made. The stub returns simulated settlement responses.
The AP2 client (src/protocols/ap2/client.ts) is integrated as a payment backend for paying
any AP2-compliant external service. When the protocol router determines the payment should go
through AP2 (e.g., the recipient is a URL of an AP2 payment processor), the orchestrator invokes
the full AP2 client flow:
PaymentIntent with intent details, amount
constraints, validity window, and delegator info.Trigger: Set gateway: "ap2" in the PaymentIntent, or use a URL as the recipient with
protocol: "ap2".
Example intent:
{
"protocol": "ap2",
"action": "pay",
"amount": "49.99",
"currency": "USD",
"recipient": "https://merchant.example.com/ap2/process-payment",
"gateway": "ap2",
"description": "Premium subscription",
"metadata": {
"payment_method_type": "stripe"
}
}
In dry-run mode, the AP2 client flow is fully stubbed โ no real HTTP requests are made. The stub returns simulated mandate and payment responses.
The MPP client (src/protocols/mpp/client.ts) is integrated as a payment
backend. When the protocol router determines the payment should go through
MPP (e.g., the recipient is an MPP endpoint URL), the orchestrator invokes
the full four-step flow:
POST /mpp/quote.POST /mpp/invoice.POST /mpp/settle.rail: "x402", the wallet private key is decrypted through the
configured KMS backend (AWS KMS / OS Keyring / D-Bus / GPG / Local AES)
and a fresh EIP-3009 TransferWithAuthorization is signed via Viem.rail: "stripe" | "paypal" | "card", a tokenized payment method is
attached.MPPReceipt.Trigger: set gateway: "mpp" or use an MPP URL as recipient with
protocol: "mpp".
In dry-run mode the whole MPP flow is stubbed โ no real HTTP requests are made.
The skill uses a pluggable KMS (Key Management System) provider architecture for all secret management. Every sensitive credential โ web3 wallet private keys (Viem), API tokens (Stripe, PayPal, Visa, Mastercard, Google Pay, Apple Pay), and authentication secrets โ flows through a single pair of functions:
| Function | Description |
|---|---|
encryptAndStore(keyAlias, keyType, plaintext) |
Encrypt and persist a secret |
retrieveAndDecrypt(keyAlias) |
Fetch and decrypt a secret for use |
All payment consumers (ethereum.ts, gateways.ts, cli.ts) call these same
two functions regardless of which KMS backend is active. Plaintext values are
never logged or persisted.
The kms.provider configuration field selects which backend handles secret
encryption and storage:
| Provider | Config Value | Description | Platforms |
|---|---|---|---|
| AWS KMS | aws-kms |
Cloud HSM-backed encryption via AWS Key Management Service. Ciphertext stored in SQLite. | All (requires AWS credentials) |
| OS Keyring | os-keyring |
OS-native keyring integration via @aspect-build/keytar. Secrets stored in the platform's native credential store. |
Linux (KDE Wallet / GNOME Keyring), macOS (Keychain), Windows (Credential Manager) |
| D-Bus Secret Service | dbus-secret |
Linux-only pure JavaScript client for the freedesktop.org Secret Service API via dbus-next. No native compilation required. |
Linux (GNOME Keyring, KDE Wallet with Secret Service bridge) |
| GnuPG | gpg |
Asymmetric encryption via gpg2 CLI. Ideal for headless Linux servers without a desktop session. Ciphertext stored in SQLite. |
Linux, macOS, Windows (gpg4win) |
| Local AES | local-aes |
Local AES-256-GCM symmetric encryption. Key sourced from an environment variable (auto-generated if missing). Ciphertext stored in SQLite. | All (zero external dependencies) |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ KMS Provider Selection Logic โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ config.kms.provider = ? โ
โ โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ "aws-kms" โ AwsKmsProvider โโ
โ โ โ โ AWS KMS encrypt/decrypt + SQLite ciphertext โโ
โ โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโคโ
โ โ "os-keyring" โ if Linux: โโ
โ โ โ linux_keyring_backend = "keytar"? โโ
โ โ โ โ OsKeyringProvider (@aspect-build/keytar) โโ
โ โ โ linux_keyring_backend = "dbus-next"? โโ
โ โ โ โ DbusSecretServiceProvider (dbus-next) โโ
โ โ โ if macOS / Windows: โโ
โ โ โ โ OsKeyringProvider (@aspect-build/keytar) โโ
โ โ โ โ auto-fallback โ LocalAesProvider if headless โโ
โ โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโคโ
โ โ "dbus-secret" โ DbusSecretServiceProvider (dbus-next, Linux only) โโ
โ โ โ โ auto-fallback โ LocalAesProvider if headless โโ
โ โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโคโ
โ โ "gpg" โ GpgProvider (gpg2 CLI) โโ
โ โ โ โ GPG encrypt/decrypt + SQLite ciphertext โโ
โ โ โ Requires gpg_key_id in config โโ
โ โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโคโ
โ โ "local-aes" โ LocalAesProvider โโ
โ โ โ โ AES-256-GCM + SQLite ciphertext โโ
โ โ โ Key from env var (auto-generated if missing) โโ
โ โโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ dry_run.enabled = true? โ
โ โ Always uses local AES (bypasses provider entirely) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Uses AWS KMS
for HSM-backed encryption. Ciphertext blobs are stored in the encrypted_keys
SQLite table.
Configuration:
kms:
enabled: true
provider: "aws-kms"
region: "us-east-1"
key_id_env: "AWS_KMS_KEY_ID"
Required environment variables:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_KMS_KEY_ID (KMS key ARN or alias)AWS_SESSION_TOKEN (optional, for temporary credentials)Important: AWS credentials are only loaded from environment variables. They are never stored in configuration files or the database.
Integrates with the operating system's native credential store using
@aspect-build/keytar (a maintained
fork of Atom's keytar). Secrets are managed directly by the OS โ no ciphertext
is stored in SQLite.
| Platform | Backend | Notes |
|---|---|---|
| Linux (KDE) | KDE Wallet (KWallet) | Accessed via D-Bus org.kde.KWallet or Secret Service bridge |
| Linux (GNOME) | GNOME Keyring | Accessed via D-Bus org.freedesktop.secrets |
| macOS | Keychain (Security.framework) |
Transparent integration |
| Windows | Credential Manager (DPAPI) | Transparent integration |
Configuration (Linux with keytar):
kms:
enabled: true
provider: "os-keyring"
linux_keyring_backend: "keytar" # native addon
Configuration (Linux with dbus-next, no native compilation):
kms:
enabled: true
provider: "os-keyring"
linux_keyring_backend: "dbus-next" # pure JS
Configuration (macOS / Windows):
kms:
enabled: true
provider: "os-keyring"
# linux_keyring_backend is ignored on non-Linux
Note:
@aspect-build/keytaris a native Node.js addon (C++ / N-API) and requires compilation or prebuilt binaries. If you want to avoid native compilation on Linux, uselinux_keyring_backend: "dbus-next"or thedbus-secretprovider directly.
KDE Wallet compatibility check:
Ensure the Secret Service API is available on your KDE system:
dbus-send --session --print-reply \
--dest=org.freedesktop.secrets \
/org/freedesktop/secrets org.freedesktop.DBus.Peer.Ping
If this fails, enable the KDE Wallet Secret Service integration in System Settings โ KDE Wallet โ Secret Service integration.
A pure JavaScript (zero native compilation) provider that communicates
directly with the freedesktop.org Secret Service API
over D-Bus using dbus-next.
Works with:
kwalletd5/kwalletd6)Configuration:
kms:
enabled: true
provider: "dbus-secret"
This provider can also be selected indirectly:
kms:
enabled: true
provider: "os-keyring"
linux_keyring_backend: "dbus-next" # routes to D-Bus Secret Service
Linux-only. This provider is not available on macOS or Windows.
Uses GnuPG (gpg2) for asymmetric encryption. Ideal
for headless Linux servers and CI/CD environments that have no desktop
session, no D-Bus, and no AWS credentials โ but do have a GPG keypair.
Secrets are encrypted with the public key and stored as ASCII-armored ciphertext
in the encrypted_keys SQLite table. Decryption uses the corresponding private
key from the local GPG keyring. If the private key has a passphrase, gpg-agent
handles the prompt.
Configuration:
kms:
enabled: true
provider: "gpg"
gpg_key_id: "agentic-payments-bot@yourcompany.com" # fingerprint or email
gpg_binary: "gpg2" # path to gpg binary
Setup โ generate a dedicated GPG keypair:
# Generate a key (non-interactive)
gpg2 --batch --gen-key <<EOF
Key-Type: RSA
Key-Length: 4096
Subkey-Type: RSA
Subkey-Length: 4096
Name-Real: Agent Payments
Name-Email: agentic-payments-bot@yourcompany.com
Expire-Date: 2y
%no-protection
%commit
EOF
# Verify it was created
gpg2 --list-keys agentic-payments-bot@yourcompany.com
For Docker / CI: Import the key at container startup:
echo "$GPG_PRIVATE_KEY_BASE64" | base64 -d | gpg2 --batch --import
Symmetric AES-256-GCM encryption using a 256-bit key from an environment variable. Ciphertext stored in SQLite. This is the simplest provider โ zero external dependencies, works everywhere.
Configuration:
kms:
enabled: true
provider: "local-aes"
The encryption key is read from the DRYRUN_ENCRYPTION_KEY environment variable
(64 hex characters = 256 bits). If the variable is missing on first run, a
random key is auto-generated and appended to the .env file.
โ ๏ธ Guard the
.envfile carefully. If you lose the encryption key, previously encrypted entries become unreadable. The.envfile is in.gitignoreby default.
kms:
enabled: true
provider: "os-keyring"
linux_keyring_backend: "keytar"
kms:
enabled: true
provider: "os-keyring"
linux_keyring_backend: "dbus-next"
kms:
enabled: true
provider: "gpg"
gpg_key_id: "agentic-payments-bot@yourcompany.com"
gpg_binary: "gpg2"
kms:
enabled: true
provider: "local-aes"
kms:
enabled: true
provider: "os-keyring"
kms:
enabled: true
provider: "aws-kms"
region: "us-east-1"
key_id_env: "AWS_KMS_KEY_ID"
| AWS KMS | OS Keyring | D-Bus Secret Service | GnuPG | Local AES | |
|---|---|---|---|---|---|
| Encryption | AES-256 (HSM-backed) | OS-managed (DPAPI / Keychain / kernel) | Same as OS Keyring | RSA/ECC asymmetric | AES-256-GCM |
| At-rest storage | SQLite (ciphertext) | OS keyring DB | OS keyring DB | SQLite (ciphertext) | SQLite (ciphertext) |
| Key custody | AWS (cloud HSM) | OS user session | OS user session | Local GPG keyring | Env var / .env file |
| Headless server | โ | โ (needs D-Bus session) | โ (needs D-Bus session) | โ | โ |
| Native addon required | No | Yes (keytar) |
No (pure JS) | No (CLI) | No |
| Linux (KDE) | โ | โ (KWallet) | โ (KWallet bridge) | โ | โ |
| Linux (GNOME) | โ | โ (gnome-keyring) | โ (gnome-keyring) | โ | โ |
| macOS | โ | โ (Keychain) | โ | โ | โ |
| Windows | โ | โ (Credential Manager) | โ | โ (gpg4win) | โ |
| Docker / CI | โ | โ | โ | โ (import keyring) | โ |
| Web3 private key | โ (66 bytes) | โ | โ | โ | โ |
| API tokens | โ | โ | โ | โ | โ |
| AWS KMS | OS Keyring | D-Bus Secret Service | GPG | Local AES | |
|---|---|---|---|---|---|
| Encryption | AES-256 (HSM-backed) | OS-managed (DPAPI/Keychain/kernel) | Same as OS Keyring | RSA/ECC asymmetric | AES-256-GCM |
| At-rest storage | SQLite (ciphertext) | OS keyring DB | OS keyring DB | SQLite (ciphertext) | SQLite (ciphertext) |
| Key custody | AWS (cloud HSM) | OS user session | OS user session | Local GPG keyring | Env var / .env file |
| Headless server | โ | โ (needs D-Bus) | โ (needs D-Bus) | โ | โ |
| Native addon | No | Yes (keytar) | No (pure JS) | No (CLI) | No |
| Linux KDE | โ | โ (KWallet) | โ (KWallet bridge) | โ | โ |
| Linux GNOME | โ | โ (gnome-keyring) | โ (gnome-keyring) | โ | โ |
| macOS | โ | โ (Keychain) | โ | โ | โ |
| Windows | โ | โ (Credential Mgr) | โ | โ (gpg4win) | โ |
| Docker/CI | โ | โ | โ | โ (if keyring imported) | โ |
The OS Keyring and D-Bus Secret Service providers are designed for desktop environments with an active user session. When running on a headless server (no X11 / Wayland, no D-Bus session bus), these providers will automatically fall back to the Local AES provider.
The fallback is logged and audited:
[warn] OS keyring unavailable (headless or missing D-Bus session).
Falling back to local-aes provider.
This means you can safely set provider: "os-keyring" in your default config
and deploy to both desktop and server environments โ the skill will
adapt automatically.
Recommended per-environment configuration:
| Environment | Recommended Provider |
|---|---|
| Developer desktop (Linux KDE/GNOME) | os-keyring (with linux_keyring_backend: "keytar" or "dbus-next") |
| Developer desktop (macOS) | os-keyring |
| Developer desktop (Windows) | os-keyring |
| Production cloud (AWS) | aws-kms |
| Headless Linux server (with GPG) | gpg |
| Headless Linux / Docker (simple) | local-aes |
| CI/CD pipeline | local-aes or aws-kms |
For providers that store ciphertext (AWS KMS, GnuPG, Local AES), the
encrypted_keys table holds the encrypted blobs:
| Column | Type | Description |
|---|---|---|
id |
TEXT PK | UUID |
key_type |
TEXT | web3_private_key, stripe_token, paypal_token, visa_token, mastercard_token, googlepay_token, applepay_token |
key_alias |
TEXT UNIQUE | Human-readable name (e.g., default_wallet, stripe_api_key) |
ciphertext |
BLOB | Encrypted payload |
kms_key_id |
TEXT | Provider identifier: KMS key ARN, gpg:<key_id>, local-aes256, or dryrun-local-aes256 |
created_at |
TEXT | ISO 8601 timestamp |
updated_at |
TEXT | ISO 8601 timestamp |
Note: The OS Keyring and D-Bus Secret Service providers store secrets directly in the OS credential store and do not use the
encrypted_keysSQLite table.
| Variable | Required | Provider | Description |
|---|---|---|---|
AWS_ACCESS_KEY_ID |
โ
(for aws-kms) |
aws-kms |
AWS IAM access key for KMS |
AWS_SECRET_ACCESS_KEY |
โ
(for aws-kms) |
aws-kms |
AWS IAM secret key for KMS |
AWS_SESSION_TOKEN |
โ | aws-kms |
Optional, for temporary credentials / STS |
AWS_KMS_KEY_ID |
โ
(for aws-kms) |
aws-kms |
KMS key ARN or alias (e.g., alias/agentic-payments-bot) |
AWS_REGION |
โ | aws-kms |
Overrides kms.region in config |
DRYRUN_ENCRYPTION_KEY |
โ | local-aes |
256-bit hex key (64 chars). Auto-generated if missing. |
CONFIG_PATH |
โ | All | Override default config file path (for web API) |
โ ๏ธ Never commit secret values to source control. Use a secrets manager,
.envfile with appropriate.gitignore, or container environment injection.
The policy engine (src/policy/engine.ts) acts as a compliance interceptor. It evaluates
every payment intent against a configurable rule set before any real transaction is executed.
| Rule | Config Key | Description |
|---|---|---|
| Single transaction limit | policy.rules.single_transaction.max_amount_usd |
Maximum USD equivalent for any one payment |
| Daily aggregate limit | policy.rules.daily.max_total_usd |
Max total USD in a rolling 24-hour window |
| Daily transaction count | policy.rules.daily.max_transaction_count |
Max number of transactions in 24 hours |
| Weekly aggregate limit | policy.rules.weekly.max_total_usd |
Max total USD in a rolling 7-day window |
| Weekly transaction count | policy.rules.weekly.max_transaction_count |
Max transactions in 7 days |
| Monthly aggregate limit | policy.rules.monthly.max_total_usd |
Max total USD in a rolling 30-day window |
| Monthly transaction count | policy.rules.monthly.max_transaction_count |
Max transactions in 30 days |
| Time-of-day restrictions | policy.rules.time_restrictions |
Restrict payments to specific UTC hours and days of week |
| Blacklist | policy.rules.blacklist |
Block payments to specific addresses/merchant IDs |
| Whitelist | policy.rules.whitelist |
Only allow payments to specific addresses (when enabled) |
| Currency restrictions | policy.rules.allowed_currencies |
Only allow payments in listed currencies |
Aggregate limits are computed against the transactions table in SQLite using rolling windows:
Daily window: NOW - 24 hours โ NOW
Weekly window: NOW - 7 days โ NOW
Monthly window: NOW - 30 days โ NOW
The engine queries:
SELECT COALESCE(SUM(amount_usd), 0) as total_usd, COUNT(*) as count
FROM transactions
WHERE status IN ('executed', 'approved', 'pending', 'awaiting_confirmation')
AND created_at >= ? AND created_at < ?
This ensures that even pending/awaiting-confirmation transactions count toward limits, preventing circumvention by rapid-fire requests.
When a policy violation with severity: "block" is detected and
require_human_confirmation_on_violation is true, the system pauses execution and requests
human confirmation:
| Channel | Behavior |
|---|---|
| CLI | Interactive terminal prompt with violation details. User types yes or no. |
| Chat | Returns a Markdown-formatted confirmation prompt. User replies confirm <txId> or reject <txId>. |
| Web API | Returns HTTP 202 with the tx.id. Client must POST /api/v1/confirm/:txId with {"confirmed": true}. |
Confirmation details logged include:
The skill implements a dual-write audit strategy: structured records in SQLite and multi-target log output via Winston.
Every significant action writes to the audit_log table:
| Column | Type | Description |
|---|---|---|
id |
INTEGER PK | Auto-incrementing |
timestamp |
TEXT | ISO 8601 UTC |
level |
TEXT | info ยท warn ยท error ยท critical |
category |
TEXT | payment ยท policy ยท kms ยท protocol ยท auth ยท system |
action |
TEXT | Specific action identifier (see table below) |
tx_id |
TEXT | Related transaction ID (nullable) |
actor |
TEXT | agent ยท human ยท system ยท cli ยท web_api |
details |
TEXT | JSON payload with full context |
ip_address |
TEXT | Requesting IP (web API only) |
user_agent |
TEXT | HTTP User-Agent (web API only) |
Tracked actions:
| Category | Action | Trigger |
|---|---|---|
system |
skill_bootstrapped |
On startup |
protocol |
intent_routed |
After protocol router decision |
protocol |
x402_payment_submitted |
After x402 client payment sent |
protocol |
ap2_mandate_signed |
After AP2 client mandate signature |
protocol |
ap2_payment_submitted |
After AP2 client payment execution |
x402_server |
payment_required |
x402 server returned 402 to an agent |
x402_server |
payment_settled |
x402 server settled a payment from an agent |
x402_server |
settlement_failed |
x402 server settlement failed |
ap2_server |
mandate_accepted |
AP2 server accepted a mandate from an agent |
ap2_server |
mandate_signed |
AP2 server signed a mandate |
ap2_server |
credentials_issued |
AP2 server issued payment credentials |
ap2_server |
payment_processed |
AP2 server executed a mandate payment |
mpp_server |
quote_issued |
MPP server issued a quote |
mpp_server |
invoice_issued |
MPP server issued a signed invoice |
mpp_server |
invoice_settled |
MPP server settled an invoice and issued a receipt |
protocol |
mpp_quote_received |
MPP client received a quote |
protocol |
mpp_invoice_created |
MPP client received an invoice |
protocol |
mpp_settle_submitted |
MPP client submitted settle request |
payment |
mpp_client_payment_completed |
After MPP client lifecycle completes |
payment |
dryrun_mpp_client_executed |
Dry-run MPP client executed |
payment |
eth_transfer_sent |
After Viem ETH tx broadcast |
payment |
erc20_transfer_sent |
After Viem ERC-20 tx broadcast |
payment |
web3_payment_confirmed |
After on-chain confirmation |
payment |
stripe_intent_created |
After Stripe PaymentIntent |
payment |
paypal_order_created |
After PayPal Order creation |
payment |
visa_payment_submitted |
After Visa Direct push |
payment |
mastercard_payment_submitted |
After MC Send transfer |
payment |
googlepay_payment_processed |
After Google Pay token processed |
payment |
applepay_payment_processed |
After Apple Pay token processed |
payment |
x402_remote_payment_completed |
After x402 client resource access |
payment |
ap2_remote_payment_completed |
After AP2 client mandate submission |
payment |
payment_rejected_by_human |
On human rejection |
payment |
payment_execution_failed |
On any execution error |
policy |
violations_detected |
When rules are violated |
policy |
human_confirmed |
Human approved despite violation |
policy |
human_rejected |
Human rejected |
kms |
key_stored |
New key encrypted and stored |
kms |
key_encrypted_and_stored |
Via encryptAndStore() |
kms |
key_decrypted |
Key decrypted for use |
kms |
key_deleted |
Key removed from store |
Winston is configured with multiple transports (all configurable):
| Transport | Config Key | Default |
|---|---|---|
| Console (stdout) | logging.stdout |
true |
| Console (stderr for errors) | logging.stderr_errors |
true |
| File | logging.file.enabled |
true |
| File path | logging.file.path |
./logs/payment-skill.log |
| Max file size | logging.file.max_size_mb |
50 MB |
| Max file count (rotation) | logging.file.max_files |
10 |
Audit log entries are simultaneously written to both SQLite and Winston, ensuring coverage
even if one subsystem fails. Audit writes use try/catch internally and never crash the
payment flow.
Three tables are created during initialization (src/db/sqlite.ts):
encrypted_keysCREATE TABLE encrypted_keys (
id TEXT PRIMARY KEY,
key_type TEXT NOT NULL,
key_alias TEXT NOT NULL UNIQUE,
ciphertext BLOB NOT NULL,
kms_key_id TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
transactionsCREATE TABLE transactions (
id TEXT PRIMARY KEY,
protocol TEXT NOT NULL, -- 'x402' | 'ap2'
gateway TEXT, -- 'viem' | 'stripe' | 'paypal' | 'visa' | 'mastercard' | 'googlepay' | 'applepay'
action TEXT NOT NULL,
amount REAL NOT NULL,
amount_usd REAL NOT NULL,
currency TEXT NOT NULL,
recipient TEXT NOT NULL,
network TEXT,
status TEXT NOT NULL,
tx_hash TEXT,
error_message TEXT,
policy_violations TEXT, -- JSON array
confirmed_by TEXT, -- 'auto' | 'human'
metadata TEXT, -- JSON
created_at TEXT NOT NULL DEFAULT (datetime('now')),
executed_at TEXT,
completed_at TEXT
);
-- Indexes: idx_transactions_created, idx_transactions_status, idx_transactions_recipient
Transaction statuses:
pending โ policy_check โ awaiting_confirmation โ approved โ executed
โ rejected โ failed
audit_logCREATE TABLE audit_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL DEFAULT (datetime('now')),
level TEXT NOT NULL,
category TEXT NOT NULL,
action TEXT NOT NULL,
tx_id TEXT,
actor TEXT,
details TEXT, -- JSON
ip_address TEXT,
user_agent TEXT
);
-- Indexes: idx_audit_timestamp, idx_audit_tx_id, idx_audit_category
fetch)better-sqlite3, no system dependency needed)aws-kms provider)os-keyring provider)gpg provider on headless Linux)local-aes provider โ zero-dependency fallback)# 1. Clone / copy the skill directory
git clone https://github.com/sentient-agi/agentic-payments-bot.git
cd agentic-payments-bot
# 2. Install dependencies
npm install
# 3. (Optional) Install OS keyring support
# @aspect-build/keytar โ native addon for OS keyring (Linux/macOS/Windows)
npm install @aspect-build/keytar --save-optional
# dbus-next โ pure JS D-Bus client for Linux Secret Service API
npm install dbus-next --save-optional
# 4. Build TypeScript
npm run build
# 5. Configure KMS provider in config/default.yaml (or config/production.yaml)
# See "KMS Provider System" section for all options.
#
# For AWS KMS (default):
export AWS_ACCESS_KEY_ID="your-aws-access-key"
export AWS_SECRET_ACCESS_KEY="your-aws-secret-key"
export AWS_KMS_KEY_ID="arn:aws:kms:us-east-1:123456789012:key/your-key-id"
#
# For OS Keyring โ no env vars needed (just set kms.provider: "os-keyring")
# For Local AES โ no env vars needed (key auto-generates)
# For GPG โ set kms.provider: "gpg" and kms.gpg_key_id in YAML
# 6. Customize configuration
cp config/default.yaml config/production.yaml
# Edit config/production.yaml with your RPC URLs, gateway settings, policy rules
# 7. Store encrypted keys (first-time setup)
npx agentic-payments-bot keys store --alias default_wallet --type web3_private_key --value "0xYOUR_PRIVATE_KEY"
npx agentic-payments-bot keys store --alias stripe_api_key --type stripe_token --value "sk_live_YOUR_STRIPE_KEY"
npx agentic-payments-bot keys store --alias paypal_client_id --type paypal_token --value "YOUR_PAYPAL_CLIENT_ID"
npx agentic-payments-bot keys store --alias paypal_secret --type paypal_token --value "YOUR_PAYPAL_SECRET"
# Google Pay credentials
npx agentic-payments-bot keys store --alias googlepay_merchant_id --type googlepay_token --value "YOUR_GOOGLE_MERCHANT_ID"
npx agentic-payments-bot keys store --alias googlepay_merchant_key --type googlepay_token --value "YOUR_GOOGLE_MERCHANT_KEY"
# Apple Pay credentials
npx agentic-payments-bot keys store --alias applepay_merchant_id --type applepay_token --value "merchant.com.yourapp"
npx agentic-payments-bot keys store --alias applepay_merchant_cert --type applepay_token --value "BASE64_ENCODED_CERT"
npx agentic-payments-bot keys store --alias applepay_merchant_key --type applepay_token --value "BASE64_ENCODED_KEY"
npx agentic-payments-bot keys store --alias applepay_processor_key --type applepay_token --value "YOUR_PROCESSOR_API_KEY"
# 8. Register open agents skill
npx skills add ./agentic-payments-bot
Once installed, activate in your OpenClaw configuration:
{
"skills": {
"allow": ["agentic-payments-bot"]
}
}
The agent will now be able to use the payment skill when it detects payment-related prompts.
Dry-run mode lets you explore every feature of the skill โ protocol routing, policy engine, human-in-the-loop confirmation, audit trail, CLI, and web API โ without any real payments, real blockchain transactions, or AWS credentials.
| Component | Production | Dry-Run |
|---|---|---|
| AWS KMS | Encrypts/decrypts via real KMS API | Bypassed โ local AES-256-GCM with a key from DRYRUN_ENCRYPTION_KEY env var |
| Encryption key | KMS key ARN | 256-bit hex key, auto-generated on first run and written to .env |
| Wallet keys | Viem generatePrivateKey() โ encrypted via KMS |
Viem generatePrivateKey() โ encrypted via local AES โ stored in SQLite |
| Web3 payments | Real on-chain transactions via Viem | Stub: returns fake tx hash, simulated confirmation |
| Web2 payments | Real API calls to Stripe / PayPal / Visa / MC / Google Pay / Apple Pay | Stub: returns fake transaction IDs, simulated status |
| x402 remote payments | Real HTTP to x402 resource, on-chain settlement | Stub: returns fake tx hash and simulated resource data |
| AP2 remote payments | Real HTTP to AP2 mandate issuer + credential provider | Stub: returns fake mandate ID and simulated payment result |
| x402 server (paywall) | Verifies payment and settles via facilitator | Stub: returns simulated settlement success |
| AP2 server (mandates) | Processes mandates against real payment backends | Stubs: routes to stubbed backends (Stripe/PayPal/Viem stubs) |
| Policy engine | โ runs normally | โ runs normally |
| Human confirmation | โ prompts on violations | โ prompts on violations |
| Audit trail | โ writes to SQLite + Winston | โ
writes to SQLite + Winston (tagged with dryrun_* actions) |
| Transaction records | โ stored in SQLite | โ stored in SQLite |
Activation โ Enable via dry_run.enabled: true in YAML, or pass --dry-run on the CLI.
Encryption key โ On first run, if DRYRUN_ENCRYPTION_KEY is not set, a random 256-bit key is generated, written to .env, and loaded into process.env. All subsequent runs reuse it.
Wallet generation โ bootstrap() calls ensureDryRunWallet("default_wallet") which uses Viem's generatePrivateKey(), encrypts the key with AES-256-GCM (local, no KMS), and stores the ciphertext in the encrypted_keys SQLite table with kms_key_id = "dryrun-local-aes256".
Key storage/retrieval โ encryptAndStore() and retrieveAndDecrypt() in aws-kms.ts check isDryRun() at the top. If true, they delegate to dry-run/wallet.ts which uses dry-run/crypto.ts โ never touching AWS.
Payment execution โ sendEth(), sendErc20(), and executeWeb2Payment() detect dry-run and call the appropriate stub from dry-run/stubs.ts. Stubs simulate latency, return fake tx hashes / order IDs, and respect the stub_mode setting (success / failure / random).
Policy engine runs normally โ even in dry-run, all policy checks and human confirmation flows work identically. This lets you demo the full compliance flow.
Demo command โ agentic-payments-bot demo forces dry-run on, runs 6 sample payments covering all gateways and an over-limit scenario, and prints results:
agentic-payments-bot demo --stub-mode random
Option 1 โ YAML configuration:
dry_run:
enabled: true
encryption_key_env: "DRYRUN_ENCRYPTION_KEY"
stub_mode: "success" # "success" | "failure" | "random"
simulated_latency_ms: 500 # fake network delay
Option 2 โ CLI flag (overrides YAML):
agentic-payments-bot --dry-run pay \
--protocol x402 --amount 5 --currency USDC \
--to 0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65 --network base
Option 3 โ Demo command (always forces dry-run):
agentic-payments-bot demo
agentic-payments-bot demo --stub-mode random
agentic-payments-bot demo --stub-mode failure
First run (DRYRUN_ENCRYPTION_KEY not set)
โ
โโ Generate random 256-bit key
โโ Write to .env: DRYRUN_ENCRYPTION_KEY=<64 hex chars>
โโ Set in process.env for current session
โ
โผ
Subsequent runs
โ
โโ dotenv loads .env on startup
โโ DRYRUN_ENCRYPTION_KEY is present
โโ Same key reuses โ same wallet is decryptable
โ ๏ธ The
.envfile is in.gitignore. If you delete it, a new key is generated and previously encrypted entries become unreadable. For reproducible demos, you can setDRYRUN_ENCRYPTION_KEYto a fixed 64-char hex string.
On bootstrap in dry-run mode, the skill:
generatePrivateKey() to produce a valid secp256k1 private keyencrypted_keys SQLite table
(with kms_key_id = "dryrun-local-aes256")privateKeyToAccount() and logs itOn subsequent runs, if default_wallet already exists in SQLite, the existing
key is reused (decrypted locally, address re-derived).
| Mode | Behavior | Use Case |
|---|---|---|
success |
All simulated payments return success | Happy-path demos, integration testing |
failure |
All simulated payments return failure | Error-handling demos, policy engine testing |
random |
~70% success, ~30% failure | Realistic mixed-outcome demos |
Stubs also simulate configurable network latency (simulated_latency_ms) to
make the demo feel realistic.
Web3 (Viem) stub โ success:
{
"txHash": "0x8f3a1b2c4d5e6f7a8b9c0d1e2f3a4b5caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"network": "base",
"from": "0x1234...abcd",
"to": "0x742d...f2bD65",
"amount": "5.00",
"currency": "USDC"
}
Stripe stub โ success:
{
"gateway": "stripe",
"transaction_id": "pi_dryrun_a1b2c3d4e5f6",
"status": "success",
"amount": "49.99",
"currency": "USD"
}
PayPal stub โ success:
{
"gateway": "paypal",
"transaction_id": "PAYPAL-DRYRUN-A1B2C3D4E5",
"status": "success",
"amount": "25.00",
"currency": "USD",
"receipt_url": "https://sandbox.paypal.com/dryrun/approval"
}
Visa Direct stub โ failure (stub_mode: failure):
{
"gateway": "visa",
"transaction_id": "VISA-DRYRUN-1739184000000",
"status": "failed",
"amount": "100.00",
"currency": "USD",
"error": "[DRY-RUN] Visa push funds declined"
}
Mastercard Send stub โ success:
{
"gateway": "mastercard",
"transaction_id": "MC-DRYRUN-1739184000000",
"status": "success",
"amount": "75.00",
"currency": "USD"
}
Google Pay stub โ success:
{
"gateway": "googlepay",
"transaction_id": "GPAY-DRYRUN-A1B2C3D4E5F6",
"status": "success",
"amount": "35.00",
"currency": "USD"
}
Apple Pay stub โ success:
{
"gateway": "applepay",
"transaction_id": "APAY-DRYRUN-A1B2C3D4E5F6",
"status": "success",
"amount": "59.99",
"currency": "USD",
"receipt_url": "https://sandbox.apple.com/dryrun/receipt"
}
x402 remote resource stub โ success:
{
"data": { "dryRun": true, "message": "Simulated x402 resource access" },
"txHash": "0x8f3a1b2c4d5e6f7a8b9c0d1e2f3a4b5caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"network": "base"
}
AP2 remote mandate stub โ success:
{
"mandate_id": "mandate_dryrun_1739184000000",
"status": "success",
"transaction_id": "ap2-dryrun-a1b2c3d4e5f6",
"receipt": {
"amount": "19.99",
"currency": "USD",
"timestamp": "2026-03-06T12:00:00.000Z",
"reference": "REF-DRYRUN-1739184000000"
}
}
The demo command runs 11 pre-built sample payments across all supported
gateways, protocol clients, and an over-limit policy scenario:
agentic-payments-bot demo --stub-mode success
๐งช โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
AGENTIC PAYMENT SKILL โ INTERACTIVE DEMO
Stub mode: success
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโ 1๏ธโฃ x402 USDC payment on Base (web3) โโโ
โ
Success | TX: 0x8f3a1b2c...
โโโ 2๏ธโฃ AP2 Stripe payment (web2) โโโ
โ
Success | ID: pi_dryrun_a1b2c3d4e5f6
โโโ 3๏ธโฃ AP2 PayPal payment (web2) โโโ
โ
Success | ID: PAYPAL-DRYRUN-A1B2C3D4E5
โโโ 4๏ธโฃ x402 ETH transfer on Ethereum (web3) โโโ
โ
Success | TX: 0x9c4b2d3e...
โโโ 5๏ธโฃ AP2 Visa Direct payment (web2) โโโ
โ
Success | ID: VISA-DRYRUN-1739184000000
โโโ 6๏ธโฃ AP2 Mastercard Send payment (web2) โโโ
โ
Success | ID: MC-DRYRUN-1739184000000
โโโ 7๏ธโฃ AP2 Google Pay payment (web2) โโโ
โ
Success | ID: GPAY-DRYRUN-A1B2C3D4E5F6
โโโ 8๏ธโฃ AP2 Apple Pay payment (web2) โโโ
โ
Success | ID: APAY-DRYRUN-A1B2C3D4E5F6
โโโ 9๏ธโฃ x402 remote resource payment (x402 client) โโโ
โ
Success | x402 TX: 0xabc123def456...
โโโ ๐ AP2 remote mandate payment (AP2 client) โโโ
โ
Success | Mandate: mandate_dryrun_1739184000
โโโ โ ๏ธ Over-limit payment (triggers policy engine) โโโ
โ Not executed: Payment rejected by human confirmation.
โ ๏ธ Policy: [single_transaction.max_amount_usd] Amount $99999.99 exceeds limit of $1000.00
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Demo complete. All transactions are in SQLite.
Run: agentic-payments-bot audit --limit 30
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
After the demo, inspect the results:
# View all transactions created during the demo
sqlite3 data/payments.db "SELECT id, protocol, gateway, amount, currency, status FROM transactions ORDER BY created_at DESC LIMIT 10;"
# View the full audit trail
agentic-payments-bot audit --limit 30
# Check the generated wallet
agentic-payments-bot keys list
dry_run:
# Master toggle. Overridden by --dry-run CLI flag.
enabled: false
# Name of the environment variable holding the 256-bit AES key
# (64 hex characters). If empty on first run, auto-generated
# and appended to .env in the project root.
encryption_key_env: "DRYRUN_ENCRYPTION_KEY"
# How stubs behave:
# "success" โ all stubs return successful responses
# "failure" โ all stubs return error responses
# "random" โ ~70% success, ~30% failure (randomized)
stub_mode: "success"
# Simulated network latency in milliseconds.
# Set to 0 for instant responses (useful in tests).
simulated_latency_ms: 500
In dry-run mode, audit log entries use dryrun_* action prefixes so they are
easily distinguishable from production entries:
| Action | Trigger |
|---|---|
dryrun_mode_activated |
On bootstrap when dry-run is enabled |
dryrun_wallet_generated |
New wallet key generated and stored |
dryrun_key_stored |
Any key/token encrypted with local AES |
dryrun_key_decrypted |
Key retrieved and decrypted locally |
dryrun_eth_transfer |
Simulated ETH transfer |
dryrun_erc20_transfer |
Simulated ERC-20 transfer |
dryrun_stripe |
Simulated Stripe payment |
dryrun_paypal |
Simulated PayPal payment |
dryrun_visa |
Simulated Visa Direct payment |
dryrun_mastercard |
Simulated Mastercard Send payment |
dryrun_googlepay |
Simulated Google Pay payment |
dryrun_applepay |
Simulated Apple Pay payment |
dryrun_x402_remote |
Simulated x402 remote resource access (client) |
dryrun_ap2_remote |
Simulated AP2 remote mandate submission (client) |
dryrun_web2_executed |
Web2 payment stub completed |
dryrun_web3_confirmed |
Web3 tx stub confirmed |
Run the entire skill with zero AWS credentials and zero payment gateway accounts:
# 1. Clone and install
git clone https://github.com/sentient-agi/agentic-payments-bot.git
cd agentic-payments-bot
npm install
npm run build
# 2. Run the demo (no env vars needed โ key auto-generates)
npx agentic-payments-bot demo
# 3. Try individual payments
npx agentic-payments-bot --dry-run pay \
--protocol x402 --amount 10 --currency USDC \
--to 0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65 --network base
npx agentic-payments-bot --dry-run pay \
--protocol ap2 --amount 29.99 --currency USD \
--to merchant-test --gateway stripe
# 4. Trigger a policy violation (default limit is $1000)
npx agentic-payments-bot --dry-run pay \
--protocol ap2 --amount 5000 --currency USD \
--to big-purchase --gateway paypal
# 5. Inspect results
npx agentic-payments-bot --dry-run audit --limit 30
npx agentic-payments-bot --dry-run keys list
# 6. Start the web API in dry-run
npx agentic-payments-bot --dry-run & # or set dry_run.enabled: true in YAML
curl http://localhost:3402/api/v1/health
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{"protocol":"x402","action":"pay","amount":"5","currency":"USDC","recipient":"0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65","network":"base"}'
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Agent Payments Skill โ Master Configuration
# File: config/default.yaml
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# โโ Skill Metadata โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
skill:
name: agentic-payments-bot # Skill identifier (matches SKILL.md)
version: 0.6.0 # Skill version
# โโ SQLite Database โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
database:
path: "./data/payments.db" # Path to SQLite database file
# (directory created automatically)
wal_mode: true # Enable WAL journal mode (recommended
# for concurrent reads during writes)
busy_timeout_ms: 5000 # SQLite busy timeout in milliseconds
# โโ Protocols โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
protocols:
x402:
enabled: true # Enable/disable x402 protocol
facilitator_url: "https://x402.org/facilitator"
# Facilitator URL for settlement
# verification. Coinbase default:
# https://x402.org/facilitator
default_network: "base" # Default chain if not specified in intent
default_asset: "USDC" # Default token if not specified
timeout_ms: 30000 # HTTP request timeout for x402 ops
# Server-side (paywall) configuration
# When enabled, the web API exposes x402-protected endpoints
# that external agents can pay to access.
server:
enabled: true # Enable x402 server endpoints
pay_to_address: "0x..." # Wallet address that receives x402 payments
# Override via X402_PAY_TO_ADDRESS env var
default_price: "1000000" # Default price in asset base units
# (e.g. "1000000" = 1 USDC with 6 decimals)
default_description: "Access to premium agentic data feed"
ap2:
enabled: true # Enable/disable AP2 protocol
mandate_issuer: "https://your-ap2-issuer.example.com"
# URL of your AP2 mandate issuer /
# merchant payment processor
credential_provider_url: "https://credentials.example.com"
# AP2 credential provider for mandate
# signing and payment credential retrieval
timeout_ms: 30000 # HTTP request timeout
# Server-side (mandate processor) configuration
# When enabled, the web API exposes AP2 mandate lifecycle endpoints
# for external agents to submit mandates and trigger payments.
server:
enabled: true # Enable AP2 server endpoints
agent_id: "agentic-payments-bot"
# Agent ID used when this service acts
# as an AP2 client
# โโ Web3 Networks โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Each key is a network name used in PaymentIntent.network
web3:
ethereum:
enabled: true
rpc_url: "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"
chain_id: 1
base:
enabled: true
rpc_url: "https://mainnet.base.org"
chain_id: 8453
polygon:
enabled: true
rpc_url: "https://polygon-rpc.com"
chain_id: 137
# Add more EVM-compatible chains as needed:
# arbitrum:
# enabled: true
# rpc_url: "https://arb1.arbitrum.io/rpc"
# chain_id: 42161
# โโ Web2 Payment Gateways โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
web2:
stripe:
enabled: true
api_version: "2025-01-27.acacia" # Stripe API version string
paypal:
enabled: true
environment: "sandbox" # "sandbox" or "live"
base_url: "https://api-m.sandbox.paypal.com"
# Live: https://api-m.paypal.com
visa:
enabled: true
base_url: "https://sandbox.api.visa.com"
# Live: https://api.visa.com
mastercard:
enabled: true
base_url: "https://sandbox.api.mastercard.com"
# Live: https://api.mastercard.com
googlepay:
enabled: true
environment: "TEST" # "TEST" or "PRODUCTION"
base_url: "https://pay.google.com/gp/p"
allowed_card_networks: # Card networks accepted via Google Pay
- "AMEX"
- "DISCOVER"
- "JCB"
- "MASTERCARD"
- "VISA"
allowed_auth_methods: # Token authentication methods
- "PAN_ONLY" # PAN with expiry + billing address
- "CRYPTOGRAM_3DS" # 3D Secure device token
applepay:
enabled: true
base_url: "https://apple-pay-gateway.apple.com/paymentservices"
# Apple Pay payment services endpoint
domain: "your-domain.example.com"
# Must be verified with Apple
display_name: "OpenClaw Payments"
# Shown on the Apple Pay payment sheet
supported_networks: # Card networks accepted via Apple Pay
- "visa"
- "masterCard"
- "amex"
- "discover"
merchant_capabilities: # Supported capabilities
- "supports3DS"
- "supportsCredit"
- "supportsDebit"
# โโ AWS KMS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# NOTE: AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
# must be set as environment variables. They are NEVER read from this file.
kms:
enabled: true # Enable KMS integration
# โโ Provider Selection โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Selects which backend handles secret encryption/storage.
#
# "aws-kms" โ AWS KMS (production cloud). Requires AWS env vars.
# "os-keyring" โ OS-native keyring: KDE Wallet / GNOME Keyring
# (Linux), Keychain (macOS), Credential Manager
# (Windows). Uses @aspect-build/keytar. Falls back
# to local-aes on headless systems without D-Bus.
# "dbus-secret" โ Linux-only: D-Bus Secret Service API via dbus-next
# (pure JS, no native compilation). Works with
# GNOME Keyring and KDE Wallet (Secret Service
# bridge). Falls back to local-aes on headless.
# "gpg" โ GnuPG encryption. Ideal for headless Linux
# servers without D-Bus. Requires a GPG keypair.
# "local-aes" โ Local AES-256-GCM. Key from DRYRUN_ENCRYPTION_KEY
# env var (auto-generated if missing). No external
# dependencies.
provider: "aws-kms"
# โโ AWS KMS Settings (only when provider is "aws-kms") โโโโโโโโโโโโโ
region: "us-east-1" # AWS region for KMS API calls
key_id_env: "AWS_KMS_KEY_ID" # Name of env var holding the KMS key ARN
# AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from environment
# โโ Linux Keyring Backend (only when provider is "os-keyring") โโโโโ
# Selects the library used for OS keyring access on Linux:
# "keytar" โ @aspect-build/keytar (native addon, full cross-platform)
# "dbus-next" โ Pure JS D-Bus Secret Service client (Linux only,
# no native compilation needed)
linux_keyring_backend: "keytar"
# โโ GnuPG Settings (only when provider is "gpg") โโโโโโโโโโโโโโโโโโ
# gpg_key_id: "your-fingerprint-or-email@example.com"
# # GPG key fingerprint or email. Required
# # when provider is "gpg".
# gpg_binary: "gpg2" # Path to gpg binary (default: gpg2)
# โโ Policy Engine โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
policy:
enabled: true # Master switch for policy enforcement
rules:
# Per-transaction limits
single_transaction:
max_amount_usd: 1000.00 # Max USD per single payment
# Rolling daily window (24 hours)
daily:
max_total_usd: 5000.00 # Max aggregate USD per day
max_transaction_count: 50 # Max number of transactions per day
# Rolling weekly window (7 days)
weekly:
max_total_usd: 25000.00
max_transaction_count: 200
# Rolling monthly window (30 days)
monthly:
max_total_usd: 80000.00
max_transaction_count: 500
# Time-of-day restrictions (evaluated in UTC)
time_restrictions:
enabled: false # Set to true to enforce
allowed_hours:
start: 8 # 08:00 UTC (inclusive)
end: 22 # 22:00 UTC (exclusive)
allowed_days: [1, 2, 3, 4, 5]
# JS weekday: 0=Sun, 1=Mon, ... 6=Sat
# Default: MonโFri only
# Blacklist โ block payments to these addresses/IDs
blacklist:
enabled: true
addresses:
- "0x0000000000000000000000000000000000000000"
# Add more:
# - "0xDEADBEEF..."
# Whitelist โ if enabled, ONLY these addresses are allowed
whitelist:
enabled: false # Usually disabled (restrictive)
addresses: []
# - "0xALLOWED_ADDRESS_1"
# - "merchant-id-1"
# Allowed currencies
allowed_currencies:
- "USDC"
- "ETH"
- "USD"
- "EUR"
# - "DAI"
# - "USDT"
# When violations occur, require human confirmation before proceeding
require_human_confirmation_on_violation: true
# โโ Logging & Audit โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
logging:
level: "info" # Minimum log level: debug|info|warn|error
stdout: true # Log to stdout (console)
stderr_errors: true # Route error/warn to stderr
file:
enabled: true # Log to file
path: "./logs/payment-skill.log"
max_size_mb: 50 # Max single file size before rotation
max_files: 10 # Keep N rotated files
audit:
sqlite: true # Write audit records to SQLite audit_log
verbose: true # Include full request/response payloads
# in audit details JSON
# โโ Web API Server โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
web_api:
enabled: true
host: "0.0.0.0" # Bind address
port: 3402 # Listen port (3402 = "x402" ๐)
cors_origins:
- "http://localhost:*" # Allowed CORS origins (wildcard supported)
# - "https://your-app.example.com"
# โโ CLI Behavior โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
cli:
interactive_confirmation: true # Prompt for confirmation on violations
colored_output: true # ANSI color codes in terminal output
| Section | Purpose | Key Settings |
|---|---|---|
skill |
Metadata | name, version โ must match SKILL.md |
database |
SQLite | path, wal_mode, busy_timeout_ms |
protocols.x402 |
x402 client + server | facilitator_url, default_network, default_asset, server.enabled, server.pay_to_address, server.default_price |
protocols.ap2 |
AP2 client + server | mandate_issuer, credential_provider_url, server.enabled, server.agent_id |
web3.<network> |
EVM chains | rpc_url, chain_id, enabled |
web2.<gateway> |
Payment APIs | Gateway-specific URLs, API versions |
kms |
Key management | provider, region, key_id_env, linux_keyring_backend, gpg_key_id, gpg_binary |
policy |
Compliance | All rule definitions + human confirmation toggle |
logging |
Observability | Multi-transport config, audit detail level |
web_api |
REST server | host, port, cors_origins |
cli |
Terminal UX | Confirmation mode, color output |
The CLI is available as agentic-payments-bot (via npm bin) or npx agentic-payments-bot.
| Flag | Description | Default |
|---|---|---|
-c, --config <path> |
Path to YAML config file | config/default.yaml |
-V, --version |
Print version | โ |
-h, --help |
Show help | โ |
pay โ Execute a Paymentagentic-payments-bot pay [options]
| Option | Required | Description |
|---|---|---|
--protocol <x402|ap2> |
โ | Protocol to use |
--amount <string> |
โ | Decimal amount (e.g., "10.50") |
--currency <string> |
โ | Currency code (USDC, ETH, USD, EUR) |
--to <string> |
โ | Recipient address, merchant ID, or URL (for x402/AP2 remote payments) |
--network <string> |
โ | Blockchain network (ethereum, base, polygon, web2) |
--gateway <string> |
โ | Payment gateway (viem, stripe, paypal, visa, mastercard, googlepay, applepay, x402, ap2) |
--description <string> |
โ | Human-readable description |
--wallet <string> |
โ | Wallet key alias in encrypted store (default: default_wallet) |
Examples:
# x402 USDC payment on Base
agentic-payments-bot pay \
--protocol x402 \
--amount 5.00 \
--currency USDC \
--to 0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65 \
--network base
# AP2 Stripe payment
agentic-payments-bot pay \
--protocol ap2 \
--amount 49.99 \
--currency USD \
--to merchant-12345 \
--gateway stripe \
--description "Monthly subscription"
# PayPal payment with custom config
agentic-payments-bot pay \
--config config/production.yaml \
--protocol ap2 \
--amount 25.00 \
--currency USD \
--to seller@example.com \
--gateway paypal
# Visa Direct payment
agentic-payments-bot pay \
--protocol ap2 \
--amount 100.00 \
--currency USD \
--to 4111111111111111 \
--gateway visa
# Mastercard Send payment
agentic-payments-bot pay \
--protocol ap2 \
--amount 75.00 \
--currency USD \
--to 5500000000000004 \
--gateway mastercard
# x402 remote resource payment (pay for a URL)
agentic-payments-bot pay \
--protocol x402 \
--amount 1.00 \
--currency USDC \
--to https://api.premium-service.com/v1/data \
--network base \
--gateway x402
# AP2 remote mandate submission (pay via AP2 to a URL)
agentic-payments-bot pay \
--protocol ap2 \
--amount 19.99 \
--currency USD \
--to https://merchant.example.com/ap2/process-payment \
--gateway ap2
parse โ Parse AI OutputExtract a PaymentIntent JSON from free-form AI text.
# Direct text
agentic-payments-bot parse '{"protocol":"x402","action":"pay","amount":"10","currency":"USDC","recipient":"0x..."}'
# From stdin (pipe AI model output)
echo '... AI response with embedded JSON ...' | agentic-payments-bot parse -
keys โ Key ManagementManage encrypted keys/tokens stored in SQLite via AWS KMS.
# Store a new encrypted key
agentic-payments-bot keys store \
--alias default_wallet \
--type web3_private_key \
--value "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
# List all stored keys (metadata only โ no plaintext)
agentic-payments-bot keys list
# Delete a key
agentic-payments-bot keys delete stripe_api_key
Key types:
| Type | Alias Convention | Used By |
|---|---|---|
web3_private_key |
default_wallet |
Viem transaction signing |
stripe_token |
stripe_api_key |
Stripe SDK initialization |
paypal_token |
paypal_client_id, paypal_secret |
PayPal OAuth2 |
visa_token |
visa_user_id, visa_password |
Visa Direct auth |
mastercard_token |
mastercard_consumer_key, mastercard_signing_key |
MC Send auth |
googlepay_token |
googlepay_merchant_id, googlepay_merchant_key |
Google Pay token processing |
applepay_token |
applepay_merchant_id, applepay_merchant_cert, applepay_merchant_key, applepay_processor_key |
Apple Pay merchant validation & token processing |
tx โ Transaction Lookupagentic-payments-bot tx <transaction-id>
Outputs the full transaction record as JSON, including status, policy violations, tx hash, and timestamps.
audit โ Query Audit Logagentic-payments-bot audit [options]
| Option | Description |
|---|---|
--category <string> |
Filter: payment, policy, kms, protocol, system |
--tx <string> |
Filter by transaction ID |
--since <ISO 8601> |
Filter by timestamp (e.g., 2026-02-10T00:00:00Z) |
--limit <number> |
Max results (default: 50) |
Examples:
# All payment audit entries from today
agentic-payments-bot audit --category payment --since 2026-02-10T00:00:00Z
# Audit trail for a specific transaction
agentic-payments-bot audit --tx "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
# Recent policy violations
agentic-payments-bot audit --category policy --limit 30
http://<host>:<port>/api/v1
Default: http://0.0.0.0:3402/api/v1
Start the server:
# Via npm script
npm run web
# Or directly
node dist/web-api.js
# With custom config
CONFIG_PATH=config/production.yaml node dist/web-api.js
GET /api/v1/healthHealth check endpoint.
Response 200:
{
"status": "ok",
"skill": "agentic-payments-bot",
"version": "0.6.0",
"dryRun": false,
"protocols": {
"x402": { "enabled": true },
"ap2": { "enabled": true }
}
}
POST /api/v1/paymentExecute a payment from a PaymentIntent.
Request body:
{
"protocol": "x402",
"action": "pay",
"amount": "10.00",
"currency": "USDC",
"recipient": "0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65",
"network": "base",
"gateway": "viem",
"description": "API access payment",
"metadata": {},
"walletKeyAlias": "default_wallet"
}
| Field | Type | Required | Description |
|---|---|---|---|
protocol |
"x402" | "ap2" |
โ | Payment protocol |
action |
"pay" |
โ | Action (only "pay" supported) |
amount |
string | โ | Decimal amount |
currency |
string | โ | Currency code |
recipient |
string | โ | Destination address, merchant ID, or URL (for x402/AP2 remote payments) |
network |
string | โ | Blockchain network name |
gateway |
string | โ | Explicit gateway selection: viem, stripe, paypal, visa, mastercard, googlepay, applepay, x402, ap2 |
description |
string | โ | Human-readable description |
metadata |
object | โ | Arbitrary metadata (e.g., paymentToken for GPay/APay, payment_method_type for AP2) |
walletKeyAlias |
string | โ | Key alias (default: "default_wallet") |
Response 200 (success):
{
"success": true,
"tx": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"protocol": "x402",
"gateway": "viem",
"amount": 10.0,
"amount_usd": 10.0,
"currency": "USDC",
"recipient": "0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65",
"network": "base",
"status": "executed",
"created_at": "2026-02-10T12:00:00.000Z"
},
"txHash": "0xabc123...",
"policyResult": {
"allowed": true,
"violations": [],
"requiresHumanConfirmation": false
},
"confirmationRequired": false,
"dryRun": false
}
Response 202 (confirmation required):
{
"success": false,
"tx": { "id": "...", "status": "awaiting_confirmation", "..." : "..." },
"policyResult": {
"allowed": true,
"violations": [
{
"rule": "single_transaction.max_amount_usd",
"message": "Amount $1500.00 exceeds single transaction limit of $1000.00",
"severity": "block"
}
],
"requiresHumanConfirmation": true
},
"confirmationRequired": true,
"confirmationPrompt": "Confirmation required for tx a1b2c3d4... POST /api/v1/confirm/a1b2c3d4..."
}
Response 400 (validation/execution error):
{
"error": "Amount must be a decimal string"
}
POST /api/v1/parseParse a PaymentIntent from free-form AI output text.
Request body:
{
"text": "I've processed the request. Here's the payment:\n```json\n{\"protocol\":\"x402\",\"action\":\"pay\",\"amount\":\"5.00\",\"currency\":\"USDC\",\"recipient\":\"0x...\"}\n```"
}
Response 200:
{
"found": true,
"intent": {
"protocol": "x402",
"action": "pay",
"amount": "5.00",
"currency": "USDC",
"recipient": "0x..."
}
}
Response 200 (no intent found):
{
"found": false,
"intent": null
}
POST /api/v1/confirm/:txIdConfirm or reject a pending transaction that requires human approval.
URL parameters:
txId โ Transaction ID from the 202 responseRequest body:
{
"confirmed": true,
"reason": "Approved by finance team"
}
| Field | Type | Required | Description |
|---|---|---|---|
confirmed |
boolean | โ | true to approve, false to reject |
reason |
string | โ | Optional note (especially useful for rejections) |
Response 200:
{
"success": true,
"message": "Transaction a1b2c3d4... confirmed"
}
Response 404:
{
"error": "No pending confirmation for tx a1b2c3d4..."
}
GET /api/v1/pendingList all transactions awaiting human confirmation.
Response 200:
[
{
"txId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 1500.0,
"currency": "USD",
"recipient": "merchant-12345",
"violations": [
{
"rule": "single_transaction.max_amount_usd",
"message": "Amount $1500.00 exceeds single transaction limit of $1000.00",
"severity": "block"
}
]
}
]
GET /api/v1/transactions/:txIdRetrieve a transaction record by ID.
Response 200:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"protocol": "x402",
"gateway": "viem",
"action": "pay",
"amount": 10.0,
"amount_usd": 10.0,
"currency": "USDC",
"recipient": "0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65",
"network": "base",
"status": "executed",
"tx_hash": "0xabc123def456...",
"error_message": null,
"policy_violations": null,
"confirmed_by": "auto",
"metadata": "{}",
"created_at": "2026-02-10T12:00:00",
"executed_at": "2026-02-10T12:00:05",
"completed_at": null
}
Response 404:
{
"error": "Transaction not found"
}
GET /api/v1/auditQuery the audit log with optional filters.
Query parameters:
| Param | Type | Description |
|---|---|---|
category |
string | Filter: payment, policy, kms, protocol, system, x402_server, ap2_server |
tx_id |
string | Filter by transaction ID |
since |
string | ISO 8601 timestamp lower bound |
limit |
number | Max results (default: 100) |
Example:
GET /api/v1/audit?category=policy&since=2026-02-10T00:00:00Z&limit=20
Response 200:
[
{
"id": 42,
"timestamp": "2026-02-10T12:00:03",
"level": "warn",
"category": "policy",
"action": "violations_detected",
"tx_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"actor": "system",
"details": "{\"violations\":[{\"rule\":\"single_transaction.max_amount_usd\",\"message\":\"...\"}]}",
"ip_address": null,
"user_agent": null
}
]
These endpoints allow external agents and services to pay you via the x402 protocol.
GET /api/v1/x402/premium/data (Paywall-Protected)An example x402-protected resource. Returns premium data after successful payment.
Without X-PAYMENT header โ Response 402:
The server returns payment requirements in the X-PAYMENT response header:
HTTP/1.1 402 Payment Required
X-PAYMENT: eyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOi4uLn0=
Content-Type: application/json
{
"error": "Payment Required",
"accepts": {
"scheme": "exact",
"network": "base",
"maxAmountRequired": "1000000",
"resource": "/api/v1/x402/premium/data",
"description": "Access to premium agentic data feed",
"mimeType": "application/json",
"payTo": "0x...",
"maxTimeoutSeconds": 60,
"asset": "USDC"
}
}
With valid X-PAYMENT header โ Response 200:
The agent sends a Base64-encoded signed payment payload:
GET /api/v1/x402/premium/data
X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwi...
On successful settlement:
HTTP/1.1 200 OK
X-PAYMENT-RESPONSE: eyJzdWNjZXNzIjp0cnVlLCJ0eEhhc2giOi4uLn0=
Content-Type: application/json
{
"data": "This is premium data, paid for via x402.",
"timestamp": "2026-03-06T12:00:00.000Z",
"source": "agentic-payments-bot"
}
x402 Payment Flow (from the agent's perspective):
Agent Server
โ โ
โโโ GET /api/v1/x402/premium/data โโโบโ
โ โ
โโโโ 402 + X-PAYMENT (requirements)โโโ
โ โ
โ [sign EIP-3009 authorization] โ
โ โ
โโโ GET /api/v1/x402/premium/data โโโบโ
โ X-PAYMENT: <signed payload> โ
โ โโโ [verify + settle on-chain]
โ โ
โโโโ 200 + X-PAYMENT-RESPONSE โโโโโโโโ
โ + resource data โ
GET /api/v1/x402/pricingList all registered x402-priced resources.
Response 200:
{
"resources": [
{
"route": "/api/v1/x402/premium/data",
"maxAmountRequired": "1000000",
"asset": "USDC",
"network": "base",
"payTo": "0x...",
"description": "Access to premium agentic data feed",
"mimeType": "application/json"
}
]
}
POST /api/v1/x402/verifyVerify a settlement transaction hash through the facilitator.
Request body:
{
"txHash": "0xabc123...",
"network": "base"
}
Response 200:
{
"verified": true,
"details": {
"blockNumber": 12345678,
"from": "0x...",
"to": "0x...",
"value": "1000000"
}
}
These endpoints allow external agents to pay you via the AP2 mandate protocol. The server acts as a mandate issuer, credential provider, and payment processor.
POST /api/v1/ap2/mandatesAccept a new mandate from an external agent.
Request body:
{
"mandate_id": "mandate_1709712000_abc123",
"version": "1.0",
"intent": {
"action": "pay",
"description": "Purchase premium API access",
"amount": {
"value": "49.99",
"currency": "USD"
},
"recipient": {
"id": "merchant-001",
"name": "Example Merchant"
}
},
"constraints": {
"max_amount": "49.99",
"valid_from": "2026-03-06T00:00:00.000Z",
"valid_until": "2026-03-06T01:00:00.000Z",
"single_use": true
},
"delegator": {
"agent_id": "claude-agent-001",
"user_id": "user-12345"
}
}
Response 201:
{
"mandate_id": "mandate_1709712000_abc123",
"status": "accepted"
}
Response 400:
{
"error": "Mandate has expired"
}
Response 409:
{
"error": "Mandate ID already exists",
"mandate_id": "mandate_1709712000_abc123"
}
GET /api/v1/ap2/mandatesList all accepted mandates.
Response 200:
{
"mandates": [
{
"mandate_id": "mandate_1709712000_abc123",
"status": "accepted",
"amount": "49.99",
"currency": "USD",
"agent_id": "claude-agent-001",
"created_at": "2026-03-06T12:00:00.000Z",
"executed_at": null
}
]
}
GET /api/v1/ap2/mandates/:mandateIdGet the status of a specific mandate.
Response 200:
{
"mandate_id": "mandate_1709712000_abc123",
"status": "executed",
"created_at": "2026-03-06T12:00:00.000Z",
"executed_at": "2026-03-06T12:01:00.000Z",
"transaction_id": "pi_3Abc123..."
}
Response 404:
{
"error": "Mandate not found"
}
POST /api/v1/ap2/sign-mandateSign a mandate (acting as a credential provider). In production, this verifies the delegator's identity and signs the mandate with the server's ECDSA key.
Request body:
{
"mandate": {
"mandate_id": "mandate_1709712000_abc123",
"version": "1.0",
"intent": { "..." : "..." },
"constraints": { "..." : "..." },
"delegator": { "..." : "..." }
}
}
Response 200:
{
"signed_mandate": {
"mandate_id": "mandate_1709712000_abc123",
"version": "1.0",
"intent": { "..." : "..." },
"constraints": { "..." : "..." },
"delegator": { "..." : "..." },
"signature": "sig_1709712000_a1b2c3d4"
}
}
POST /api/v1/ap2/payment-credentialsIssue tokenized payment credentials for a specific mandate and payment method.
Request body:
{
"mandate_id": "mandate_1709712000_abc123",
"payment_method_type": "stripe"
}
Response 200:
{
"type": "stripe",
"details": {
"token": "tok_mandate_1709712000_abc123_1709712060000",
"scoped_to_mandate": "mandate_1709712000_abc123",
"max_amount": "49.99",
"currency": "USD"
}
}
Response 409 (mandate already executed):
{
"error": "Mandate already executed (single-use)"
}
POST /api/v1/ap2/process-paymentExecute a mandate against the server's internal payment backends. This is the final step in the AP2 flow โ the agent submits a mandate and payment method, and the server routes the payment to Stripe, PayPal, Viem, or any other configured backend.
Request body:
{
"mandate": {
"mandate_id": "mandate_1709712000_abc123",
"version": "1.0",
"intent": {
"action": "pay",
"description": "Premium API access",
"amount": { "value": "49.99", "currency": "USD" },
"recipient": { "id": "merchant-001" }
},
"constraints": {
"max_amount": "49.99",
"valid_from": "2026-03-06T00:00:00.000Z",
"valid_until": "2026-03-06T01:00:00.000Z",
"single_use": true
},
"delegator": { "agent_id": "claude-agent-001" },
"signature": "sig_1709712000_a1b2c3d4"
},
"payment_method": {
"type": "stripe",
"details": {
"token": "tok_mandate_1709712000_abc123_1709712060000"
}
}
}
Supported payment_method.type values:
| Type | Backend | Description |
|---|---|---|
stripe |
Stripe | Routes to Stripe Payment Intents API |
paypal |
PayPal | Routes to PayPal Orders API |
card |
Stripe (default) | Generic card payment, routes to Stripe |
crypto |
Viem | On-chain transfer (ETH or ERC-20). Specify details.network and optionally details.wallet_alias. |
bank_transfer |
โ | Not yet supported |
Response 200 (success):
{
"mandate_id": "mandate_1709712000_abc123",
"status": "success",
"transaction_id": "pi_3Abc123...",
"receipt": {
"amount": "49.99",
"currency": "USD",
"timestamp": "2026-03-06T12:01:00.000Z",
"reference": "pi_3Abc123..."
}
}
Response 202 (pending):
{
"mandate_id": "mandate_1709712000_abc123",
"status": "pending",
"transaction_id": "pi_3Abc123..."
}
Response 400 (failed):
{
"mandate_id": "mandate_1709712000_abc123",
"status": "failed",
"error": "Mandate has expired"
}
These endpoints allow external agents to pay you via the MPP protocol.
POST /api/v1/mpp/quoteIssue a quote. Body: { "mpp_version": "1.0", "amount": "<decimal>", "currency": "<code>", "description"?: "..." }.
Response 200: MPPQuote (with quote_id, accepted_rails, expires_at).
POST /api/v1/mpp/invoiceIssue a content-addressed signed invoice for an existing quote.
Body: { "mpp_version": "1.0", "quote_id": "...", "preferred_rail"?: "x402" | "stripe" | "paypal" | "card" | "crypto" }.
Response 201: MPPInvoice (with invoice_id, rail, pay_to, signature).
Response 410: quote has expired.
POST /api/v1/mpp/settleSettle an invoice using a rail-specific payload (see MPP Rails above).
Response 200: MPPReceipt with status: "settled" + rail_reference.
Response 202: status: "pending" for async rails.
Response 409: invoice already settled.
Response 410: invoice has expired.
GET /api/v1/mpp/receipt/:invoiceIdFetch the signed receipt for a previously settled invoice.
Response 200: MPPReceipt.
Response 404: receipt not found.
GET /api/v1/mpp/invoices/:invoiceIdFetch invoice + status. Response 200: { "invoice": MPPInvoice, "status": "issued" | "settled" | "failed" }.
All endpoints return errors in a consistent format:
{
"error": "Human-readable error description"
}
| HTTP Status | Meaning |
|---|---|
200 |
Success |
202 |
Accepted โ payment pending human confirmation |
400 |
Bad request (validation error, execution failure) |
404 |
Resource not found (transaction, pending confirmation) |
500 |
Internal server error |
When the skill is activated in OpenClaw, the agent uses the SKILL.md instructions to output
structured payment intents during conversation.
The agent is instructed to output this exact JSON when a payment is needed:
{
"protocol": "x402 | ap2",
"action": "pay",
"amount": "<decimal string>",
"currency": "USDC | USDT | ETH | WETH | DAI | USD | EUR",
"recipient": "<0x address | merchant ID | URL>",
"network": "ethereum | base | polygon | web2 | null",
"gateway": "viem | stripe | paypal | visa | mastercard | googlepay | applepay | x402 | ap2 | null",
"description": "<optional text>",
"metadata": {}
}
| Field | Required | Description |
|---|---|---|
protocol |
โ | Metadata tag: "x402" (onchain flavour) or "ap2" (mandate flavour). Does not determine execution โ gateway does. |
action |
โ | Always "pay" |
amount |
โ | Decimal string (e.g. "10.50") |
currency |
โ | Currency code |
recipient |
โ | 0x... address (web3), merchant ID (web2), or URL (x402/AP2 outbound client) |
network |
โ | Blockchain network or "web2". Defaults from config. |
gateway |
โ | Execution backend. See routing matrix. Auto-detected when omitted. |
description |
โ | Human-readable note |
metadata |
โ | Gateway-specific extras (paymentToken, payment_method_type, etc.) |
The protocol router extracts this JSON from the agent's message (even when surrounded by natural language) using regex-based extraction.
The SKILL.md instructs the agent:
| Signal | Routed To |
|---|---|
| Target is an HTTP resource returning 402 | x402 โ x402 gateway (client) |
Recipient is a URL + protocol: "x402" |
x402 โ x402 gateway (client, remote resource payment) |
| User mentions "x402", "stablecoin", "USDC", "onchain" | x402 |
| Payment involves a mandate, delegated purchase | AP2 |
Recipient is a URL + protocol: "ap2" |
AP2 โ ap2 gateway (client, remote mandate submission) |
| Traditional card/gateway payment via agent | AP2 |
| User mentions "Google Pay", "GPay" | AP2 โ googlepay gateway |
| User mentions "Apple Pay" | AP2 โ applepay gateway |
| Crypto currency (USDC, ETH, DAI) | web3 (Viem) |
| Fiat currency (USD, EUR) | web2 (Stripe default) |
The protocol field is a classification tag, not a routing directive:
| Signal | protocol |
gateway (auto-detected if omitted) |
|---|---|---|
| User mentions USDC, ETH, stablecoin, onchain, x402 | x402 |
viem (or x402 if recipient is a URL) |
| Target is a URL returning HTTP 402 | x402 |
x402 |
| User mentions Stripe, PayPal, card payment, mandate | ap2 |
stripe, paypal, etc. |
| User mentions Google Pay / GPay | ap2 |
googlepay |
| User mentions Apple Pay | ap2 |
applepay |
| User wants to submit a mandate to an external AP2 service | ap2 |
ap2 |
Rule of thumb: Use
protocol: "x402"for anything blockchain/crypto, andprotocol: "ap2"for anything fiat/mandate-based. Thegatewayfield (or auto-detection) handles the rest.
When a policy violation is detected during a chat-initiated payment:
Skill returns a Markdown prompt to the agent, which presents it to the user:
โ ๏ธ **Payment Requires Your Confirmation**
| Field | Value |
|-------|-------|
| Transaction ID | `a1b2c3d4...` |
| Protocol | x402 |
| Amount | 1500 USDC ($1500.00 USD) |
| Recipient | `0x742d...` |
| Gateway | viem |
**Policy Violations:**
- **single_transaction.max_amount_usd**: Amount $1500.00 exceeds limit of $1000.00
Reply **"confirm a1b2c3d4"** to proceed or **"reject a1b2c3d4"** to cancel.
User responds in the chat with confirm <txId> or reject <txId>
Skill parses the response and resumes/cancels the payment
Tip: All examples below work in dry-run mode (no real payments, no credentials needed). Prefix every CLI command with
--dry-runor setDRY_RUN=truein your environment.
Via CLI:
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_KMS_KEY_ID="arn:aws:kms:..."
agentic-payments-bot pay \
--protocol x402 \
--amount 5.00 \
--currency USDC \
--to 0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65 \
--network base \
--gateway viem \
--wallet default_wallet
--description "USDC payment on Base"
Output:
2026-02-10T12:00:00.000Z [info] Transaction created { id: 'a1b2...', protocol: 'x402' }
2026-02-10T12:00:00.010Z [info] Policy check passed { amountUsd: 5 }
2026-02-10T12:00:00.020Z [info] web3: Preparing ERC-20 transfer { to: '0x742d...', amount: '5.00' }
2026-02-10T12:00:02.500Z [info] web3: ERC-20 transfer sent { txHash: '0xdef456...' }
2026-02-10T12:00:15.000Z [info] web3: Transaction confirmed { status: 'success', block: '12345678' }
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
Payment executed successfully!
TX Hash: 0xdef456...
Internal TX ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Via Web API (curl):
# Start the web API
npm run web
# In another terminal, execute a payment
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "x402",
"action": "pay",
"amount": "5.00",
"currency": "USDC",
"recipient": "0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65",
"network": "base",
"gateway": "viem",
"description": "USDC payment on Base"
}'
Response:
{
"success": true,
"tx": {
"id": "a1b2c3d4-5678-9012-3456-789012345678",
"protocol": "x402",
"gateway": "viem",
"amount": 5.0,
"amount_usd": 5.0,
"currency": "USDC",
"status": "executed"
},
"txHash": "0xabc123...def456",
"policyResult": { "allowed": true, "violations": [], "requiresHumanConfirmation": false },
"confirmationRequired": false,
"dryRun": true
}
Via CLI:
agentic-payments-bot pay \
--protocol x402 \
--amount 10.00 \
--currency USDC \
--to 0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97 \
--network ethereum \
--gateway viem
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "x402",
"action": "pay",
"amount": "10.00",
"currency": "USDC",
"recipient": "0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97",
"network": "ethereum",
"gateway": "viem",
"description": "USDC payment on Ethereum"
}'
Via CLI:
agentic-payments-bot pay \
--protocol x402 \
--amount 25.00 \
--currency USDT \
--to 0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65 \
--network base \
--gateway viem
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "x402",
"action": "pay",
"amount": "25.00",
"currency": "USDT",
"recipient": "0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65",
"network": "base",
"gateway": "viem",
"description": "USDT payment on Base"
}'
Via CLI:
agentic-payments-bot pay \
--protocol x402 \
--amount 50.00 \
--currency USDT \
--to 0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97 \
--network ethereum \
--gateway viem
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "x402",
"action": "pay",
"amount": "50.00",
"currency": "USDT",
"recipient": "0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97",
"network": "ethereum",
"gateway": "viem",
"description": "USDT payment on Ethereum"
}'
Via CLI:
agentic-payments-bot pay \
--protocol x402 \
--amount 0.01 \
--currency ETH \
--to 0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97 \
--network ethereum \
--gateway viem
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "x402",
"action": "pay",
"amount": "0.01",
"currency": "ETH",
"recipient": "0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97",
"network": "ethereum",
"gateway": "viem",
"description": "ETH transfer on Ethereum"
}'
Via CLI:
agentic-payments-bot pay \
--protocol ap2 \
--amount 49.99 \
--currency USD \
--to merchant-stripe-001 \
--network web2 \
--gateway stripe \
--description "Stripe payment"
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "49.99",
"currency": "USD",
"recipient": "merchant-stripe-001",
"gateway": "stripe",
"description": "Stripe payment"
}'
Response:
{
"success": true,
"tx": {
"id": "b2c3d4e5-6789-0123-4567-890123456789",
"protocol": "ap2",
"gateway": "stripe",
"amount": 49.99,
"amount_usd": 49.99,
"currency": "USD",
"status": "executed"
},
"web2Result": {
"gateway": "stripe",
"transaction_id": "pi_dryrun_abc123def456",
"status": "success",
"amount": "49.99",
"currency": "USD"
},
"policyResult": {
"allowed": true,
"violations": [],
"requiresHumanConfirmation": false
},
"confirmationRequired": false,
"dryRun": true
}
Via CLI:
agentic-payments-bot pay \
--protocol ap2 \
--amount 25.00 \
--currency USD \
--to seller@example.com \
--gateway paypal \
--description "PayPal payment"
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "25.00",
"currency": "USD",
"recipient": "seller@example.com",
"gateway": "paypal",
"description": "PayPal payment"
}'
Response:
{
"success": true,
"tx": { "id": "...", "protocol": "ap2", "gateway": "paypal", "status": "executed" },
"web2Result": {
"gateway": "paypal",
"transaction_id": "PAYPAL-DRYRUN-ABC1234567",
"status": "success",
"amount": "25.00",
"currency": "USD",
"receipt_url": "https://sandbox.paypal.com/dryrun/approval"
},
"dryRun": true
}
Via CLI:
agentic-payments-bot pay \
--protocol ap2 \
--amount 100.00 \
--currency USD \
--to 4111111111111111 \
--gateway visa \
--description "Visa Direct push payment"
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "100.00",
"currency": "USD",
"recipient": "4111111111111111",
"gateway": "visa",
"description": "Visa Direct push payment"
}'
Via CLI:
agentic-payments-bot pay \
--protocol ap2 \
--amount 75.00 \
--currency USD \
--to 5111111111111118 \
--gateway mastercard \
--description "Mastercard Send payment"
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "75.00",
"currency": "USD",
"recipient": "5111111111111118",
"gateway": "mastercard",
"description": "Mastercard Send payment"
}'
Response:
{
"success": true,
"tx": {
"id": "c3d4e5f6-7890-abcd-ef12-345678901234",
"protocol": "ap2",
"gateway": "mastercard",
"amount": 75.0,
"amount_usd": 75.0,
"currency": "USD",
"status": "executed"
},
"web2Result": {
"gateway": "mastercard",
"transaction_id": "MC-TXN-12345678",
"status": "success",
"amount": "75.00",
"currency": "USD"
},
"policyResult": {
"allowed": true,
"violations": [],
"requiresHumanConfirmation": false
},
"confirmationRequired": false,
"dryRun": false
}
Via CLI:
agentic-payments-bot pay \
--protocol ap2 \
--amount 35.00 \
--currency USD \
--to merchant-gpay-001 \
--gateway googlepay \
--description "Google Pay payment"
Note: The
paymentTokeninmetadatamust be the encrypted payment token obtained from the client-side Google Pay JS API. The server never generates this token โ it only processes it.
Note: In production,
metadata.paymentTokenmust be supplied via the Web API (the token comes from the client-side Google Pay JS API). The CLI works in dry-run mode without it.
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "35.00",
"currency": "USD",
"recipient": "merchant-gpay-001",
"gateway": "googlepay",
"description": "Google Pay payment",
"metadata": {
"paymentToken": "<encrypted-token-from-google-pay-js-api>",
"countryCode": "US"
}
}'
Response:
{
"success": true,
"tx": {
"id": "d4e5f678-9012-bcde-f123-456789012345",
"protocol": "ap2",
"gateway": "googlepay",
"amount": 35.0,
"amount_usd": 35.0,
"currency": "USD",
"status": "executed"
},
"web2Result": {
"gateway": "googlepay",
"transaction_id": "GPAY-DRYRUN-ABC123DEF456",
"status": "success",
"amount": "35.00",
"currency": "USD"
},
"dryRun": true
}
Via CLI:
agentic-payments-bot pay \
--protocol ap2 \
--amount 59.99 \
--currency USD \
--to merchant-applepay-001 \
--gateway applepay \
--description "Apple Pay payment"
Note: The
paymentTokenmust be the encrypted token from the client-side Apple Pay JS API. The optionalvalidationURLtriggers server-to-server merchant session validation with Apple before the token is processed.
Note: In production,
metadata.paymentTokenmust be supplied via the Web API (the token comes from the client-side Apple Pay JS API). The CLI works in dry-run mode without it.
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "59.99",
"currency": "USD",
"recipient": "merchant-applepay-001",
"gateway": "applepay",
"description": "Apple Pay payment",
"metadata": {
"paymentToken": "<encrypted-token-from-apple-pay-js-api>",
"validationURL": "https://apple-pay-gateway-cert.apple.com/paymentservices/startSession"
}
}'
Response:
{
"success": true,
"tx": {
"id": "e5f67890-1234-cdef-0123-567890123456",
"protocol": "ap2",
"gateway": "applepay",
"amount": 59.99,
"amount_usd": 59.99,
"currency": "USD",
"status": "executed"
},
"web2Result": {
"gateway": "applepay",
"transaction_id": "APAY-DRYRUN-XYZ789ABC012",
"status": "success",
"amount": "59.99",
"currency": "USD",
"receipt_url": "https://sandbox.apple.com/dryrun/receipt"
},
"dryRun": true
}
This demonstrates the client side โ your agent pays for access to an x402-protected resource hosted by another service.
Via CLI:
agentic-payments-bot pay \
--protocol x402 \
--amount 1.00 \
--currency USDC \
--to https://api.premium-service.com/v1/data \
--network base \
--gateway x402 \
--description "Access premium data via x402"
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "x402",
"action": "pay",
"amount": "1.00",
"currency": "USDC",
"recipient": "https://api.premium-service.com/v1/data",
"network": "base",
"gateway": "x402",
"description": "Access premium data via x402"
}'
Response:
{
"success": true,
"tx": {
"id": "f6789012-3456-def0-1234-567890abcdef",
"protocol": "x402",
"gateway": "x402",
"amount": 1.0,
"currency": "USDC",
"recipient": "https://api.premium-service.com/v1/data",
"status": "executed"
},
"txHash": "0xabc123...",
"policyResult": { "allowed": true, "violations": [], "requiresHumanConfirmation": false },
"confirmationRequired": false,
"dryRun": true
}
This demonstrates the client side โ your agent creates and submits a mandate to an AP2-compliant external payment processor.
Via CLI:
agentic-payments-bot pay \
--protocol ap2 \
--amount 79.99 \
--currency USD \
--to https://merchant.example.com/ap2/process-payment \
--gateway ap2 \
--description "Annual subscription via AP2"
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "79.99",
"currency": "USD",
"recipient": "https://merchant.example.com/ap2/process-payment",
"gateway": "ap2",
"description": "Annual subscription via AP2",
"metadata": {
"payment_method_type": "card"
}
}'
This demonstrates the client side โ your agent discovers, invoices, and settles an MPP payment at an external merchant.
Via CLI:
agentic-payments-bot pay \
--protocol mpp \
--amount 1.00 \
--currency USDC \
--to https://merchant.example.com/mpp \
--network base \
--gateway mpp \
--description "Pay via MPP on Base"
Via Web API (curl):
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "mpp",
"action": "pay",
"amount": "1.00",
"currency": "USDC",
"recipient": "https://merchant.example.com/mpp",
"network": "base",
"gateway": "mpp",
"description": "Pay via MPP on Base",
"metadata": { "payment_method_type": "x402" }
}'
Response (dry-run):
{
"success": true,
"tx": { "id": "...", "protocol": "mpp", "gateway": "mpp", "status": "executed" },
"mppResult": {
"invoice_id": "inv_dryrun_abc123",
"receipt_id": "rcpt_dryrun_abc123",
"status": "settled"
},
"dryRun": true
}
User prompt in OpenClaw chat:
"Pay 10 USDC to 0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65 on Base for API access"
The agent responds with embedded JSON (per SKILL.md instructions):
I'll process this payment for you now:
```json
{
"protocol": "x402",
"action": "pay",
"amount": "10.00",
"currency": "USDC",
"recipient": "0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65",
"network": "base",
"gateway": "viem",
"description": "API access payment"
}
The payment has been submitted.
The skill's protocol router extracts this JSON, validates it, runs policy checks, and executes
the payment.
The skill automatically parses the JSON block using `parsePaymentIntentFromAIOutput()`.
**Via CLI parse:**
```bash
agentic-payments-bot parse '{"protocol":"x402","action":"pay","amount":"5.00","currency":"USDC","recipient":"0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65","network":"base"}'
Via Web API:
curl -X POST http://localhost:3402/api/v1/parse \
-H "Content-Type: application/json" \
-d '{"text": "{\"protocol\":\"x402\",\"action\":\"pay\",\"amount\":\"5.00\",\"currency\":\"USDC\",\"recipient\":\"0x742d35Cc6635C0532925a3b844Bc9e7595f2bD65\",\"network\":\"base\"}"}'
Via CLI (over-limit triggers policy engine):
agentic-payments-bot pay \
--protocol ap2 \
--amount 99999.99 \
--currency USD \
--to merchant-big-spender \
--gateway stripe \
--description "Large payment (expect policy violation)"
The CLI will prompt for human confirmation:
โ ๏ธ Policy violations detected:
โข [single_transaction] Amount $99999.99 exceeds single-tx limit of $1000.00
Confirm payment? (yes/no):
Via Web API (returns 202 with confirmation required):
# 1. Submit a payment that exceeds the single-transaction limit
curl -X POST http://localhost:3402/api/v1/payment \
-H "Content-Type: application/json" \
-d '{
"protocol": "ap2",
"action": "pay",
"amount": "99999.99",
"currency": "USD",
"recipient": "merchant-big-spender",
"gateway": "stripe"
}'
Response: 202 with confirmationRequired: true
{
"confirmationRequired": true,
"confirmationPrompt": "Confirmation required for tx abc123... POST /api/v1/confirm/abc123..."
}
# 2. Check pending confirmations
curl http://localhost:3402/api/v1/pending
Confirm via API:
# 3. Approve the payment
curl -X POST http://localhost:3402/api/v1/confirm/<tx-id> \
-H "Content-Type: application/json" \
-d '{"confirmed": true, "reason": "One-time approved by CFO"}'
# Store a wallet private key
agentic-payments-bot keys store \
--alias trading_wallet \
--type web3_private_key \
--value "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
# Store Stripe API key
agentic-payments-bot keys store \
--alias stripe_api_key \
--type stripe_token \
--value "sk_test_..."
# List all stored keys (metadata only, plaintext is NEVER shown)
agentic-payments-bot keys list
# โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโ
# โ id โ key_type โ key_alias โ kms_key_id โ created_at โ
# โโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโค
# โ a1b2... โ web3_private_key โ trading_wallet โ arn:aws:kms:us-east-1:... โ 2026-02-10 12:00:00 โ
# โ c3d4... โ stripe_token โ stripe_api_key โ arn:aws:kms:us-east-1:... โ 2026-02-10 12:01:00 โ
# โโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโ
# Delete a key
agentic-payments-bot keys delete trading_wallet
agentic-payments-bot keys delete stripe_api_key
This demonstrates the server side โ an external agent pays for access to a resource protected by the x402 paywall middleware.
Step 1 โ Agent discovers payment requirements:
# Agent requests the resource โ gets 402 + payment details
curl -v http://localhost:3402/api/v1/x402/premium/data
Response:
< HTTP/1.1 402 Payment Required
< X-PAYMENT: eyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJiYXNlIiwi...
<
{
"error": "Payment Required",
"accepts": {
"scheme": "exact",
"network": "base",
"maxAmountRequired": "1000000",
"asset": "USDC",
"payTo": "0x...",
"resource": "/api/v1/x402/premium/data",
"description": "Access to premium agentic data feed"
}
}
Step 2 โ Agent signs and submits payment:
# Agent retries with a signed X-PAYMENT header
curl -v http://localhost:3402/api/v1/x402/premium/data \
-H "X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwisc2NoZW1lIjoiZXhhY3QiLC..."
Response (success):
< HTTP/1.1 200 OK
< X-PAYMENT-RESPONSE: eyJzdWNjZXNzIjp0cnVlLCJ0eEhhc2giOiIweGFiYy4uLiJ9
<
{
"data": "This is premium data, paid for via x402.",
"timestamp": "2026-03-06T12:00:00.000Z",
"source": "agentic-payments-bot"
}
Step 3 โ Check available pricing:
curl http://localhost:3402/api/v1/x402/pricing
Response:
{
"resources": [
{
"route": "/api/v1/x402/premium/data",
"maxAmountRequired": "1000000",
"asset": "USDC",
"network": "base",
"payTo": "0x...",
"description": "Access to premium agentic data feed"
}
]
}
This demonstrates the server side โ an external agent submits an AP2 mandate and the server processes the payment internally.
Step 1 โ Agent submits a mandate:
curl -X POST http://localhost:3402/api/v1/ap2/mandates \
-H "Content-Type: application/json" \
-d '{
"mandate_id": "mandate_1709712000_demo",
"version": "1.0",
"intent": {
"action": "pay",
"description": "API access subscription",
"amount": { "value": "29.99", "currency": "USD" },
"recipient": { "id": "merchant-001" }
},
"constraints": {
"max_amount": "29.99",
"valid_from": "2026-03-28T00:00:00.000Z",
"valid_until": "2026-03-29T00:00:00.000Z",
"single_use": true
},
"delegator": {
"agent_id": "external-agent-001",
"user_id": "user-42"
}
}'
Response:
{
"mandate_id": "mandate_1709712000_demo",
"status": "accepted"
}
Step 2 โ Agent requests mandate signing:
curl -X POST http://localhost:3402/api/v1/ap2/sign-mandate \
-H "Content-Type: application/json" \
-d '{
"mandate": {
"mandate_id": "mandate_1709712000_demo",
"version": "1.0",
"intent": {
"action": "pay",
"description": "API access subscription",
"amount": {
"value": "29.99",
"currency": "USD"
},
"recipient": { "id": "merchant-001" }
},
"constraints": {
"max_amount": "29.99",
"valid_from": "2026-03-28T00:00:00.000Z",
"valid_until": "2026-03-29T00:00:00.000Z",
"single_use": true
},
"delegator": { "agent_id": "external-agent-001" }
}
}'
Step 3 โ Agent obtains payment credentials:
curl -X POST http://localhost:3402/api/v1/ap2/payment-credentials \
-H "Content-Type: application/json" \
-d '{
"mandate_id": "mandate_1709712000_demo",
"payment_method_type": "stripe"
}'
Step 4 โ Agent submits for payment processing:
curl -X POST http://localhost:3402/api/v1/ap2/process-payment \
-H "Content-Type: application/json" \
-d '{
"mandate": {
"mandate_id": "mandate_1709712000_demo",
"version": "1.0",
"intent": {
"action": "pay",
"description": "API access subscription",
"amount": {
"value": "29.99",
"currency": "USD"
},
"recipient": { "id": "merchant-001" }
},
"constraints": {
"max_amount": "29.99",
"valid_from": "2026-03-28T00:00:00.000Z",
"valid_until": "2026-03-29T00:00:00.000Z",
"single_use": true
},
"delegator": { "agent_id": "external-agent-001" },
"signature": "sig_1709712000_a1b2c3d4"
},
"payment_method": {
"type": "stripe",
"details": { "token": "tok_mandate_1709712000_demo_1709712060000" }
}
}'
Response:
{
"mandate_id": "mandate_1709712000_demo",
"status": "success",
"transaction_id": "pi_3Abc123...",
"receipt": {
"amount": "29.99",
"currency": "USD",
"timestamp": "2026-03-06T12:01:00.000Z",
"reference": "pi_3Abc123..."
}
}
Step 5 โ Verify mandate status:
curl http://localhost:3402/api/v1/ap2/mandates/mandate_1709712000_demo
Response:
{
"mandate_id": "mandate_1709712000_demo",
"status": "executed",
"created_at": "2026-03-06T12:00:00.000Z",
"executed_at": "2026-03-06T12:01:00.000Z",
"transaction_id": "pi_3Abc123..."
}
Step 1 โ Agent requests a quote:
curl -X POST http://localhost:3402/api/v1/mpp/quote \
-H "Content-Type: application/json" \
-d '{
"mpp_version": "1.0",
"amount": "1.00",
"currency": "USDC",
"description": "Premium feed access"
}'
Response:
{
"mpp_version": "1.0",
"quote_id": "quo_7f2c...",
"merchant_id": "agentic-payments-bot",
"amount": "1.00",
"currency": "USDC",
"accepted_rails": ["x402", "stripe"],
"network": "base",
"asset": "USDC",
"pay_to": "0x...",
"expires_at": "2026-04-24T12:05:00.000Z"
}
Step 2 โ Agent requests the invoice:
curl -X POST http://localhost:3402/api/v1/mpp/invoice \
-H "Content-Type: application/json" \
-d '{ "mpp_version": "1.0", "quote_id": "quo_7f2c..." }'
Response:
{
"mpp_version": "1.0",
"invoice_id": "inv_8a2f9c4b...",
"quote_id": "quo_7f2c...",
"amount": "1.00",
"currency": "USDC",
"rail": "x402",
"network": "base",
"asset": "USDC",
"pay_to": "0x...",
"expires_at": "2026-04-24T12:10:00.000Z",
"signature": "ab12cd34..."
}
Step 3 โ Agent settles with a signed x402 authorization:
curl -X POST http://localhost:3402/api/v1/mpp/settle \
-H "Content-Type: application/json" \
-d '{
"mpp_version": "1.0",
"invoice_id": "inv_8a2f9c4b...",
"rail": "x402",
"payload": {
"x402Payload": {
"x402Version": 1,
"scheme": "exact",
"network": "base",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0x...",
"to": "0x...",
"value": "1000000",
"validAfter": "0",
"validBefore": "1745501160",
"nonce": "0x..."
}
}
}
},
"payer": { "agent_id": "external-agent-001" }
}'
Response:
{
"mpp_version": "1.0",
"receipt_id": "rcpt_6e3d...",
"invoice_id": "inv_8a2f9c4b...",
"status": "settled",
"rail": "x402",
"amount": "1.00",
"currency": "USDC",
"rail_reference": "0xabc...def",
"settled_at": "2026-04-24T12:06:10.000Z",
"signature": "9f1e2d3c...",
"verified": true
}
Step 4 โ Fetch (or re-verify) the receipt later:
curl http://localhost:3402/api/v1/mpp/receipt/inv_8a2f9c4b...
npm run build # Compile TypeScript to dist/
npm test # Run Jest test suite
npm run dev # ts-node src/index.ts
| Package | Version | Purpose |
|---|---|---|
@coinbase/x402 |
^2.1.0 |
x402 facilitator SDK |
viem |
^2.28.0 |
Ethereum wallet, signing, tx building |
stripe |
^17.0.0 |
Stripe payment SDK |
@paypal/paypal-server-sdk |
^2.0.0 |
PayPal payments |
@aws-sdk/client-kms |
^3.750.0 |
AWS KMS encrypt/decrypt (aws-kms provider) |
better-sqlite3 |
^12.8.0 |
SQLite driver (native, synchronous) |
yaml |
^2.7.0 |
YAML config parsing |
express |
^5.1.0 |
Web API server |
commander |
^13.1.0 |
CLI framework |
winston |
^3.17.0 |
Multi-transport logging |
zod |
^3.24.0 |
Schema validation |
uuid |
^11.1.0 |
UUID generation for IDs |
readline-sync |
^1.4.10 |
CLI interactive prompts |
chalk |
^5.4.0 |
Terminal color output |
dotenv |
^16.5.0 |
Environment variable loading |
Optional dependencies (install only for the KMS providers you need):
| Package | Version | Purpose | Install Command |
|---|---|---|---|
@aspect-build/keytar |
* |
OS Keyring integration (native addon) โ KDE Wallet, GNOME Keyring, macOS Keychain, Windows Credential Manager | npm install @aspect-build/keytar --save-optional |
dbus-next |
* |
Linux D-Bus Secret Service API (pure JS, no native compilation) | npm install dbus-next --save-optional |
| Symptom | Cause | Fix |
|---|---|---|
AWS KMS key ID not found in env var |
Missing AWS_KMS_KEY_ID environment variable |
Export AWS_KMS_KEY_ID before running, or switch to a different kms.provider |
Unknown KMS provider: 'X' |
Invalid kms.provider value in config |
Use one of: aws-kms, os-keyring, dbus-secret, gpg, local-aes |
OS keyring unavailable ... Falling back to local-aes |
No D-Bus session (headless server) | Expected behavior โ use gpg or local-aes provider explicitly, or install a D-Bus session |
GPG provider requires 'kms.gpg_key_id' |
Missing GPG key ID in config | Set kms.gpg_key_id to your GPG key fingerprint or email |
gpg2: command not found |
GnuPG not installed | Install gnupg2 package, or set kms.gpg_binary to the correct path |
D-Bus Secret Service: key not found |
Secret not stored in keyring | Store the key first via agentic-payments-bot keys store, or check that the correct keyring is unlocked |
| KDE Wallet prompt on every access | KWallet locked or Secret Service bridge disabled | Unlock KDE Wallet, or enable Secret Service integration in KDE System Settings |
@aspect-build/keytar build failure |
Missing C++ build tools for native addon | Install build-essential (Linux), Xcode CLI tools (macOS), or Visual Studio Build Tools (Windows). Or use linux_keyring_backend: "dbus-next" to avoid native compilation. |
Encrypted key not found for alias 'X' |
Key not stored yet | Run agentic-payments-bot keys store --alias X ... |
Network 'X' is disabled in configuration |
Chain disabled in YAML | Set web3.X.enabled: true in config |
x402 protocol is disabled in configuration |
Protocol toggle | Set protocols.x402.enabled: true |
Could not parse a valid payment intent |
AI output doesn't contain valid JSON | Ensure agent uses the exact JSON schema from SKILL.md |
SQLITE_BUSY errors |
Concurrent writes | Increase database.busy_timeout_ms or ensure WAL mode |
Policy violations detected (unexpected) |
Aggregate limits hit | Check agentic-payments-bot audit --category policy and adjust policy.rules |
| Web API not starting | Port conflict | Change web_api.port in config |
Google Pay requires a 'paymentToken' in metadata |
Missing client-side token | Ensure the Google Pay JS API token is passed in metadata.paymentToken |
Apple Pay requires a 'paymentToken' in metadata |
Missing client-side token | Ensure the Apple Pay JS API token is passed in metadata.paymentToken |
Apple Pay merchant validation failed |
Invalid cert or domain | Verify domain is registered with Apple and applepay_merchant_cert is valid |
x402 settlement failed: Facilitator rejected |
Invalid payment payload or facilitator unreachable | Check facilitator_url in config, verify the signed authorization fields (amount, payTo, time bounds) |
MPP /quote failed: 404 |
Recipient URL is not an MPP endpoint | Ensure the recipient points to <origin>/mpp (the client also accepts a deeper path and strips it back to /mpp) |
MPP /invoice failed: 410 Quote has expired |
Client took too long between quote and invoice | Re-run the flow; quotes expire after 5 minutes by default |
MPP /settle failed: 410 Invoice has expired |
Took too long to settle | Request a new invoice (default TTL is 10 minutes) |
Invoice rail is X, got Y |
rail in /settle does not match the invoice |
Use the rail the invoice was issued for (or request a new invoice with preferred_rail) |
MPP x402 rail requires network/asset/pay_to in invoice |
Merchant configured the MPP x402 rail without specifying on-chain details | Set protocols.mpp.default_network, default_asset, and pay_to in your config |
AP2 mandate has expired |
Mandate valid_until is in the past |
Create a new mandate with a future expiry |
Mandate already executed (single-use) |
Attempting to reuse a single-use mandate | Create a new mandate for each payment |
Invalid X-PAYMENT header |
Malformed Base64 or JSON in x402 payment header | Ensure the X-PAYMENT header is valid Base64-encoded JSON matching X402PaymentPayload |
Unsupported payment method type: X |
AP2 payment method not implemented | Use one of: stripe, paypal, card, crypto |
Set log level to debug in config/default.yaml:
logging:
level: "debug"
Check the audit log for full context:
agentic-payments-bot audit --limit 30
Inspect a specific transaction:
agentic-payments-bot tx <transaction-id>
Query SQLite directly:
sqlite3 data/payments.db "SELECT * FROM transactions ORDER BY created_at DESC LIMIT 10;"
sqlite3 data/payments.db "SELECT * FROM audit_log ORDER BY timestamp DESC LIMIT 20;"
This project is licensed under the Apache 2.0 License. See the LICENSE-APACHE file for the details.
Built with ๐ค๐ต for the Open Agent Skills Ecosystem and for the OpenClaw ecosystem. Protocols: x402 ยท AP2
๐ค๐ต Agentic Payment Service for Open Agent Skills Ecosystem.
The open authority layer + SDKs for AI-agent payments. Thin Python/TS clients, an MCP server, framework adapters (LangChain/CrewAI/Hermes/OpenClaw/โฆ), and @sardis/reference โ a pure policy simulator + AP2/TAP/x402 verifiers showing exactly how Sardis decides if an agent may spend. The hosted engine that moves money is private.
Give AI agents a wallet โ x402 payment tools over Model Context Protocol.
The brutally honest map of where AI-agent money actually flows. 51 rounds, 137 angles, 230+ platforms. 3 self-hosted x402 v2 endpoints + 3 tools in the official MCP Registry. 385K star distribution.
x402 (HTTP 402 Payment Required) SDK + MCP server: let any API charge for itself and any AI agent pay for itself, USDC & stablecoins across EVM, Solana & 8 more chain families, in a couple of lines. Backendless, no fee, self-custodial, paid straight to your wallet. TypeScript, MIT.
Stateless Solana program for validating transaction deadlines. Reference implementation for x402 SVM Extension RFC
Lucid Agents Commerce SDK. Bootstrap AI agents in 60 seconds that can pay, sell, and participate in agentic commerce supply chains. Our protocol agnostic SDK provides CLI-generated templates and drop-in adapters for Hono, Express, Next.js, and TanStack, giving you instant access to crypto/fiat payment rails (AP2, A2A, x402, ERC8004).
Building blocks for Agentic payments (x402, MPP, AP2) for TypeScript, Rust, Go, Python, Ruby, PHP, Lua, Kotlin and Swift.
Building blocks for Agentic payments (x402, MPP, AP2) for TypeScript, Rust, Go, Python, Ruby, PHP, Lua, Kotlin and Swift.
Skills & plugins for agentic commerce : UCP, ACP, AP2, A2A, WebMCP, Magento 2, BigCommerce, WooCommerce
Trust infrastructure for million-agent economies on Solana - identity, reputation, and validation designed for continuous feedback at scale.
A chain-agnostic AI-native payment infrastructure, authz layer for x402