The Lightning Offer

Decode, explore, and learn the inner workings of BOLT12 Lightning Network offers.

Paste a BOLT12 offer above to decode it.

Hover over a highlighted section above to see more information.

Try it

Edit the code below and see the result instantly. The bolt12 library runs entirely in your browser.

Editor
Output

          
Install in your project npm install bolt12-utils

What is BOLT12?

BOLT12 is a protocol for requesting and receiving invoices over the Lightning Network itself. It replaces the static, single-use BOLT11 invoice with a reusable offer that a merchant can publish once (as a QR code, link, or NFC tag), from which payers derive fresh invoices on demand.

BOLT11 (Legacy)

  • Single-use invoices
  • Requires out-of-band server (LNURL)
  • Payee node ID exposed
  • No native proof of payment provenance
  • Hard to extend (fixed field encoding)

BOLT12 (Offers)

  • Reusable offers
  • Native onion message exchange
  • Blinded paths for privacy
  • Payer proofs with selective disclosure
  • Extensible TLV encoding

Message Flow

BOLT12 defines a 4-step protocol between a merchant and a payer:

1

Offer lno

Merchant publishes a static, reusable offer (QR code, web page, NFC). Contains description, amount, paths, and issuer identity.

2

Invoice Request lnr

Payer decodes the offer and sends an invoice request over an onion message. Includes payer identity, quantity, and reply path.

3

Invoice lni

Merchant validates the request, generates a fresh invoice with a unique payment hash, and sends it back over an onion message.

4

Payment (HTLC)

Payer validates the invoice signature, then pays using standard HTLC routing (possibly via the blinded paths in the invoice).

Offer Fields

An offer is a TLV stream encoded with the lno prefix. These are the defined fields:

TypeFieldDescription
2offer_chainsWhich blockchain(s) the offer is valid for (default: Bitcoin mainnet)
4offer_metadataArbitrary bytes for stateless request validation
6offer_currencyISO 4217 currency code (e.g., "USD") if amount is not in msat
8offer_amountPrice in millisatoshis or currency units
10offer_descriptionHuman-readable description of the offer
12offer_featuresFeature bits the offer requires/supports
14offer_absolute_expiryUnix timestamp after which the offer expires
16offer_pathsBlinded paths to reach the merchant
18offer_issuerHuman-readable name of the issuer
20offer_quantity_maxMaximum quantity a payer can request
22offer_issuer_idMerchant's compressed public key (33 bytes)

Key Concepts

Blinded Paths

Blinded paths let a node receive messages and payments without revealing its node ID or network position. A path consists of an introduction node, a blinding point, and encrypted hops that only each successive node can decrypt. They appear in offers (for onion messages) and invoices (for payment routing).

TLV Encoding

All BOLT12 messages use Type-Length-Value encoding with BigSize integers. Fields must appear in ascending type order. Unknown odd types are ignored (forward compatible); unknown even types cause rejection. This makes the protocol natively extensible.

Merkle Signatures

Signatures use BIP-340 Schnorr over a Merkle root computed from all TLV fields. Each field becomes a leaf paired with a nonce, then branches are built bottom-up. This enables selective disclosure: either party can reveal specific fields to a third party without exposing the entire message.

Bech32 (No Checksum)

BOLT12 strings use bech32-style encoding but without the 6-character checksum. QR codes provide error detection, and cryptographic signatures serve as integrity checks. The + character can split long strings across lines. Uppercase is preferred for QR efficiency.

Payer Proofs

A payer proof (lnp) allows a payer to prove they paid a specific invoice while selectively disclosing only certain fields. This enables privacy-preserving proof of payment for receipts, warranties, and dispute resolution.

1

Selective Disclosure

The payer chooses which invoice fields to reveal (e.g., payment hash, node ID) and which to keep private (e.g., amount, description). Type 0 (invreq_metadata) is always kept secret.

2

Merkle Proof

The proof includes the Merkle branch hashes needed to reconstruct the root from the disclosed fields, plus nonce hashes for each included TLV. The verifier can recompute the root and verify the invoice signature.

3

Payer Signature

The payer signs SHA256(note || merkle_root) with their key, binding an optional note (e.g., "Payment for coffee") to the proof.

TypeFieldDescription
88invreq_payer_idPayer's public key (required, always included)
168invoice_payment_hashPayment hash from the invoice (required)
176invoice_node_idMerchant's node ID for signature verification (required)
240signatureInvoice signature (BIP-340 Schnorr, 64 bytes)
242preimagePayment preimage (32 bytes, proves payment was completed)
244omitted_tlvsMarker numbers for omitted fields (BigSize array)
246missing_hashesMerkle branch hashes for tree reconstruction (32 bytes each)
248leaf_hashesNonce hashes for included TLVs (32 bytes each)
250payer_signaturePayer's BIP-340 signature + optional UTF-8 note

Learning Resources

Further your Lightning Network knowledge with these resources:

Support Development

If you find this library useful, consider donating via on-chain (Taproot), ARK, or BOLT12:

MethodAddress / Offer
On-chain (Taproot)bc1pyys36jag8qug09c36d9j6427kny3d0x08u3wf5l89sks5sxyq3fsp2vddt
ARKark1qq4hfssprtcgnjzf8qlw2f78yvjau5kldfugg29k34y7j96q2w4t5fjuejh7a4eauna0vf2eegcw95w3dyjzl8gykpye50e9qneuwezqdfwupf
BOLT12 Offerlno1pgqppmsrse80qf0aara4slvcjxrvu6j2rp5ftmjy4yntlsmsutpkvkt6878sxn8g96fuzlhw75hendmuhjy0gp607tsgzaasdvjmstcwcgc6vgwyqgp6mv9u948ngt3j0urev4ga0vw06cpvasexgn00feez9vfgdkyykfgqxdaa8ysjuy8um26ekywlceecwalj0zvqu5h0dd486uhhzvj9m3qlnmaa9awj0cft7x95h7yn9vaep4gm055q8rsctl6lthka2htmk8pzxvgyzae72gnapuhg2v9rtgwfg4mlr56lqqerat2vv2u2aka8e592vqluf5erqqs2ve30snd2pr2d0h7fdfl9js6wyzjl4c66nu6d32nj4w2ft0um9q4q

BIP21/321 unified URI:

bitcoin:bc1pyys36jag8qug09c36d9j6427kny3d0x08u3wf5l89sks5sxyq3fsp2vddt?ark=ark1qq4hfssprtcgnjzf8qlw2f78yvjau5kldfugg29k34y7j96q2w4t5fjuejh7a4eauna0vf2eegcw95w3dyjzl8gykpye50e9qneuwezqdfwupf&lno=lno1pgqppmsrse80qf0aara4slvcjxrvu6j2rp5ftmjy4yntlsmsutpkvkt6878sxn8g96fuzlhw75hendmuhjy0gp607tsgzaasdvjmstcwcgc6vgwyqgp6mv9u948ngt3j0urev4ga0vw06cpvasexgn00feez9vfgdkyykfgqxdaa8ysjuy8um26ekywlceecwalj0zvqu5h0dd486uhhzvj9m3qlnmaa9awj0cft7x95h7yn9vaep4gm055q8rsctl6lthka2htmk8pzxvgyzae72gnapuhg2v9rtgwfg4mlr56lqqerat2vv2u2aka8e592vqluf5erqqs2ve30snd2pr2d0h7fdfl9js6wyzjl4c66nu6d32nj4w2ft0um9q4q