Wrapper around reqwest that transparently handles HTTP 402 Payment Required responses using the x402 protocol.
This crate enables your reqwest or reqwest-middleware-based HTTP clients to:
- Detect
402 Payment Requiredresponses - Build and sign x402 payment payloads
- Retry the request with the
X-Paymentheader attached - Respect client-defined preferences like token priority and per-token payment caps
All in all: automatically pay for resources using the x402 protocol.
Built with reqwest-middleware and compatible with any alloy::Signer.
- Pluggable
reqwestmiddleware - EIP-712-compatible signing with
alloy - Fluent builder-style configuration
- Token preferences & per-asset payment limits
- Tracing support (opt-in via
telemetryfeature)
Add the dependency:
# Cargo.toml
x402-reqwest = "0.4"To enable tracing:
x402-reqwest = { version = "0.4", features = ["telemetry"] }use reqwest::Client;
use x402_reqwest::{ReqwestWithPayments, ReqwestWithPaymentsBuild, MaxTokenAmountFromAmount};
use alloy::signers::local::PrivateKeySigner;
use x402_rs::network::{Network, USDCDeployment};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let signer: PrivateKeySigner = "0x...".parse()?; // never hardcode real keys!
let client = Client::new()
.with_payments(signer)
.prefer(USDCDeployment::by_network(Network::Base))
.max(USDCDeployment::by_network(Network::Base).amount("1.00")?)
.build();
let res = client
.get("https://example.com/protected")
.send()
.await?;
println!("Status: {}", res.status());
Ok(())
}See more examples on docs.rs
- A 402 Payment Required is received from a server.
- The middleware parses the Payment-Required response body.
- A compatible payment requirement is selected, based on client preferences.
- A signed payload is created (compatible with EIP-3009
TransferWithAuthorization). - The payload is base64-encoded into an
X-Paymentheader. - The request is retried, now with the payment inside the header.
telemetry: Enables tracing annotations for richer observability.
Enable it via:
x402-reqwest = { version = "0.4", features = ["telemetry"] }