t402 Python
Python SDK for the T402 HTTP-native stablecoin payments protocol.

Installation
pip install t402
uv add t402
Features
- Multi-Chain Support: EVM (19 USDT0 networks), TON, TRON, Solana, NEAR, Aptos, Tezos, Polkadot, Stacks, Cosmos
- Server Middleware: FastAPI, Flask, Django, and Starlette integrations
- Client Libraries: httpx and requests adapters
- ERC-4337 Account Abstraction: Gasless payments with smart accounts
- USDT0 Cross-Chain Bridge: LayerZero-powered bridging
- WDK Integration: Tether Wallet Development Kit support
FastAPI Integration
The simplest way to add t402 payment protection to your FastAPI application:
from fastapi import FastAPI
from t402.fastapi.middleware import require_payment
app = FastAPI()
app.middleware("http")(
require_payment(price="0.01", pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C")
)
@app.get("/")
async def root():
return {"message": "Hello World"}
To protect specific routes:
app.middleware("http")(
require_payment(price="0.01",
pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C"),
path="/foo"
)
Flask Integration
The simplest way to add t402 payment protection to your Flask application:
from flask import Flask
from t402.flask.middleware import PaymentMiddleware
app = Flask(__name__)
payment_middleware = PaymentMiddleware(app)
payment_middleware.add(
price="$0.01",
pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
)
@app.route("/")
def root():
return {"message": "Hello World"}
To protect specific routes:
payment_middleware.add(
path="/foo",
price="$0.001",
pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
)
Client Integration
Simple Usage
Httpx Client
from eth_account import Account
from t402.clients.httpx import t402HttpxClient
account = Account.from_key("your_private_key")
async with t402HttpxClient(account=account, base_url="https://api.example.com") as client:
response = await client.get("/protected-endpoint")
print(await response.aread())
Requests Session Client
from eth_account import Account
from t402.clients.requests import t402_requests
account = Account.from_key("your_private_key")
session = t402_requests(account)
response = session.get("https://api.example.com/protected-endpoint")
print(response.content)
Advanced Usage
Httpx Extensible Example
import httpx
from eth_account import Account
from t402.clients.httpx import t402_payment_hooks
account = Account.from_key("your_private_key")
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
client.event_hooks = t402_payment_hooks(account)
response = await client.get("/protected-endpoint")
print(await response.aread())
Requests Session Extensible Example
import requests
from eth_account import Account
from t402.clients.requests import t402_http_adapter
account = Account.from_key("your_private_key")
session = requests.Session()
adapter = t402_http_adapter(account)
session.mount("http://", adapter)
session.mount("https://", adapter)
response = session.get("https://api.example.com/protected-endpoint")
print(response.content)
Manual Server Integration
If you're not using the FastAPI middleware, you can implement the t402 protocol manually. Here's what you'll need to handle:
- Return 402 error responses with the appropriate response body
- Use the facilitator to validate payments
- Use the facilitator to settle payments
- Return the appropriate response header to the caller
Here's an example of manual integration:
from typing import Annotated
from fastapi import FastAPI, Request
from t402.types import PaymentRequiredResponse, PaymentRequirements
from t402.encoding import safe_base64_decode
payment_requirements = PaymentRequirements(...)
facilitator = FacilitatorClient(facilitator_url)
@app.get("/foo")
async def foo(req: request: Request):
payment_required = PaymentRequiredResponse(
t402_version: 2,
accepts=[payment_requirements],
error="",
)
payment_header = req.headers.get("PAYMENT-SIGNATURE", "") or req.headers.get("X-PAYMENT", "")
if payment_header == "":
payment_required.error = "PAYMENT-SIGNATURE header not set"
return JSONResponse(
content=payment_required.model_dump(by_alias=True),
status_code=402,
)
payment = PaymentPayload(**json.loads(safe_base64_decode(payment_header)))
verify_response = await facilitator.verify(payment, payment_requirements)
if not verify_response.is_valid:
payment_required.error = "Invalid payment"
return JSONResponse(
content=payment_required.model_dump(by_alias=True),
status_code=402,
)
settle_response = await facilitator.settle(payment, payment_requirements)
if settle_response.success:
response.headers["PAYMENT-RESPONSE"] = base64.b64encode(
settle_response.model_dump_json().encode("utf-8")
).decode("utf-8")
else:
payment_required.error = "Settle failed: " + settle_response.error
return JSONResponse(
content=payment_required.model_dump(by_alias=True),
status_code=402,
)
For more examples and advanced usage patterns, check out our examples directory.
Multi-Chain Support
TON Network
from t402 import (
TON_MAINNET,
TON_TESTNET,
validate_ton_address,
prepare_ton_payment_header,
get_ton_network_config,
)
is_valid = validate_ton_address("EQD...")
config = get_ton_network_config(TON_MAINNET)
TRON Network
from t402 import (
TRON_MAINNET,
TRON_NILE,
validate_tron_address,
prepare_tron_payment_header,
get_tron_network_config,
)
is_valid = validate_tron_address("T...")
config = get_tron_network_config(TRON_MAINNET)
Solana (SVM) Network
from t402 import (
SOLANA_MAINNET,
SOLANA_DEVNET,
SOLANA_TESTNET,
validate_svm_address,
prepare_svm_payment_header,
get_svm_network_config,
get_svm_usdc_address,
is_svm_network,
)
is_valid = validate_svm_address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
config = get_svm_network_config(SOLANA_MAINNET)
usdc_mint = get_svm_usdc_address(SOLANA_MAINNET)
is_solana = is_svm_network("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")
Install with optional Solana dependencies:
pip install t402[svm]
ERC-4337 Account Abstraction
Gasless payments using smart accounts and paymasters:
from t402 import (
create_bundler_client,
create_paymaster,
create_smart_account,
SafeAccountConfig,
)
bundler = create_bundler_client(
bundler_type="pimlico",
api_key="your_api_key",
chain_id=8453
)
paymaster = create_paymaster(
paymaster_type="pimlico",
api_key="your_api_key",
chain_id=8453
)
account = create_smart_account(
config=SafeAccountConfig(
owner_private_key="0x...",
chain_id=8453,
),
bundler=bundler,
paymaster=paymaster,
)
USDT0 Cross-Chain Bridge
Bridge USDT0 across chains using LayerZero:
from t402 import (
create_usdt0_bridge,
create_cross_chain_payment_router,
get_bridgeable_chains,
)
chains = get_bridgeable_chains()
bridge = create_usdt0_bridge(
private_key="0x...",
source_chain_id=1,
)
quote = await bridge.get_quote(
destination_chain_id=8453,
amount="1000000",
)
result = await bridge.bridge(
destination_chain_id=8453,
amount="1000000",
recipient="0x...",
)
Deprecation Notice: exact-legacy Scheme
⚠️ Deprecated: The exact-legacy scheme is deprecated and will be removed in a future major version.
The exact-legacy scheme uses the traditional approve + transferFrom pattern for legacy USDT tokens. This has been superseded by the exact scheme with USDT0.
Why Migrate?
| Transactions | 2 (approve + transfer) | 1 (single signature) |
| Gas Cost | User pays gas | Gasless (EIP-3009) |
| Chains | ~5 chains | 19+ chains |
| Cross-chain | ❌ | ✅ LayerZero bridge |
Migration Guide
from t402.schemes.evm import ExactLegacyEvmClientScheme, ExactLegacyEvmServerScheme
client_scheme = ExactLegacyEvmClientScheme(signer)
server_scheme = ExactLegacyEvmServerScheme()
from t402.schemes.evm import ExactEvmClientScheme, ExactEvmServerScheme
client_scheme = ExactEvmClientScheme(signer)
server_scheme = ExactEvmServerScheme()
USDT0 Token Addresses
| Ethereum | 0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee |
| Arbitrum | 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9 |
| Ink | 0x0200C29006150606B650577BBE7B6248F58470c1 |
| Berachain | 0x779Ded0c9e1022225f8E0630b35a9b54bE713736 |
| And 15+ more... | See USDT0 documentation |
WDK Integration
Tether Wallet Development Kit support:
from t402 import (
WDKSigner,
generate_seed_phrase,
WDKConfig,
get_wdk_usdt0_chains,
)
seed = generate_seed_phrase()
signer = WDKSigner(
config=WDKConfig(
seed_phrase=seed,
chains=get_wdk_usdt0_chains(),
)
)
address = await signer.get_address(chain_id=8453)
signature = await signer.sign_payment(
chain_id=8453,
amount="1000000",
recipient="0x...",
)
API Reference
Core Types
PaymentRequirements | Payment configuration |
PaymentPayload | Signed payment data |
VerifyResponse | Verification result |
SettleResponse | Settlement result |
Network Utilities
is_evm_network(network) | Check if EVM network |
is_ton_network(network) | Check if TON network |
is_tron_network(network) | Check if TRON network |
is_svm_network(network) | Check if Solana SVM network |
get_network_type(network) | Get network type string |
Facilitator Client
from t402 import FacilitatorClient, FacilitatorConfig
client = FacilitatorClient(FacilitatorConfig(
url="https://facilitator.t402.io"
))
result = await client.verify(payload, requirements)
result = await client.settle(payload, requirements)
Requirements
- Python 3.10+
- pip or uv package manager
Documentation
Full documentation available at docs.t402.io