Skip to content

2.5 Wallet Transfer (Deposit / Withdraw) ​

http
POST /api/v1/user/exchange/wallets/{external_player_id}/deposits
POST /api/v1/user/exchange/wallets/{external_player_id}/withdrawals
  • deposits: wallet deposit
  • withdrawals: wallet withdraw

Request Body (JSON) ​

FieldRequiredTypeDescription
currencyTRUEstringMust match the currency bound to the agent; see Supported Currencies
amountTRUEstringAmount change, represented as a string; per-transaction cap 10,000,000, up to 8 decimal places
ticket_idTRUEstringIdempotency key, a unique string, up to 256 characters; the same ticket_id will not take effect twice
json
{
  "currency": "CNY",
  "amount": "10",
  "ticket_id": "3e2178ba-269c-4649-2fdb-a2099d6479a6"
}

TIP

ticket_id is the idempotency key: when a request is repeated with the same ticket_id, provided the request body (amount, currency) is identical, the system returns the original response from the first successful call (including the balance at that time) and does not post the entry again. If the body differs, 10050 is returned. That balance is a snapshot from the initial processing and does not reflect the current balance; for the latest balance, call the Balance Query API.

A player being in-game does not affect transfer operations; deposits / withdrawals can be initiated normally.

Response data ​

FieldTypeDescription
wallet.currencystringCurrency
wallet.balancestringBalance snapshot after this transaction is processed
created_atstringInitial processing time (RFC 3339, nanosecond precision)
json
{
  "code": 0,
  "message": "success",
  "data": {
    "wallet": {
      "currency": "CNY",
      "balance": "251080.82"
    },
    "created_at": "2026-06-18T05:00:02.962216637Z"
  }
}

Idempotency and Deduplication Rules ​

IMPORTANT

The deduplication key for ticket_id is "player + ticket_id + transaction type" — it includes the transaction type. The same ticket_id therefore takes effect once on a deposit and once on a withdrawal. It is not a globally unique transaction ID; do not reuse it across directions.

Amount and currency are not part of the deduplication key; they are compared field by field against the first record:

ScenarioResult
Same ticket_id, amount and currency identicalReturns the original response of the first successful call; no second posting
Same ticket_id, amount or currency differsReturns 10050; do not retry — use a new ticket_id if the amount must change
Another request with the same ticket_id is still in flightReturns 10040; the entry is never posted twice — resend the exact same request shortly to obtain the first result

TIP

X-Idempotency-Key plays no part in transfer idempotency — the idempotency key for transfers is ticket_id. The same X-Idempotency-Key used on deposits and withdrawals therefore has no cross-effect; on this endpoint it is only a required signing field.

Only the Login API uses that header for idempotency: the same key returns the same token while that token is still valid, so send a new key with every login request.

Transfer-Specific Error Codes ​

codeMeaningHandling
10040Another request with the same ticket_id is currently being processedThe entry is never posted twice. Resend the exact same request shortly to obtain the result of the first call
10050The same ticket_id has already been used, but this call carries a different amount or currencyDo not retry. Use a new ticket_id if the amount must change
20160Player balance is insufficient to complete the withdrawalConfirm the balance before retrying

The message for 10050 names the mismatched field and both values, for example:

ticket_id already used with a different amount (recorded 100, requested 100.5)

Transaction Failures and Refund Handling ​

IMPORTANT

Before issuing a refund or reprocessing, you must first call the Transaction Status Query API to confirm the final status of the original transaction, to avoid duplicate refunds or refunding a transaction that was never actually charged.

On timeout, network error, or an ambiguous response, do not issue a refund directly. The correct procedure:

  1. Call the transaction status query API with the original ticket_id to confirm whether the transaction was successfully posted.
  2. After confirming it was not successful, issue the refund (deposit) with a new ticket_id.
  3. If confirmed successful, no action is needed, or initiate a separate refund flow according to your business requirements.

BFX EXCHANGE · BE THE GAME CHANGER