Skip to main content

Command Palette

Search for a command to run...

BOLT 12: Reusable Payments on the Bitcoin Lightning Network

Published
3 min read
BOLT 12: Reusable Payments on the Bitcoin Lightning Network
M

Backend Software Engineer with over 5 years of working experience with engineering teams building and maintaining solutions across various sections

I have solid experience in building products using technologies such as JavaScript, nodeJs, ExpressJs, Typescript, ReactJs, NoSQL/SQL database, PHP/Laravel, Firebase, AWS S3, elastic beanstalk, and AWS Lambda function

I write articles on my blog around backend engineering, Bitcoin Lighening, building distributed Microservice systems and give talks in my local tech communities.

BOLT 12 introduces a new payment flow for the Bitcoin Lightning Network that enables reusable payment codes, improved privacy, and more flexible payment interactions than traditional BOLT 11 invoices.

At the core of BOLT 12 is the Offer: a static, reusable payment descriptor that allows a sender to pay without knowing the receiver’s node identity.

Why BOLT 12?

BOLT 11 invoices work well, but they have structural limitations:

  • Single-use (unsafe if reused)

  • Amount-specific (poor UX for donations, subscriptions, or dynamic pricing)

  • Receiver must often be online to generate an invoice

  • Not ideal for static identifiers or merchant checkout flows

BOLT 12 addresses these issues by separating payment intent from invoice creation.

Key Concepts in BOLT 12

1. Offer (Static & Reusable)

An Offer is a reusable Lightning payment descriptor published by the receiver.

An offer:

  • Can be paid multiple times

  • Can specify a fixed amount or no amount at all

  • Can be encoded as a QR code, URL, or text

  • Is safe to reuse

  • Does not require revealing the receiver’s node ID

Internally, an offer encodes everything needed to request an invoice:

  • How to reach the receiver (node ID or blinded path)

  • Description

  • Expiry time

  • Currency

  • Minimum / maximum quantity

  • Optional fixed amount

An offer does not move funds — it only enables invoice discovery.

2. Creating Offers in Rust (LDK)

Fixed-amount Offer

let offer = context.node.bolt12_payment().receive(
    50_000,                 // amount in msat
    "Coffee payment",
    Some(3600),             // expiry in seconds
    Some(1),                // quantity
)?;

Use this when:

  • The price is fixed

  • You want deterministic payments

Variable-amount Offer

let offer = context.node.bolt12_payment().receive_variable_amount(
    "Donation",
    Some(3600),
)?;

Use this when:

  • The payer chooses the amount

  • The receiver computes pricing dynamically (e.g. fiat → sats)

3. Invoice Request (Payer → Receiver)

Once a payer obtains an offer, they create an InvoiceRequest.

The payer:

  • Selects an offer

  • Optionally chooses an amount

  • Specifies quantity and metadata (payer note)

This request is:

  • Onion-routed

  • End-to-end encrypted

  • Sent over Lightning without requiring a channel

Sending an Invoice Request in Rust

Receiver decide the amount

let payment_id = context.node.bolt12_payment().send(
    &offer,
    Some(1),                        
    Some("Thanks!"),                // payer note
    route_parameters,
)?;

Here:

  • The payer sends intent

  • The receiver computes the final invoice amount

Payer decides the amount

let payment_id = context.node.bolt12_payment().send_using_amount(
    &offer,
    100_000,                        // amount in msat
    Some(1),
    Some("Tip"),
    route_parameters,
)?;

This is common for:

  • Donations

  • Tips

  • Pay-what-you-want flows

Invoice (Receiver → Payer)

Upon receiving the InvoiceRequest, the offer creator:

  • Validates the request

  • Computes the amount (if not specified)

  • Generates a real Lightning invoice

  • Cryptographically signs it

  • Sends it back to the payer

At this point, the payer receives a standard payable invoice.

Payment Execution

The final step is identical to BOLT 11:

  • Routes are found

  • HTLCs are constructed

  • Funds are transferred

The difference is how the invoice was obtained, not how it is paid.

Privacy Improvements in BOLT 12

BOLT 12 significantly improves privacy:

  • Receiver node ID is not revealed up front

  • Invoice requests are onion-routed

  • Supports blinded paths, hiding network topology

  • No static invoices to track or correlate

This makes BOLT 12 ideal for:

  • Merchant payments

  • Static Lightning identifiers

  • Recurring and subscription payments

Conclusion

BOLT 12 introduces a cleaner and more powerful Lightning payment model:

  • Static, reusable offers

  • Flexible pricing models

  • Better privacy

  • Improved merchant UX

By separating offers, invoice requests, and invoices, BOLT 12 enables payment flows that were awkward or impossible with BOLT 11.