Before you go live
Work through this list before you take a real payment. Every item is about your own integration.
- [ ] You have a live key (
sk_live_) and you have run one small real payment through it, end to end: invoice, payment,invoice.paid, your order credited. A test key cannot create an invoice today, so this is the only full rehearsal there is. - [ ] Your webhook handler is idempotent on
event.id. A retry, a slow response and an operator replay all arrive as the same event id. - [ ] You verify against the RAW request body, and you answer
400on a signature refusal, never5xx. How. - [ ] You credit on
invoice.paid, not oninvoice.payment_detected. A detected payment is not settled and the chain can still take it back. - [ ] You handle
invoice.settled_payment_reorged. The invoice stayspaid; this event is the only thing that tells you the money is gone. Paging a human is a legitimate handler. - [ ] Your
Idempotency-Keys are derived from your own order ids, not generated per call, so a timeout at your process boundary is recoverable. Why. - [ ] You parse token amounts with
BigInt.token_base_units,received_base_units,amount_base_unitsandnetwork_fee.native_base_unitsare decimal strings because they do not fit a JavaScript number. - [ ] You branch on
livemode. Test and live events arrive at the same URL. - [ ] You have handled a failure, not just the happy path. With a live key and small amounts: an invoice you never pay (it becomes
expired), and a payment smaller than the invoice (it becomesunderpaidand stays open). Your code should also acceptinvoice.paid_late, which you can read about in the quickstart.