Payment API timeout? Retry skin checkout without creating duplicates
Handle lost checkout responses with persisted idempotency keys, bounded retries, Retry-After and status reconciliation instead of duplicate attempts.
A timeout does not prove checkout creation failed
Your server sends a checkout-create request, then loses the response. The request might have failed before reaching the API—or the API might have created the checkout before the connection dropped. A timeout alone cannot distinguish those outcomes. Treat it as an unknown result, not automatic permission to create another payment attempt.
Skinloop’s retry documentation says to resend the same logical create request with the same persisted Idempotency-Key and effective body when a response is lost. The key connects the retry to the original operation. Generating a new key for every network error defeats that protection.
Persist the attempt before sending the first request
- Attach one logical payment attempt to the stored merchant order.
- Save its idempotency key and effective request inputs before making the network call.
- Send checkout creation from the server, not a browser holding a merchant secret.
- Persist the returned checkout identity and hosted URL as soon as they are available.
- Reuse that attempt’s stored key and inputs if the response was lost.
A customer refreshing a page should load the existing attempt, not create a new logical operation by default. Likewise, an application restart should not discard the only copy of the key. Durable storage makes recovery possible across processes and deployments.
Keep the same key bound to the same request
Idempotency is not a way to edit a checkout by retrying it. Keep the order reference, amount, game choices and other effective inputs consistent with the original operation. Skinloop documents a 409 conflict when a key is reused with changed effective request content.
If you need to change the order, first establish the original attempt’s outcome. Do not respond to a conflict by blindly minting another key. A payment already in flight can still complete for the original order. Whitespace or JSON property ordering alone is different from changing the business meaning of a request.
Retry temporary failures, not authorization or validation errors
Skinloop distinguishes temporary failures from definite rejections. A 429 requires attention to Retry-After; a 503 calls for backoff. Missing credentials, missing permission, invalid input and idempotency conflicts need correction or investigation, not an unchanged request loop. Read the error body without logging secrets.
The documented ordinary-request policy uses bounded attempts and a time budget, with exponential backoff and jitter. Its published baseline is at most five attempts within a 30-second retry budget. Follow the current retry guide rather than repeatedly hitting the API until a request happens to work.
Honor a valid Retry-After and do not retry earlier than it allows. If that wait exceeds your application’s remaining budget, stop the automated loop and preserve the unresolved operation for recovery. Exhausting a client retry budget does not turn an uncertain payment into a failed one.
Once an attempt is identified, reconcile it
When you have the checkout or deposit identity, use the appropriate documented status endpoint and authorization for that object. Follow any returned polling interval. A temporary status-fetch failure is a reason to retry the read safely, not to create a replacement payment.
Do not replace an attempt while it is pending, active, protected, completed or awaiting reconciliation. An accepted or ambiguous create response is not evidence that a trade failed. If identity, amount or status evidence conflicts, stop automatic replacement and investigate the original operation.
A genuinely new customer attempt after a documented safe terminal outcome can use a new key. That decision belongs to the order lifecycle, not an HTTP timeout handler. The customer-flow documentation describes when a new attempt is appropriate.
Checkout retries and webhook retries solve different problems
A checkout idempotency key prevents repeat create requests from becoming different logical operations. A stable webhook event ID lets your receiver deduplicate notifications. A unique fulfillment job prevents repeated product delivery. None of these controls replaces the others.
Do not create a new checkout because a webhook was delayed, or treat a delivered notification as proof that an earlier create attempt is safe to repeat under a new key. Save the original attempt, reconcile its state and process verified completion independently.
A useful recovery record contains the merchant and order reference, attempt key identifier, known checkout identity, last safe status and the next permitted action. Keep secrets out of that record’s logs. This helps support resolve uncertainty without charging through another trade attempt.