Skip to main content

Retries and timeouts

A timeout is not a failure. It is the absence of an answer.

When a POST to create a withdrawal times out, LB Pay may have processed it completely, partially, or not at all. Your system cannot tell the difference from the client side — and the two wrong reactions both cost money:

  • Treating it as success → the player never receives funds you marked as sent.
  • Treating it as failure and refunding the wallet → the player keeps the balance and receives the PIX.

The only safe move is to ask.

Decision procedure​

Never return the balance to the player before confirming

A withdrawal stuck in an unknown state must stay debited until a GET or a webhook confirms FAILED. Refunding on a timeout is how operators pay twice.

Query endpoints per operation:

OperationQuery
WithdrawalGET /v1/pix/withdraw/{externalId}
DepositGET /v1/pix/deposit/immediate-charge/{chargeId}
RefundGET /v1/pix/refund/{endToEndId}
Internal transferGET /v1/transfer/{externalId}

Let the response tell you​

Error responses carry a retryable boolean. It is false for every business-rule rejection, because those are deterministic — the same request will be rejected the same way forever.

Branch on that field instead of hardcoding a list of status codes. It is the API stating its own intent, and it stays correct when new error codes appear.

What is safe to retry​

SituationRetry?How
Timeout / connection reset⚠️ Only after a GETSame externalId
503 Service Unavailable⚠️ Only after a GETSame externalId
500 Internal Server Error❌ NoThe transaction failed. Close it as failed — see below
401 Unauthorized✅ Yes, onceRenew the token first
400 Bad Request❌ NoFix the payload — retrying sends the same invalid data
422 Business rule❌ NoDefinitive. See below
404 Not Found❌ NoInvalid PIX key or account. Notify the player

A 500 is an answer — a timeout is not​

The two look similar in a log and mean opposite things.

What you gotWhat it meansWhat to do
500 in the responseThe platform evaluated the request and rejected it. It is a confirmed failure.Close the transaction as failed. Do not retry the same request, do not poll it.
No response — timeout, connection reset, 503The platform may have processed it. The outcome is genuinely unknown.Follow the GET procedure above before deciding anything.
Do not confuse the two

Treating a 500 as unknown leaves a dead transaction polling forever. Treating a timeout as a 500 closes a transaction that may have settled — and that is how a player gets paid twice.

Backoff​

For the retries that are allowed, use exponential backoff with jitter and a hard cap of 2–3 attempts. Fixed-interval retries from a fleet of workers synchronise into a thundering herd precisely when the platform is already degraded.

attempt 1 → wait ~1s  ± jitter
attempt 2 → wait ~4s ± jitter
attempt 3 → wait ~12s ± jitter
→ then stop and alert

Retrying forever is not resilience. After the cap, escalate the operation to a human queue and leave it in a transitional state that your contingency polling job will keep watching.

422 is final — do not retry it​

A 422 means the platform evaluated your request and rejected it on a business rule. The same request will be rejected identically every time.

errorCodeMeaningCorrect action
IGAMING_CPF_MISMATCHThe PIX key belongs to a CPF other than the player'sAsk the player for a key registered to their own CPF
SECURE_LOOP_ACCOUNT_MISMATCHBank details failed Secure Loop verificationAsk the player to confirm the bank details
Automatic retries on 422 trigger compliance flags

Systems that reprocess 422 responses generate support noise and can activate automatic compliance blocks on the account. Treat 422 as a definitive business outcome and surface it to the player.

See Ownership rules for why these rejections exist.