Skip to content
ln.bot

REST API

REST API reference for ln.bot covering accounts, wallets, invoices, payments, addresses, webhooks, events, and L402.

Updated View as Markdown

Standard HTTP endpoints for programmatic access.

  • Base URL: https://api.ln.bot
  • Auth: Authorization: Bearer uk_... (user key) or Bearer wk_... (wallet key)
  • Content-Type: application/json

Two key types:

Key typePrefixScope
User keyuk_All wallets under the account
Wallet keywk_Single wallet only

Account

POST/v1/register

Register a new account. No authentication required.

Response:

json
{
  "userId": "usr_a1b2c3d4",
  "primaryKey": "uk_...",
  "secondaryKey": "uk_...",
  "recoveryPassphrase": "abandon ability able about ..."
}

No auth required. Save both keys — the recovery passphrase is shown only once.

GET/v1/me

Get authenticated identity. Works with both user keys and wallet keys.

Response:

json
{
  "walletId": "wal_c7i0hnuoxxupuwej"
}

Wallets

POST/v1/wallets

Create a new wallet. Requires user key authentication. Name is auto-generated.

Response:

json
{
  "walletId": "wal_c7i0hnuoxxupuwej",
  "name": "k9x2mwp",
  "address": "k9x2mwp@ln.bot"
}

GET/v1/wallets

List all wallets. Requires user key authentication.

Response:

json
[
  {
    "walletId": "wal_c7i0hnuoxxupuwej",
    "name": "k9x2mwp",
    "createdAt": "2026-01-15T10:00:00Z"
  }
]

GET/v1/wallets/{walletId}

Get wallet details. With a wallet key (wk_), use /v1/wallets/current.

Response:

json
{
  "walletId": "wal_c7i0hnuoxxupuwej",
  "name": "k9x2mwp",
  "balance": 12500,
  "onHold": 0,
  "available": 12500
}

PATCH/v1/wallets/{walletId}

Update wallet name. With a wallet key (wk_), use /v1/wallets/current.

Request body:

json
{
  "name": "my-agent"
}

Response:

json
{
  "walletId": "wal_c7i0hnuoxxupuwej",
  "name": "my-agent",
  "balance": 12500,
  "onHold": 0,
  "available": 12500
}

Wallet Keys

Wallet keys (wk_) give scoped access to a single wallet. Maximum 1 per wallet.

POST/v1/wallets/{walletId}/key

Create a wallet key.

Response:

json
{
  "key": "wk_...",
  "hint": "wk_...a1b2"
}

The key is shown once and cannot be retrieved again.

GET/v1/wallets/{walletId}/key

Get wallet key info (no plaintext key).

Response:

json
{
  "hint": "wk_...a1b2",
  "createdAt": "2026-01-15T10:00:00Z",
  "lastUsedAt": "2026-01-16T08:00:00Z"
}

DELETE/v1/wallets/{walletId}/key

Revoke the wallet key immediately.

Returns 204 No Content on success.

POST/v1/wallets/{walletId}/key/rotate

Rotate the wallet key. Old key is immediately invalidated.

Response:

json
{
  "key": "wk_...",
  "hint": "wk_...c3d4"
}

Invoices

POST/v1/wallets/{walletId}/invoices

Create an invoice. Creates a BOLT11 invoice valid for 60 minutes. Optionally include a reference for tracking and a memo embedded in the invoice.

Request body:

json
{
  "amount": 1000,
  "memo": "AI task payment",
  "reference": null
}

Response:

json
{
  "number": 1,
  "status": "pending",
  "amount": 1000,
  "bolt11": "lnbc10u1pn...",
  "reference": null,
  "memo": "AI task payment",
  "preimage": null,
  "txNumber": null,
  "createdAt": "2026-01-15T10:30:00Z",
  "settledAt": null,
  "expiresAt": "2026-01-15T11:30:00Z"
}

GET/v1/wallets/{walletId}/invoices

List invoices. Returns invoices in reverse chronological order.

ParameterInTypeDescription
limitqueryintMax results
afterqueryintPaginate by invoice number

Response:

json
[
  {
    "number": 2,
    "status": "settled",
    "amount": 500,
    "bolt11": "lnbc5u1pn...",
    "reference": null,
    "memo": null,
    "preimage": "d4e5f6...",
    "txNumber": 3,
    "createdAt": "2026-01-15T11:00:00Z",
    "settledAt": "2026-01-15T11:02:00Z",
    "expiresAt": "2026-01-15T12:00:00Z"
  }
]

GET/v1/wallets/{walletId}/invoices/{number}

Get invoice by number.

ParameterInTypeRequiredDescription
numberpathintyesInvoice number

Response: Same shape as POST, with settlement data populated.

GET/v1/wallets/{walletId}/invoices/{paymentHash}

Get invoice by payment hash.

ParameterInTypeRequiredDescription
paymentHashpathstringyesPayment hash

Same response as GET by number.

GET/v1/wallets/{walletId}/invoices/{number}/events

Wait for invoice (SSE). Server-Sent Events stream. Emits 'settled' or 'expired' then closes. Requires wallet key (wk_).

