165 / 736BOLT12

BOLT 12

One QR code, a fresh invoice for each payment

Why should a merchant create another Lightning invoice for the next customer? BOLT 12 adds a reusable offer: each person requests their own invoice from the same published code. A more convenient beginning is still not the payment itself.

BOLT 12 is a protocol for arranging a payment over the Lightning Network. It distinguishes an offer, an invoice_request and the resulting invoice. An offer can stay public for multiple payments, while each invoice specifies the terms of the particular payment being arranged.

Imagine a café that wants one counter-top code for voluntary contributions. Repeatedly paying the same ordinary BOLT 11 invoice would cause problems. BOLT 12 instead publishes an offer. The customer’s wallet sends an invoice_request based on it, asking for its own invoice, and the recipient returns a fresh invoice. Only then can it be paid. One printed QR can serve different people without all of them using the same invoice. Fetching an invoice, for example with fetchinvoice, still does not send money. Nor does the offer itself give the café permission to debit further payments from somebody else’s wallet. [1] [3] [4]

An offer can quote a price in bitcoin or another currency. The offer_currency field uses ISO 4217 codes; a USD amount, for example, is expressed in cents. Quantity and currency conversion may affect the invoice when it is issued. The final bitcoin invoice_amount is in millisatoshi, thousandths of a satoshi: 1000 msat = 1 sat. The payer needs to know that amount and the fee before paying, not just the original price on a sign. If the request specifies an exact invreq_amount, the invoice must match it. Otherwise the wallet checks the authorized range and should seek renewed approval for an amount outside it. Conversion must not become invisible consent to any price. [1] [3]

The printed code may remain on the counter, but the offer itself can expire at offer_absolute_expiry. Each invoice also has its own creation time, invoice_created_at, and validity period, invoice_relative_expiry. If that period is absent, the default is 7200 seconds, or two hours. An old invoice is therefore not a permanently valid contact. Wallets must also understand the mandatory features declared in messages. An unknown even bit denotes a required feature and leads to rejection; an unknown odd bit is optional and can be ignored. This is about safe compatibility, not an obstacle users should bypass by manually rewriting the code. [1]

After paying, retain the invoice and the wallet’s result. Settlement evidence also includes the preimage, a secret value obtained when the payment completes. The wallet calculates its hash, a value used for checking, and compares it with the payment hash in the invoice. Together with the invoice, this can demonstrate that it was paid, but does not by itself identify the person who paid. If the app disconnects or loses the response, check the previous payment’s status before trying again; a new invoice can lead to another payment. Treat claims about recurring payments just as carefully. Supporting BOLT 12 does not automatically mean supporting every extension or authorizing automatic debits. Check separately whether the wallet can receive payments through offers, pay somebody else’s offer, and what access you granted a connected application. [1] [3]

Requesting an invoice and transferring funds use the network for different purposes. offer_paths carries the request message, while invoice_paths supplies payment routes. BOLT 12 uses blinded paths, routes that conceal some connection details leading to the recipient. Disclosing less of the network’s layout helps privacy but does not promise complete anonymity. A hidden route also guarantees neither an available recipient nor liquidity: enough money on the required sides of payment channels. Technically, a current invoice must include these paths and matching invoice_blindedpay payment parameters, even for a route leading directly to the recipient. Requesting the invoice does not require a conventional HTTPS payment server. [1] [2]

When a merchant wants to refund a customer, the negotiation changes direction. The prospective payer can publish an invoice_request without a preceding offer. The customer, now the intended recipient, answers with their own invoice for the merchant to pay. This does not erase or reverse the original payment; it creates a new payment in the other direction. The merchant must verify that the invoice belongs to the intended recipient, sometimes by communicating outside the protocol. Scanning a request alone neither proves entitlement to a refund nor approves a transfer. The technical process helps communication; it does not decide who should receive the money. [1]

BOLT 12 stores data as TLV: each field states its type, length and value. A text offer starts with lno, a request with lnr. The character set resembles Bech32, but lacks its trailing checksum. This says nothing by itself about who should be paid. The offer is unsigned. BIP340 Schnorr digital signatures authenticate the invoice and an ordinary request responding to an offer. A standalone request published without an offer, for example for a refund, has no signature. The signature is tied to the root of a Merkle structure: a combined checking value calculated from the relevant fields. Selected fields can therefore be proved without always revealing every detail. That does not permit changing signed terms or prove a merchant’s legal identity. [1]

A wallet must establish that it received an answer to its request, not merely some correctly signed invoice. It compares copied invoice_request fields against the invoice, along with the network, amount and signature. The invoice_node_id public key must match offer_issuer_id; when an offer instead uses the relevant hidden route without that identifier, the wallet checks its final blinded_node_id. Think of checking that a bill belongs to your table, not merely that its stamp is genuine. The Merkle structure supports proofs of selected information but does not remove the wallet’s duty to verify all conditions needed for payment. Somebody else’s valid invoice does not become the right one just because its signature passes. [1]

For the clearest picture, read this entry together with BOLT 11, Lightning Network, Lightning Routing, Bitcoin Privacy, Satoshi, LNURL. The reverse links also lead from BOLT 11, LNURL, Just-in-Time Channels.

DOC · 001BOLT 12 — Negotiation protocolSpecification DOC · 002BOLT 4 — Route blindingSpecification DOC · 003Core Lightning — Fetching an invoiceDocumentation DOC · 004BOLT 12 — Project overviewPrimary
Revised: Source-first · No investment advice