StableOps
FAQ

When orders expire and what happens if a payment never arrives

Learn when StableOps orders expire, how late transfers are handled, how to choose payment windows, and why expired and canceled orders need reconciliation.

Every payment order carries an expiresAt timestamp. If no matching transfer arrives before then, the order is moved to expired and a payment.expired webhook is sent.

How expiration is processed

A background worker scans for expired orders on a short repeating interval (roughly once a minute), so an order flips to expired shortly after expiresAt passes, not at the exact second. Each expiration runs in a transaction that:

  1. moves the order from created to expired,
  2. releases the addresses that were allocated to it back to the pool, and
  3. enqueues a payment.expired webhook.

Only orders still in created can expire. Once an order reaches detected, confirmed, or finalized, the deadline no longer applies. A payment already in flight is never dropped just because the clock ran out.

A payment that arrives after expiry

If a customer pays after the order has expired, the transfer will not revive the order:

  • The order is no longer in created, so the exact-match rule can't promote it.
  • The address may already have been released and reused by another order.

Handle this the same way as any other misdirected transfer: reconcile or refund manually against the address the funds landed on. With BYO addresses those funds are in an address you control.

Choosing an expiration window

  • Pick a window long enough for a real human to open a wallet, copy the amount, and have the transfer confirm. A few minutes is usually too tight; 15–60 minutes is a common range.
  • Don't set it so long that abandoned orders hold addresses (in single-address mode) far longer than needed.
  • If you don't need an order anymore before anyone has paid, cancel it instead of waiting for expiry. Cancellation also releases the addresses and emits payment_order.canceled. Only orders still in created can be canceled.

expired vs canceled

StateTriggerEmits
expiredexpiresAt passed with no matching transferpayment.expired
canceledYou called the cancel endpoint while still createdpayment_order.canceled

Both release any addresses still held by the order.

How is this guide?

Last updated

On this page