Skip to content

Agent Quick Start

Machine-readable guide for AI agents integrating with the Subscriptions Manager API.

TL;DR

bash
# List available plans (read-only)
curl -X GET "https://your-lnbits.com/subscriptions_manager/api/v1/plans" \
  -H "X-Api-Key: YOUR_INVOICE_KEY"

# Create a subscription for a user (no auth needed)
curl -X POST "https://your-lnbits.com/subscriptions_manager/api/v1/public/subscribe" \
  -H "Content-Type: application/json" \
  -d '{
    "plan_id": "PLAN_ID",
    "payment_method": "lightning",
    "email": "user@example.com"
  }'

Authentication

LNbits uses API keys passed in the X-Api-Key header.

KeyHeaderUse For
Admin KeyX-Api-Key: {key}Create/update/delete plans, manage subscriptions
Invoice KeyX-Api-Key: {key}Read-only: list plans, subscriptions, payments
Subscriber TokenX-Subscriber-Token: {token}Subscriber self-service (cancel, manage wallets)

Find your keys: LNbits dashboard → Wallet → API Info (key icon).

All endpoints are under the base path /subscriptions_manager appended to your LNbits URL.

Core Operations

1. List Plans

bash
GET /api/v1/plans
Header: X-Api-Key: {invoice_key}
Query: ?limit=50&offset=0

Returns a paginated list of active plans with items, total, limit, offset.

2. Create a Plan

bash
POST /api/v1/plans
Header: X-Api-Key: {admin_key}
Content-Type: application/json

{
  "name": "Pro Plan",
  "amount_sats": 10000,
  "interval": "monthly",
  "description": "Premium access",
  "trial_days": 7,
  "grace_period_days": 3,
  "allow_lightning": true,
  "allow_onchain": false,
  "allow_stripe": false,
  "allow_paypal": false
}
FieldTypeRequiredDescription
namestringYesPlan display name
amount_satsintegerYesPrice in satoshis
intervalstringYesweekly, monthly, or yearly
descriptionstringNoShown on checkout
trial_daysintegerNoFree trial period (default: 0)
grace_period_daysintegerNoDays after failed payment (default: 0)
allow_lightningbooleanNoEnable Lightning (default: true)
allow_onchainbooleanNoEnable on-chain Bitcoin
allow_stripebooleanNoEnable Stripe cards
allow_paypalbooleanNoEnable PayPal

3. Create a Subscription (Public)

bash
POST /public/subscribe
Content-Type: application/json
# No auth required

{
  "plan_id": "plan_abc123",
  "payment_method": "lightning",
  "email": "user@example.com",
  "name": "John Doe"
}

Returns a payment invoice (Lightning) or redirect URL (Stripe/PayPal). For trial plans, returns an immediately active subscription.

4. Check Payment Status (Public)

bash
GET /public/payment/{payment_id}/status
# No auth required

Returns: { "payment_id": "...", "status": "pending|paid|expired", "paid_at": ..., "subscription_id": "..." }

5. Manage Subscriptions

bash
# Pause
POST /api/v1/subscriptions/{id}/pause
Header: X-Api-Key: {admin_key}

# Resume
POST /api/v1/subscriptions/{id}/resume
Header: X-Api-Key: {admin_key}

# Cancel
POST /api/v1/subscriptions/{id}/cancel
Header: X-Api-Key: {admin_key}
Body (optional): { "reason": "...", "immediate": false }

# Extend (add free days)
POST /api/v1/subscriptions/{id}/extend?days=7
Header: X-Api-Key: {admin_key}

NWC Autopay Flow

NWC (Nostr Wallet Connect) enables automatic recurring payments. No manual invoice payment needed.

bash
# Step 1: Validate the NWC connection string
POST /public/nwc/validate
Content-Type: application/json
{ "nwc_string": "nostr+walletconnect://pubkey?relay=wss://relay.example.com&secret=..." }

# Step 2: Create NWC subscription
POST /public/subscribe/nwc
Content-Type: application/json
{
  "plan_id": "plan_abc123",
  "email": "user@example.com",
  "nwc_connection_string": "nostr+walletconnect://...",
  "contact_preference": "email"
}

If the wallet has sufficient balance, the first payment is completed immediately and the subscription becomes active.

Public Endpoints (No Auth)

These endpoints power the checkout flow and require no API key:

