Python SDK for x402 payments - pay and charge for APIs with stablecoins. OpenClaw compatible.
Project description
primer-x402
Python SDK for x402 HTTP payments by Primer. OpenClaw compatible 🦞
Easily add pay-per-request monetization to your Python APIs using the x402 protocol. Accept stablecoin payments (USDC, EURC) or any ERC-20 token with gasless transactions—payers never pay gas fees.
Quick Start (CLI)
# Create a new wallet
x402 wallet create
# Check balance
x402 wallet balance 0xYourAddress
# Probe a URL for x402 support
x402 probe https://api.example.com/paid
# Set up for OpenClaw
x402 openclaw init
Why x402?
- HTTP-native payments - Uses the standard HTTP 402 Payment Required status code
- Gasless for payers - Payments are authorized via EIP-712 signatures; facilitators handle gas
- Stablecoin support - Native support for USDC/EURC via EIP-3009
transferWithAuthorization - Any ERC-20 token - Support for other tokens via Primer's Prism settlement contract
- Multi-chain - Base, Ethereum, Arbitrum, Optimism, Polygon (mainnet + testnet)
- Framework integrations - Flask, FastAPI middleware included
- Testing utilities - Mock facilitator for integration testing
Installation
pip install primer-x402
With optional dependencies:
pip install primer-x402[flask] # Flask middleware
pip install primer-x402[fastapi] # FastAPI middleware
pip install primer-x402[httpx] # Async HTTP client
pip install primer-x402[all] # All optional dependencies
Quick Start
Payer (Client)
Wrap your HTTP client to automatically handle 402 responses:
import os
from primer_x402 import create_signer, x402_requests
# Create a signer with your wallet
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
# Create a session that handles 402 payments automatically
with x402_requests(signer, max_amount='1.00') as session:
response = session.get('https://api.example.com/paid-endpoint')
print(response.json())
When the server returns 402 Payment Required, the SDK automatically:
- Parses the payment requirements from the response
- Creates a signed payment authorization (no gas required)
- Retries the request with the payment header
- Returns the successful response
Payee (Server)
Add payment requirements to your API routes:
from flask import Flask, jsonify
from primer_x402 import x402_flask
app = Flask(__name__)
@app.before_request
@x402_flask('0xYourWalletAddress', {
'/api/premium': {
'amount': '0.01', # $0.01 USDC
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', # USDC on Base
'network': 'eip155:8453' # Base mainnet
}
})
def require_payment():
pass
@app.route('/api/premium')
def premium_content():
return jsonify({'data': 'premium content'})
Token Types
EIP-3009 Tokens (USDC, EURC)
These tokens support gasless transfers natively via transferWithAuthorization. The payer signs an authorization, and the facilitator executes the transfer—payer pays zero gas.
Standard ERC-20 Tokens
For other ERC-20 tokens, Primer's Prism contract enables gasless payments:
- One-time approval - Approve the Prism contract to spend your tokens
- Gasless payments - Sign authorizations; Prism handles the transfers
from primer_x402 import create_signer, approve_token
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
# One-time approval (this transaction requires gas)
receipt = approve_token(signer, '0xTokenAddress')
# Now you can make gasless payments with this token
Supported Networks
Networks use CAIP-2 identifiers.
| Network | CAIP-2 ID | Default Facilitator |
|---|---|---|
| Base | eip155:8453 |
Primer |
| Base Sepolia | eip155:84532 |
Primer |
| Ethereum | eip155:1 |
Custom required |
| Arbitrum | eip155:42161 |
Custom required |
| Optimism | eip155:10 |
Custom required |
| Polygon | eip155:137 |
Custom required |
Legacy network names (
'base','ethereum') are accepted for compatibility but CAIP-2 is recommended.
Custom Facilitator
For non-Base networks, provide your own facilitator:
# Payer
session = x402_requests(signer, max_amount='1.00', facilitator='https://your-facilitator.com')
# Payee
@x402_flask('0xAddress', routes, facilitator='https://your-facilitator.com')
FastAPI Example
from fastapi import FastAPI
from primer_x402 import x402_fastapi
app = FastAPI()
app.add_middleware(x402_fastapi(
'0xYourWalletAddress',
{
'/api/premium': {
'amount': '0.01',
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
'network': 'eip155:8453'
}
}
))
@app.get('/api/premium')
async def premium():
return {'data': 'premium content'}
Testing
The SDK includes utilities for testing your integration without real payments:
import pytest
from primer_x402.testing import create_mock_facilitator, create_test_payment
@pytest.fixture
def mock_facilitator():
mock = create_mock_facilitator(mode='approve')
yield mock
mock.close()
def test_paid_endpoint(client, mock_facilitator):
payment = create_test_payment(amount='10000') # 0.01 USDC
response = client.get(
'/api/premium',
headers={'X-PAYMENT': payment}
)
assert response.status_code == 200
Debug Logging
import logging
logging.getLogger('x402').setLevel(logging.DEBUG)
CLI Reference
x402 <command> [options]
| Command | Description |
|---|---|
wallet create |
Create a new wallet |
wallet balance <address> |
Check USDC/ETH balance |
wallet from-mnemonic |
Restore wallet from mnemonic |
probe <url> |
Check if URL supports x402 |
pay <url> |
Make a payment to a 402 endpoint |
pay <url> --dry-run |
Preview payment without paying |
networks |
List supported networks |
facilitator |
Show facilitator info |
openclaw init |
Set up x402 for OpenClaw |
openclaw status |
Check OpenClaw status |
Environment Variables
| Variable | Description |
|---|---|
X402_PRIVATE_KEY |
Wallet private key |
X402_NETWORK |
Default network (default: base) |
X402_MAX_AMOUNT |
Default max payment amount |
X402_FACILITATOR |
Facilitator URL override |
Examples
# Create wallet and save output
x402 wallet create --json > wallet.json
# Check balance on Arbitrum
x402 wallet balance 0x... --network arbitrum
# Preview payment (dry run)
x402 pay https://api.example.com/data --dry-run
# Pay for an API
X402_PRIVATE_KEY=0x... x402 pay https://api.example.com/data --max-amount 0.10
Wallet Utilities
from primer_x402 import create_wallet, get_balance, x402_probe
# Create wallet
wallet = create_wallet()
print(wallet.address, wallet.private_key, wallet.mnemonic)
# Check balance
balance = get_balance('0x...', 'base', 'USDC')
print(f"{balance.balance} {balance.token}")
# Probe URL
probe = x402_probe('https://api.example.com/paid')
if probe.supports_402:
print(probe.requirements)
Error Handling
from primer_x402 import X402Error, ErrorCodes
try:
response = session.get(url)
except X402Error as e:
if e.code == ErrorCodes.INSUFFICIENT_FUNDS:
print(f"Need more funds: {e.details}")
OpenClaw Integration
pip install primer-x402
x402 openclaw init
Or install skill from ClawHub: clawhub install primer/x402
Changelog
v0.5.0
- CLI: New command-line interface (
x402 ...) - Wallet utilities:
create_wallet(),get_balance(),x402_probe() - Structured errors:
X402Errorclass with error codes - OpenClaw integration:
openclaw initandopenclaw statuscommands
v0.4.3
- Cleaned up legacy v1 protocol remnants for pure v2 compliance
v0.4.2
- Bug fix: 402 Payment Required responses now include JSON body (
{}) instead of empty body - Fixes Chrome content script injection blocking issue
- Aligns with Coinbase x402 specification
v0.4.1
- Updated package name to
primer-x402 - Renamed module to
primer_x402
v0.4.0
- x402 v2 protocol: Full upgrade to x402 v2 specification
- CAIP-2 network identifiers: All networks now use CAIP-2 format (e.g.,
'eip155:8453') - Multi-chain support: Base, Ethereum, Arbitrum, Optimism, and Polygon
- Testing utilities: Mock facilitator and test helpers
Links
License
MIT - Primer Systems
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file primer_x402-0.5.0.tar.gz.
File metadata
- Download URL: primer_x402-0.5.0.tar.gz
- Upload date:
- Size: 47.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b49cb732af4cb26da3c236affaa65f6b2a482d7670b2d969b234e4f1ca5c72a
|
|
| MD5 |
85fbbab08b837f3d11f53ba00de2481a
|
|
| BLAKE2b-256 |
a577f80bdc5aa6a3429a3f6dcd4b20ed90263be8df22d14e00bc72469efecc56
|
File details
Details for the file primer_x402-0.5.0-py3-none-any.whl.
File metadata
- Download URL: primer_x402-0.5.0-py3-none-any.whl
- Upload date:
- Size: 39.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f4d8e24f4766f8fdcb3f900be81166d148ad28377071b370a7a023491927b5f
|
|
| MD5 |
0cacb8b1b859da24e9ba747f16e3c91b
|
|
| BLAKE2b-256 |
ab80a69beb67a75ad6c5c2b3dec1d645a005a34fde01b13ad37f090a0517312e
|