A Rust implementation of an API paywalled with the L402 protocol. This project demonstrates how to implement a server that charges per API call using Lightning Network or other payment methods to get access to paywalled resources.
Live Demo web app - Demo frontend repo
This example Rust backend for L402 protocol is based on the L402 protocol specification and is designed to be a simple, easy-to-understand reference for developers looking to implement L402 in their own projects, akin to the L402 Python reference server.
- User creation and management
- Credits-based API paywall system
- Bitcoin blockchain data API endpoint
- Payment processing via:
- Lightning Network
- Webhook handling for payment confirmations
- Redis-based data storage and caching
- GET /signup - Create a new user account with 1 free credit
- GET /info - Get current user info (requires authentication)
- GET /block - Get the latest Bitcoin block hash, costs 1 credit (requires authentication)
- POST /l402/payment-request - Initiate a payment to purchase more credits
- POST /credits-payment-options - Get available credit purchase options
- POST /webhook/lightning - Lightning payment webhooks
- POST /webhook/coinbase - Coinbase payment webhooks
Authentication is handled via a simple token-based system. When a user signs up, they receive a unique ID that serves as their API token. This token must be included in the Authorization
header as a Bearer token:
Authorization: Bearer <user_id>
- Rust (latest stable)
- Redis (for data storage)
- Optional: LNBits account (for Lightning Network payments)
- Optional: Coinbase Commerce account
Configuration is done via environment variables or a .env
file:
# Server configuration
PORT=8080
HOST=127.0.0.1
# Redis configuration
REDIS_URL=redis://localhost:6379
# Payment request URL (optional, defaults to http://HOST:PORT/l402/payment-request)
# PAYMENT_REQUEST_URL=https://your-domain.com/l402/payment-request
# Lightning payment configuration
LIGHTNING_ENABLED=true
# LNBits configuration (preferred)
# LNBITS_URL=https://legend.lnbits.com
# LNBITS_ADMIN_KEY=your_admin_key_here
# LNBITS_INVOICE_READ_KEY=your_invoice_read_key_here
# LNBITS_WEBHOOK_KEY=your_webhook_verification_key_here
# Coinbase payment configuration
COINBASE_ENABLED=true
# COINBASE_API_KEY=your_coinbase_api_key
# COINBASE_WEBHOOK_SECRET=your_webhook_secret
# Credit offers
OFFERS_JSON='{"id":"offer1","title":"1 Credit Package","description":"Purchase 1 credit for API access","credits":1,"amount":0.01,"currency":"USD"},{"id":"offer2","title":"5 Credits Package","description":"Purchase 5 credits for API access","credits":5,"amount":0.05,"currency":"USD"}]'
# Logging configuration
RUST_LOG=info,l402_server_example_rs=debug
A .env.example
file is provided as a template.
The easiest way to run the server is with Docker and Docker Compose:
# Build and start the containers
docker-compose up -d
# View logs
docker-compose logs -f
This will start the server and a Redis instance.
To run the server locally:
-
Start a Redis server:
redis-server
-
Build and run the application:
cargo build cargo run
curl http://localhost:8080/signup
Response:
{
"id": "57d102ff-7188-4eff-b868-2d46d649aafe",
"credits": 1,
"created_at": "2024-03-20T02:39:44Z",
"last_credit_update_at": "2024-03-20T02:39:44Z"
}
curl -H "Authorization: Bearer 57d102ff-7188-4eff-b868-2d46d649aafe" http://localhost:8080/info
Response:
{
"id": "57d102ff-7188-4eff-b868-2d46d649aafe",
"credits": 1,
"created_at": "2024-03-20T02:39:44Z",
"last_credit_update_at": "2024-03-20T02:39:44Z"
}
curl -H "Authorization: Bearer 57d102ff-7188-4eff-b868-2d46d649aafe" http://localhost:8080/block
If the user has credits, they will receive the latest Bitcoin block hash:
{
"hash": "000000000000000000007b05bde2eb0be32cc10ec811cb636728e647e7cc0c63",
"timestamp": "2024-03-20T04:15:32Z"
}
If the user is out of credits, they will receive a 402 Payment Required response with available offers:
{
"expiry": "2024-03-20T04:45:32Z",
"offers": [
{
"id": "offer1",
"title": "1 Credit Package",
"description": "Purchase 1 credit for API access",
"credits": 1,
"amount": 0.01,
"currency": "USD"
},
{
"id": "offer2",
"title": "5 Credits Package",
"description": "Purchase 5 credits for API access",
"credits": 5,
"amount": 0.05,
"currency": "USD"
}
],
"payment_context_token": "57d102ff-7188-4eff-b868-2d46d649aafe",
"payment_request_url": "http://localhost:8080/l402/payment-request"
}
curl -X POST -H "Content-Type: application/json" \
-d '{"offer_id":"offer1","payment_method":"lightning","payment_context_token":"57d102ff-7188-4eff-b868-2d46d649aafe"}' \
http://localhost:8080/l402/payment-request
Response for Lightning:
{
"lightning_invoice": "lnbc...",
"offer_id": "offer1",
"expires_at": "2024-03-20T03:09:44Z"
}
Response for Coinbase:
{
"checkout_url": "https://commerce.coinbase.com/charges/...",
"address": "0x...",
"asset": "USDC",
"chain": "base-mainnet",
"offer_id": "offer1",
"expires_at": "2024-03-20T03:09:44Z"
}
This project demonstrates the L402 payment protocol flow:
- A user signs up and receives 1 free credit
- The user makes a request to
/block
to get Bitcoin block data - After using their credit, the next request returns a 402 Payment Required response
- The response includes available payment options (offers)
- The user selects an offer and initiates a payment via Lightning or other payment methods
- Once payment is confirmed (via webhook), credits are added to the user's account
- The user can now make another request to
/block
using their new credits
This implementation shows how micropayments can be used to monetize API access with Bitcoin, making it suitable for applications where users pay small amounts for specific pieces of data.
To run the code with hot-reloading for development:
cargo install cargo-watch
cargo watch -x run
Run all checks and tests (requires Redis running):
./scripts/ci-check.sh
Run linting:
cargo clippy
Format code:
cargo fmt
Prepare a new release:
./scripts/prepare-release.sh v1.0.0
This project uses GitHub Actions for continuous integration and deployment:
On every push and pull request to the main branch, the CI workflow runs:
-
Code Checks:
- Code formatting verification
- Clippy linting
- Compilation check
-
Tests:
- Runs all unit and integration tests
- Generates code coverage metrics
-
Security Audit:
- Scans dependencies for known vulnerabilities with cargo-audit
-
Build:
- Builds the release binary
- Uploads the binary as an artifact
-
Docker:
- Builds the Docker image (on main branch only)
When a new release is published or triggered manually:
-
Release Build:
- Builds the release binary
- Creates a distributable archive with documentation
- Uploads the archive as a release asset
-
Docker Publish:
- Builds and pushes the Docker image to GitHub Container Registry
- Tags the image with the release version and latest
This project is licensed under the MIT License - see the LICENSE file for details.
Built with 🧡 by @AbdelStark
Feel free to follow me on Nostr if you'd like, using my public key:
npub1hr6v96g0phtxwys4x0tm3khawuuykz6s28uzwtj5j0zc7lunu99snw2e29
Or just scan this QR code to find me: