LNClear Public API v1

API Reference

Manage LNClear subscriptions programmatically. Full headless flow — no browser required. Perfect for RaspiBlitz scripts, Umbrel apps, and automation.

Base URL
https://lnclear.com/api/public/v1
All requests and responses use application/json.

Authentication

Most endpoints require ownership proof — pass your Nostr pubkey or Lightning node pubkey as a query param or request body field. No API keys required for the basic subscription flow.

nostr_pubkey — your hex-encoded Nostr public key (from any NIP-07 extension or nostr-tools)

ln_node_pubkey — your Lightning node's public key (66 hex chars from lncli getinfo)

Either one is accepted, but you must provide the same one you used when creating the subscription.

Quick Start Flow

1
GET/serversList available server locations
2
POST/subscription/createCreate subscription → get Lightning invoice
3
Pay the invoice with any Lightning wallet ⚡
4
POST/subscription/claimClaim your WireGuard config
Code examples:
GET/api/public/v1/servers

List Servers

Returns all available VPN server locations with live latency and load data. No authentication required.

Example Request
curl https://lnclear.com/api/public/v1/servers
Example Response
{
  "servers": [
    {
      "id": "uuid-...",
      "name": "Sydney",
      "slug": "au-sydney",
      "country_code": "AU",
      "country_flag": "🇦🇺",
      "city": "Sydney",
      "region": "APAC",
      "endpoint": "au1.lnclear.com",
      "listen_port": 51820,
      "ping_ms": 12,
      "load": "Low",
      "full": false
    }
  ]
}
POST/api/public/v1/subscription/create

Create Subscription

Creates a subscription and returns a Lightning invoice. Pay the invoice to activate your WireGuard peer.

Request Body
server_idstringrequired
Server UUID or slug (e.g. "au-sydney")
client_public_keystringrequired
WireGuard public key — 44-character base64
duration_monthsnumberrequired
1 | 3 | 6 | 12
nostr_pubkeystringoptional
Hex Nostr pubkey — used for dashboard login and ownership
ln_node_pubkeystringoptional
Lightning node pubkey — alternative login
Example Request
curl -X POST https://lnclear.com/api/public/v1/subscription/create \
  -H "Content-Type: application/json" \
  -d '{
    "server_id": "au-sydney",
    "client_public_key": "YOUR_WG_PUBLIC_KEY=",
    "duration_months": 1,
    "nostr_pubkey": "YOUR_NOSTR_HEX_PUBKEY"
  }'
Example Response
{
  "subscription_id": "a1b2c3d4-...",
  "payment_hash": "abc123...",
  "payment_request": "lnbc60000n1p...",
  "amount_sats": 6000,
  "expires_at": "2026-02-22T10:00:00.000Z"
}
POST/api/public/v1/subscription/claim

Claim Config

Checks payment status and returns WireGuard peer config. Poll this every 3 seconds after showing the invoice to your user.

Returns {"status":"pending"} if invoice not yet paid. Poll until status === "active".
Request Body
payment_hashstringrequired
payment_hash from /create response
client_private_keystringoptional
Optional. If provided, returns a complete .conf file. HTTPS only — prefer generating locally.
Example Request
curl -X POST https://lnclear.com/api/public/v1/subscription/claim \
  -H "Content-Type: application/json" \
  -d '{"payment_hash": "PAYMENT_HASH_FROM_CREATE"}'
Example Response
{
  "subscription_id": "a1b2c3d4-...",
  "status": "active",
  "peer_info": {
    "server_public_key": "ABC...=",
    "server_endpoint": "au1.lnclear.com:51820",
    "assigned_ip": "10.9.0.5",
    "assigned_port": 9738,
    "dns": "1.1.1.1,1.0.0.1",
    "expires_at": "2026-03-22T10:00:00.000Z"
  },
  "instructions": {
    "message": "Create lnclear.conf with the following content:",
    "template": "[Interface]\nPrivateKey = YOUR_PRIVATE_KEY\n..."
  }
}
POST/api/public/v1/subscription/renew

Renew Subscription

Extends an existing subscription. Returns a new Lightning invoice. No config changes needed after payment — same WireGuard peer, same IP, same port.

Request Body
subscription_idstringrequired
UUID of subscription to renew
duration_monthsnumberrequired
1 | 3 | 6 | 12
nostr_pubkeystringoptional
Must match the pubkey used at creation
ln_node_pubkeystringoptional
Must match the pubkey used at creation
Example Request
curl -X POST https://lnclear.com/api/public/v1/subscription/renew \
  -H "Content-Type: application/json" \
  -d '{
    "subscription_id": "YOUR_SUBSCRIPTION_UUID",
    "duration_months": 12,
    "nostr_pubkey": "YOUR_NOSTR_HEX_PUBKEY"
  }'
Example Response
{
  "subscription_id": "a1b2c3d4-...",
  "payment_hash": "def456...",
  "payment_request": "lnbc576000n1p...",
  "amount_sats": 57600,
  "current_expires_at": "2026-03-22T10:00:00.000Z",
  "new_expires_at": "2027-03-22T10:00:00.000Z",
  "note": "Pay this invoice to extend your subscription. No config changes needed."
}
GET/api/public/v1/subscription/:id

Get Subscription

Returns subscription status, bandwidth usage, server details, and expiry. Requires ownership proof.

Query Parameters
nostr_pubkeystringoptional
Must match original subscription
ln_node_pubkeystringoptional
Alternative to nostr_pubkey
Example Request
curl "https://lnclear.com/api/public/v1/subscription/YOUR_UUID?nostr_pubkey=YOUR_PUBKEY"
Example Response
{
  "id": "a1b2c3d4-...",
  "status": "active",
  "server": {
    "name": "Sydney",
    "city": "Sydney",
    "country_code": "AU",
    "endpoint": "au1.lnclear.com"
  },
  "assigned_ip": "10.9.0.5",
  "assigned_port": 9738,
  "expires_at": "2026-03-22T10:00:00.000Z",
  "duration_months": 1,
  "bandwidth": {
    "used_bytes": 5368709120,
    "used_gb": 5,
    "unlimited": true
  },
  "created_at": "2026-02-22T10:00:00.000Z"
}

Error Codes

CodeStatusDescription
400Bad RequestMissing or invalid field — check request body
401UnauthorizedMissing or invalid authentication
403ForbiddenPubkey does not match subscription ownership
404Not FoundSubscription, invoice, or server not found
405Method Not AllowedWrong HTTP method
409ConflictDuplicate: subscription or peer already exists
500Internal ErrorServer-side error — contact support

All error responses include an error field with a human-readable message.

Pricing

duration_monthsDiscountPriceamount_sats
1$9dynamic
311%$24dynamic
622%$42dynamic
1233%$72dynamic

Sat prices are calculated dynamically using the live BTC/USD rate from Kraken. The exact amount_sats is always returned by the /create endpoint. All plans include unlimited traffic.

Rate Limits

GET /servers — 60 req/min per IP

POST /subscription/create — 10 req/min per IP

POST /subscription/claim — 30 req/min per IP (polling use case)

All other endpoints — 30 req/min per IP

Exceeding limits returns 429 Too Many Requests.

Webhooks (Advanced)

Instead of polling /claim, you can receive a webhook when payment is confirmed. Pass a webhook_url in your create request (coming soon).

Webhook payload will be a POST with subscription_id, status, and full peer info. Secured with HMAC-SHA256 signature in the X-LNClear-Signature header.