Expand description
Axum middleware for enforcing x402 payments on protected routes.
This middleware validates incoming payment headers using a configured x402 facilitator, and settles valid payments either before or after request execution (configurable).
Returns a 402 Payment Required response if the request lacks a valid payment.
§Example Usage
use alloy_primitives::address;
use axum::{Router, routing::get};
use axum::response::IntoResponse;
use http::StatusCode;
use x402_axum::X402Middleware;
use x402_chain_eip155::{KnownNetworkEip155, V1Eip155Exact};
use x402_types::networks::USDC;
let x402 = X402Middleware::new("https://facilitator.x402.rs");
let app: Router = Router::new().route(
"/protected",
get(my_handler).layer(
x402.with_price_tag(V1Eip155Exact::price_tag(
address!("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"),
USDC::base_sepolia().parse("0.01").unwrap(),
))
),
);
async fn my_handler() -> impl IntoResponse {
(StatusCode::OK, "This is VIP content!")
}See X402Middleware for full configuration options.
For low-level interaction with the facilitator, see facilitator_client::FacilitatorClient.
§Protocol Support
Supports both V1 and V2 x402 protocols through the PaygateProtocol trait.
The protocol version is determined by the price tag type used.
§Dynamic Pricing
For dynamic pricing based on request context, use X402Middleware::with_dynamic_price:
use axum::Router;
use axum::routing::get;
use axum::response::IntoResponse;
use axum::http::StatusCode;
use alloy_primitives::address;
use x402_axum::X402Middleware;
use x402_chain_eip155::KnownNetworkEip155;
use x402_chain_eip155::V1Eip155Exact;
use x402_types::networks::USDC;
let x402 = X402Middleware::new("https://facilitator.x402.rs");
let app: Router = Router::new().route(
"/protected",
get(my_handler).layer(
x402.with_dynamic_price(|headers, uri, base_url| {
// Compute price based on request context
let is_premium = headers
.get("X-User-Tier")
.and_then(|v| v.to_str().ok())
.map(|v| v == "premium")
.unwrap_or(false);
let amount = if is_premium { "0.005" } else { "0.01" };
async move {
vec![V1Eip155Exact::price_tag(address!("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"), USDC::base_sepolia().parse(amount).unwrap())]
}
})
),
);
async fn my_handler() -> impl IntoResponse {
(StatusCode::OK, "This is a VIP content!")
}§Settlement Timing
By default, settlement occurs after the request is processed. You can change this behavior:
X402Middleware::settle_before_execution- Settle payment before request execution. This prevents issues where failed settlements need retry or authorization expires.X402Middleware::settle_after_execution- Settle payment after request execution (default). This allows processing the request before committing the payment on-chain.
§Configuration Notes
X402Middleware::with_price_tagsets the assets and amounts accepted for payment (static pricing).X402Middleware::with_dynamic_pricesets a callback for dynamic pricing based on request context.X402Middleware::with_base_urlsets the base URL for computing full resource URLs. If not set, defaults tohttp://localhost/(avoid in production).X402Middleware::with_supported_cache_ttlconfigures the TTL for caching facilitator capabilities.X402LayerBuilder::with_descriptionis optional but helps the payer understand what is being paid for.X402LayerBuilder::with_mime_typesets the MIME type of the protected resource (default:application/json).X402LayerBuilder::with_resourceexplicitly sets the full URI of the protected resource.
Re-exports§
pub use layer::X402LayerBuilder;pub use layer::X402Middleware;pub use paygate::DynamicPriceTags;pub use paygate::PaygateProtocol;pub use paygate::PriceTagSource;pub use paygate::StaticPriceTags;
Modules§
- facilitator_
client - A
x402_types::facilitator::Facilitatorimplementation that interacts with a remote x402 Facilitator over HTTP. - layer
- Axum middleware for enforcing x402 payments on protected routes.
- paygate
- Unified Paygate implementation supporting both V1 and V2 x402 protocols.