x402 Payment Harness
The missing developer tool for x402. Pay x402-protected APIs from Python using any Ethereum EOA private key — no Coinbase CDP wallet, no vendor lock-in, no account setup.
pip install x402-payment-harness
What is x402?
x402 is an open HTTP payment standard built on Base. When an agent or developer calls a paid API, the server responds with HTTP 402 Payment Required and a payment challenge. The client signs a TransferWithAuthorization payload (ERC-3009 / EIP-712) and retries with an X-PAYMENT header. The server verifies and grants access.
This library implements the client side of that protocol — the signing, header construction, and retry logic — in pure Python.
Why This Exists
The official x402 SDK requires a Coinbase Developer Platform (CDP) wallet. That means:
- Creating a CDP account and completing their onboarding
- Vendor lock-in to Coinbase infrastructure
- No path for server-side agents using standard EOA keys
x402 Payment Harness works with any Ethereum private key. Import your wallet, point it at a protected URL, done.
Who needs this
| Use case | Why this helps |
|---|---|
| Server-side agents | Use a standard EOA without CDP account setup |
| Protocol testing | Verify your x402 server implementation against a real client |
| CI/CD pipelines | Automated payment flow tests with no browser auth |
| Researchers | Study the protocol with a minimal, readable implementation |
Quick Start
CLI
# Install
pip install x402-payment-harness
# Pay a protected endpoint
x402-pay --key 0xYOUR_PRIVATE_KEY https://x402-discovery-api.onrender.com/discover
# Safer: use environment variable for key
export X402_PRIVATE_KEY=0xYOUR_PRIVATE_KEY
x402-pay --env-key X402_PRIVATE_KEY https://api.example.com/endpoint
# Verbose mode (shows full payment header and response)
x402-pay --key 0xYOUR_KEY --verbose https://api.example.com/endpoint
# JSON output (for scripting)
x402-pay --key 0xYOUR_KEY --json https://api.example.com/endpoint
Python Library
from x402_harness import X402Client, PaymentConfig
# Configure your wallet
config = PaymentConfig(
private_key="0xYOUR_PRIVATE_KEY",
network="eip155:8453", # Base mainnet
)
# Create client and pay
client = X402Client()
result = client.pay("https://api.example.com/protected", config)
if result.success:
print(f"Access granted: {result.response_body}")
else:
print(f"Payment failed: {result.error}")
Full example with amount override
from x402_harness import X402Client, PaymentConfig
# The payment config — wallet + optional overrides
config = PaymentConfig(
private_key="0xYOUR_PRIVATE_KEY",
to="0xRECIPIENT_ADDRESS", # Optional: override server-specified recipient
amount_usd=0.005, # Optional: override server-specified amount
network="eip155:8453", # Base mainnet
)
client = X402Client(timeout=30)
result = client.pay(
url="https://api.example.com/data",
config=config,
method="GET",
)
print(f"Status: {result.status_code}")
print(f"Success: {result.success}")
print(f"Response: {result.response_body}")
Protocol Flow
This library implements the complete HTTP 402 client-side handshake:
Client Server
│ │
├──── GET /protected ──────────►│
│ │
│◄─── 402 Payment Required ─────┤
│ {accepts: [{network, │
│ maxAmountRequired, │
│ payTo, asset}]} │
│ │
├── Sign EIP-712 payload ────────┤ (local, no RPC needed)
│ TransferWithAuthorization │
│ │
├──── GET /protected ──────────►│
│ X-PAYMENT: <base64> │
│ │
│◄─── 200 OK ───────────────────┤
│ X-PAYMENT-RESPONSE: ... │
The library handles:
- Challenge parsing — reads the 402 response to extract payment requirements
- EIP-712 signing — constructs and signs a
TransferWithAuthorizationpayload - Header encoding — base64-encodes the signed payload as
X-PAYMENT - Retry — replays the original request with the payment header
- Result parsing — returns success/failure with the response body
PaymentResult
@dataclass
class PaymentResult:
success: bool # True if server returned 2xx
status_code: int # HTTP status code
response_body: Any # Parsed JSON response (or raw text)
error: Optional[str] # Error message if failed
payment_header_sent: Optional[str] # The X-PAYMENT header value (for debugging)
CLI Reference
x402-pay [options] URL
Required:
URL The x402-protected endpoint to access
Key options (one required):
--key HEX Private key (hex, 0x-prefixed)
--env-key ENV_VAR Name of environment variable containing private key
Optional:
--to ADDRESS Override recipient address from server challenge
--amount USD Override amount in USD from server challenge
--network NETWORK Network ID (default: eip155:8453 = Base mainnet)
--method METHOD HTTP method (default: GET)
--timeout SECONDS Request timeout (default: 30)
--verbose, -v Show payment header and full response
--json Output as JSON (for scripting)
Installation
# Latest stable
pip install x402-payment-harness
# From source
git clone https://github.com/rplryan/x402-payment-harness
cd x402-payment-harness
pip install -e .
Dependencies:
eth-account >= 0.11.0— EIP-712 signingrequests >= 2.28.0— HTTP client- Python 3.10+
Tests
pip install pytest
pytest tests/ -v
All 4 tests cover: EIP-712 signing correctness, payment header encoding, PaymentConfig validation, and CLI argument parsing.
Integration with x402 Service Discovery
Combine with the x402 Service Discovery API to find and pay x402 services programmatically:
import requests
from x402_harness import X402Client, PaymentConfig
# 1. Discover an x402 service
discovery = requests.get(
"https://x402-discovery-api.onrender.com/search",
params={"q": "token prices", "max_price_usd": 0.01}
).json()
service = discovery["results"][0]
print(f"Found: {service["name"]} at {service["url"]}")
print(f"Price: ${service["price_usd"]}/call, Trust: {service["trust_score"]}")
# 2. Pay for access
config = PaymentConfig(private_key="0xYOUR_PRIVATE_KEY")
client = X402Client()
result = client.pay(service["url"], config)
if result.success:
print(f"Data: {result.response_body}")
The x402 Discovery API indexes 251+ live x402 services with quality signals, uptime data, and ERC-8004 trust scores. The x402 RouteNet adds smart routing (cheapest, fastest, most trusted) across multiple providers.
Project Context: CDP Builder Grant
This library is part of a broader x402 infrastructure suite built for the Coinbase Developer Platform ecosystem:
| Project | Role | Status |
|---|---|---|
| x402-payment-harness (this) | Client-side EIP-712 signing library | ✅ v1.0.1 on PyPI |
| x402-discovery-mcp | MCP server — 6 tools for agent discovery | ✅ Live |
| x402-discovery-api | Discovery & enrichment API (251+ services) | ✅ Live on Render |
| x402-routenet | Smart routing across x402 providers | ✅ Live on Render |
Together these address the gap explicitly named in Coinbase's PROJECT-IDEAS.md: the "Dynamic Endpoint Shopper" — an agent that discovers, evaluates, and pays the best x402 endpoint at runtime.
License
MIT. See LICENSE.
Links
- GitHub: https://github.com/rplryan/x402-payment-harness
- PyPI: https://pypi.org/project/x402-payment-harness/
- x402 Protocol: https://x402.org
- Base Network: https://base.org
- Discovery API: https://x402-discovery-api.onrender.com
Metadata
Release files for x402-payment-harness 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| x402_payment_harness-1.0.1.tar.gz | 13.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| x402_payment_harness-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.7 kB
Release files / x402_payment_harness-1.0.1.tar.gz
| Download URL | x402_payment_harness-1.0.1.tar.gz |
|---|---|
| Size | 13.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d0399071ab6ef67dc228670d2fa457787c3e3cdf5b58a0304ea66c282f0aeeb0
|
|
BLAKE2b-256 checksum How to use checksums |
410a5d930190f41ce9e51013fa1e5a4a4711841520021989b1d4afbb219ec593
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|
Release files / x402_payment_harness-1.0.1-py3-none-any.whl
| Download URL | x402_payment_harness-1.0.1-py3-none-any.whl |
|---|---|
| Size | 12.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
705da29009b18a3fd8450e9176ff54934713b8d186981dd13d708624213b5999
|
|
BLAKE2b-256 checksum How to use checksums |
1e508228b69ad52e9fd37d17973ba5e16eae2bb396faffb426179682354e0329
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|