x402-reqwest 1.0.1

Wrapper for reqwest for transparent x402 payments
docs.rs failed to build x402-reqwest-1.0.1
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: x402-reqwest-1.0.0

x402-reqwest

Crates.io Docs.rs

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:

  • Detect 402 Payment Required responses
  • Extract payment requirements from the response
  • Sign payments using registered scheme clients
  • Retry the request with the payment header attached

All in all: automatically pay for resources using the x402 protocol.

Features

  • Pluggable reqwest middleware using reqwest-middleware
  • Multi-chain support (EVM via EIP-155, Solana)
  • Full V1 and V2 protocol support with automatic detection and handling
  • Multi-scheme architecture supporting various payment schemes
  • Customizable payment selection logic
  • Tracing support (opt-in via telemetry feature)

Installation

Add the dependency:

# Cargo.toml
x402-reqwest = "0.6"

To enable tracing:

x402-reqwest = { version = "0.6", features = ["telemetry"] }

Quickstart

use x402_reqwest::{ReqwestWithPayments, ReqwestWithPaymentsBuild, X402Client};
use x402_chain_eip155::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());

Registering Scheme Clients

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_chain_eip155::{V1Eip155ExactClient, V2Eip155ExactClient};
use x402_chain_solana::{V1SolanaExactClient, 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();

How It Works

  1. A request is made to a server
  2. If a 402 Payment Required response is received, the middleware:
    • Parses the Payment-Required response (V1 body or V2 header)
    • Finds registered scheme clients that can handle the payment
    • Selects the best matching payment option
    • Signs the payment using the scheme client
    • Retries the request with the payment header attached

Payment Selection

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_types::scheme::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);

Optional Features

  • telemetry: Enables tracing annotations for richer observability
  • json: Enables JSON support for the reqwest-middleware, allowing .json() calls when making a HTTP request

Enable them via:

x402-reqwest = { version = "0.6", features = ["telemetry", "json"] }

Telemetry

When the telemetry feature is enabled, the middleware emits structured tracing events for key operations:

  • x402.reqwest.handle: Span covering the entire middleware handling, including 402 detection and payment retry
  • x402.reqwest.next: Span for the underlying HTTP request (both initial and retry)
  • x402.reqwest.make_payment_headers: Span for payment header creation and signing
  • x402.reqwest.parse_payment_required: Span for parsing 402 responses (V1 body or V2 header)

The telemetry includes:

  • Payment version (V1 or V2)
  • Selected scheme and network
  • Request URLs and response status codes
  • Payment parsing results

This integrates with any tracing-compatible subscriber. For OpenTelemetry export, see x402-types telemetry.

Related Crates

License

Apache-2.0