Skip to main content

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
StatusMeaningWhat to do
pendingWaiting for payment.Show the payment page.
paidThe address holds at least amount. The withdrawal to the merchant is pending.Fulfil the order. The webhook fires on this transition.
completedFunds were swept to the merchant's payout address (withdrawn: true).Nothing; use for accounting.
cancelledDeleted via the API or dashboard.Release the order.
expiredexpiresAt passed without a full payment.Release the order or create a new invoice.

Expiry​

Every invoice gets a deadline, returned as expiresAt (Unix ms):

  1. duration (seconds from now), if provided;
  2. otherwise expiresAt, if it is in the future;
  3. otherwise 36 hours after creation.

How payments are detected​

  • Pending invoices are checked on-chain automatically within seconds of a payment.
  • GET /integration/invoices/status re-reads the balance on-chain before answering, so it always returns the latest state.
  • An invoice is paid when balanceRaw >= requiredRaw. Partial payments keep it pending, and the current balance is visible in balance / 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​

FieldDescription
amountRequested amount in human units, as a string ("12.5").
requiredRawamount in the token's smallest unit (wei for native tokens).
balanceRawCurrent balance of the payment address, smallest unit.
balanceSame balance in human units (number).
usdPrice / usdValueToken price and value in USD when a price is available.
lastCheckedAtLast 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 returns 400 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.