Payment Layer
l402-kit is a managed middleware that adds a Bitcoin Lightning paywall to any HTTP endpoint in 3 lines of code. This page explains every layer of the payment stack.Protocol: L402
L402 is an open standard that extends HTTP/1.1 with a native payment handshake:paymentHash. The preimage is the cryptographic secret released by the Lightning node when payment settles. The server verifies:
Invoice Creation Flow
Payment Settlement Flow
Fee Model
l402-kit uses a 0.3% pass-through fee. No monthly subscription, no per-call overhead for the developer.| Party | What they receive |
|---|---|
| Your Lightning address | 99.7% of every payment |
| ShinyDapps | 0.3% fee |
/api/data endpoint.
- You receive 997 sats
- ShinyDapps receives 3 sats
Data Storage (Supabase)
Payments are persisted in a Supabase PostgreSQL table:anonkey: can INSERT new pending rows and SELECT rows filtered byowner_address(used by VS Code extension)service_rolekey: unrestricted — used only by server-side/api/*endpointspreimagefield: never returned to the anon key layer
Verification (Client Side)
When the client re-calls your endpoint with theAuthorization: L402 <macaroon>:<preimage> header, l402-kit verifies locally — no network call required:
- Parse
macaroonandpreimagefrom the header SHA256(preimage)→ compare topaymentHashembedded in macaroon- Verify macaroon signature with the shared secret
- If valid → call
next(), else →401 Unauthorized
Lightning Providers
l402-kit is provider-agnostic. The current managed backend uses Blink (formerly Bitcoin Jungle). Self-hosted deployments can use:
See the Providers page for integration details.
Security Guarantees
| Threat | Mitigation |
|---|---|
| Replay attack | preimage is unique per payment; Supabase UNIQUE constraint rejects reuse |
| Fake preimage | SHA256(preimage) == paymentHash is cryptographically unforgeable |
| Webhook spoofing | HMAC-SHA256(secret, body) verified before any DB write |
| Anon data exposure | Supabase RLS: pro_access table has zero anon SELECT; payments filtered by owner_address |
| Secret URL leak | API secret never returned to client; stored only in environment variables |