Installation
Cargo.toml:
Quickstart
The fastest path usesManagedProvider — no Lightning node needed, 0.3% fee:
LightningProvider trait — see Custom provider below.
Custom provider
Options
| Field | Type | Description |
|---|---|---|
price_sats | u64 | Price per call in satoshis (required) |
lightning | Arc<dyn LightningProvider> | Your Lightning backend (required) |
on_payment | Option<Box<dyn Fn(L402Token, u64)>> | Callback fired after each verified payment |
Deprecated: with_address()
Options::with_address(address) was removed in v1.4.0. Use Options::new(sats, ManagedProvider::new(address)) instead:
l402_middleware(opts: Options)
Returns an axum::middleware::Layer compatible with axum 0.8+.
Behavior
| Request | Response |
|---|---|
No Authorization header | 402 + WWW-Authenticate: L402 macaroon="...", invoice="lnbc..." |
Valid L402 <macaroon>:<preimage> | Handler executes |
| Invalid or expired token | 401 Unauthorized |
| Replayed preimage | 401 Token already used |
402 response body
on_payment callback
Feature flags
axum-middleware to use only the core verification functions without axum or reqwest:
Verification
SHA256(preimage) == paymentHash is verified locally using the sha2 crate — no network call on the hot path. Token expiry is checked in the same operation.
Error codes
| Status | Meaning |
|---|---|
402 | No payment token — pay the invoice |
401 | Invalid token or expired macaroon |
401 | Replayed preimage (already used) |