Machine-payable AI microservices via the 402 Payment Required protocol (x402 / MPP)
No accounts. No API keys. No OAuth. Pay per call in USDC on Base.
AgentPay is an open-source reference implementation of the Machine Payments Protocol — wrapping local AI models behind an HTTP 402 paywall so that AI agents (and humans) can pay for compute on a per-request basis using stablecoins.
Built with Express 5, @x402/express, and Ollama-served Gemma models. Live on Base mainnet with the PayAI facilitator.
Table of Contents
Quick Start
Prerequisites
- Node.js ≥ 20
- Ollama running locally with the required model pulled
- A wallet private key (for receiving payments)
1. Clone & install
git clone https://github.com/ronaldanton/x402-shop.git
cd x402-shop
npm install
2. Pull the AI model
4. Start the server
5. Test a paid request
curl -s -o /dev/null -w "%{http_code}" -X POST https://agentpay.help/v1/summarize \
-H 'Content-Type: application/json' \
-d '{"text":"Machine Payments Protocol lets AI agents pay for API calls using the HTTP 402 status code."}'
npm run test:402
6. Buy a service (buyer client)
echo "BUYER_PK=0xYourPrivateKey" >> .env
npm run buyer -- /v1/summarize ./payload.json
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ AgentPay Architecture │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ HTTP POST ┌───────────────────────────┐ │
│ │ Client │ ──────────────► │ Express 5 Server │ │
│ │ (Agent / │ (no auth) │ (port 4021) │ │
│ │ Human) │ │ │ │
│ └──────────┘ │ ┌─────────────────────┐ │ │
│ │ │ │ Payment Middleware │ │ │
│ │ │ │ (@x402/express) │ │ │
│ │ │ │ │ │ │
│ │ ◄── HTTP 402 ───────│ │ • Validates x402 │ │ │
│ │ (paywall) │ │ payment headers │ │ │
│ │ │ │ • Verifies on-chain │ │ │
│ │ ──── signed payment ►│ │ via facilitator │ │ │
│ │ (USDC) │ │ │ │ │
│ │ │ └──────────┬──────────┘ │ │
│ │ ◄── 200 OK ─────────│ │ │ │
│ │ (result JSON) │ ┌──────────▼──────────┐ │ │
│ │ │ │ Service Handlers │ │ │
│ │ │ │ │ │ │
│ │ │ │ /v1/summarize │ │ │
│ │ │ │ /v1/classify-ins │ │ │
│ │ │ │ /v1/extract │ │ │
│ │ │ └──────────┬──────────┘ │ │
│ │ └─────────────┼─────────────┘ │
│ │ │ │
│ │ ┌──────▼──────┐ │
│ │ │ Ollama │ │
│ │ │ (local LLM) │ │
│ │ │ gemma3:1b │ │
│ │ └─────────────┘ │
│ │ │
│ ┌────▼────────────────────────────────────────────────────┐ │
│ │ Payment Flow (x402) │ │
│ │ │ │
│ │ Client ──► HTTP 402 ──► Facilitator ──► On-Chain ──► │ │
│ │ │ (PayAI) Base Mainnet │ │
│ │ ▼ (USDC) │ │
│ │ Payment Required │ │
│ │ (price + accepts[]) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Free Endpoints (no paywall) │ │
│ │ • / — Landing page (HTML) │ │
│ │ • /health — Health check │ │
│ │ • /stats — Revenue & usage stats │ │
│ │ • /.well-known/x402 — Machine-readable service catalog │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Data Layer │ │
│ │ • data/ledger.json — Append-only payment ledger │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
How it works:
- Client sends
POST /v1/summarize (or any paid endpoint) — no auth headers needed
- Payment middleware intercepts, returns HTTP 402 with pricing info (
accepts[])
- Client constructs a USDC payment, signs it, attaches
X-PAYMENT header
- Facilitator verifies the payment on Base mainnet
- Middleware grants access → request proceeds to the service handler
- Handler calls Ollama, returns AI-generated result as JSON
Services & Pricing
| Endpoint | Price | Description |
|---|
POST /v1/summarize | $0.01 | AI text summarization — crisp 250-word summary of any text up to 20k chars |
POST /v1/classify-insurance | $0.02 | Insurance lead classifier — intent, urgency, line of business, confidence |
POST /v1/sentiment | $0.02 | Sentiment analysis — positive/negative/neutral with emotions and keywords |
POST /v1/extract | $0.03 | Structured field extraction — key-value pairs from emails, forms, documents |
POST /v1/translate | $0.03 | Text translation — translate to any language |
POST /v1/code-review | $0.05 | AI code review — bugs, security, performance, quality score |
POST /v1/insurance-analysis | $0.10 | Full insurance analysis bundle — classification + field extraction + summary in one call |
POST /v1/token-safety | $0.02 | Token safety check - rug pull risk, honeypot detection, liquidity analysis |
POST /v1/wallet-risk | $0.02 | Wallet risk screening - OFAC sanctions, scam flags, tx patterns |
POST /v1/web-scrape | $0.01 | Extract clean text from any URL - agents read web pages |
POST /v1/crypto-price | $0.005 | Real-time crypto prices - BTC, ETH, SOL + more |
POST /v1/image-describe | $0.03 | Vision AI - describe any image from URL |
POST /v1/defi-yields | $0.01 | DeFi yield data - APY, TVL, protocol info |
POST /v1/threat-intel | $0.02 | CVE/threat intelligence - vulnerability lookup, severity |
POST /v1/sanctions-screen | $0.02 | OFAC/EU sanctions screening - entity check |
POST /v1/market-intel | $0.02 | Macro/economic snapshot - GDP, inflation, rates |
POST /v1/on-chain-events | $0.01 | Decoded on-chain events - recent transfers |
POST /v1/content-safety | $0.02 | Content security scan - PII, toxicity, bias |
POST /v1/agent-reputation | $0.01 | Agent reputation score - endpoint trustworthiness |
POST /v1/legal-lookup | $0.03 | Legal/regulatory lookup - company registration |
POST /v1/news-feed | $0.005 | Real-time news feed - headlines by topic |
POST /v1/weather-data | $0.005 | Weather data - current conditions and forecast |
POST /v1/web-search | $0.01 | Web search - top results for any query with title, url, snippet |
POST /v1/memory | $0.005 | Persistent key-value memory scoped to your wallet - agents remember across runs |
POST /v1/geocode | $0.005 | Geocode place names to lat/lon; reverse geocode coordinates to addresses |
POST /v1/eth-gas | $0.003 | Ethereum gas prices - rapid/fast/standard/slow in gwei plus ETH spot price |
POST /v1/prediction-market | $0.01 | Polymarket prediction market odds - live probabilities for any topic |
POST /v1/deep-research | $0.25 | PREMIUM deep research - multi-source web research into a cited markdown report |
All services accept USDC on Base mainnet (chain ID 8453) via the exact payment scheme. Testnet (Base Sepolia) is available via configuration.
MCP Server
AgentPay ships two Model Context Protocol servers so any MCP-capable client (Claude Desktop, Cursor, Windsurf, VS Code, Smithery hosts, …) can call the paid endpoints directly.
1. Remote (Streamable HTTP) — no install, no API keys
The live server exposes all 28 services as MCP tools:
POST https://agentpay.help/mcp
- Transport: Streamable HTTP (JSON-RPC 2.0)
- Auth: none — connecting is free; the underlying endpoint is paid
tools/list → 28 tools, one per service
When a tool is called, the handler performs the real HTTP request and, on HTTP 402, returns the x402 v2 payment challenge (decoded from the PAYMENT-REQUIRED response header) to the calling agent, along with the price and a ready-to-send X-PAYMENT hint. An x402-capable client pays in USDC on Base and retries to receive the result.
Verify the handshake:
curl -s -X POST https://agentpay.help/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jq '.result.tools | length'
Discovery manifests: /.well-known/mcp.json (both servers) and /.well-known/mcp-endpoint.json.
2. Local (stdio) — pays from a local wallet
npx github:ronaldanton/x402-shop mcp-server.js
| Env var | Description |
|---|
SHOP_URL | Base URL of the AgentPay deployment (default https://agentpay.help) |
BUYER_PRIVATE_KEY | Hex private key of the buyer wallet — the MCP server signs and settles the x402 payment automatically |
This variant settles payments itself, so the MCP client needs no x402 awareness.
Registry
Published to the official MCP Registry as io.github.ronaldanton/agentpay with the remote transport declared:
{ "type": "streamable-http", "url": "https://agentpay.help/mcp" }
Tech Stack
| Component | Technology |
|---|
| Runtime | Node.js ≥ 20 (ESM) |
| HTTP Server | Express 5.2 |
| Payment Protocol | @x402/express 2.22, @x402/evm, @x402/fetch, @x402/extensions |
| Blockchain | Base (OP Stack L2), USDC stablecoin |
| Facilitator | PayAI x402 facilitator (x402.org/facilitator) |
| AI Runtime | Ollama (local inference) |
| LLM | Gemma 3 1B (default) / Gemma 4 31B (recommended) |
| Wallet | viem (Ethereum client library) |
| Config | dotenv |
Deployment
Local Development
cp .env.example .env
npm start
Production (Base Mainnet)
PAYMENT_NETWORK=eip155:8453
SELLER_ADDRESS=0xYourMainnetWallet
OLLAMA_URL=http://127.0.0.1:11434
MODEL_SUMMARIZE=gemma4:31b-cloud
MODEL_CLASSIFY=gemma4:31b-cloud
MODEL_EXTRACT=gemma4:31b-cloud
Docker (recommended for production)
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY src/ ./src/
COPY data/ ./data/
EXPOSE 4021
HEALTHCHECK CMD curl -f https://agentpay.help/health || exit 1
CMD ["node", "src/server.js"]
Environment Variables
| Variable | Required | Default | Description |
|---|
PORT | No | 4021 | Server port |
SELLER_ADDRESS | Yes | — | Wallet address to receive USDC payments |
PAYMENT_NETWORK | No | eip155:84532 | Blockchain network (eip155:8453 for mainnet) |
FACILITATOR_URL | No | https://x402.org/facilitator | x402 facilitator endpoint |
OLLAMA_URL | No | http://127.0.0.1:11434 | Ollama API base URL |
MODEL_SUMMARIZE | No | gemma3:1b | Model for summarize endpoint |
MODEL_CLASSIFY | No | gemma3:1b | Model for classify-insurance endpoint |
MODEL_EXTRACT | No | gemma3:1b | Model for extract endpoint |
PUBLIC_URL | No | — | Public URL for discovery metadata |
API Reference
Free Endpoints
GET /
Landing page with service catalog and usage stats.
GET /health
Health check.
{ "ok": true, "ts": "2025-01-01T00:00:00.000Z" }
GET /stats
Revenue and usage statistics.
{
"requests_paid": 42,
"gross_usd": 0.84,
"by_service": { "summarize": 0.42, "classify-insurance": 0.28, "extract": 0.14 },
"last_20": [...]
}
GET /.well-known/x402
Machine-readable service catalog (Bazaar discovery extension). Use this for automated service discovery by AI agents.
{
"name": "AgentPay",
"description": "Pay-per-call AI microservices (x402 / MPP)",
"endpoints": [
{ "path": "/v1/summarize", "method": "POST", "price": "$0.01", "description": "Summarize text (200-20k chars)" },
{ "path": "/v1/classify-insurance", "method": "POST", "price": "$0.02", "description": "Insurance lead classification" },
{ "path": "/v1/extract", "method": "POST", "price": "$0.03", "description": "Structured field extraction" }
]
}
Paid Endpoints
All paid endpoints require a valid x402 payment in the X-PAYMENT header. Unpaid requests receive HTTP 402 Payment Required.
POST /v1/summarize — $0.01
Summarize text into a concise ~250-word output.
Request:
{
"text": "Your text to summarize (200-20000 characters)..."
}
Response (200 OK):
{
"summary": "The text discusses...",
"words": 247
}
Errors:
400 — Missing text field or text exceeds 20,000 characters
402 — Payment required (see x402 protocol)
502 — Upstream AI model failed
POST /v1/classify-insurance — $0.02
Classify an insurance lead or customer message.
Request:
{
"text": "I was in a car accident last week and need to file a claim urgently..."
}
Response (200 OK):
{
"intent": "claim",
"urgency": "high",
"line": "auto",
"confidence": 0.92
}
Possible values:
intent: quote_request | renewal | claim | complaint | other
urgency: low | medium | high
line: auto | home | life | health | commercial | other
Extract structured fields from raw text (emails, forms, documents).
Request:
{
"text": "From: john@example.com\nSubject: Policy #12345 renewal\nDear customer, your auto policy expires on March 15...",
"fields": ["email", "policy_number", "expiry_date"]
}
Response (200 OK):
{
"email": "john@example.com",
"policy_number": "12345",
"expiry_date": "March 15"
}
If fields is omitted, all extractable key-value pairs are returned.
Client Library (Buyer)
Use @x402/fetch to automatically handle the 402 → payment → retry flow:
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(process.env.BUYER_PK);
const client = x402Client.fromConfig({
schemes: [{ network: "eip155:*", client: new ExactEvmScheme(signer) }],
});
const payFetch = wrapFetchWithPayment(globalThis.fetch, client);
const res = await payFetch("https://agentpay.help/v1/summarize", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: "Your text here..." }),
});
const result = await res.json();
console.log(result.summary);
Contributing
Contributions are welcome! This is an open-source reference implementation of the x402 / MPP protocol.
Development Setup
git clone https://github.com/ronaldanton/x402-shop.git
cd x402-shop
npm install
cp .env.example .env
npm start
Adding a New Service
- Define the payment middleware entry in
src/server.js under the paymentMiddleware() call
- Add the route handler after the middleware block
- Register the endpoint in
/.well-known/x402 discovery
- Add to the landing page HTML
Guidelines
- Keep it simple. This is a reference implementation — clarity over complexity.
- Test on Base Sepolia first. Use the testnet before going to mainnet.
- Use
@x402/ packages. Don't reinvent payment verification.
- Append-only ledger. Never modify
data/ledger.json — only append.
Reporting Issues
Open a GitHub issue with:
- Steps to reproduce
- Expected vs. actual behavior
- Environment (Node version, OS, model used)
License
MIT
Resources