x402 Python SDK
Core implementation of the x402 payment protocol. Provides transport-agnostic client, server, and facilitator components with both async and sync variants.
Installation
Install the core package with your preferred framework/client:
# HTTP clients (pick one)
uv add x402[httpx] # httpx client
uv add x402[requests] # requests client
# Server frameworks (pick one)
uv add x402[fastapi] # FastAPI middleware
uv add x402[flask] # Flask middleware
# Blockchain mechanisms (pick one or more)
uv add x402[evm] # EVM/Ethereum
uv add x402[svm] # Solana
uv add x402[tvm] # TON/TVM
# Multiple extras
uv add x402[fastapi,httpx,evm]
# Everything
uv add x402[all]
Quick Start
Client (Async)
from x402 import x402Client
from x402.mechanisms.evm.exact import ExactEvmScheme
client = x402Client()
client.register("eip155:*", ExactEvmScheme(signer=my_signer))
# Create payment from 402 response
payload = await client.create_payment_payload(payment_required)
Client (Sync)
from x402 import x402ClientSync
from x402.mechanisms.evm.exact import ExactEvmScheme
client = x402ClientSync()
client.register("eip155:*", ExactEvmScheme(signer=my_signer))
payload = client.create_payment_payload(payment_required)
TVM Client (Async)
import os
from x402 import x402Client
from x402.mechanisms.tvm import (
TVM_PROVIDER_TONAPI,
TVM_TESTNET,
WalletV5R1Config,
WalletV5R1MnemonicSigner,
)
from x402.mechanisms.tvm.exact import ExactTvmScheme
tvm_config = WalletV5R1Config.from_private_key(
TVM_TESTNET,
os.environ["TVM_PRIVATE_KEY"],
)
tvm_config.api_key = os.environ.get("TONCENTER_API_KEY")
# Optional: use TonAPI instead of Toncenter.
# tvm_config.provider = TVM_PROVIDER_TONAPI
# tvm_config.api_key = os.environ.get("TONAPI_API_KEY")
# tvm_config.provider_base_url = os.environ.get("TONAPI_BASE_URL")
client = x402Client()
client.register(TVM_TESTNET, ExactTvmScheme(WalletV5R1MnemonicSigner(tvm_config)))
Server (Async)
from x402 import x402ResourceServer, ResourceConfig
from x402.http import HTTPFacilitatorClient
from x402.mechanisms.evm.exact import ExactEvmServerScheme
facilitator = HTTPFacilitatorClient(url="https://x402.org/facilitator")
server = x402ResourceServer(facilitator)
server.register("eip155:*", ExactEvmServerScheme())
server.initialize()
# Build requirements
config = ResourceConfig(
scheme="exact",
network="eip155:8453",
pay_to="0x...",
price="$0.01",
)
requirements = server.build_payment_requirements(config)
# Verify payment
result = await server.verify_payment(payload, requirements[0])
Server (Sync)
from x402 import x402ResourceServerSync, ResourceConfig
from x402.http import HTTPFacilitatorClientSync
from x402.mechanisms.evm.exact import ExactEvmServerScheme
facilitator = HTTPFacilitatorClientSync(url="https://x402.org/facilitator")
server = x402ResourceServerSync(facilitator)
server.register("eip155:*", ExactEvmServerScheme())
server.initialize()
result = server.verify_payment(payload, requirements[0])
Facilitator (Async)
from x402 import x402Facilitator
from x402.mechanisms.evm.exact import ExactEvmFacilitatorScheme
facilitator = x402Facilitator()
facilitator.register(
["eip155:8453", "eip155:84532"],
ExactEvmFacilitatorScheme(wallet=wallet),
)
result = await facilitator.verify(payload, requirements)
if result.is_valid:
settle_result = await facilitator.settle(payload, requirements)
Facilitator (Sync)
from x402 import x402FacilitatorSync
from x402.mechanisms.evm.exact import ExactEvmFacilitatorScheme
facilitator = x402FacilitatorSync()
facilitator.register(
["eip155:8453", "eip155:84532"],
ExactEvmFacilitatorScheme(wallet=wallet),
)
result = facilitator.verify(payload, requirements)
Async vs Sync
Each component has both async and sync variants:
| Async (default) | Sync |
|---|---|
x402Client |
x402ClientSync |
x402ResourceServer |
x402ResourceServerSync |
x402Facilitator |
x402FacilitatorSync |
HTTPFacilitatorClient |
HTTPFacilitatorClientSync |
Async variants support both sync and async hooks (auto-detected). Sync variants only support sync hooks and raise TypeError if async hooks are registered.
Framework Pairing
| Framework | HTTP Client | Server | Facilitator Client |
|---|---|---|---|
| FastAPI | httpx | x402ResourceServer |
HTTPFacilitatorClient |
| Flask | requests | x402ResourceServerSync |
HTTPFacilitatorClientSync |
Mismatched variants raise TypeError at runtime.
Client Configuration
Use from_config() for declarative setup. Accept selection runs in three stages: spend_controls enforce built-in safety caps, policies filter the remaining list, and payment_requirements_selector picks one accept (default: first remaining).
from x402 import x402Client, x402ClientConfig, SchemeRegistration
from x402 import prefer_network
from x402.mechanisms.evm.exact import ExactEvmScheme
from x402.mechanisms.svm.exact import ExactSvmScheme
from x402.mechanisms.tvm.exact import ExactTvmScheme
config = x402ClientConfig(
schemes=[
SchemeRegistration(network="eip155:*", client=ExactEvmScheme(signer)),
SchemeRegistration(network="solana:*", client=ExactSvmScheme(signer)),
SchemeRegistration(network="tvm:*", client=ExactTvmScheme(tvm_signer)),
],
spend_controls={"max_amount_per_payment": "$5"},
policies=[prefer_network("eip155:8453")],
)
client = x402Client.from_config(config)
Spend controls
Built-in safety rails applied before policies. Use these for amount and asset bounds—not for network preference.
By default only assets find_default_asset recognizes are allowed, with a $1 USD ceiling. Opt into other tokens via allowed_assets, or pass spend_controls=False to disable all spend controls.
spend_controls = {
"max_amount_per_payment": "$5", # USD cap on default assets; False to remove
"allowed_assets": [
# opt-in non-default with atomic cap
{"network": "eip155:8453", "asset": "0xCustomToken", "max_amount_per_payment": "2000000"},
# opt-in non-default uncapped
{"network": "eip155:8453", "asset": "0xOtherToken"},
# override USD cap for a default asset by ticker (or on-chain id)
{"network": "eip155:8453", "asset": "PYUSD", "max_amount_per_payment": "500000"},
],
# or: "allowed_assets": True # allow any asset (USD cap still applies to defaults)
}
# or: spend_controls=False # disable all spend controls (any asset, no caps)
| Control | Purpose |
|---|---|
spend_controls: False |
Disable all spend controls (any asset, no caps). Useful for UI-confirmed flows (paywall) and tests. |
max_amount_per_payment |
USD ceiling on payments in recognized USD-pegged assets (default $1). Set a higher value to raise the cap, or False to remove it. |
allowed_assets |
Opt-in for non-default tokens. Omit for default assets only; True to allow any asset; or a list of { network, asset } with optional integer atomic max_amount_per_payment per entry (e.g. "2000000", not "$1"). |
Policies
Filter or prioritize payment requirements. Policies run after spend controls and before the selector. Do not use policies for USD caps or asset allowlists—that is what spend_controls is for.
from x402 import prefer_network, prefer_scheme, max_amount
client.register_policy(prefer_network("eip155:8453"))
client.register_policy(prefer_scheme("exact"))
client.register_policy(max_amount(1_000_000)) # 1 USDC max
Lifecycle Hooks
Client Hooks
from x402 import AbortResult, RecoveredPayloadResult
def before_payment(ctx):
print(f"Creating payment for: {ctx.selected_requirements.network}")
# Return AbortResult(reason="...") to cancel
def after_payment(ctx):
print(f"Payment created: {ctx.payment_payload}")
def on_failure(ctx):
print(f"Payment failed: {ctx.error}")
# Return RecoveredPayloadResult(payload=...) to recover
client.on_before_payment_creation(before_payment)
client.on_after_payment_creation(after_payment)
client.on_payment_creation_failure(on_failure)
Server Hooks
server.on_before_verify(lambda ctx: print(f"Verifying: {ctx.payload}"))
server.on_after_verify(lambda ctx: print(f"Result: {ctx.result.is_valid}"))
server.on_verify_failure(lambda ctx: print(f"Failed: {ctx.error}"))
server.on_before_settle(lambda ctx: ...)
server.on_after_settle(lambda ctx: ...)
server.on_settle_failure(lambda ctx: ...)
Facilitator Hooks
facilitator.on_before_verify(...)
facilitator.on_after_verify(...)
facilitator.on_verify_failure(...)
facilitator.on_before_settle(...)
facilitator.on_after_settle(...)
facilitator.on_settle_failure(...)
Network Pattern Matching
Register handlers for network families using wildcards:
# All EVM networks
client.register("eip155:*", ExactEvmScheme(signer))
# Specific network (takes precedence)
client.register("eip155:8453", CustomScheme())
HTTP Headers
V2 Protocol (Current)
| Header | Description |
|---|---|
PAYMENT-SIGNATURE |
Base64-encoded payment payload |
PAYMENT-REQUIRED |
Base64-encoded payment requirements |
PAYMENT-RESPONSE |
Base64-encoded settlement response |
V1 Protocol (Legacy)
| Header | Description |
|---|---|
X-PAYMENT |
Base64-encoded payment payload |
X-PAYMENT-RESPONSE |
Base64-encoded settlement response |
Related Modules
x402.http- HTTP clients, middleware, and facilitator clientx402.mechanisms.evm- EVM/Ethereum implementationx402.mechanisms.svm- Solana implementationx402.mechanisms.tvm- TON/TVM implementationx402.extensions- Protocol extensions (Bazaar discovery)
Examples
See examples/python.
Release files for x402 2.21.0
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-2.21.0.tar.gz | 2.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| x402-2.21.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.4 MB
Release files / x402-2.21.0.tar.gz
| Download URL | x402-2.21.0.tar.gz |
|---|---|
| Size | 2.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7a574422e2ee69e8f9ae0b55d9be36c28a453528c6ce89867c9c7537718a8837
|
|
BLAKE2b-256 checksum How to use checksums |
a0fd67a23df8e625ad4a103c9d46e68700e8a8280652a7c521151691fb9bbd51
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / x402-2.21.0-py3-none-any.whl
| Download URL | x402-2.21.0-py3-none-any.whl |
|---|---|
| Size | 2.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec9e26af56f5761c79df8c73e2043884c82b790935e02284918028465efacb2b
|
|
BLAKE2b-256 checksum How to use checksums |
6ba4aee09dd594b3107613ca9322cf43c894e69d4d0b3fc0f69e2d0e5303c44b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency log