v1.0

Troubleshooting#

Symptoms you will actually hit, and what causes them.

Availability. CentaPay is pre-launch. Production is expected in Q4 2026, with sandbox access ahead of it. Coverage differs by market, and the payment methods available differ by market too. The coverage table on our main site is the single source for what is live where, and for current dates. Nothing in this documentation should be read as a service available today.

Every entry here is a failure mode documented in the reference. Nothing on this page is speculative: if a cause is not established, the symptom says so rather than offering a guess.

Requests get no response at all#

Not an error, not a timeout you can distinguish from a network fault. Nothing.

Requests from un-whitelisted IP addresses are rejected silently. That is the documented behaviour, and it is indistinguishable from your own connectivity failing.

Before assuming a network problem, confirm every address your server can send from is on the whitelist, including the ones you forgot: a second data centre, a NAT gateway, a scheduled job running somewhere else.

Separately, you cannot process payments at all until the S2S CARD protocol has been mapped to your account during onboarding. Both are configuration held by CentaPay, not something you can change from your side.

Every request fails authentication#

Almost always the wrong formula for the action, not a wrong password.

The formulas are not interchangeable, and picking the wrong one produces an authentication failure that says nothing about which part was wrong.

SendingSigns with
SALE with card dataFormula 1
SALE with card_tokenFormula 1 variant, token replaces the card fragment
SALE with a walletFormula 8, email and password only
CAPTURE, CREDITVOID, VOIDFormula 2
RECURRING_SALE, RETRYFormula 1
CREDIT2CARDFormula 5
CREATE_SCHEDULEFormula 3
Other schedule operationsFormula 4

Three specific traps inside that table.

A wallet sale signed with Formula 1 fails, because Formula 8 has no card term and a wallet sends no card fields.

RECURRING_SALE signs with Formula 1, which needs the card's first six and last four digits, but the request itself sends no card fields. Those digits must come from the mask you stored at the initial sale.

CREDIT2CARD signs with Formula 5, which has no email term at all.

Callback verification fails but requests work#

Three separate causes, all common.

The formula differs between request and callback. This is the norm, not the exception. A wallet sale signs Formula 8 and verifies Formula 2. A VOID signs Formula 2 and verifies with the Void signature. A CREDIT2CARD signs Formula 5 and verifies Formula 6. One shared verification routine will pass on most callbacks and fail on those.

trans_id is not uppercased. Every formula uppercases the whole concatenation. A lowercase UUID passed through unchanged produces a silent mismatch.

The callback has no card field. Declined callbacks, 3DS and redirect callbacks, and undefined callbacks all omit card and card_expiration_date. Formula 2 needs a card fragment, so verification has to fall back to the mask you stored when you created the payment. If you did not store it, you cannot verify those callbacks at all.

The masked PAN behaves exactly like a full one. First six characters joined to the last four, and the asterisks in the middle are never used.

Callbacks stop arriving#

Five consecutive timeouts within five minutes blocks your callback URL for fifteen minutes. Any successful response resets the counter. Unblocking early is done through the admin panel, under Configuration, Merchants, Edit Merchant.

Two consequences worth designing around.

Your endpoint must return the plain string OK. Any other content counts as a failure, and so does a timeout. Acknowledge first and process afterwards, so slow downstream work cannot trip the counter.

All merchants sharing that URL are affected. One slow consumer takes the others down with it, which is the argument against a single shared callback endpoint across environments or entities.

A payment succeeded but the customer was not charged, or vice versa#

You are reading the synchronous response as the outcome. It is not.

The synchronous response tells you the request was accepted and what happened at that instant. result can be UNDEFINED, which is not an error and frequently settles. It can be REDIRECT, which means authentication is still ahead. The callback is authoritative in every case.

Duplicate orders after a timeout#

order_id must be unique per payment. Submitting one already used returns error code 400.

If a request times out or the connection drops, do not resend it. Call GET_TRANS_STATUS_BY_ORDER with your order_id and read the actual state.

Blind resubmission creates duplicates, and where cascading is enabled a single payment request can already have generated several underlying transactions, so a retry can multiply rather than repeat.

A capture or refund is rejected on amount#

Both are arithmetic, and both are terminal for the request as sent.

Capture amount exceeding the authorised amount returns 208004. Refund amount exceeding the payment returns 208006, and reversal amount exceeding it returns 208008.

Note the asymmetry that catches people: one partial capture is allowed, and the remainder of the authorisation is then gone. Multiple partial refunds are allowed. Code written for one does not transfer to the other.

A partial refund callback says SETTLED#

That is correct and is not a failure.

A partial refund reports status: SETTLED because the original transaction keeps its settled status. A full refund reports REFUND or REVERSAL.

A VOID was declined#

A declined VOID returns result: DECLINED with status: SETTLED, leaving the original transaction settled and a customer expecting their money back.

VOID only applies to transactions in SETTLED status from SALE, CAPTURE or RECURRING_SALE, and only on the same financial day. Outside that window the operation is CREDITVOID.

A payout response is missing fields#

CREDIT2CARD success responses do not include amount or currency, unlike a SALE. A handler that reads them unconditionally breaks on the success path.

A wallet payment declines after the customer has paid#

allowedCardNetworks populates the Google Pay payment sheet. Any network listed is offered to the cardholder. If they pick one your account cannot acquire, Google returns a valid token, the sale declines, and the customer has already been told they paid.

List only the networks enabled on your account, confirmed at onboarding.

Also check that the Environment setting matches, TEST or PRODUCTION, between your Google Pay configuration and your CentaPay account.

Recurring will not start in sandbox#

Only the test card with expiry 01/2038 returns a recurring_token. The other expiries will not produce one.

If a recurring charge then fails, note that RETRY applies to soft declines only. Hard declines such as a stolen card or fraud will not succeed on retry.

The 3DS redirect does nothing#

redirect_params varies by acquirer. It may contain PaReq, TermUrl or other values, it may be empty, and it may be absent altogether, most commonly when redirect_method is GET.

Code that assumes an array here fails on the acquirer that sends nothing. Check for presence before iterating.

What next#

Each guide documents the failure modes specific to its operation.

Technical questions go to [email protected].