Your AI agent can call a gas price API, a web scraper, a CAPTCHA solver, or a Polymarket data feed — and pay for each call in USDC, automatically, without an API key, without a subscription. This tutorial walks through building one in Python, from discovery to payment.
We'll build an agent that:
Everything runs from a single Python file. No browser. No signup form. Just code.
An agent that pays for APIs needs to do three things. Each maps to a real HTTP call:
GET /api/services
Returns every available endpoint with price, category, trial count, and health status. Your agent picks the ones it needs.
GET /x402/{service}?trial=1
First 15 calls are free. No wallet. No signup. The response includes real data. Your agent verifies the API actually returns what it needs before committing money.
POST /api/v1/register-simple {"name":"my-agent"}
GET /x402/{service}?wallet=0x...
Register to get 500 free credits and a wallet. After credits run out, send USDC on Base to buy more. Each API call deducts credits automatically.
Here's the complete Python agent. Save it as agent.py and run it:
#!/usr/bin/env python3
"""
x402 Agent — discovers APIs, claims free trials, pays for calls.
No API keys. No subscriptions. Just HTTP 402 + USDC.
"""
import requests
import json
import time
import sys
BASE = "https://minia2a.uk"
class X402Agent:
def __init__(self):
self.wallet = None
self.credits = 0
self.session = requests.Session()
self.session.headers.update({"User-Agent": "x402-agent-tutorial/1.0"})
# ── Discovery ────────────────────────────────────────────
def discover(self, category=None, max_price=5):
"""Find available APIs. Filter by category and max price in cents."""
r = self.session.get(f"{BASE}/api/services")
r.raise_for_status()
services = r.json()["services"]
results = []
for s in services:
if category and s.get("category") != category:
continue
if s.get("priceCents", 0) > max_price:
continue
results.append({
"id": s["id"],
"name": s["name"],
"price": s.get("priceCents", 0),
"category": s.get("category", "unknown"),
"endpoint": s["endpoint"],
"trials": s.get("trialCount", 0),
})
return sorted(results, key=lambda x: x["trials"], reverse=True)
# ── Trial ────────────────────────────────────────────────
def try_service(self, service_id):
"""Call an API with free trial. Returns data or 402 if exhausted."""
url = f"{BASE}/x402/{service_id.replace('x402-', '')}?trial=1"
r = self.session.get(url)
if r.status_code == 200:
return {"ok": True, "data": r.json()}
elif r.status_code == 402:
info = r.json()
return {
"ok": False,
"exhausted": True,
"message": info.get("message", "Trial limit reached"),
"trials_max": info.get("trialsMax", 0),
}
else:
return {"ok": False, "error": f"HTTP {r.status_code}"}
# ── Registration ─────────────────────────────────────────
def register(self, name="my-agent"):
"""Register to get 500 free credits and a wallet address."""
r = self.session.post(
f"{BASE}/api/v1/register-simple",
json={"name": name}
)
if r.status_code == 200:
data = r.json()
self.wallet = data.get("wallet")
print(f"✅ Registered! Wallet: {self.wallet[:10]}...")
self._fetch_credits()
return True
else:
print(f"Registration failed: {r.json().get('error', 'unknown')}")
return False
def _fetch_credits(self):
"""Check credit balance."""
if not self.wallet:
return
r = self.session.get(f"{BASE}/api/v1/credits?wallet={self.wallet}")
if r.status_code == 200:
data = r.json()
self.credits = data.get("credits_remaining", 0)
print(f"💳 Credits: {self.credits}")
# ── Paid call ────────────────────────────────────────────
def call_with_credits(self, service_id):
"""Call API using credits from wallet."""
if not self.wallet:
print("❌ Register first to get a wallet")
return None
url = f"{BASE}/x402/{service_id.replace('x402-', '')}?wallet={self.wallet}"
r = self.session.get(url)
if r.status_code == 200:
self._fetch_credits()
return {"ok": True, "data": r.json()}
elif r.status_code == 402:
info = r.json()
print(f"Credits exhausted: {info.get('credits_remaining', 0)} remaining")
return {"ok": False, "need_payment": True, "info": info}
else:
return {"ok": False, "error": f"HTTP {r.status_code}"}
# ── Orchestration ────────────────────────────────────────
def find_and_call(self, keyword, max_price=5):
"""Discover APIs matching a keyword, trial the top one, then pay if needed."""
print(f"\n🔍 Searching for: {keyword}")
all_services = self.discover(max_price=max_price)
matches = [s for s in all_services if keyword.lower() in s["name"].lower()]
if not matches:
print(f" No services found matching '{keyword}'")
return None
print(f" Found {len(matches)} matching services:")
for m in matches[:5]:
print(f" • {m['name']} — {m['price']}¢/call, {m['trials']}+ trials")
# Trial the most popular one
best = matches[0]
print(f"\n🧪 Trying: {best['name']} (free trial)")
result = self.try_service(best["id"])
if result["ok"]:
print(f" ✅ Trial worked! Got data.")
return result
if result.get("exhausted"):
print(f" ⚠️ Trials exhausted. Need registration.")
if not self.wallet:
if self.register(keyword.replace(" ", "-")):
print(f"\n🔄 Retrying with credits: {best['name']}")
time.sleep(1)
return self.call_with_credits(best["id"])
else:
return self.call_with_credits(best["id"])
return result
# ── Demo ─────────────────────────────────────────────────────
if __name__ == "__main__":
agent = X402Agent()
# 1. See what's available
print("═══ Available Crypto APIs ═══")
crypto = agent.discover(category="crypto", max_price=3)
for s in crypto[:5]:
print(f" {s['name']:30s} {s['price']:3d}¢ {s['trials']:5d}+ trials")
# 2. Try one for free
print("\n═══ Free Trial Demo ═══")
gas = agent.try_service("x402-gas")
if gas["ok"]:
data = gas["data"]
if isinstance(data, dict):
# Print first 3 keys
keys = list(data.keys())[:5]
for k in keys:
v = str(data[k])[:80]
print(f" {k}: {v}")
# 3. If trials exhausted, register and pay
if not gas["ok"] and gas.get("exhausted"):
print("\n═══ Registration ═══")
agent.register("tutorial-agent")
print("\n═══ Paid Call ═══")
result = agent.call_with_credits("x402-gas")
if result and result["ok"]:
print(" ✅ Paid call succeeded!")
print("\n═══ Agent complete ═══")
Every IP gets 15 free calls to each endpoint. The server tracks this by IP — no account needed. When trials run out, the server returns HTTP 402 with a JSON body telling the agent how to register:
Your agent reads the 402, extracts the registration endpoint, and registers programmatically. No human clicks a signup form.
After registration, your agent gets a wallet address and 500 free credits. Each API call deducts 1–5 credits depending on the endpoint price. The server returns credits_remaining in the response so your agent knows when it's running low:
When credits hit zero, your agent sends USDC on Base to the platform wallet. 1 USDC = 200 credits. Standard APIs cost 1–3 credits per call — that's half a cent. Premium APIs (AI inference, heavy compute) cost more and are paid directly per call.
Here's what agents are actually doing with this pattern today:
| Agent Type | APIs Called | Cost/hr |
|---|---|---|
| DeFi monitor | gas, price oracle, swap safety, fee history | ~$0.02 |
| Research crawler | web scrape, search, summarize, web-retrieve | ~$0.08 |
| Security auditor | token security, contract scan, email verify, DNS | ~$0.05 |
| Market analyst | Polymarket, fear-greed, sentiment, funding rate | ~$0.04 |
At under $0.10/hour for most workloads, agents can be always-on without worrying about API bills. The pay-per-call model means you only pay for what you use — no monthly minimum, no unused subscription.
The agent above discovers and calls APIs mechanically. The real power comes when you add an LLM that decides which API to call based on the task:
def decide_and_call(self, task: str) -> dict:
"""Ask an LLM which API to use, then call it."""
services = self.discover()
# Build a prompt with available tools
tools_desc = "\n".join(
f"- {s['name']}: {s['price']}¢ — {s['trials']}+ trials"
for s in services[:20]
)
prompt = f"""You can call these APIs:
{tools_desc}
Task: {task}
Return JSON: {{"service": "x402-name", "reason": "..."}}"""
# Call your LLM of choice
response = your_llm(prompt) # Claude, GPT, etc.
choice = json.loads(response)
# Try the chosen service
result = self.try_service(choice["service"])
if not result["ok"] and result.get("exhausted"):
result = self.call_with_credits(choice["service"])
return {"choice": choice, "result": result}
The agent's workflow becomes: task → LLM selects API → trial call → if 402, pay → return result. The LLM is the brain. The x402 marketplace is the hands.
Everything above runs with just pip install requests. No SDK. No API key provisioning. No wallet setup (the platform creates one for you). The agent discovers, trials, registers, and pays — all in HTTP.
This is what makes the x402 model different from traditional API marketplaces. Your agent doesn't need a human to create accounts, manage keys, or fund wallets. It handles the full lifecycle: discovery → trial → payment → delivery.
Try it: browse 328 live endpoints, each with free trials. Your agent can be paying for its own API calls in under 10 minutes.