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:
| Status | Meaning |
|---|---|
New | Invoice created, waiting for payment |
Processing | Payment detected, waiting for confirmation (on-chain only) |
Settled | Payment confirmed and funds are being forwarded to your wallet |
Expired | Invoice expired before full payment was received |
Invalid | Invoice was invalidated (e.g. tip amount exceeded total) |
The additionalStatus field refines Settled and Expired:
status | additionalStatus | Meaning |
|---|---|---|
Settled | None | Exact amount received |
Settled | Overpaid | Customer paid more than the invoice amount |
Settled | PaidAfterExpiration | Payment received after the invoice expired |
Expired | None | No payment at all |
Expired | Underpaid | Partial 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
}
| Field | What to do with it |
|---|---|
id | Store in your database to correlate with the webhook |
checkoutLink | Redirect the customer here (easiest path) |
lightningInvoice | Render as QR if building a custom UI |
onchainAddress | On-chain fallback QR in custom UI |
bip21 | BIP-21 URI combining address + amount — use for a unified QR |
orderId | Your reference — echoed back in the webhook |
createdAt | Unix 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
redirectUrlafter 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.