How to Monetize Your API for AI Agents Using XRP Payment Channels
AI agents are becoming significant API consumers. As autonomous programs chain calls across services to complete tasks, the traditional model of API keys and monthly subscriptions creates friction. This guide walks through adding micropayment billing to a Python API using XRP payment channels.
Prerequisites
- Python 3.9+
- A REST API (Flask, FastAPI, or Django)
- An XRP testnet wallet (we'll set one up below)
- Basic familiarity with decorators and middleware patterns
Testnet Setup
Before writing code, get a funded testnet wallet. The XRPL testnet faucet provides free test XRP:
# Get a funded testnet wallet
# Visit: https://faucet.altnet.rippletest.net/accounts
# Or use the SDK:
from clasp import create_testnet_wallet
wallet = create_testnet_wallet()
print(f"Address: {wallet.address}")
print(f"Seed: {wallet.seed}") # Save this for configuration
The testnet mirrors mainnet behavior but with free XRP. All examples below use
network="testnet" — switch to "mainnet" when you're ready for production.
Install
pip install clasp-protocol
Initialize
from clasp import CLASPServer
# Configure with your XRP address and network
sp = CLASPServer(
xrp_address="rYourTestnetAddress...",
network="testnet", # Use "mainnet" for production
)
Protect Endpoints
from flask import Flask, request
app = Flask(__name__)
@app.route("/api/weather/forecast")
@sp.require_payment(price_drops=1000) # 0.001 XRP per call
def get_forecast():
city = request.args.get("city", "Toronto")
return {"forecast": get_weather(city)}
@app.route("/api/translate")
@sp.require_payment(price_drops=5000) # 0.005 XRP per call (heavier compute)
def translate():
text = request.json["text"]
target = request.json.get("target_lang", "en")
return {"translation": translate_text(text, target)}
That's it. Your API now accepts CLASP micropayments. Requests without a valid payment claim
receive an HTTP 402 Payment Required response with instructions.
Under the Hood
When a request arrives, the SDK does the following:
- Extracts the
X-CLASP-Claimheader (base64-encoded claim + signature) - Decodes the 44-byte claim: 4-byte magic (
CLM), 32-byte channel ID, 8-byte amount - Verifies the ECDSA secp256k1 signature against the channel's public key
- Confirms the claimed amount exceeds the previous claim by at least
price_drops - Returns the response if valid, or
402with payment instructions if not
No blockchain call is needed for verification. The signature check is pure cryptography, completing in under 1ms. The channel's existence and funding are verified only at channel open time.
Security Model
The cryptographic properties of payment channels provide strong guarantees:
- Double-spend prevention: Claims are cumulative and monotonically increasing. A claim for 5,000 drops followed by a claim for 3,000 drops is invalid by definition.
- Forgery prevention: Claims require a valid ECDSA signature from the channel's source keypair. Without the private key, claims cannot be fabricated.
- Rate limiting: The channel has a finite deposit. Once the cumulative claims reach the channel balance, the agent must fund or open a new channel.
For additional protection, add standard rate limiting on top of payment verification:
# Optional: combine with rate limiting
@app.route("/api/expensive-operation")
@rate_limit(max_per_minute=60) # Your rate limiter
@sp.require_payment(price_drops=10000)
def expensive_operation():
return {"result": run_expensive_computation()}
Settlement
# Settle all open channels — one on-chain transaction each
sp.settle_all()
# Or settle a specific channel
sp.settle(channel_id="ABC123...")
Settlement submits the latest claim for each channel to the XRP Ledger. The provider receives the claimed amount; the remainder returns to the agent. Run settlement on a schedule (daily, weekly) or when channel balances reach a threshold.
Framework Compatibility
The require_payment decorator works with Flask out of the box. For other frameworks:
- FastAPI: Use
sp.fastapi_dependency(price_drops=1000)as a Depends() parameter - Django: Use
sp.django_middleware()in your MIDDLEWARE setting - Express.js: Use the Node SDK:
sp.requirePayment({priceDrops: 1000})as middleware
Pricing Guide
Suggested pricing tiers based on computational cost (1 XRP = 1,000,000 drops):
| Operation Type | Drops | USD Equivalent* |
|---|---|---|
| Simple lookups (key-value, status checks) | 100-500 | $0.0002-$0.001 |
| Database queries (filtered, paginated) | 500-2,000 | $0.001-$0.004 |
| Complex computation (aggregation, analysis) | 2,000-10,000 | $0.004-$0.02 |
| LLM inference (prompt + completion) | 10,000-100,000 | $0.02-$0.20 |
| GPU workloads (image gen, fine-tuning) | 50,000-500,000 | $0.10-$1.00 |
* At ~$2.00/XRP. Prices in drops remain stable; USD equivalent varies with XRP price.
Troubleshooting
- 402 with "no claim header": The client isn't sending the
X-CLASP-Claimheader. Ensure the agent SDK is configured with the correct server URL. - 402 with "insufficient amount": The claim increment is less than
price_drops. The agent's cumulative claim must increase by at least the endpoint price with each call. - 402 with "invalid signature": The claim signature doesn't match the channel's public key. Verify the agent is using the correct keypair for the channel.
- Channel not found: The channel ID in the claim doesn't exist on-ledger. The agent needs to open a channel to your address first.
Next Steps
For the business case behind micropayment APIs, read From SaaS to Pay-Per-Call. For the technical comparison of payment protocols, see Stripe x402 vs XRP Payment Channels.
Full SDK documentation: symplesolutions.ca/clasp
Want to learn more about developer guide?
Get in touch →