| Crates.io | x402-reqwest |
| lib.rs | x402-reqwest |
| version | 0.6.0 |
| created_at | 2025-06-17 20:44:50.195935+00 |
| updated_at | 2026-01-19 15:16:28.363347+00 |
| description | Wrapper for reqwest for transparent x402 payments |
| homepage | https://x402.rs |
| repository | https://github.com/x402-rs/x402-rs |
| max_upload_size | |
| id | 1716271 |
| size | 241,995 |
Reqwest middleware that transparently handles HTTP 402 Payment Required responses using the x402 protocol.
This crate enables your reqwest or reqwest-middleware-based HTTP clients to:
402 Payment Required responsesAll in all: automatically pay for resources using the x402 protocol.
telemetry feature)Add the dependency:
# Cargo.toml
x402-reqwest = "0.6"
To enable tracing:
x402-reqwest = { version = "0.6", features = ["telemetry"] }
use x402_reqwest::{ReqwestWithPayments, ReqwestWithPaymentsBuild, X402Client};
use x402_rs::scheme::v1_eip155_exact::client::V1Eip155ExactClient;
use alloy_signer_local::PrivateKeySigner;
use std::sync::Arc;
use reqwest::Client;
let signer: Arc<PrivateKeySigner> = Arc::new("0x...".parse().unwrap());
// Create an X402 client and register scheme handlers
let x402_client = X402Client::new()
.register(V1Eip155ExactClient::new(signer.clone()));
// Build a reqwest client with x402 middleware
let http_client = Client::new()
.with_payments(x402_client)
.build();
// Use the client - payments are handled automatically
let response = http_client
.get("https://api.example.com/protected")
.send()
.await?;
println!("Status: {}", response.status());
The [X402Client] uses a plugin architecture for supporting different payment schemes.
Register scheme clients for each chain/network you want to support:
use x402_reqwest::{ReqwestWithPayments, ReqwestWithPaymentsBuild, X402Client};
use x402_rs::scheme::v1_eip155_exact::client::V1Eip155ExactClient;
use x402_rs::scheme::v2_eip155_exact::client::V2Eip155ExactClient;
use x402_rs::scheme::v1_solana_exact::client::V1SolanaExactClient;
use x402_rs::scheme::v2_solana_exact::client::V2SolanaExactClient;
use alloy_signer_local::PrivateKeySigner;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_keypair::Keypair;
use std::sync::Arc;
use reqwest::Client;
let evm_signer: Arc<PrivateKeySigner> = Arc::new("0x...".parse().unwrap());
let solana_keypair = Arc::new(Keypair::from_base58_string("..."));
let solana_rpc_client = Arc::new(RpcClient::new("https://api.devnet.solana.com"));
let x402_client = X402Client::new()
// Register EVM schemes (V1 and V2)
.register(V1Eip155ExactClient::new(evm_signer.clone()))
.register(V2Eip155ExactClient::new(evm_signer))
// Register Solana schemes (V1 and V2)
.register(V1SolanaExactClient::new(
solana_keypair.clone(),
solana_rpc_client.clone(),
))
.register(V2SolanaExactClient::new(solana_keypair, solana_rpc_client));
let http_client = Client::new()
.with_payments(x402_client)
.build();
402 Payment Required response is received, the middleware:
When multiple payment options are available, the [X402Client] uses a [PaymentSelector]
to choose the best option. By default, it uses [FirstMatch] which selects the first
matching scheme.
You can implement custom selection logic:
use x402_reqwest::X402Client;
use x402_rs::proto::client::{PaymentSelector, PaymentCandidate};
struct MyCustomSelector;
impl PaymentSelector for MyCustomSelector {
fn select(&self, candidates: &[PaymentCandidate]) -> Option<&PaymentCandidate> {
// Custom selection logic
candidates.first()
}
}
let client = X402Client::new()
.with_selector(MyCustomSelector);
telemetry: Enables tracing annotations for richer observabilityjson: Enables JSON support for the reqwest-middleware, allowing .json() calls when making a HTTP requestEnable them via:
x402-reqwest = { version = "0.6", features = ["telemetry", "json"] }
When the telemetry feature is enabled, the middleware emits structured tracing events for key operations:
The telemetry includes:
This integrates with any tracing-compatible subscriber. For OpenTelemetry export, see x402-rs telemetry.