SatLane
Documentation

Statuses

Invoice statuses

StatusMeaningTerminal?
pendingNo payment seen yetno
seenPayment detected in mempool (0 conf). Once seen, we do not auto-expire even if expires_at elapses; the next block decides.no
paidPayment confirmed (≥ conf_threshold) and amount within amount_sats ± amount_tolerance_satsno (can become reverted via reorg)
expiredpending past expires_at with no detected paymentno; address still watched through the grace window for a possible late_paid
late_paidConfirmed payment arrived after expires_at but inside the grace windowno (can become reverted)
underpaidConfirmed amount is less than amount_sats − amount_tolerance_sats. Buyer can top up; we auto-merge.no
overpaidConfirmed cumulative amount exceeds amount_sats + amount_tolerance_satsno; you may want to refund the difference
requires_reviewRouting landed on "no-match" (payment to a recycled address with no matching invoice), or cross-check disagreed. Manual admin action.no
revertedPreviously paid, then a chain reorg removed the txyes
cancelledVendor cancelled before paymentyes

Top-up payments (short-pay recovery)

If a buyer sends less than the invoice amount (outside tolerance), the invoice becomes underpaid and the watcher keeps listening. When a second on-chain transaction lands on the same address:

  1. Sum all non-reverted payments for that invoice plus the new tx.
  2. If the total lands within [amount_sats − tolerance, amount_sats + tolerance], the invoice flips to paid (or late_paid if past expiry).
  3. If still short, it stays underpaid and amount_paid_sats reflects the new total.
  4. If the total exceeds amount_sats + tolerance, it becomes overpaid.

Webhook implication: you may receive invoice.underpaid more than once for the same invoice, then invoice.paid / invoice.late_paid / invoice.overpaid when the cumulative total settles. Deduplicate by event_id only, never by invoice.id.

Hosted checkout surfaces this automatically: an underpaid invoice shows a "Send remaining X sats" CTA with a fresh bitcoin: URI for only the remaining amount.