A BOLT11 invoice is a bech32-encoded payment request. It tells a payer what to pay, where hints might help, and when the request expires.
Complete Step 1 // Required reading in the study plan above, then continue here.
Step 2 — Core idea: fields, expiry, uniqueness
POS apps, SaaS billing, and wallets all mint invoices. Incorrect expiry or amount handling causes failed payments and angry users.
Analogy: A temporary ticket — amount, destination commitment (payment hash), and a deadline. After expiry, the ticket is useless even if someone pays late.
Key fields:
- Payment hash / payment secret
- Amount (optional for “any amount”)
- Expiry / timestamp
- Description or description hash
- Routing hints for unannounced channels
Loading diagram…
Invoices can omit amount (payer chooses) — receivers must still validate paid amounts against app expectations. Long descriptions can be hashed into the invoice to keep QRs small; full text travels out of band.
Show countdowns. Disable Pay on expiry. When regenerating, rotate payment hashes — never recycle.
Done when: You can list the fields a payer UI must show before Pay is enabled.
Step 3 — Try it: create + decode (lab)
# CLN example (Polar or local)
lightning-cli invoice 10000 "coffee" "cup #42"
lightning-cli decodepay <bolt11>Label hash, amount, and expiry in the decode output. Prefer Polar if you are not running a node yet.
Common mistakes
- Showing expired invoices in UI
- Ignoring
msatprecision vs display rounding - Forgetting routing hints for private channels
Done when: Lab evidence (create/decode + labeled fields + BOLT11 link) is complete.
Next lesson
BOLT12 Offers — reusable payment UX beyond one-shot invoices.