ParameterInTypeRequiredDescription
numberpathintyesInvoice number
timeoutqueryintnoMax wait in seconds (default 60, max 300)

Also available as /v1/wallets/{walletId}/invoices/{paymentHash}/events. Keepalive comments every 30s.

POST/v1/invoices/for-wallet

Create an invoice for a wallet. Creates a BOLT11 invoice for the given wallet ID (wal_xxx). The invoice is not saved until payment settles. No authentication required. Rate limited by IP.

Request body:

json
{
  "walletId": "wal_c7i0hnuoxxupuwej",
  "amount": 1000,
  "reference": null,
  "comment": null
}

Response:

json
{
  "bolt11": "lnbc10u1pn...",
  "amount": 1000,
  "expiresAt": "2026-01-15T11:30:00Z"
}

No auth required.

POST/v1/invoices/for-address

Create an invoice for a Lightning address. Creates a BOLT11 invoice for the wallet that owns the given address. No authentication required. Rate limited by IP.

Request body:

json
{
  "address": "mybot@ln.bot",
  "amount": 1000,
  "tag": null,
  "comment": null
}

Response:

json
{
  "bolt11": "lnbc10u1pn...",
  "amount": 1000,
  "expiresAt": "2026-01-15T11:30:00Z"
}

No auth required.

Payments

POST/v1/wallets/{walletId}/payments

Send a payment. Accepts a Lightning address (user@domain), LNURL (lnurl1...), or BOLT11 invoice in 'target'. Amount required for addresses and LNURLs, optional for BOLT11 (uses invoice amount). Use idempotencyKey to safely retry.

Request body:

json
{
  "target": "r7vq3np@ln.bot",
  "amount": 500,
  "maxFee": null,
  "idempotencyKey": null,
  "reference": null
}

Response:

json
{
  "number": 1,
  "status": "settled",
  "amount": 500,
  "maxFee": 10,
  "serviceFee": 0,
  "actualFee": 0,
  "address": "r7vq3np@ln.bot",
  "reference": null,
  "preimage": "e5f6a7b8...",
  "txNumber": 2,
  "failureReason": null,
  "createdAt": "2026-01-15T10:35:00Z",
  "settledAt": "2026-01-15T10:35:01Z"
}

GET/v1/wallets/{walletId}/payments

List payments. Returns payments in reverse chronological order.

ParameterInTypeDescription
limitqueryintMax results
afterqueryintPaginate by payment number

Response:

json
[
  {
    "number": 1,
    "status": "settled",
    "amount": 500,
    "maxFee": 10,
    "serviceFee": 0,
    "actualFee": 0,
    "address": "r7vq3np@ln.bot",
    "reference": null,
    "preimage": "e5f6a7b8...",
    "txNumber": 2,
    "failureReason": null,
    "createdAt": "2026-01-15T10:35:00Z",
    "settledAt": "2026-01-15T10:35:01Z"
  }
]

GET/v1/wallets/{walletId}/payments/{number}

Get payment by number.

ParameterInTypeRequiredDescription
numberpathintyesPayment number

Same response shape as POST.

GET/v1/wallets/{walletId}/payments/{paymentHash}

Get payment by payment hash.

ParameterInTypeRequiredDescription
paymentHashpathstringyesPayment hash

Same response shape as POST.

GET/v1/wallets/{walletId}/payments/resolve

Inspect a payment target before sending. Returns amount constraints.

ParameterInTypeRequiredDescription
targetquerystringyesLightning address, LNURL, or BOLT11

Response:

json
{
  "type": "address",
  "min": 1,
  "max": 1000000000,
  "fixed": false,
  "amount": null
}

GET/v1/wallets/{walletId}/payments/{number}/events

Wait for payment (SSE). Server-Sent Events stream. Emits 'settled' or 'failed' then closes. Requires wallet key (wk_).

ParameterInTypeRequiredDescription
numberpathintyesPayment number
timeoutqueryintnoMax wait in seconds (default 60, max 300)

Also available as /v1/wallets/{walletId}/payments/{paymentHash}/events. Keepalive comments every 30s.

Addresses

POST/v1/wallets/{walletId}/addresses

Create an address. Creates a random address (if address is null) or claims a vanity address. Vanity addresses are charged based on length.

Request body:

json
{
  "address": null
}

Response:

json
{
  "address": "j4hf8tj",
  "generated": true,
  "cost": 0,
  "createdAt": "2026-01-15T10:00:00Z"
}

GET/v1/wallets/{walletId}/addresses

List addresses.

Response:

json
[
  {
    "address": "j4hf8tj",
    "generated": true,
    "cost": 0,
    "createdAt": "2026-01-15T10:00:00Z"
  },
  {
    "address": "mybot",
    "generated": false,
    "cost": 2000,
    "createdAt": "2026-01-16T08:00:00Z"
  }
]

DELETE/v1/wallets/{walletId}/addresses/{address}

Delete an address. No refund for vanity addresses.

ParameterInTypeRequiredDescription
addresspathstringyesAddress to delete

Returns 204 No Content on success.

POST/v1/wallets/{walletId}/addresses/{address}/transfer

