Invoice lifecycle
Statuses, timers, and what each signal means for fulfillment.
Create an invoice with POST /v1/invoices. The customer pays on hosted checkout (checkoutUrl). Track progress with webhooks (preferred) or status polling.
Happy path
CREATED → CONFIRMING → PAID → SETTLED- You create the invoice → customer opens checkout and chooses network/token
- Payment detected →
CONFIRMING/invoice.payment_detected - Payment confirmed within the checkout window →
PAID/invoice.paid(fulfill here) - Settlement finishes →
SETTLED/invoice.settled(accounting)
Statuses
| Status | Meaning |
|---|---|
CREATED | Waiting for payment |
CONFIRMING | Payment seen; waiting for confirmation |
PAID | Paid on time — safe to fulfill |
UNDERPAID | Partial payment; top-up window open |
EXPIRED_UNDERPAID | Top-up window ended still short |
LATE_PAID | Paid after checkout expired — funds accepted, not standard fulfillment |
OVERPAID | Amount above required — contact support if needed |
SETTLED | Settlement complete — accounting confirmation |
EXPIRED | No payment before checkout expired |
Timers
| Timer | Duration | Starts |
|---|---|---|
| Checkout window | 1 hour | Invoice creation |
| Underpaid top-up | 30 minutes | First partial payment |
Payment that confirms after the 1h window becomes LATE_PAID, not PAID.
What to fulfill on
| Signal | Fulfill goods? |
|---|---|
invoice.paid / PAID | Yes |
invoice.late_paid / LATE_PAID | No (unless you explicitly choose to) |
invoice.settled / SETTLED | Accounting only |
invoice.underpaid | Wait for top-up |
invoice.expired / invoice.expired_underpaid | Close the order |
Polling (optional)
Prefer webhooks. If you must poll:
curl http://api.localhost:4000/v1/invoices/<id>/status \
-H "Authorization: Bearer test_..."Returns status, amount, amountReceived, and expiresAt.
Full detail: Get invoice.
Amounts and checkout
- Amounts are decimal strings in major units (up to 6 decimal places).
"10.50"= 10.50 USDC/USDT. - Customers choose network/token at checkout unless you lock them with
networkIdand/ortokenon create. - Prefer sending customers to
checkoutUrl. If you show deposit addresses yourself, show the network name and only the listed tokens for that address.
Important
Do not fulfill on invoice.payment_detected alone. Wait for invoice.paid. If a payment is later invalidated, you receive invoice.payment_invalidated — reconcile carefully.