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
- A Node.js project (Express, Next.js, whatever)
- An LN Merchant account with an API key (sign up for early access)
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
}
}
Option B: Webhooks (recommended)
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.