When orders expire and what happens if a payment never arrives
How order expiration works, when payment.expired fires, and what happens to a transfer that arrives too late.
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:
- moves the order from
createdtoexpired, - releases the addresses that were allocated to it back to the pool, and
- enqueues a
payment.expiredwebhook.
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 increatedcan be canceled.
expired vs canceled
| State | Trigger | Emits |
|---|---|---|
expired | expiresAt passed with no matching transfer | payment.expired |
canceled | You called the cancel endpoint while still created | payment_order.canceled |
Both release any addresses still held by the order.
Related
How is this guide?
Last updated
A customer underpaid, overpaid, or sent on the wrong chain
What happens when a transfer doesn't match the order amount, asset, or chain — and how to recover the funds.
A payment was confirmed but then reverted
Why a detected or confirmed order can roll back to reverted, and why you should fulfill on payment.finalized.