The API is synchronous: every call holds the connection open and returns its final result inline, in the standard envelope. There is no asynchronous mode and no result to poll. It also has no idempotency mechanism, which changes how you must handle a failed POST /deposit or POST /withdraw — that is the second half of this page, and it is the part worth reading twice.
Every response comes back inline, in the standard envelope, with async always false:
{"response":{"...":"..."},"async":false}
There is no 202 Accepted, no urlResponse, and nothing to poll. If an operation takes too long, the connection times out and you receive 503. On a call that moves money, that timeout tells you nothing about whether the operation was created — check its status before deciding what to do (see Retrying safely).
X-Async was part of an earlier asynchronous model that has been removed. Sending X-Async: true (or X-Async: 1) is now rejected up front, before any work is done, with HTTP 400:
{"response":{"errorMessage":"X-Async: true is no longer supported"},"async":false}
Any other value (false, auto, or omitting the header entirely) is accepted and served synchronously, so the simplest integration just leaves the header off.
Remove X-Async from your requests
If you previously sent X-Async: true to defer work, stop — that request now fails with 400. Drop the header and read the result inline. There is no polling URL to migrate to.
X-Nonce is a tracing header, not an idempotency key#
The API has no idempotency mechanism
X-Nonce is generated by the server, one per request, and returned to you in the response header. A nonce you set on the request is not read and deduplicates nothing. There is no idempotency key, and no other mechanism that makes a repeated POST /deposit or POST /withdraw resolve to the original operation.If you retry a value-moving call, you can execute it twice.
Use the nonce for what it is: a correlation identifier. Log it and quote it in support requests.
Three identifiers show up around a single call, and only one of them names the operation itself:
Identifier
Where it arrives
What it identifies
id
response body, e.g. "id": "019b76daa8007000000000000000000d"
the operation. Pass it to GET /deposit-status?id= or GET /withdraw-status?id= to read the outcome. This is the one to store.
X-Request-ID
response header
one HTTP round trip, for tracing and support. A retry of the same operation gets a new one.
X-Nonce
response header
the same round trip, from the server's own counter. Not an input and not an idempotency key.
Store the id alongside your own reference for the operation. It is the only one of the three that survives a retry, and it is what turns an uncertain outcome into a definitive one.
Because nothing deduplicates for you, the safe pattern is to establish the outcome before resending.
Read-only calls (GET /ping, /deposit-status, /withdraw-status, /deposits, /user-info) are safe to retry freely.
POST /deposit and POST /withdraw are not. After a timeout, a 5xx, or a dropped connection, do not resend blindly. Confirm the outcome first:
1.
Query GET /deposit-status or GET /withdraw-status, or wait for the webhook.
2.
Resend only after confirming the operation was never created.
Definitive refusals are not retryable at all. A 520 (business rejection) and a 422 (compliance block) will return the same answer every time.
Turn off automatic retry on the two write endpoints
Most HTTP libraries retry 5xx by default, and the rejection code 520 sits inside that range — so a business refusal can be retried by your client library without you writing a single line of retry code. On POST /deposit and POST /withdraw, disable automatic retries and handle the outcome explicitly.
Log the X-Nonce and X-Request-ID from every response. When an operation's outcome is unclear and the status endpoints do not settle it, those two values are what support needs to trace the call.
-i prints the response headers, where both identifiers arrive: