Skip to main content
grid

June 23, 2026

Lightning Payments API: A Developer Integration Guide

How a Lightning Network payment API works end to end, with the invoice and settlement flow, code examples, and the cost comparison to card APIs.

LightningPaymentsRails
author

Amboss Team

Bitcoiner

post

How to accept lightning payments via api

Accepting Lightning payments via an API is a three-step pattern: your server creates a BOLT 11 invoice, returns it to the customer's wallet, then watches for the settlement event. Lightning (Bitcoin's payment layer that settles transactions in under a second for fractions of a cent) does not use cards, interchange, or chargebacks, so the API surface is smaller and the settlement guarantees are stronger than a card API.

What is a Lightning Network payment API and how does it differ from card payment APIs?

A Lightning payments API exposes two primary operations: create an invoice and confirm a payment. There is no card object, no customer object, no 3D Secure step, and no chargeback webhook. The invoice itself is a self-contained BOLT 11 string defined in the BOLT 11 invoice protocol, which encodes the amount, expiry, description, and a payment hash the merchant uses to verify settlement.

Card APIs (Stripe, Adyen, Square) sit on top of the Visa and Mastercard scheme, which means the API has to model authorization, capture, refunds, disputes, and chargebacks. Lightning settles atomically. A payment either completes within seconds or it never happens. The merchant never sees a pending state that can reverse a week later.

The economic shape is different too. Stripe charges 2.9% + $0.30 per online card payment per Stripe's published pricing. A Lightning payment uses routing fees set by individual node operators on each channel they forward through, declared in channel_update messages defined by the BOLT 7 routing-gossip specification. Routing fees are paid by the sender, not the merchant, and competition between operators pushes them toward marginal cost.

ConceptCard API (Stripe)Lightning Payments API
Primary objectPaymentIntentInvoice (BOLT 11 string)
Authorize vs captureTwo stepsSingle atomic settlement
Refund flowStripe API callOut of band (no protocol refund)
ChargebacksUp to 120 days post-saleNone (irreversible)
Merchant fee~2.9% + $0.30Routing fees paid by sender
Settlement currencyFiat (USD)Satoshis (1 BTC = 100M sats)
Settlement timeHours to days (T+1, T+2)Sub-second to a few seconds
Webhook for successpayment_intent.succeededinvoice.settled (or subscribe)

The two APIs solve the same business problem (accept money) with very different protocol shapes. Most of the integration work in Lightning is about handling the absence of card-API concepts, not their presence.

What does the Lightning payment flow look like step by step?

A complete Lightning payment via API has five steps. The merchant server drives steps 1, 2, and 5. The customer's wallet drives 3 and 4. The whole thing typically completes in seconds end to end, with live network capacity and node-level metrics published on the Amboss Space Lightning explorer.

  1. Customer initiates checkout. Your server calls the Lightning API to create an invoice for the order amount, expressed in satoshis or millisatoshis.
  2. The API returns a BOLT 11 invoice string (a long lnbc… payment request) and a payment_hash. The merchant renders the invoice as a QR code or a deep link for the customer's wallet.
  3. The customer's wallet decodes the invoice, finds a route to the merchant's node, and sends the payment along that route using onion-routed HTLCs defined by the BOLT 4 onion-routing specification.
  4. Each hop on the route forwards the HTLC. When the payment reaches the merchant's node, the merchant reveals the preimage that hashes to payment_hash. The preimage settles the HTLC backward across every hop.
  5. Your server receives an invoice.settled event (or finds the invoice in a SETTLED state when polled). You fulfill the order.

The BOLT 11 spec defines this directly:

MUST set payment_hash to the SHA2 256-bit hash of the payment_preimage that will be given in return for payment.

The merchant never holds the customer's funds in escrow. The HTLC chain across the route is the settlement guarantee, anchored by the payee's exclusive possession of that preimage.

How do you generate a Lightning invoice via an API call?

Generating an invoice is one HTTP call. Below are the request and response shapes for the LND REST API, which is the most widely deployed Lightning node implementation, maintained as the Lightning Network Daemon project on GitHub.

curl -X POST https://your-node.example.com:8080/v1/invoices \
  -H "Grpc-Metadata-macaroon: $LND_MACAROON_HEX" \
  -H "Content-Type: application/json" \
  -d '{
    "value": 50000,
    "memo": "Order #1234",
    "expiry": 600
  }'
{
  "r_hash": "BqcMSGm...",
  "payment_request": "lnbc500u1pjxyz...",
  "add_index": "42"
}

The TypeScript equivalent against the same endpoint:

type InvoiceResponse = {
  r_hash: string;
  payment_request: string;
  add_index: string;
};

async function createInvoice(amountSats: number, memo: string) {
  const res = await fetch(`${process.env.LND_HOST}/v1/invoices`, {
    method: 'POST',
    headers: {
      'Grpc-Metadata-macaroon': process.env.LND_MACAROON_HEX!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      value: amountSats,
      memo,
      expiry: 600,
    }),
  });

  if (!res.ok) throw new Error(`LND error ${res.status}`);
  return (await res.json()) as InvoiceResponse;
}

Two things to know. First, value is the amount in satoshis, not millisatoshis (LND has a separate value_msat field for sub-satoshi precision). Second, the r_hash returned is base64 by default. Convert it to hex if you store it alongside an order, which most merchants do for lookup.

For higher-level APIs (managed services that wrap a node), the call is usually simpler. A typical managed endpoint takes the amount in cents and a reference ID and returns the same BOLT 11 string. The tradeoff is operational: you do not run a node, but you trust the operator's uptime and routing economics.

How do you confirm a Lightning payment was received?

There are two reliable patterns: subscribe to a settlement stream, or poll the invoice endpoint. Subscriptions are preferred for production because they avoid the polling latency-vs-load tradeoff. Webhooks are a third option offered by most managed Lightning APIs.

The LND subscription pattern uses a gRPC server-stream that emits an event every time an invoice changes state:

import { subscribeInvoices } from './lnd-client';

const stream = subscribeInvoices({});

stream.on('data', invoice => {
  if (invoice.state === 'SETTLED') {
    await fulfillOrder(invoice.r_hash);
  }
});

The poll pattern is a single GET against the invoice endpoint, useful for simple integrations or as a backup if the subscription drops:

curl -H "Grpc-Metadata-macaroon: $LND_MACAROON_HEX" \
  https://your-node.example.com:8080/v1/invoice/$R_HASH_HEX

The state field on the returned object will be OPEN, SETTLED, CANCELED, or ACCEPTED (for HOLD invoices, which let you delay final settlement). Production code should treat anything other than SETTLED as not yet paid.

Three failure modes to handle. Expired invoices: the customer waited too long to scan, the invoice is dead, generate a new one. Underpaid or overpaid invoices: BOLT 11 invoices with a fixed value cannot be underpaid, but zero-amount invoices (value: 0) can be paid for any amount — make sure the settled amount matches expectations before fulfilling. Network failures during the wallet's route attempt: the payment never reaches you, the invoice stays OPEN, and the customer's wallet shows an error.

What does it cost to accept Lightning payments via API?

The fee structure depends on whether you run your own node or use a managed Lightning payments API. The numbers below are publicly available baselines.

If you run your own node, the routing fee is paid by the sender across the route, and individual node operators set their own per-channel rates declared in protocol gossip messages, as specified in the BOLT 7 routing-gossip specification. The merchant's cost is operational: server hosting for the node, on-chain fees to open and rebalance channels, and the inbound liquidity needed to accept payments of your typical size.

If you use a managed Lightning API, the merchant fee is usually in the 0.4% to 1% range. The Amboss Payments API charges 0.5% of payment volume plus $30 per month for managed infrastructure, per the Amboss Payments documentation. Lightning Labs ecosystem providers and OpenNode publish similar headline rates.

Compared to cards, the cost difference is structural rather than incremental. Stripe states its rate plainly on the pricing page:

2.9% + 30¢ per successful transaction for domestic cards

A $100 Lightning payment on a managed API at 0.5% costs the merchant $0.50, versus about $3.20 on Stripe per Stripe's pricing page. Lightning has no interchange equivalent. There is no entity setting a network-wide fee floor. Routing fees are set by individual node operators on each channel they own, and competition between operators pushes them toward marginal cost.

What are the operational tradeoffs of running your own Lightning node versus using a Lightning payments API?

Running your own node gives you the lowest per-payment cost and full custody, at the price of operational work. A managed Lightning payments API removes the operational work, at the price of a per-payment fee and counterparty risk on the operator. Most businesses below a certain payment volume find the managed path cheaper in total cost of ownership.

The operational work of self-hosted includes: keeping a node online 24/7 (downtime equals lost payments), managing channels (opening, closing, rebalancing as your payment direction shifts inbound vs outbound), monitoring for force closes, keeping macaroons and seeds backed up, and on-chain fee management when channel operations land on the base layer.

A managed API hands all of that to the operator. The integration work is the same shape as integrating Stripe: API keys, idempotency, webhook signature verification. The tradeoff is that you are trusting the operator's uptime and pricing, and if they go down you cannot accept payments until they come back.

Hybrid options exist. Some merchants run a node for primary acceptance and fall back to a managed API for redundancy. Some run a node only for receiving and use a managed service for any outbound payments.

Where does Amboss Rails fit into this stack?

Most of this post is vendor-agnostic on purpose. The question of "how do I accept Lightning payments via API" has the same answer regardless of which node implementation or managed service you pick. Amboss Rails is the payment infrastructure and yield product built on top of this stack: it gives you the managed-API integration experience (0.5% per payment, no node operations), and pairs it with an optional product that lets bitcoin you've deployed earn fees from payment activity on the network. Rails is not the right pick if you want to self-host your node or if your volume is below the level where managed infrastructure makes sense. For those cases, run LND directly. For everyone else, Rails is one of the two or three places worth comparing.

Frequently asked questions

Which Lightning node implementation should I use for an API integration?

LND is the most widely deployed and has the largest ecosystem of libraries and managed providers. Core Lightning (CLN) is the second most common and is preferred by users who want a smaller, plugin-driven node. LDK is a library for embedding Lightning into your own application. For a typical API integration where you want to accept payments, LND is the default choice. If you already have backend code in Rust or want fine-grained control over routing, LDK is worth evaluating.

Do Lightning payments support refunds via the API?

No, the protocol has no refund primitive. A Lightning payment is irreversible once settled. Refunds happen out of band: the merchant pays the customer back as a separate Lightning payment, which the customer initiates by sending an invoice. Most merchant APIs include a helper to make this easier (a "refund" endpoint that prompts the customer's wallet for an invoice), but underneath it is just a second payment in the opposite direction.

How do I handle currency conversion if my prices are in USD?

You quote the customer in USD, fetch a BTC/USD rate at invoice creation time, and create the invoice for the equivalent satoshi amount. Most Lightning APIs offer this as a built-in option (you pass USD cents, the API does the conversion). For self-hosted nodes, you call a price oracle yourself. The risk is FX drift between when the invoice is created and when it is paid, which is why invoices typically expire within 5 to 15 minutes.

What stops someone from copying my invoice and paying it themselves to get the goods?

Nothing, and that is fine. The invoice is single-use: once paid, it cannot be paid again. Whoever pays it first triggers the settlement event and you fulfill that order. If a customer shares their invoice, they have shared their payment obligation, not their order. The merchant's payment_hash lookup ties the settled invoice back to the original order in your database.

Can I accept Lightning payments without running a node at all?

Yes. Managed Lightning payment APIs (Amboss, OpenNode, ZBD, Strike, Voltage) all expose the create-invoice + confirm-payment pattern over a normal HTTP API with no node infrastructure required on your side. The tradeoff is that you do not custody the funds yourself during the payment lifecycle — the operator settles into your account, and you withdraw on a schedule you control.

How big should each Lightning payment be?

Lightning is suitable for payments from about 1 satoshi (a few thousandths of a cent) up to roughly 0.1 BTC per single-path payment. Larger payments work via multi-part payments (MPP), where the wallet splits the amount across multiple routes, as defined in the BOLT 4 onion-routing specification. Most consumer Lightning payments today are between $0.50 and $500. The protocol scales further; the practical ceiling depends on inbound liquidity at the merchant's node.

author

Amboss Team

Bitcoiner