MethodEndpointDescription
GET/public/plan/{id}Get plan info for checkout display
POST/public/subscribeCreate subscription (returns invoice)
GET/public/payment/{id}/statusPoll payment status
POST/public/nwc/validateValidate NWC connection
POST/public/subscribe/nwcCreate NWC autopay subscription

Subscription Statuses

StatusMeaning
pendingWaiting for first payment
activePaid and current
pausedTemporarily suspended by admin
past_duePayment failed, in grace period
payment_failedGrace period ended, payment still failed
cancelledManually cancelled
expiredBilling period ended

Pagination

All list endpoints support pagination:

?limit=50&offset=0
  • limit: 1–200 (default 50)
  • offset: 0+ (default 0)
  • Response: { "items": [...], "total": N, "limit": 50, "offset": 0 }

Complete Python Example

python
import requests

BASE = "https://your-lnbits.com/subscriptions_manager"
ADMIN_KEY = "your_admin_key"
INVOICE_KEY = "your_invoice_key"

# Create a plan
plan = requests.post(
    f"{BASE}/api/v1/plans",
    headers={"X-Api-Key": ADMIN_KEY},
    json={
        "name": "Pro Monthly",
        "amount_sats": 10000,
        "interval": "monthly",
        "allow_lightning": True,
    }
).json()
print(f"Plan created: {plan['id']}")

# List plans
plans = requests.get(
    f"{BASE}/api/v1/plans",
    headers={"X-Api-Key": INVOICE_KEY}
).json()
print(f"Total plans: {plans['total']}")

# Subscribe a user (public, no auth)
checkout = requests.post(
    f"{BASE}/api/v1/public/subscribe",
    json={
        "plan_id": plan["id"],
        "payment_method": "lightning",
        "email": "user@example.com",
    }
).json()
print(f"Invoice: {checkout['payment_request']}")

# Poll for payment
import time
while True:
    status = requests.get(
        f"{BASE}/api/v1/public/payment/{checkout['payment_id']}/status"
    ).json()
    if status["status"] == "paid":
        print(f"Paid! Subscription: {status['subscription_id']}")
        break
    time.sleep(3)

# Check subscription
sub = requests.get(
    f"{BASE}/api/v1/subscriptions/{status['subscription_id']}",
    headers={"X-Api-Key": INVOICE_KEY}
).json()
print(f"Status: {sub['status']}")

Complete JavaScript Example

javascript
const BASE = 'https://your-lnbits.com/subscriptions_manager'
const ADMIN_KEY = 'your_admin_key'
const INVOICE_KEY = 'your_invoice_key'

// Create a plan
const plan = await fetch(`${BASE}/api/v1/plans`, {
  method: 'POST',
  headers: {
    'X-Api-Key': ADMIN_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Pro Monthly',
    amount_sats: 10000,
    interval: 'monthly',
    allow_lightning: true,
  }),
}).then(r => r.json())

// Subscribe a user (public, no auth)
const checkout = await fetch(`${BASE}/api/v1/public/subscribe`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    plan_id: plan.id,
    payment_method: 'lightning',
    email: 'user@example.com',
  }),
}).then(r => r.json())

console.log('Invoice:', checkout.payment_request)

// Poll for payment
const poll = setInterval(async () => {
  const status = await fetch(
    `${BASE}/api/v1/public/payment/${checkout.payment_id}/status`
  ).then(r => r.json())

  if (status.status === 'paid') {
    clearInterval(poll)
    console.log('Paid! Subscription:', status.subscription_id)
  }
}, 3000)

Error Codes

HTTP StatusMeaning
200Success
201Created
400Bad request (missing/invalid fields)
401Unauthorized (missing or invalid API key)
403Forbidden (wrong key type, e.g. Invoice Key for admin action)
404Not found
422Validation error
500Server error

Decision Tree

Need to READ data (list plans, subscriptions, payments)?
  → Use Invoice Key with GET endpoints

Need to WRITE data (create plan, cancel subscription)?
  → Use Admin Key with POST/PUT/DELETE endpoints

Building a checkout for end users?
  → Use public endpoints (no auth needed)
  → POST /public/subscribe → returns invoice
  → GET /public/payment/{id}/status → poll until "paid"

Want automatic recurring payments?
  → Use NWC flow
  → POST /public/nwc/validate → then POST /public/subscribe/nwc

Subscriber wants self-service?
  → Use Subscriber Token with /public/manage/* endpoints

Further Reading