Wallet (transfer)
Transfer wallet: deposit, withdraw, look up a transfer and read the balance. Transfers are idempotent on txnId.
Guide: read the integration guide for this area
TIP
Examples are signed with the example key and timestamp from "Authentication & signing", so you can re-check them in the Signature debugger.
Deposit (transfer in)
POST /api/tenant/v1/wallet/deposit
Moves money into the player's game wallet. Single-step and idempotent: resending the same txnId never credits twice; it returns the original result (the same balance) with duplicate: true. The same txnId with a different amount or direction, or one used for another player within the last two months, returns TXN_CONFLICT.
- If the player does not exist it is created with the request's
currency. currencymust equal the player's currency, otherwiseCURRENCY_MISMATCH.balanceis the balance right after this transfer.- A transfer that returned success can always be looked up:
GET /wallet/transfer?txnId=…&username=…. - After a timeout or a 5xx, resend with the same
txnIdand the same content, or look it up withGET /wallet/transferfirst. Never switch to a newtxnId.
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
username | string | yes | Player username, 1–32 characters (letters, digits and _ . @ -). Case-insensitive (Alice and alice are the same player).Format: ^[A-Za-z0-9_.@-]{1,32}$ |
txnId | string | yes | Your transfer ID, 1–64 characters (letters, digits and _ . : -), used as the idempotency key. Keep it unique across your whole tenant (never reuse it for another player).Format: ^[A-Za-z0-9_.:-]{1,64}$ |
amount | string | yes | An amount greater than 0 as a decimal string with at most 4 decimals, for example "1000" or "99.5". Send a string, not a floating-point number.Format: ^\d{1,15}(\.\d{1,4})?$ |
currency | string | yes | Must equal the player's currency. Format: ^[A-Za-z]{3,5}$ |
Example request
POST /api/tenant/v1/wallet/deposit HTTP/1.1
Host: elite.ewin888.com
X-Api-Key: ek_s_1a_XXXXXXXXXXXXXXXX
X-Timestamp: 1790218800
X-Nonce: exc3b9fb78a452ce2fc90cff
X-Signature: a43ebc031d05839610a3d5e52eb10ffa82fd8c83f87e8476d57c3cde3b80917a
Content-Type: application/json
{"username":"alice","txnId":"dep-20260924-000123","amount":"1000","currency":"TWD"}Response data
| Field | Type | Description |
|---|---|---|
txnId | string | The txnId from the request. |
status | string | Always done (single step; there is no pending state). |
balance | string | Balance right after this transfer; a resent txnId returns the original value.Format: ^-?\d{1,15}(\.\d{1,4})?$ |
duplicate | boolean | true means this txnId had already been processed: the balance was not changed again and this is the original result. |
Example response
First time
{
"ok": true,
"data": {
"txnId": "dep-20260924-000123",
"status": "done",
"balance": "2500.5",
"duplicate": false
}
}Same txnId resent (the original result)
{
"ok": true,
"data": {
"txnId": "dep-20260924-000123",
"status": "done",
"balance": "2500.5",
"duplicate": true
}
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
INVALID_PARAMETER | 400 | A required field is missing, or a field has the wrong format or value; message names the field. |
INVALID_AMOUNT | 400 | The amount is not a positive decimal string with at most 4 decimals. |
INVALID_USERNAME | 400 | The username breaks the rules (1–32 characters of letters, digits and _ . @ -), or username is missing from a query. |
INVALID_CURRENCY | 400 | The currency code given for a new player is invalid (3–5 letters required). |
CURRENCY_NOT_ENABLED | 400 | The currency given for a new player is not enabled for the operator (Console → Bet limits → Currencies). Existing players are not affected. |
CURRENCY_MISMATCH | 400 | The transfer currency differs from the player's currency, which is fixed when the player is created. |
PLAYER_LIMIT | 403 | The plan's player limit is reached (50 by default on the free demo plan, 500 in the sandbox). |
TXN_CONFLICT | 409 | This txnId was already used for a transfer with a different amount or direction, or for another player within the last two months. |
Every endpoint can also return the common errors (UNAUTHORIZED, IP_NOT_ALLOWED, TENANT_SUSPENDED, RATE_LIMITED, INTERNAL_ERROR…).
Withdraw (transfer out)
POST /api/tenant/v1/wallet/withdraw
Moves money out of the player's game wallet. Same idempotency rules as deposit: resending the same txnId returns the original result.
- Only the available balance can be withdrawn: stakes are deducted when bets are placed, so unsettled bets can never be withdrawn. Otherwise
INSUFFICIENT_BALANCE. - The player must exist (
PLAYER_NOT_FOUND).
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
username | string | yes | Player username, 1–32 characters (letters, digits and _ . @ -). Case-insensitive (Alice and alice are the same player).Format: ^[A-Za-z0-9_.@-]{1,32}$ |
txnId | string | yes | Your transfer ID, 1–64 characters (letters, digits and _ . : -), used as the idempotency key. Keep it unique across your whole tenant (never reuse it for another player).Format: ^[A-Za-z0-9_.:-]{1,64}$ |
amount | string | yes | An amount greater than 0 as a decimal string with at most 4 decimals, for example "1000" or "99.5". Send a string, not a floating-point number.Format: ^\d{1,15}(\.\d{1,4})?$ |
currency | string | yes | Must equal the player's currency. Format: ^[A-Za-z]{3,5}$ |
Example request
POST /api/tenant/v1/wallet/withdraw HTTP/1.1
Host: elite.ewin888.com
X-Api-Key: ek_s_1a_XXXXXXXXXXXXXXXX
X-Timestamp: 1790218800
X-Nonce: exc26f22db83dc51cea1eb7f
X-Signature: 3cdc9cb2100e63618316b3d333d880daab0adae2e861f2a40e1ff8ab4fd971a7
Content-Type: application/json
{"username":"alice","txnId":"wd-20260924-000077","amount":"500.25","currency":"TWD"}Response data
| Field | Type | Description |
|---|---|---|
txnId | string | The txnId from the request. |
status | string | Always done (single step; there is no pending state). |
balance | string | Balance right after this transfer; a resent txnId returns the original value.Format: ^-?\d{1,15}(\.\d{1,4})?$ |
duplicate | boolean | true means this txnId had already been processed: the balance was not changed again and this is the original result. |
Example response
{
"ok": true,
"data": {
"txnId": "wd-20260924-000077",
"status": "done",
"balance": "2000.25",
"duplicate": false
}
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
INVALID_PARAMETER | 400 | A required field is missing, or a field has the wrong format or value; message names the field. |
INVALID_AMOUNT | 400 | The amount is not a positive decimal string with at most 4 decimals. |
INVALID_USERNAME | 400 | The username breaks the rules (1–32 characters of letters, digits and _ . @ -), or username is missing from a query. |
CURRENCY_MISMATCH | 400 | The transfer currency differs from the player's currency, which is fixed when the player is created. |
PLAYER_NOT_FOUND | 404 | No player with this username. |
TXN_CONFLICT | 409 | This txnId was already used for a transfer with a different amount or direction, or for another player within the last two months. |
INSUFFICIENT_BALANCE | 409 | The withdrawal is larger than the available balance (stakes of unsettled bets cannot be withdrawn). |
Every endpoint can also return the common errors (UNAUTHORIZED, IP_NOT_ALLOWED, TENANT_SUSPENDED, RATE_LIMITED, INTERNAL_ERROR…).
Look up a transfer
GET /api/tenant/v1/wallet/transfer
Looks up a transfer by txnId. Use it after a deposit or withdrawal timed out, to find out whether it was processed.
- Pass
usernameas well: then any transfer that succeeded is always found (even while the tenant ledger copy is still on its way). - The tenant ledger search covers the current month and the previous 3 months (UTC months).
TXN_NOT_FOUNDmeans the transfer was not executed (or is still being processed): resend it with the sametxnIdand the same content until you get a definite success or 4xx answer. Never switch to a newtxnId.dir: adjustmeans the ID belongs to a manual adjustment made in the Console.
Parameter
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
txnId | query | string | yes | The txnId used for the transfer.Format: ^[A-Za-z0-9_.:-]{1,64}$ |
username | query | string | no | The player of the transfer (recommended). When the tenant ledger has no record, the player's own wallet record is used. Format: ^[A-Za-z0-9_.@-]{1,32}$ |
Example request
GET /api/tenant/v1/wallet/transfer?txnId=dep-20260924-000123&username=alice HTTP/1.1
Host: elite.ewin888.com
X-Api-Key: ek_s_1a_XXXXXXXXXXXXXXXX
X-Timestamp: 1790218800
X-Nonce: ex6926b9a725a67c6cc02f60
X-Signature: 93a44cb15149333af7e00fc57274af52ba62f79f102be9a9269edc1eaede7a67Response data
| Field | Type | Description |
|---|---|---|
txnId | string | Transfer ID. |
username | string | Username. |
dir | string | in deposit, out withdrawal, adjust manual adjustment made in the Console.Values: in, out, adjust |
amount | string | Amount (positive). Format: ^-?\d{1,15}(\.\d{1,4})?$ |
status | string | Always done. |
balance | string | null | Balance right after this transfer. |
at | string (date-time) | UTC time, ISO-8601 with milliseconds. |
Example response
{
"ok": true,
"data": {
"txnId": "dep-20260924-000123",
"username": "alice",
"dir": "in",
"amount": "1000",
"status": "done",
"balance": "2500.5",
"at": "2026-09-24T03:00:01.250Z"
}
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
INVALID_PARAMETER | 400 | A required field is missing, or a field has the wrong format or value; message names the field. |
TXN_NOT_FOUND | 404 | No transfer with this txnId was found. With username in the query this means the transfer was not executed (or is still being processed); without it only the tenant ledger (current and previous 3 months) is searched. |
Every endpoint can also return the common errors (UNAUTHORIZED, IP_NOT_ALLOWED, TENANT_SUSPENDED, RATE_LIMITED, INTERNAL_ERROR…).
Get a balance
GET /api/tenant/v1/wallet/balance
The player's current available balance (stakes of unsettled bets already deducted).
Parameter
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
username | query | string | yes | Player username. Format: ^[A-Za-z0-9_.@-]{1,32}$ |
Example request
GET /api/tenant/v1/wallet/balance?username=alice HTTP/1.1
Host: elite.ewin888.com
X-Api-Key: ek_s_1a_XXXXXXXXXXXXXXXX
X-Timestamp: 1790218800
X-Nonce: ex176285a304e084623ee6cf
X-Signature: d80f06a9225952f186571488addf4319ae8f87645fb80486d46cf5eac36db51fResponse data
| Field | Type | Description |
|---|---|---|
balance | string | A player amount as a decimal string with at most 4 decimals. Responses drop trailing zeros (for example "100", "0.95", "1000.5").Format: ^-?\d{1,15}(\.\d{1,4})?$ |
currency | string | Currency. |
Example response
{
"ok": true,
"data": {
"balance": "2500.5",
"currency": "TWD"
}
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
INVALID_USERNAME | 400 | The username breaks the rules (1–32 characters of letters, digits and _ . @ -), or username is missing from a query. |
PLAYER_NOT_FOUND | 404 | No player with this username. |
Every endpoint can also return the common errors (UNAUTHORIZED, IP_NOT_ALLOWED, TENANT_SUSPENDED, RATE_LIMITED, INTERNAL_ERROR…).