Lightning Beginner 8 min read
LNbits API Reference
Complete LNbits REST API documentation for Lightning payments. Create invoices, pay invoices, check balances, and manage wallets.
lnbits api rest wallet payments
LNbits API Reference
LNbits provides a simple REST API for Lightning operations. It’s the recommended interface for agents due to its simplicity and stateless design.
Base URL
Production: https://your-lnbits-instance.com/api/v1
Demo: https://legend.lnbits.com/api/v1 (testing only!)
Warning: The demo instance (legend.lnbits.com) is for testing. Do not use for real funds.
Authentication
All requests require an API key in the X-Api-Key header.
Key Types
| Key Type | Permission | Use For |
|---|---|---|
| Invoice/Read Key | Create invoices, check payments | Receiving |
| Admin Key | All operations including payments | Sending |
headers = {
"X-Api-Key": "your-api-key-here",
"Content-Type": "application/json"
}
Core Endpoints
Get Wallet Info
GET /api/v1/wallet
X-Api-Key: {invoice_key}
Response:
{
"id": "wallet-id",
"name": "My Wallet",
"balance": 100000
}
Note: Balance is in millisatoshis. Divide by 1000 for satoshis.
Create Invoice
POST /api/v1/payments
X-Api-Key: {invoice_key}
Content-Type: application/json
{
"out": false,
"amount": 1000,
"memo": "Payment description",
"expiry": 3600,
"webhook": "https://your-server.com/webhook"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
out | boolean | Yes | false for receiving |
amount | integer | Yes | Amount in satoshis |
memo | string | No | Invoice description |
expiry | integer | No | Seconds until expiry (default: 3600) |
webhook | string | No | URL to call when paid |
unit | string | No | Currency unit (sat, USD, etc.) |
Response:
{
"payment_hash": "abc123...",
"payment_request": "lnbc10u1pj9nrfz..."
}
Pay Invoice
POST /api/v1/payments
X-Api-Key: {admin_key}
Content-Type: application/json
{
"out": true,
"bolt11": "lnbc10u1pj9nrfz..."
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
out | boolean | Yes | true for sending |
bolt11 | string | Yes | BOLT11 invoice to pay |
Response:
{
"payment_hash": "abc123...",
"checking_id": "internal-id"
}
Check Payment Status
GET /api/v1/payments/{payment_hash}
X-Api-Key: {invoice_key}
Response:
{
"paid": true,
"preimage": "def456...",
"details": {
"memo": "Payment description",
"amount": 1000,
"fee": 0,
"time": 1706745600
}
}
List Payments
GET /api/v1/payments?limit=20&offset=0
X-Api-Key: {invoice_key}
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Max results (default: 20) |
offset | integer | Pagination offset |
sortby | string | Sort field |
direction | string | asc or desc |
Response:
[
{
"checking_id": "...",
"pending": false,
"amount": 1000,
"fee": 0,
"memo": "Coffee",
"time": 1706745600,
"bolt11": "lnbc...",
"preimage": "...",
"payment_hash": "...",
"wallet_id": "..."
}
]
Decode Invoice
POST /api/v1/payments/decode
X-Api-Key: {invoice_key}
Content-Type: application/json
{
"data": "lnbc10u1pj9nrfz..."
}
Response:
{
"payment_hash": "abc123...",
"amount_msat": 10000000,
"description": "Coffee",
"description_hash": null,
"payee": "03abc...",
"date": 1706745600,
"expiry": 3600,
"secret": null,
"route_hints": [],
"min_final_cltv_expiry": 18
}
Python Implementation
Complete Agent Class
import requests
import time
from typing import Optional
class LNbitsAgent:
def __init__(self, url: str, invoice_key: str, admin_key: str):
self.url = url.rstrip('/')
self.invoice_key = invoice_key
self.admin_key = admin_key
def _request(self, method: str, endpoint: str, key: str, **kwargs):
headers = {"X-Api-Key": key, "Content-Type": "application/json"}
response = requests.request(
method,
f"{self.url}/api/v1{endpoint}",
headers=headers,
**kwargs
)
response.raise_for_status()
return response.json()
def get_balance(self) -> int:
"""Get wallet balance in satoshis."""
data = self._request("GET", "/wallet", self.invoice_key)
return data["balance"] // 1000
def create_invoice(
self,
amount: int,
memo: str = "",
expiry: int = 3600,
webhook: Optional[str] = None
) -> dict:
"""Create a Lightning invoice."""
payload = {
"out": False,
"amount": amount,
"memo": memo,
"expiry": expiry
}
if webhook:
payload["webhook"] = webhook
return self._request("POST", "/payments", self.invoice_key, json=payload)
def pay_invoice(self, bolt11: str) -> dict:
"""Pay a Lightning invoice."""
return self._request(
"POST", "/payments",
self.admin_key,
json={"out": True, "bolt11": bolt11}
)
def check_payment(self, payment_hash: str) -> dict:
"""Check if a payment has been received."""
return self._request(
"GET", f"/payments/{payment_hash}",
self.invoice_key
)
def wait_for_payment(
self,
payment_hash: str,
timeout: int = 300,
interval: int = 5
) -> bool:
"""Wait until invoice is paid or timeout."""
start = time.time()
while time.time() - start < timeout:
status = self.check_payment(payment_hash)
if status.get("paid"):
return True
time.sleep(interval)
return False
def decode_invoice(self, bolt11: str) -> dict:
"""Decode a BOLT11 invoice."""
return self._request(
"POST", "/payments/decode",
self.invoice_key,
json={"data": bolt11}
)
Usage Example
# Initialize agent
agent = LNbitsAgent(
url="https://your-lnbits.com",
invoice_key="your-invoice-key",
admin_key="your-admin-key"
)
# Check balance
balance = agent.get_balance()
print(f"Balance: {balance} sats")
# Create invoice
invoice = agent.create_invoice(
amount=1000,
memo="Agent service fee",
expiry=600 # 10 minutes
)
print(f"Invoice: {invoice['payment_request']}")
# Wait for payment
if agent.wait_for_payment(invoice['payment_hash'], timeout=600):
print("Payment received!")
else:
print("Payment timed out")
# Pay an invoice
result = agent.pay_invoice("lnbc10u1...")
print(f"Payment sent: {result['payment_hash']}")
Error Handling
HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad request (invalid parameters) |
| 401 | Unauthorized (invalid API key) |
| 404 | Not found |
| 500 | Server error |
Common Errors
{
"detail": "Insufficient balance"
}
{
"detail": "Invoice already paid"
}
{
"detail": "Bad auth"
}
Error Handling Example
def safe_pay(agent, bolt11):
try:
result = agent.pay_invoice(bolt11)
return {"success": True, "data": result}
except requests.HTTPError as e:
if e.response.status_code == 400:
error = e.response.json()
if "Insufficient" in error.get("detail", ""):
return {"success": False, "error": "insufficient_balance"}
if "already paid" in error.get("detail", ""):
return {"success": False, "error": "already_paid"}
return {"success": False, "error": str(e)}
Webhook Integration
Webhook Payload
When an invoice is paid, LNbits sends:
{
"payment_hash": "abc123...",
"payment_request": "lnbc...",
"amount": 1000,
"comment": "memo",
"time": 1706745600
}
Webhook Server
from flask import Flask, request
app = Flask(__name__)
@app.route('/lnbits-webhook', methods=['POST'])
def webhook():
data = request.json
payment_hash = data['payment_hash']
amount = data['amount']
# Process payment
print(f"Received {amount} sats: {payment_hash}")
# Verify payment (optional but recommended)
status = agent.check_payment(payment_hash)
if status['paid']:
# Fulfill order
pass
return {'status': 'ok'}
Extensions API
LNbits has extensions that add functionality:
LNURL-Pay Extension
GET /lnurlp/api/v1/links
X-Api-Key: {invoice_key}
Bolt Cards Extension
GET /boltcards/api/v1/cards
X-Api-Key: {invoice_key}
Rate Limits
| Instance | Limits |
|---|---|
| Self-hosted | No limits |
| legend.lnbits.com | ~100 req/min |
Related Topics
Machine-Readable Summary
{
"api": "lnbits",
"base_path": "/api/v1",
"authentication": "X-Api-Key header",
"endpoints": [
{
"method": "GET",
"path": "/wallet",
"key": "invoice",
"description": "Get wallet info"
},
{
"method": "POST",
"path": "/payments",
"key": "invoice",
"description": "Create invoice (out=false)"
},
{
"method": "POST",
"path": "/payments",
"key": "admin",
"description": "Pay invoice (out=true)"
},
{
"method": "GET",
"path": "/payments/{hash}",
"key": "invoice",
"description": "Check payment status"
}
]
}