Skip to main content

What is an Invoice?

If you've used Stripe, you're familiar with a PaymentIntent. A Coinsnap invoice is the equivalent — a payment request for a specific amount.


The lifecycle

New → Processing → Settled
→ Expired
→ Invalid

The main statuses are:

StatusMeaning
NewInvoice created, waiting for payment
ProcessingPayment detected, waiting for confirmation (on-chain only)
SettledPayment confirmed and funds are being forwarded to your wallet
ExpiredInvoice expired before full payment was received
InvalidInvoice was invalidated (e.g. tip amount exceeded total)

The additionalStatus field refines Settled and Expired:

statusadditionalStatusMeaning
SettledNoneExact amount received
SettledOverpaidCustomer paid more than the invoice amount
SettledPaidAfterExpirationPayment received after the invoice expired
ExpiredNoneNo payment at all
ExpiredUnderpaidPartial payment received before expiry

What's inside an invoice

When you create an invoice, Coinsnap returns everything you need to present payment options to your customer:

{
"id": "inv_4Kz9mXpQ2rNvBtYwLs8cDf",
"status": "New",
"amount": 10.00,
"currency": "EUR",
"orderId": "order-123",
"checkoutLink": "https://app.coinsnap.io/i/4Kz9mXpQ2rNvBtYwLs8cDf",
"lightningInvoice": "lnbc100u1p...",
"onchainAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"bip21": "bitcoin:bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh?amount=0.00010000",
"createdAt": 1705312800
}
FieldWhat to do with it
idStore in your database to correlate with the webhook
checkoutLinkRedirect the customer here (easiest path)
lightningInvoiceRender as QR if building a custom UI
onchainAddressOn-chain fallback QR in custom UI
bip21BIP-21 URI combining address + amount — use for a unified QR
orderIdYour reference — echoed back in the webhook
createdAtUnix timestamp (seconds) of invoice creation

The simplest integration path

You don't have to render QR codes yourself. The checkoutLink points to a Coinsnap-hosted page that:

  • Shows both Lightning and Bitcoin QR codes
  • Updates the status in real time
  • Redirects to your redirectUrl after payment
// After creating the invoice, just redirect:
window.location.href = invoice.checkoutLink;

One invoice = one payment

Invoices are single-use. Once paid, the same invoice cannot receive another payment. If a customer needs to pay again (e.g. after a session timeout), create a new invoice.

For a reusable payment link (e.g. a donation page), use Pay Links instead.


What happens if a customer underpays?

If a customer pays less than the invoice amount, the invoice expires with additionalStatus: Underpaid and you receive an Expired webhook.


Confirming payment

Never trust the redirect. The redirect to your redirectUrl is a UX convenience — it can be spoofed or bypassed. Always confirm payment via webhook.

See Webhooks → Verification for the signature check.