Transfer to another wallet. Only vanity (purchased) addresses can be transferred.

ParameterInTypeRequiredDescription
addresspathstringyesAddress to transfer

Request body:

json
{
  "targetWalletKey": "uk_..."
}

Response:

json
{
  "address": "mybot",
  "transferredTo": "wal_x8j2knroyyqpvwfh"
}

Transactions

GET/v1/wallets/{walletId}/transactions

List transactions. Returns credit and debit transactions in reverse chronological order. Each includes the balance after it was applied.

ParameterInTypeDescription
limitqueryintMax results
afterqueryintPaginate by transaction number

Response:

json
[
  {
    "number": 3,
    "type": "credit",
    "amount": 500,
    "balanceAfter": 13000,
    "networkFee": 0,
    "serviceFee": 0,
    "paymentHash": "a1b2c3...",
    "preimage": "d4e5f6...",
    "reference": null,
    "note": null,
    "createdAt": "2026-01-15T11:02:00Z"
  },
  {
    "number": 2,
    "type": "debit",
    "amount": 500,
    "balanceAfter": 12500,
    "networkFee": 0,
    "serviceFee": 0,
    "paymentHash": "f6e5d4...",
    "preimage": "c3b2a1...",
    "reference": null,
    "note": null,
    "createdAt": "2026-01-15T10:35:01Z"
  }
]

Webhooks

POST/v1/wallets/{walletId}/webhooks

Create a webhook. Registers a URL to receive event callbacks. The signing secret is returned only once. Max 10 per wallet.

Request body:

json
{
  "url": "https://example.com/hooks/lnbot"
}

Response:

json
{
  "id": "whk_a1b2c3d4",
  "url": "https://example.com/hooks/lnbot",
  "secret": "whsec_...",
  "createdAt": "2026-01-15T10:00:00Z"
}

Save the secret — it cannot be retrieved again.

GET/v1/wallets/{walletId}/webhooks

List webhooks. Secrets are not included in the response.

Response:

json
[
  {
    "id": "whk_a1b2c3d4",
    "url": "https://example.com/hooks/lnbot",
    "active": true,
    "createdAt": "2026-01-15T10:00:00Z"
  }
]

DELETE/v1/wallets/{walletId}/webhooks/{id}

Delete a webhook. Pending deliveries are discarded.

ParameterInTypeRequiredDescription
idpathstringyesWebhook ID

Returns 204 No Content on success.

User Keys

POST/v1/keys/{slot}/rotate

Rotate a user key. Generates a new secret for the slot (0 = primary, 1 = secondary). The old key is immediately invalidated.

ParameterInTypeRequiredDescription
slotpathintyes0 = primary, 1 = secondary

Response:

json
{
  "key": "uk_newrotated...",
  "name": "primary"
}

The new key is returned once and cannot be retrieved again.

Events

GET/v1/wallets/{walletId}/events

Real-time event stream. Opens a Server-Sent Events (SSE) stream that pushes real-time notifications for the wallet. Requires wallet key (wk_).

Events: invoice.created, invoice.settled, payment.created, payment.settled, payment.failed. Each message is a JSON object with event, created_at, and data fields. Keepalive comments every 30s.

L402

POST/v1/wallets/{walletId}/l402/challenges

Create an L402 challenge. Creates a Lightning invoice and mints a macaroon. Returns the pre-formatted WWW-Authenticate header value for use in HTTP 402 responses.

Request body:

json
{
  "amount": 100,
  "description": "API access",
  "expirySeconds": 3600,
  "caveats": null
}

Response:

json
{
  "macaroon": "AgELbG4uYm90...",
  "invoice": "lnbc1u1pn...",
  "paymentHash": "a1b2c3d4...",
  "expiresAt": "2026-01-15T11:30:00Z",
  "wwwAuthenticate": "L402 macaroon=\"...\", invoice=\"lnbc...\""
}

POST/v1/wallets/{walletId}/l402/verify

Verify an L402 token. Stateless verification of an L402 token. Checks macaroon signature, preimage proof-of-payment, and caveat validity (e.g., expiry). No database lookup needed.

Request body:

json
{
  "authorization": "L402 AgELbG4uYm90...:a1b2c3d4..."
}

Response:

json
{
  "valid": true,
  "paymentHash": "a1b2c3d4...",
  "caveats": ["expiry=1737000000"],
  "error": null
}

POST/v1/wallets/{walletId}/l402/pay

Pay an L402 challenge. Parses a WWW-Authenticate header, pays the embedded invoice, and returns a ready-to-use Authorization header. If wait=true (default), polls for settlement up to timeout seconds.

Request body:

json
{
  "wwwAuthenticate": "L402 macaroon=\"...\", invoice=\"lnbc...\"",
  "maxFee": null,
  "reference": null,
  "wait": true,
  "timeout": 60
}

Response:

json
{
  "authorization": "L402 AgELbG4uYm90...:e5f6a7b8...",
  "paymentHash": "a1b2c3d4...",
  "preimage": "e5f6a7b8...",
  "amount": 100,
  "fee": 0,
  "paymentNumber": 5,
  "status": "settled"
}