Invoice Lifecycle
An invoice asks for a fixed amount of one token on one chain, paid to its own
paymentAddress.
Statuses
balance ≥ amount withdrawal confirmed
pending ─────────────────────► paid ─────────────────────────► completed
│
├── DELETE /integration/invoices ──► cancelled
└── expiresAt passed, not paid ────► expired
| Status | Meaning | What to do |
|---|---|---|
pending | Waiting for payment. | Show the payment page. |
paid | The address holds at least amount. The withdrawal to the merchant is pending. | Fulfil the order. The webhook fires on this transition. |
completed | Funds were swept to the merchant's payout address (withdrawn: true). | Nothing; use for accounting. |
cancelled | Deleted via the API or dashboard. | Release the order. |
expired | expiresAt passed without a full payment. | Release the order or create a new invoice. |
Expiry
Every invoice gets a deadline, returned as expiresAt (Unix ms):
duration(seconds from now), if provided;- otherwise
expiresAt, if it is in the future; - otherwise 36 hours after creation.
How payments are detected
- Pending invoices are checked on-chain automatically within seconds of a payment.
GET /integration/invoices/statusre-reads the balance on-chain before answering, so it always returns the latest state.- An invoice is
paidwhenbalanceRaw >= requiredRaw. Partial payments keep itpending, and the current balance is visible inbalance/balanceRaw.
:::note Late payments
Expired invoices are no longer checked automatically. If a payer sends funds
after the deadline, call GET /integration/invoices/status: it detects the
payment, moves the invoice to paid and fires the webhook.
:::
Withdrawal
Paid invoices are withdrawn to the merchant's payout address automatically.
Once the withdrawal transaction is confirmed, the invoice becomes completed.
You can also trigger a withdrawal yourself and track withdrawal transactions with the Withdrawals API.
If you enabled owner-only withdrawals,
SodaPop does not withdraw your invoices. When your own contract sweeps a paid
invoice, the next status check sees the balance drop and marks the invoice
completed with withdrawn: true.
Cancelling an invoice that is already paid does not move or refund any funds.
Amounts and fields
| Field | Description |
|---|---|
amount | Requested amount in human units, as a string ("12.5"). |
requiredRaw | amount in the token's smallest unit (wei for native tokens). |
balanceRaw | Current balance of the payment address, smallest unit. |
balance | Same balance in human units (number). |
usdPrice / usdValue | Token price and value in USD when a price is available. |
lastCheckedAt | Last on-chain balance check (Unix ms). |
Use strings or BigInt for raw amounts. They can exceed the safe integer range
of JavaScript numbers.
Identifiers
invoiceId— your reference, unique per owner. Omit it to get the next number in the owner's sequence. Reusing one returns400 Invoice with invoiceId "…" already exists for this owner.paymentAddress— the address the payer sends funds to. Status and delete calls are keyed by it, so store it with your order.id— SodaPop's identifier of the invoice. You do not need it for API calls.