A Python client for the x402 Payment Protocol that enables seamless HTTP 402 payments using EIP-3009 gasless USDC transfers.
The x402 protocol enables payments over HTTP using the 402 Payment Required status code. This client handles the payment flow automatically:
- Makes your HTTP request to a paid endpoint
- If the server responds with
402, reads payment requirements from thepayment-requiredheader - Signs an EIP-3009
TransferWithAuthorizationmessage using your wallet - Retries the request with the signed payment in the
payment-signatureheader - Returns the successful response
You just make HTTP requests like normal - the payment handling happens transparently.
pip install x402-clientimport asyncio
from eth_account import Account
from x402_client import X402AsyncClient
account = Account.from_key("0xYOUR_PRIVATE_KEY")
async def main():
async with X402AsyncClient(account=account) as client:
response = await client.post(
"https://api.example.com/paid-endpoint",
json={"your": "params"}
)
data = response.json()
print(data)
asyncio.run(main())from eth_account import Account
from x402_client import X402Client
account = Account.from_key("0xYOUR_PRIVATE_KEY")
with X402Client(account=account) as client:
response = client.post(
"https://api.example.com/paid-endpoint",
json={"your": "params"}
)
data = response.json()
print(data)Client Server
| |
| POST /api/resource |
| ----------------------------------> |
| |
| 402 Payment Required |
| payment-required: <base64 JSON> |
| <---------------------------------- |
| |
| [Client signs EIP-3009 payment] |
| |
| POST /api/resource |
| payment-signature: <base64 JSON> |
| ----------------------------------> |
| |
| [Server settles payment on-chain] |
| |
| 200 OK |
| { "data": ... } |
| <---------------------------------- |
- Initial Request: Client makes a request to a paid endpoint
- 402 Response: Server responds with HTTP 402 and includes payment options in the
payment-requiredheader - Payment Signing: Client selects a payment option and signs an EIP-3009
TransferWithAuthorizationmessage - Retry with Payment: Client retries the original request with the
payment-signatureheader - Settlement: Server verifies the signature and settles the payment on-chain
- Success: Server returns the requested resource
Both clients accept standard httpx client options:
async with X402AsyncClient(
account=account,
timeout=120.0, # Request timeout in seconds (blockchain settlement can take time)
debug=True, # Enable debug logging
headers={"X-Custom": "header"},
) as client:
...The client supports any EVM chain with USDC and EIP-3009 support. Networks are identified using CAIP-2 format:
| Network | CAIP-2 Identifier |
|---|---|
| Ethereum Mainnet | eip155:1 |
| Base Mainnet | eip155:8453 |
| Base Sepolia (testnet) | eip155:84532 |
| Polygon | eip155:137 |
| Arbitrum One | eip155:42161 |
The network is determined by the server's payment requirements - you don't need to configure it.
class X402AsyncClient:
def __init__(self, account: Account, **kwargs):
"""
Initialize async x402 client.
Args:
account: eth_account.Account instance for signing payments
debug: Enable debug logging (default: False)
**kwargs: Passed to httpx.AsyncClient (timeout, headers, etc.)
"""
async def get(self, url: str, **kwargs) -> httpx.Response:
"""Make GET request with automatic x402 payment handling."""
async def post(self, url: str, **kwargs) -> httpx.Response:
"""Make POST request with automatic x402 payment handling."""class X402Client:
def __init__(self, account: Account, **kwargs):
"""
Initialize sync x402 client.
Args:
account: eth_account.Account instance for signing payments
debug: Enable debug logging (default: False)
**kwargs: Passed to httpx.Client (timeout, headers, etc.)
"""
def get(self, url: str, **kwargs) -> httpx.Response:
"""Make GET request with automatic x402 payment handling."""
def post(self, url: str, **kwargs) -> httpx.Response:
"""Make POST request with automatic x402 payment handling."""This client implements the x402 Payment Protocol:
- Payment Scheme:
exact- pay the exact amount requested - Authorization: EIP-3009
TransferWithAuthorizationfor gasless transfers - Signing: EIP-712 typed data signatures
- Asset: USDC (or any EIP-3009 compatible token specified by the server)
The payment-signature header contains a base64-encoded JSON payload:
{
"x402Version": 2,
"resource": {
"url": "https://api.example.com/paid-endpoint"
},
"accepted": {
"scheme": "exact",
"network": "eip155:84532",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"amount": "10000",
"payTo": "0x..."
},
"payload": {
"signature": "0x...",
"authorization": {
"from": "0xYourWallet",
"to": "0xRecipient",
"value": "10000",
"validAfter": "0",
"validBefore": "1734567890",
"nonce": "0x..."
}
}
}# Clone the repository
git clone https://github.com/agentokratia/x402-client.git
cd x402-client
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run linter
ruff check .
# Run type checker
mypy src/Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
MIT License - see LICENSE for details.