This repository demonstrates how to implement an API paywall using the L402 protocol (a standard for HTTP 402 Payment Required responses), leveraging the Fewsats service for easy integration and management.
We use a simple Weather API as a practical example, which is publicly available at https://weather.l402.org.
This project runs on Replit and you can fork and run it yourself directly from your browser here
This project serves as both a showcase of L402 capabilities and an example for developers looking to monetize their own APIs programmatically using Fewsats.
Traditional payment flows often rely on browser interactions, which is challenging for programmatic access, especially for AI agents or automated systems. L402 standardizes machine-to-machine payments directly over HTTP.
Key benefits:
- Programmatic Payments: Enables services to request payment directly via API calls, without needing a browser.
- Standardized Flow: Provides a consistent way for clients to understand pricing and complete payments.
- New Monetization Models: Opens up possibilities for micro-transactions and usage-based billing for APIs.
Fewsats is a platform that simplifies the implementation of L402 paywalls for your API. It handles the complexity of:
- Generating L402 payment information (offers, payment methods).
- Processing payments through various methods (like Lightning and Credit Cards).
- Notifying your application about successful payments via webhooks.
This demo uses Fewsats to manage credits and payments for the Weather API.
Adding Fewsats to your application to create L402 payment offers is straightforward. Here's a simplified snippet from payments.py:
from fewsats.core import *
# Initialize Fewsats client (assuming api_key is configured)
fs = Fewsats(api_key=fewsats_api_key)
# Define payment packages (offers)
offers = [
{
"id": "offer_1",
"title": "1 credit package",
"description": "Add 1 credit to your account.",
"amount": 1, # USD Cents
"currency": "USD",
"payment_methods": ["lightning"]
},
{
"id": "offer_2",
"title": "1000 credit package",
"description": "Add 1000 credits to your account.",
"amount": 500, # USD Cents
"currency": "USD",
"payment_methods": ["lightning", "credit_card"]
}
]
# Function to generate L402 response when payment is needed
def create_payment_information(current_user_id):
# Use Fewsats SDK to create the offers payload
offers_information = fs.create_offers(offers)
offers_information.raise_for_status()
# Store user context associated with the payment attempt (optional)
payment_context_token = offers_information.json().get("payment_context_token")
db[f"payment:{payment_context_token}"] = current_user_id # Example using Replit DB
# Return the L402 information generated by Fewsats
return offers_informationFewsats then sends a webhook to your configured endpoint (/webhook in payments.py) when a payment is completed, allowing you to grant access or credits to the user.
This section demonstrates the end-user and payment flow for the example Weather API.
Here's a complete flow showing how a client interacts with the L402-paywalled Weather API:
# 1. Sign up: Get a user ID (acts as an API key) and some initial credits
curl -X POST https://weather.l402.org/signup
# Example Response: {"user_id":"b6fca606-af72-4aa9-a152-1d6444d1043e","credits":1}
# Store the user ID
USER_ID=$(curl -X POST -s https://weather.l402.org/signup | jq -r '.user_id')
echo "User ID: $USER_ID"
# 2. Use the API (consumes one credit)
curl -X GET -H "Authorization: Bearer ${USER_ID}" -s "https://weather.l402.org/weather?location=vancouver" | jq
# Example Success (200 OK):
# {
# "temperature": 10.1, "condition": "Overcast", ...
# }
# 3. Out of credits: Receive an HTTP 402 Payment Required response
# This response contains L402 payment information generated by Fewsats
curl -I -X GET -H "Authorization: Bearer ${USER_ID}" -s "https://weather.l402.org/weather?location=san%francisco"
# HTTP/1.1 402 Payment Required
# WWW-Authenticate: L402 token="...", invoice="..." <- Simplified L402 header
# Full 402 Response Body (details on how to pay):
curl -X GET -H "Authorization: Bearer ${USER_ID}" -s "https://weather.l402.org/weather?location=san%francisco" | jq
# {
# "offers": [ ... ], <- List of packages generated via Fewsats
# "payment_context_token": "...",
# "payment_request_url": "https://api.fewsats.com/v0/l402/payment-request",
# "version": "0.2.2"
# }Clients need an L402-compatible tool or library to process the 402 Payment Required response. These tools handle the interaction with the payment_request_url (in this case, Fewsats) to complete the payment (e.g., paying a Lightning invoice).
Check out the L402 Protocol Specification for details on the client-side payment flow.
/signup[POST Public]- Creates a user account and returns a
user_id(used as Bearer token) with initial credits. -
⚠️ Note: This simplified authentication is for demo purposes only. Never use this approach in production!
- Creates a user account and returns a
/weather[GET Auth]- Requires
Authorization: Bearer <user_id>header. - Returns weather information for a
locationquery parameter. - Responses:
200 OK: Success, returns weather data (consumes 1 credit).401 Unauthorized: Missing or invaliduser_id.402 Payment Required: Insufficient credits. Returns L402 JSON body generated by Fewsats.
- Requires
/webhook[POST Public]- Endpoint for receiving Fewsats payment confirmation webhooks.
These are the offers configured in Fewsats and presented in the 402 response:
- Single Credit Package
- 1 credit
- Price: $0.01 USD (1 cent)
- Bundle Credit Package
- 1000 credits
- Price: $5.00 USD (500 cents)
main.py: FastAPI server implementing signup, weather, and webhook endpoints.payments.py: Fewsats integration (offer creation, webhook processing).users.py: Basic user management (credits) using Replit KV store.weather_api.py: Integration with weatherapi.com for actual weather data.
Ready to add L402 paywalls to your own APIs?
- Visit fewsats.com to learn more and sign up.
- Check out the Fewsats Documentation for detailed integration guides.