Invalid Date

Bitcoin Lightning payments settle in seconds and cost under a penny. Here’s how to accept them in your Node.js app.

What you’ll build

A simple payment flow: your app creates a Lightning invoice, the customer scans a QR code, and you get notified when they pay. Total integration time: about 5 minutes.

Prerequisites

Step 1: Create a payment

One POST request creates a Lightning invoice. You can specify the amount in USD — we handle the BTC conversion at the current spot rate.

const response = await fetch('https://api.lnmerchant.com/payments', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    currency: 'BTC',
    amountCents: 2500,  // $25.00 — auto-converted to sats
    description: 'Premium membership',
  }),
});

const payment = await response.json();
// payment.invoice = "lnbc..." (BOLT-11 invoice string)
// payment.amountSats = 26315
// payment.id = "abc-123"

The response includes a payment.invoice — that’s a BOLT-11 invoice string. Display it as a QR code for the customer to scan.

Step 2: Redirect to hosted checkout

The easiest option: redirect your customer to our hosted checkout page. It shows the QR code, handles wallet deep links, and auto-detects payment.

// After creating the payment, redirect:
res.redirect(`https://pay.lnmerchant.com/checkout/${payment.id}`);

The checkout page shows the amount, a QR code, and a “Waiting for payment…” indicator that automatically updates when the customer pays.

Step 3: Detect settlement

Poll the payment status or set up a webhook. The payment moves from pending to settled when the Lightning invoice is paid.

Option A: Poll

async function waitForPayment(paymentId) {
  while (true) {
    const res = await fetch(`https://api.lnmerchant.com/payments/${paymentId}`, {
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
    });
    const payment = await res.json();

    if (payment.status === 'settled') {
      return payment; // Payment confirmed!
    }

    await new Promise(r => setTimeout(r, 3000)); // Check every 3 seconds
  }
}

Configure a webhook URL in your LN Merchant dashboard. We’ll POST to your endpoint when the payment settles:

{
  "event": "payment.settled",
  "paymentId": "abc-123",
  "currency": "BTC",
  "amountSats": 26315,
  "amountCents": 2500,
  "status": "settled",
  "timestamp": "2026-04-28T14:30:00Z"
}

Verify the X-Webhook-Signature header (HMAC-SHA256) to ensure the request is authentic.

Step 4: Confirm the purchase

Once the payment is settled, confirm the purchase in your app — grant access, book the reservation, ship the product, whatever your business does.

app.post('/webhook', (req, res) => {
  const { event, paymentId, status } = req.body;

  if (event === 'payment.settled') {
    // Confirm the purchase in your database
    confirmPurchase(paymentId);
  }

  res.sendStatus(200);
});

Want USDC instead?

Same API, different currency. Just change currency: 'BTC' to currency: 'USDC' and you get a Solana Pay URL instead of a Lightning invoice. The checkout page handles both.

// Same code, just change the currency
body: JSON.stringify({
  currency: 'USDC',
  amountCents: 2500,
  description: 'Premium membership',
})
// Returns paymentUrl (Solana Pay) instead of invoice (BOLT-11)

What’s next

  • Auth & Capture: Hold funds before completing a booking with type: 'hold'
  • Subscriptions: Set up recurring Lightning billing
  • Refunds: Process refunds via reverse Lightning invoices

Ready to get started? Join the waitlist for early access to the API.

Ready to accept Lightning & USDC payments?

Join the waitlist for early access.

Get Early Access