Skip to main content

Python SDK for x402 payments - pay and charge for APIs with stablecoins. OpenClaw compatible.

Project description

primer-x402

PyPI version Python License: MIT

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:

  1. Parses the payment requirements from the response
  2. Creates a signed payment authorization (no gas required)
  3. Retries the request with the payment header
  4. 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:

  1. One-time approval - Approve the Prism contract to spend your tokens
  2. 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: X402Error class with error codes
  • OpenClaw integration: openclaw init and openclaw status commands

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

primer_x402-0.5.0.tar.gz (47.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

primer_x402-0.5.0-py3-none-any.whl (39.6 kB view details)

Uploaded Python 3

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

Hashes for primer_x402-0.5.0.tar.gz
Algorithm Hash digest
SHA256 8b49cb732af4cb26da3c236affaa65f6b2a482d7670b2d969b234e4f1ca5c72a
MD5 85fbbab08b837f3d11f53ba00de2481a
BLAKE2b-256 a577f80bdc5aa6a3429a3f6dcd4b20ed90263be8df22d14e00bc72469efecc56

See more details on using hashes here.

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

Hashes for primer_x402-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f4d8e24f4766f8fdcb3f900be81166d148ad28377071b370a7a023491927b5f
MD5 0cacb8b1b859da24e9ba747f16e3c91b
BLAKE2b-256 ab80a69beb67a75ad6c5c2b3dec1d645a005a34fde01b13ad37f090a0517312e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page