Troubleshooting
This page covers the integration failures verified against the sandbox during fullstack sprint 2026 testing. Each section follows the same shape: symptom (what you see), cause (why), fix (what to change). Codes referenced here are documented in the API error reference; release-level changes that affect this page are linked back to the changelog.
Quick lookup
| Symptom | Section |
|---|---|
"Hash is not valid" on every request | Hash signature failures |
error_code: 100000 and error_code: 101000 both appearing for not-found cases | Not-found errors: 100000 vs 101000 |
HTTP 404 with "Route or parameters is not supported" on S2S CARD | S2S CARD invalid action names |
CANCEL_SCHEDULE returns 404 | Schedule lifecycle uses DELETE_SCHEDULE |
"Card token is invalid or not found." (205005) on a CREDIT call | CREDIT field shape |
order_id: Duplicate payment. (100000) | Order ID reuse and idempotency |
Use merchant test key. (220002) | Sandbox vs production |
| 3DS challenge never returns | 3DS doesn't redirect back |
| Webhook never fires, or fires but signature check fails | Webhook delivery and signature verification |
"Refund is not allowed" on a payment that should be refundable | Refund not allowed |
| Connection / TLS failure from your server | TLS and IP allowlist |
Authentication and signatures
Hash signature failures
Symptom. Every request returns HTTP 400 with:
{ "result": "ERROR", "error_code": 100000, "error_message": "Hash is not valid" }
You triple-checked the API key and it's correct, so it has to be the signature.
Causes (in order of frequency).
- The concatenation is not uppercased. Checkout uses
SHA1(MD5(uppercase(concat))), and the S2S CARD and S2S APM formulas uppercase the concatenation as well. If you skip the uppercase step the hash will look superficially correct but never verify. - Fields concatenated in the wrong order. Each operation has a fixed input order (for example, Checkout purchase is
order.number + order.amount + order.currency + order.description + password). Puttingpasswordfirst, or omittingorder.description, gives a wrong hash. - You concatenated formatted values, not raw values. Send
order.amountas the same string in both the request and the hash input."10.00"in the body and10in the hash will never match. - The merchant key mixed up with
password. They are different secrets. The key identifies you and goes in the request body - it ismerchant_keyon Checkout and Hosted Payment Fields, andclient_keyon S2S CARD and S2S APM. Thepasswordnever goes in the body: it goes only into the hash input. - Test vs production password mismatch. Sandbox and production each have their own
password. If you copied the wrong one you'll get this error 100% of the time. - You signed with the card fragment on a transaction that has no card data on file. On S2S CARD,
CAPTURE,VOID,RETRY,GET_TRANS_STATUS,GET_TRANS_DETAILSandGET_TRANS_STATUS_BY_ORDERare signed with the card fragment Payment Platform stored for that transaction. A digital wallet payment whose token was never decrypted into card data has no fragment, and a different, shorter input applies: see transactions with no card data on file.
Fix.
Generate the hash with a known-good helper and compare byte-for-byte. The shell equivalent of a Checkout authentication signature (no dependencies) is:
CONCAT="${ORDER_NUMBER}${ORDER_AMOUNT}${ORDER_CURRENCY}${ORDER_DESCRIPTION}${PASSWORD}"
CONCAT_UPPER=$(printf "%s" "$CONCAT" | tr '[:lower:]' '[:upper:]')
MD5_HEX=$(printf "%s" "$CONCAT_UPPER" | md5) # or: | md5sum | awk '{print $1}'
HASH=$(printf "%s" "$MD5_HEX" | shasum -a 1 | awk '{print $1}')
echo "$HASH"
If your library output equals this output for the same inputs, the issue is in your inputs, not your hash function.
The inputs are documented per protocol on Hash signature, which maps every action and callback to its formula. The literal formulas live in S2S CARD Appendix A and S2S APM Appendix A.
S2S CARD does not use the Checkout formula. Its hashes are MD5 based, or SHA256 when the Use SHA256 encryption algorithm for hash option is enabled for your protocol mapping, and the inputs change per action. Appendix A lists them as Formula 1 to Formula 8, for example:
| Action | Formula |
|---|---|
SALE, DEBIT, RECURRING_SALE, RECURRING_DEBIT, CARD2CARD | Formula 1 |
SALE or DEBIT sent with payment_token (digital wallet) | Formula 8 |
CAPTURE, VOID, CREDITVOID, RETRY, GET_TRANS_STATUS, GET_TRANS_DETAILS | Formula 2 |
the same actions on a transaction with no payer email, for example the status of a CREDIT2CARD payout | Formula 6 |
GET_TRANS_STATUS_BY_ORDER | Formula 7 |
CREDIT2CARD | Formula 5 |
| Create a schedule | Formula 3 |
| Other schedule actions | Formula 4 |
S2S APM has its own set in Appendix A.
If you use a single helper across all calls without following the per-action formula, half of them will fail signature verification with the same "Hash is not valid" message and you will think the helper is broken when it is not.