Webhooks
Receive real-time notifications when subscription events occur.
Setup
- Go to Settings (gear icon)
- Enable Webhook notifications
- Enter your webhook URL
- Save
Your endpoint will receive POST requests for subscription events.
Payload Format
json
{
"event": "subscription.created",
"timestamp": 1704067200,
"data": {
"subscription_id": "sub_abc123",
"plan_id": "plan_xyz",
"plan_name": "Pro Plan",
"subscriber_email": "user@example.com",
"subscriber_name": "John Doe",
"status": "pending",
"amount_sats": 10000
}
}Events
| Event | Triggered When |
|---|---|
subscription.created | New subscription created |
subscription.activated | First payment received |
subscription.renewed | Renewal payment received |
subscription.payment_failed | Payment attempt failed |
subscription.cancelled | Subscription cancelled |
subscription.expired | Subscription period ended |
Event Details
subscription.created
Fired when someone starts the checkout process.
json
{
"event": "subscription.created",
"data": {
"subscription_id": "sub_abc123",
"plan_id": "plan_xyz",
"subscriber_email": "user@example.com",
"status": "pending"
}
}subscription.activated
Fired when the first payment is received.
json
{
"event": "subscription.activated",
"data": {
"subscription_id": "sub_abc123",
"plan_id": "plan_xyz",
"subscriber_email": "user@example.com",
"status": "active",
"current_period_end": 1706745600
}
}subscription.cancelled
Fired when a subscription is cancelled.
json
{
"event": "subscription.cancelled",
"data": {
"subscription_id": "sub_abc123",
"subscriber_email": "user@example.com",
"cancelled_by": "subscriber",
"reason": "User requested cancellation"
}
}Handling Webhooks
python
from flask import Flask, request
app = Flask(__name__)
@app.post("/webhook/subscriptions")
def handle_webhook():
event = request.json
if event["event"] == "subscription.activated":
# Grant access
user_email = event["data"]["subscriber_email"]
grant_premium_access(user_email)
elif event["event"] == "subscription.cancelled":
# Revoke access
user_email = event["data"]["subscriber_email"]
revoke_premium_access(user_email)
return {"ok": True}Always respond with a 200 status code quickly. Do heavy processing asynchronously.
Security
Webhooks don't include a signature by default. To verify requests:
- Use a secret URL path (e.g.,
/webhook/abc123secret) - Check the IP address matches your LNbits server
- Verify the subscription exists via API call
Retry Policy
Failed webhook deliveries (non-2xx response) are not automatically retried. Use the API to poll for missed events if needed.
