Common integration mistakes
The symptoms that most often reach support, and what causes them.
The mock answered 200 but the response fields are empty
Almost always a field in the wrong place. The sandbox does not validate the request body: unknown keys are silently ignored, and required ones it could not find are filled in as empty. The request looks successful, but the data is lost.
| Field | Where it goes |
|---|---|
merchant_order_id | inside order in POST /invoices |
merchant_contract_id | at the top level in POST /contracts, but inside contract in POST /invoices |
InvoiceID (XML) | inside <InvoiceInfo>, not directly under the operation tag |
A simple check: compare the echoed fields of the response with what you sent. If merchant_order_id came back empty, the field did not arrive and nothing will be found by it later.
getInvoice never changes status
This is the previous mistake showing up in the XML flow. The billing-delay simulation looks for InvoiceID inside <InvoiceInfo>; put it directly under <GetInvoiceRequest> and the response keeps coming from the prepared template, so the status never changes. The correct shape is in “Invoice status”.
The payment was created but the money “did not arrive”
The createInvoice response acknowledges receipt, it is not the billing result. The outcome comes later: in the sandbox after test_info. (10 seconds by default), and in the XML flow getInvoice switches to Processed / PAID six seconds after the first status request. Go by status and payment_status, not by the fact that creation succeeded.
Signature errors
| Cause | How to check |
|---|---|
| Local time instead of UTC | The most common one. The timestamp is always UTC, even if the server lives in a different zone |
| Timestamp format mixed up between protocols | XML uses yyyyMMddHHmmss, JSON uses ISO-8601. The signature is computed over the exact string you actually send |
| One timestamp signed, another sent | Do not call “get current time” twice: compute it once and use it both in the signature and in the request |
| base64 instead of hex | Both HMAC passes produce lowercase hex |
| Concatenation order swapped | login + inner, not the other way round. Check against the step-by-step example in “Request signing” |
| The server clock has drifted | The tolerance is ±20 minutes; beyond that you get AUTH_INVALID_TIMESTAMP |
The callback does not arrive
Check in order: is a callback URL configured for the project (in the sandbox the administrators set it); has the first-send delay passed; does your handler answer 2xx — everything else counts as failure, including a redirect, which the sandbox does not follow; is your address reachable from the sandbox rather than blocked by a firewall. Remember that the XML flow only delivers the payment notification — there are no refund or contract events there at all.