TL;DR: Same
order_reference, same amount and currency, within the session TTL returns the same session. A different amount or currency on a still-payable session is rejected with 409, not silently applied. After the session is no longer payable (TTL elapsed, declined, or cancelled), a new session is possible. Always check your own order state before creating one.order_reference is your idempotency key for session creation, and the hosted page itself guards against a shopper submitting payment twice for the same session. But that protection is time-boxed (it lasts only the session’s TTL) and doesn’t compare the request body — so it prevents a duplicate session, not necessarily a duplicate charge for an already-paid order.
When this happens
- Your server retries a create call after a timeout or network error, using the same
order_reference. - Your server retries with the same
order_referencebut a changed field (a different amount, for example). - Your server reuses an
order_referenceafter its original session’s TTL has already elapsed. - Two create calls for the same
order_referencerace each other (rare — only a genuine concurrent race, not a normal sequential retry). - A shopper double-clicks pay, or your page double-submits, on the hosted page itself.
What you see
What to do
1
Reuse order_reference per order attempt, not per HTTP call
Generate one
order_reference per order attempt and reuse it for every retry of that same attempt (API reference). A changed amount or currency on a retry gets rejected with 409 rather than silently applied while the original session is still live — don’t send a different total expecting it to update an in-flight order.2
Check your order isn't already paid before creating a session
The
order_reference guard only lasts the session’s TTL (5–60 minutes) — after that, the same reference happily creates a brand-new session. If your original order already completed (for example, its webhook arrived after your client gave up waiting), a later retry with the same or a fresh order_reference will charge the shopper again. Check your own order state before every create call — see Prevent duplicate payments for the full pattern.3
Handle a 409, either cause
409 session:idempotency_conflict covers two distinct causes with different detail text: a concurrent create for the same reference still in flight (“still being created; retry shortly” — the losing call has no checkout_id to look up, so retry the create after a short delay instead of fetching one), or a changed amount or currency against a still-payable session (“already in use for a different amount or currency” — fix the request or use a new order_reference).4
A new order_reference isn't required after a decline or cancellation, but keeps things clean
Reusing the
order_reference from a failed, cancelled, or expired session now creates a new session automatically — the reference is released as soon as the original stops being payable, so you don’t strictly need a new value. Many merchants still mint a fresh order_reference per attempt for their own tracking. See Handle declined hosted checkout payments.Related
Prevent duplicate payments
The full guide to guarding your own order state.
Redirect integration
Where the create-session retry guidance fits into the full flow.
Session lifecycle
Replay semantics in full, including the session-states diagram.
Handle failures
All ten failure scenarios, symptom → page.