# Apply code Source: https://docs.whitebit.com/api-reference/account-wallet/apply-code openapi/private/main_api_v4.yaml POST /api/v4/main-account/codes/apply The endpoint applies [WhiteBIT code](/glossary#whitebit-codes). Rate limit: 60 requests/1 sec. The API does not cache the response. To avoid leaking whether a code exists, most failure modes — invalid format, expired, non-existent, or wrong passphrase — collapse to one generic rejection on field `code`. Only two cases are distinguishable at the API surface: a code that has already been applied, and a code created by the same account. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. * [WaaS recipes](/guides/waas-recipes) — task-oriented Wallet-as-a-Service recipes — deposits, payouts, and codes. # Close Flex Investment Source: https://docs.whitebit.com/api-reference/account-wallet/close-flex-investment openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/investments/close Completely close investment and withdraw all funds. **Validation Rules:** - plan: required, string, UUID format, must exist - Investment must be ACTIVE Rate limit: 1000 requests/10 sec. The API does not cache the response. # Close investment Source: https://docs.whitebit.com/api-reference/account-wallet/close-investment openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart/investment/close The endpoint closes active investment. Early closure is allowed and carries no penalty — the request either succeeds or returns one of the documented errors. Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. # Create code Source: https://docs.whitebit.com/api-reference/account-wallet/create-code openapi/private/main_api_v4.yaml POST /api/v4/main-account/codes The endpoint creates [WhiteBIT code](/glossary#whitebit-codes). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. * [WaaS recipes](/guides/waas-recipes) — task-oriented Wallet-as-a-Service recipes — deposits, payouts, and codes. # Create express withdraw token Source: https://docs.whitebit.com/api-reference/account-wallet/create-express-withdraw-token openapi/private/main_api_v4.yaml POST /api/v4/main-account/express-withdraw/token The endpoint creates a signed, single-use Express Withdraw payment token that charges a specific amount from a WhiteBIT user's balance to the partner's [Main balance](/glossary#balance-main) in an instant, off-chain, zero-[fee](/glossary#fee) internal transfer. The response returns a URL that embeds the token; the paying user confirms the exact [ticker](/glossary#ticker) and amount on the WhiteBIT-hosted confirmation surface. Token and payment constraints: - Each token is single-use: WhiteBIT marks the token used at confirmation and rejects any replay. - Each token expires 90 seconds after creation; the `expireAt` response field carries the authoritative expiry timestamp. Generate the token as close as possible to the moment of presenting the URL to the user. - The [ticker](/glossary#ticker) must be a withdrawal-enabled cryptocurrency; the endpoint rejects [fiat](/glossary#fiat) tickers. - Each payment is capped at the equivalent of 10,000 USDT; WhiteBIT enforces the cap at token creation and re-enforces the cap at confirmation. - WhiteBIT rejects self-payments: the paying user and the token creator must be different WhiteBIT accounts. - The endpoint is idempotent per `externalId`: re-submitting the same `externalId` with an identical `ticker` and `amount` while the token is still valid returns the same token instead of creating a duplicate charge. After the token expires, the same `externalId` receives a fresh token. Standard private-API rate limits apply — see [Rate limits](/api-reference/rate-limits). The endpoint carries no endpoint-specific limit. The endpoint is available only for B2B partner services and requires a separate approval process. Request access at [https://institutional.whitebit.com/](https://institutional.whitebit.com/). ## Payment flow The partner integrates one endpoint; WhiteBIT hosts everything the paying user sees. 1. The partner creates a payment token with the currency, the amount, and a partner-side `externalId`. 2. The partner presents the returned `url` to the user — redirect, deep link, or QR code. 3. The user opens the URL while authenticated on WhiteBIT and confirms the displayed [ticker](/glossary#ticker) and amount on the WhiteBIT-hosted confirmation surface. 4. WhiteBIT debits the user's balance and credits the partner's Main balance in a single internal, off-chain, zero-fee transfer, then marks the token used. Each token expires 90 seconds after creation — `expireAt` in the response carries the authoritative expiry. Create the token as close as possible to the moment of presenting the URL to the user; after expiry, re-create the token with the same `externalId` to receive a fresh one. Each payment is capped at the equivalent of 10,000 USDT, enforced at token creation and re-enforced at confirmation. Requests above the cap return error code `191`. ## Notes * For the full integration walkthrough — token lifecycle, idempotency, and limits — see the [Express Withdraw section of the Payment Integration guide](/guides/payment-integration#express-withdraw-payments). * The endpoint does not support pagination. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Create Flex Investment Source: https://docs.whitebit.com/api-reference/account-wallet/create-flex-investment openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/investments/invest Create new investment in a Flex plan. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Create new address for deposit Source: https://docs.whitebit.com/api-reference/account-wallet/create-new-address-for-deposit openapi/private/main_api_v4.yaml POST /api/v4/main-account/create-new-address The endpoint creates a new address even when the last created address is not used. The endpoint is not available by default, contact support@whitebit.com to get permissions to use the endpoint. For sub-accounts, crypto deposits must also be enabled for the account (disabled by default). To enable them, contact your assigned Account Manager or email institutional@whitebit.com. **Address types:** | Currency | Types | Default | |----------|---------------------|---------| | BTC | p2sh-segwit, bech32 | bech32 | | LTC | p2sh-segwit, bech32 | bech32 | Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Create withdraw request Source: https://docs.whitebit.com/api-reference/account-wallet/create-withdraw-request openapi/private/main_api_v4.yaml POST /api/v4/main-account/withdraw The endpoint creates withdraw for the specified ticker. A withdrawal created with a [sub-account](/glossary#sub-account) API key does not settle immediately. The transaction enters `unconfirmed_by_main_account` status and is held until the main account approves it. List the pending withdrawals with [`POST /api/v4/sub-account/withdraw/unconfirmed-list`](/api-reference/sub-accounts/list-unconfirmed-sub-account-withdrawals) and approve each one by transaction id with [`POST /api/v4/sub-account/withdraw/confirm`](/api-reference/sub-accounts/confirm-sub-account-withdrawal). Rate limit: 1000 requests/10 sec. The API does not cache the response. Also, fiat currencies can't be withdrawn without KYC verification. ## Withdrawal Scenarios Guide The endpoint supports **8 different withdrawal scenarios**. Each scenario requires different fields depending on the currency type, destination, and regulatory requirements. Use the example selector above to switch between scenarios. ### 🔹 Cryptocurrency Withdrawals #### **Scenario 1: Simple Crypto Withdrawal** For standard cryptocurrencies like BTC, ETH, LTC, etc. * **Required fields**: `ticker`, `amount`, `address`, `uniqueId` * **Use when**: Withdrawing to a standard blockchain address #### **Scenario 2: Multi-Network Crypto (USDT, USDC)** For cryptocurrencies existing on multiple blockchains. * **Required fields**: Same as above + `network` * **Networks**: ERC20 (Ethereum), TRC20 (Tron), BEP20 (BSC), OMNI, etc. * **Use when**: Withdrawing tokens existing on multiple chains **Critical**: Ensure the `network` matches the destination address type. Sending ERC20 USDT to a TRC20 address will result in **permanent loss of funds**. Verify the network on [Asset Status endpoint](/api-reference/market-data/asset-status-list). #### **Scenario 3: Travel Rule Compliance (EEA Users)** Required for crypto withdrawals when the account is registered in the [EEA](/glossary#european-economic-area-eea) and the Travel Rule API is enabled. The legacy flat format (`type`, `vasp`, `name`, `address`) is still accepted but will **not pass Travel Rule verification**. Use the new structured format. For detailed requirements, field mapping, and request examples, see [Travel Rule](/concepts/travel-rule#withdrawal-examples). ### 🔹 Fiat Withdrawals (KYC Required) All fiat withdrawals require KYC verification. Ensure the account is verified before attempting fiat withdrawals. #### **Scenario 4: Basic Fiat Withdrawal** Standard fiat withdrawal via VISAMASTER provider. * **Required fields**: `ticker`, `amount`, `provider`, `uniqueId`, plus a `beneficiary` object with `firstName` and `lastName` * **Currencies**: USD, EUR * **Use when**: Standard fiat withdrawal within normal limits * **USD/EUR with VISAMASTER**: also requires `customerIp` — the end-customer IP address forwarded to the provider for antifraud checks. #### **Scenario 5: Fiat with Partial Enable** For withdrawals exceeding standard limits with "partially successful" status support. * **Required fields**: Same as basic + `partialEnable: true` + `address` (encrypted card token) * **Use when**: Withdrawing larger amounts eligible for partial processing * **Important**: The application must handle "Partially successful" withdrawal status #### **Scenario 6: IBAN Transfers (EUR)** Bank transfer withdrawals to IBAN accounts. * **Required fields**: Standard fields + `beneficiary` object with: * `firstName`, `lastName` (max 40 symbols, latin letters) * **Destination**: the beneficiary IBAN goes in the `address` field * **Use when**: Withdrawing EUR to a bank account by IBAN * Take the active provider for EUR from the [Asset Status endpoint](/api-reference/market-data/asset-status-list) #### **Scenario 7: International Fiat (USD/EUR VISAMASTER)** Withdrawals with extended beneficiary information. * **Required fields**: Standard fields + `beneficiary` object with: * `firstName`, `lastName`, `phone`, `email`, `birthDate` (YYYY-MM-DD) * **Use when**: Withdrawing USD or EUR via VISAMASTER\_PAYCORE provider * **Currencies**: USD\_VISAMASTER, EUR\_VISAMASTER #### **Scenario 8: SEPA / Bank-Rail Transfers** Bank transfers to an IBAN via SEPA and related fiat providers. * **Required fields**: Standard fields + `provider` + `bankBic` (beneficiary bank's BIC/SWIFT code) * **Providers**: `SEPA`, `SEPA_CLEAR_JUNCTION`, `SEPA_BCB_GROUP`, `FINCI`, `ZEN`, `BANKING_CIRCLE` * **Use when**: Withdrawing EUR (or other fiat) to a bank account through a SEPA/bank-rail provider *** ## Amount and Fee Calculation The `amount` field in the request **includes** the withdrawal fee. The recipient receives `amount - fee`. ### How it works: **Example request** (`/withdraw`): * Balance: 100 USDT * Withdrawal fee: 2 USDT * Request `amount: "100"` * **Result**: 100 USDT deducted from balance, recipient receives **98 USDT** **Alternative approach** (use `/withdraw-pay` instead): * Balance: 100 USDT * Withdrawal fee: 2 USDT * Request `amount: "98"` * **Result**: 100 USDT deducted from balance, recipient receives **98 USDT** To specify the exact amount the recipient should receive (with fee added on top), use the [withdraw-pay endpoint](/api-reference/account-wallet/create-withdraw-request-with-specific-amount) instead. Check current fees via [Get Fees endpoint](/api-reference/account-wallet/get-fees) before creating withdrawals. *** ## Common Pitfalls & Best Practices ### ⚠️ Unique ID Management **Critical**: Generate a **NEW** `uniqueId` for each withdrawal request. Reusing the same `uniqueId` will result in: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 0, "message": "Validation failed", "errors": { "uniqueId": ["The unique id has already been taken."] } } ``` **Best practice**: Use a timestamp-based or UUID generator: * ✅ Good: `"24529041"`, `"withdrawal_1640995200_abc123"` * ❌ Bad: Reusing `"12345"` for multiple withdrawals ### ⚠️ Address Validation Different currencies have different address formats: * **Bitcoin**: Starts with `1`, `3`, or `bc1` (SegWit) * **Ethereum/ERC20**: Starts with `0x`, 42 characters * **Tron/TRC20**: Starts with `T`, 34 characters * **Fiat**: Card token or IBAN format The platform validates addresses, but double-check addresses before sending. ### ⚠️ Memo/Destination Tag Some networks use a memo (destination tag) to route a transfer to the right account behind a shared address. | Memo on withdrawal | Assets | | - | - | | Mandatory | BABY, INIT | | Optional | ATOM, CATI, DOGS, DYDX, GRAM, HBAR, IOST, KAVA, LUNA, LUNC, NOT, OSMO, SAGA, SSLX, TIA, USTC, XLM, XRP, USDC on STELLAR, USDT on TON | Optional means the memo is accepted and passed to the network, and the withdrawal also goes through without it. On deposits a memo is mandatory for every asset in the table. **Memo format by network** Each network sets its own rules, so a value accepted on one chain is rejected on another. * **XRP**: a whole number from 0 to 4294967295. The value travels in the destination tag field of the transaction, not as text. * **STELLAR**: up to 28 characters. * **HBAR**: a whole number. Hedera carries the memo in a free-text field, so a value with a letter or a separator in it, such as `id-123`, counts as no memo at all. * **ATOM, CELESTIA, DYDX, IOST, KAVA, LUNA, LUNC, OSMO, SAGA, BABYLON, INIT**: up to 255 characters. * **TON**: latin letters `a-z` and `A-Z`, digits `0-9`, space and hyphen `-`, 1 to 255 characters. Everything else is rejected, including the dot, the underscore, `:`, `#`, `@`, Cyrillic and any other non-latin script, emoji, zero-width and non-breaking characters. `42.65` fails on the dot, `4265` passes. Leading and trailing spaces are trimmed on every network. Where no character rule is listed, pass the memo exactly as the receiving platform issued it. Memos issued by WhiteBIT for its own deposit addresses are always numeric, 4 to 15 digits depending on the network. A memo that fails the network rules returns `"memo": ["Incorrect format of memo"]`. The same error comes back when a memo is sent on a network that has no memo, so for USDT send `"network": "TON"` together with the memo: the default network for USDT is ERC20. Deposits to WhiteBIT are stricter than withdrawals. An HBAR memo that is not a whole number is dropped entirely and the deposit is not credited automatically. A Stellar memo is reduced to printable ASCII, so Cyrillic and emoji are removed without notice and the memo arrives altered. Send the deposit memo exactly as issued, with nothing added around it. Missing a required memo will result in **permanent loss of funds** or significant delays in recovery. Check currency requirements on [Asset Status endpoint](/api-reference/market-data/asset-status-list). ### ⚠️ Provider Selection (Fiat) Fiat withdrawals require the correct provider: * Check available providers via [Asset Status endpoint](/api-reference/market-data/asset-status-list) * Common providers: `VISAMASTER`, `VISAMASTER_PAYCORE`, `SEPA_BCB_GROUP` * Provider availability depends on currency and region *** ## Workflow: Complete Withdrawal Process ### Step 1: Pre-Withdrawal Checks ``` 1. Check balance: GET /api/v4/main-account/balance 2. Get withdrawal fees: POST /api/v4/main-account/fee 3. Verify currency is withdrawable: GET /api/v4/public/assets - Check "can_withdraw" status is "true" - Get available networks/providers - Check minimum/maximum amounts ``` ### Step 2: Create Withdrawal ``` POST /api/v4/main-account/withdraw ``` **Success response**: `[]` (empty array) Validation succeeded and the withdrawal process has started. The withdrawal is now queued for processing. ### Step 3: Monitor Status ``` POST /api/v4/main-account/history ``` Search by `uniqueId` to track the transaction. **Withdrawal status codes**: * **Successful**: 3, 7 * **Canceled**: 4 * **Pending**: Other codes (see [history endpoint](/api-reference/account-wallet/get-deposit-withdraw-history) for full list) Cryptocurrency withdrawals are typically processed within 15-60 minutes depending on network congestion. Fiat withdrawals may take 1-5 business days depending on the payment provider. *** ## Network Selection Guide For multi-network currencies (USDT, USDC, etc.), choosing the right network is critical: | Network | Speed | Fee | Use When | | - | - | - | - | | **ERC20** (Ethereum) | Slow | High | Large amounts, highest security | | **TRC20** (Tron) | Fast | Very Low | Small/medium amounts, fastest option | | **BEP20** (BSC) | Fast | Low | Good balance of speed and cost | | **OMNI** | Very Slow | High | Legacy, rarely used | **Default network**: If the `network` parameter is omitted, the default network is used (typically ERC20 for USDT). Always specify the network explicitly to avoid confusion. *** ## Error Handling ### Common validation errors (400): **Missing required fields**: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 0, "message": "Validation failed", "errors": { "address": ["The address field is required."], "amount": ["The amount field is required."], "ticker": ["The ticker field is required."], "uniqueId": ["The unique id field is required."] } } ``` **Invalid ticker**: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 0, "message": "Validation failed", "errors": { "ticker": ["The selected ticker is invalid."] } } ``` **KYC required**: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 0, "message": "Validation failed", "errors": { "amount": [ "This currency has no active pairs or it may have been delisted.", "Current limit exceeded" ] } } ``` ### Inner validation errors (422): **Error codes**: * `1` - Currency is not withdrawable * `2` - Specified address is invalid * `3` - Amount is too small * `4` - Amount is too small for the payment system * `5` - Not enough balance * `6` - Amount is less than or equals fee * `7` - Amount should be integer (zero precision currencies like NEO) * `8` - Target withdraw amount without fee equals zero * `9` - Address is unavailable (withdrawal to own address blocked) **Example**: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 5, "message": "Inner validation failed", "errors": { "amount": ["Not enough money, Ethereum balance = 1"] } } ``` *** ## Security Recommendations **Always verify withdrawal requests**: 1. Double-check the destination address 2. Verify the network (for multi-network currencies) 3. Confirm the amount and fee calculation 4. Test with a small amount first for new addresses **Withdrawal safety checklist**: * ✅ Address is correct and copied without errors * ✅ Network matches the destination (ERC20, TRC20, etc.) * ✅ Memo/tag included if required * ✅ Amount is within the available balance minus fees * ✅ Unique ID is newly generated * ✅ Provider is correct (for fiat) *** ## Related Endpoints * [Create withdraw request with specific amount (fee not included)](/api-reference/account-wallet/create-withdraw-request-with-specific-amount) - Alternative endpoint where fee is added on top * [Get deposit/withdraw history](/api-reference/account-wallet/get-deposit-withdraw-history) - Monitor withdrawal status * [Get fees](/api-reference/account-wallet/get-fees) - Check current withdrawal fees * [Main balance](/api-reference/account-wallet/main-balance) - Check available balance before withdrawal * [Asset Status endpoint](/api-reference/market-data/asset-status-list) - Verify currency can be withdrawn and get network/provider info ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Create withdraw request with the specific withdraw amount (fee is not included) Source: https://docs.whitebit.com/api-reference/account-wallet/create-withdraw-request-with-specific-amount openapi/private/main_api_v4.yaml POST /api/v4/main-account/withdraw-pay The endpoint has the similar logic as /main-account/withdraw, but with the only difference: amount that is specified will not include [fee](/glossary#fee) (it will be calculated to make target withdraw amount equal to the specified amount). **Example:** - When creating a base withdraw with amount = 100 USD, the receiver receives 100 USD minus the [fee](/glossary#fee), and the balance decreases by 100 USD. - When using this endpoint with amount = 100 USD, the receiver receives 100 USD, and the balance decreases by 100 USD plus the [fee](/glossary#fee). Rate limit: 1000 requests/10 sec. The API does not cache the response. Example: * When creating a base withdraw with amount = 100 USD, the receiver receives 100 USD minus the fee, and the balance decreases by 100 USD. * When calling the endpoint with amount = 100 USD, the receiver receives 100 USD, and the balance decreases by 100 USD + [fee](/glossary/#fee) amount. # Get codes history Source: https://docs.whitebit.com/api-reference/account-wallet/get-codes-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/codes/history The endpoint retrieves the whole [codes](/glossary#whitebit-codes) history for the account. Rate limit: 1000 requests/10 sec. The API does not cache the response. Results are sorted by date, newest first. **No date filtering:** the endpoint does not accept `startDate` / `endDate` parameters, and pagination is capped at `offset + limit ≤ 10000` (`limit` ≤ 100). For a complete history export beyond the cap, use the Report on the History page. # Get cryptocurrency deposit address Source: https://docs.whitebit.com/api-reference/account-wallet/get-cryptocurrency-deposit-address openapi/private/main_api_v4.yaml POST /api/v4/main-account/address Get an existing cryptocurrency deposit address for a given currency and network. Sub-accounts use this endpoint with a sub-account API key once deposits are enabled for the account. Crypto deposits are disabled by default. To enable deposits, contact the assigned account manager or email institutional@whitebit.com. Rate limit: 1000 requests/10 sec. ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Get deposit/withdraw history Source: https://docs.whitebit.com/api-reference/account-wallet/get-deposit-withdraw-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/history The endpoint retrieves the history of deposits and withdraws. **Deposit status codes:** - `Successful` - 3, 7 - `Canceled` - 4, 9 - `Unconfirmed by user` - 5 - `AML frozen` - 21 - `Uncredited` - 22 - `Pending` - 15 `Successful` (3, 7) is a final state. A credited deposit does not later transition to `AML frozen` (21) or `Uncredited` (22); those checks happen before crediting. **Travel Rule Deposit check status codes:** - `Awaiting verification` - 27: The transaction has been frozen due to the lack of data required under the Travel Rule. The user is required to provide this data manually through the exchange interface. - `Confirmation in progress` - 28: The Travel Rule data provided by the user is currently being verified by WhiteBIT. ⚠️ Due to regulatory requirements in Turkey and [EU](/glossary#european-economic-area-eea), the system places every inbound crypto deposit on hold (frozen) until confirming the transaction's origin. The sender must provide certain details if the transaction is from another Virtual Asset Service Provider (VASP) or verify the address if from a self-hosted wallet. The system credits deposited funds to the account only after successful verification. **Withdraw status codes:** - `Pending` - 1, 2, 6, 10–17 (withdrawal in progress). - `Successful` - 3, 7 - `Canceled` - 4 - `Unconfirmed by user` - 5 - `AML frozen` - 21 - `Partially successful` - 18 Rate limit: 200 requests/10 sec. Requests with `limit` values above 100 return large payloads. Use high limits only when necessary and ensure the client application can handle large response sizes. The API does not cache the response. Results are sorted newest first (descending by timestamp). **No date filtering:** the endpoint does not accept `startDate` / `endDate` parameters, and pagination is capped at `offset + limit ≤ 10000` (requests beyond the cap return `Offset is too big. Please use offset + limit less than 10000.`). To read more than 10,000 records, narrow the result set with the available filters (`transactionMethod`, `ticker`, `status`) and paginate within each subset; for a complete history export beyond the cap, use the Report on the History page. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Get fees Source: https://docs.whitebit.com/api-reference/account-wallet/get-fees openapi/private/main_api_v4.yaml POST /api/v4/main-account/fee Returns an array of objects containing deposit/withdrawal [fees](/glossary#fee) for the corresponding currencies. Zero value in amount fields means that the setting is disabled. The endpoint takes no input beyond the signed request envelope and returns the full per-currency fee schedule on success. It can return only the [common authentication errors](/api-reference/authentication). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Get fiat deposit URL Source: https://docs.whitebit.com/api-reference/account-wallet/get-fiat-deposit-url openapi/private/main_api_v4.yaml POST /api/v4/main-account/fiat-deposit-url The endpoint retrieves a deposit url of the [fiat](/glossary#fiat) invoice. The endpoint works on demand. Contact WhiteBIT support and provide the API key to get access to the functionality. When using VISAMASTER as [provider](/glossary#provider), pass the [referer header](https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Referer) when opening the invoice link (e.g. when opening https://someaddress.com). If the header is missing (e.g. when opening the link from a Telegram message), the browser is redirected to the WhiteBIT homepage Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Get Flex Investment History Source: https://docs.whitebit.com/api-reference/account-wallet/get-flex-investment-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/investments/history Retrieve complete investment operations history with advanced filtering. **Available Action Types:** - 1: INVEST - Investment creation - 2: REINVEST - Automatic reinvestment - 3: WITHDRAW_FROM_INVESTMENT - Partial withdrawal - 4: DAILY_EARNING - Daily earnings - 5: CLOSE_INVESTMENT - Investment closure - 6: OPEN_INVESTMENT - Investment opening Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. # Get Flex Payment History Source: https://docs.whitebit.com/api-reference/account-wallet/get-flex-payment-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/investments/payment-history Retrieve investment earnings history (ONLY DAILY_EARNING operations). **Note:** The endpoint automatically filters to show ONLY DAILY_EARNING operations (type 4). Rate limit: 1000 requests/10 sec. The API does not cache the response. The endpoint automatically filters to show ONLY DAILY\_EARNING operations (type 4) # Get Flex Plans Source: https://docs.whitebit.com/api-reference/account-wallet/get-flex-plans openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/plans The endpoint returns flex investment plan configurations with active status, filtered by the authenticated user's region and plan visibility. Results include public plans and private plans assigned to the account. Available after September 22, 2025. Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. The `id` field in each returned plan object is the `planId` value required by the [flex investment creation endpoint](/api-reference/account-wallet/create-flex-investment) (`POST /api/v4/main-account/smart-flex/investments/invest`). Only plans returned by this endpoint can be used to create new investments — plans with inactive or paused status are excluded automatically. # Get interest payments history Source: https://docs.whitebit.com/api-reference/account-wallet/get-interest-payments-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart/interest-payment-history The endpoint retrieves the history of interest payments. Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. # Get investments history Source: https://docs.whitebit.com/api-reference/account-wallet/get-investments-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart/investments The endpoint retrieves an investments history. Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. # Get account codes Source: https://docs.whitebit.com/api-reference/account-wallet/get-my-codes openapi/private/main_api_v4.yaml POST /api/v4/main-account/codes/my The endpoint retrieves the list of [WhiteBIT codes](/glossary#whitebit-codes) created by my account. Rate limit: 1000 requests/10 sec. The API does not cache the response. Results are sorted by creation date, newest first. Pagination is capped at `offset + limit ≤ 10000`; for a complete history export beyond the cap, use the Report on the History page. # Get plans Source: https://docs.whitebit.com/api-reference/account-wallet/get-plans openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart/plans The endpoint returns investment plan configurations with active status and API access enabled, filtered by the authenticated user's region and plan visibility. Results include public plans and private plans assigned to the account. These endpoints are available only for B2B partner services. Fill the institutional services form to get permissions to use these endpoints. **Note:** When target currency is different from source currency, interest amount in target currency will be calculated using `interestRatio` value. **Examples:** - When source currency = USDT, target currency = BTC and interest ratio = 40000, interest is received in BTC and equals the USDT interest amount divided by the interest ratio (e.g. 0.000025 BTC per 1 USDT of interest). - When source currency equals target currency, interest ratio equals 1. Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. The `id` field in each returned plan object is the `planId` value required by the [investment creation endpoint](/api-reference/account-wallet/invest) (`POST /api/v4/main-account/smart/investment`). Only plans returned by this endpoint can be used to create new investments — plans with inactive status or disabled API access are excluded automatically. # Get refund history Source: https://docs.whitebit.com/api-reference/account-wallet/get-refund-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/refund-history The endpoint returns the account's deposit refunds, including refunds requested through the WhiteBIT interface or through the API. Rate limit: 1000 requests/10 sec. The API does not cache the response. Results are sorted by refund creation, newest first. The endpoint lists full refunds only. A deposit with at least one partial refund is excluded from the results. The response does not include a total count. To read the full history, increase `offset` by `limit` until `records` contains fewer than `limit` entries. The maximum `offset` is 10000. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Get transfer history Source: https://docs.whitebit.com/api-reference/account-wallet/get-transfer-history openapi/private/main_api_v4.yaml POST /api/v4/main-account/transfer/history The endpoint returns the history of transfers between the [main](/glossary#balance-main), [spot](/glossary#balance-spotbalance-trade) and [collateral](/glossary#balance-collateral) balances of the authenticated account, newest first. The endpoint requires an API key with the **Balance transfer** permission enabled — the same permission as [Transfer between balances](/api-reference/account-wallet/transfer-between-balances). For transfers between a main account and its [sub-accounts](/glossary#sub-account), use [Get Sub-Account Transfer History](/api-reference/sub-accounts/get-sub-account-transfer-history) instead. Every transfer is recorded with the main balance on one side. A transfer between the spot and collateral balances executes as two steps through the main balance, so such a transfer appears as two records — `spot → main` and `main → collateral` — each carrying a separate identifier and the full transferred amount. Account for both records when summing amounts. Filter combinations that cannot be stored (`spot` with `collateral`, `collateral` with `spot`, or the same balance on both sides) return an empty `data` array — filter by the individual legs instead. Records are ordered from newest to oldest by the order of execution. Neither `id` nor `created_at` is a sort key — `id` is a random identifier, and two records can share the same `created_at` second — so page through the history with `limit` and `offset`. The response carries no total count and no cursor: a returned count below `limit` marks the last page, and an empty array means no further records. `offset` cannot exceed `10000` — for a longer history, use report generation on the History page. The API does not cache the response. `POST /api/v4/main-account/transfer` returns `201` as soon as a transfer is queued, so a request sent immediately afterwards can return no records yet. The history also covers transfers the platform performs for the account, such as mining-pool conversions, and transfers in delisted currencies. Every returned transfer is completed. ## Rate limit # Get User Flex Investments Source: https://docs.whitebit.com/api-reference/account-wallet/get-user-flex-investments openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/investments Retrieve user's investment portfolio with optional filtering. Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. # Invest Source: https://docs.whitebit.com/api-reference/account-wallet/invest openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart/investment The endpoint creates a new investment to the specified [invest plan](/glossary#crypto-lending). Rate limit: 1000 requests/10 sec. The API does not cache the response. These endpoints are available only for B2B partner services. Fill the form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) to request access. # Issue card token Source: https://docs.whitebit.com/api-reference/account-wallet/issue-card-token openapi/private/main_api_v4.yaml POST /api/card-token The endpoint issues a [card token](/glossary#card-token) for the specified card number. **Request Headers:** - `Authorization`: JWT token from the [Issue JWT token](/private/http-main-v4/issue-jwt-token) response field `data.token` (**Required**) - `Content-Type`: `application/json` (**Required**) Use the `data.token` value returned by [Issue JWT token](/private/http-main-v4/issue-jwt-token) as the `Authorization` header when calling this Fiat Gateway endpoint. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Issue JWT token Source: https://docs.whitebit.com/api-reference/account-wallet/issue-jwt-token openapi/private/main_api_v4.yaml POST /api/v4/jwt The endpoint issues a JWT token for the Fiat Gateway service. The token is used to authenticate requests to the Fiat Gateway API. The API does not cache the response. # List Credit Lines Source: https://docs.whitebit.com/api-reference/account-wallet/list-credit-lines openapi/private/main_api_v4.yaml POST /api/v4/credit-line/loans/info The endpoint returns an active loan. The endpoint works on demand - contact WhiteBIT support to get access. Rate limit: 1000 requests/10 sec. The API does not cache the response. The endpoint works on demand. Contact WhiteBIT support and provide the API key to get access to the functionality. # Main balance Source: https://docs.whitebit.com/api-reference/account-wallet/main-balance openapi/private/main_api_v4.yaml POST /api/v4/main-account/balance The endpoint retrieves the [main balance](/glossary#balance-main) by currency [ticker](/glossary#ticker) or all balances. An unknown or non-existent `ticker` is not an error: the endpoint returns a zero balance (`{"main_balance": "0"}`) for it. Omitting `ticker` returns balances for every currency. `main_balance` already includes deposits credited before the network fully confirms them. The part of it that is still held back is reported separately as `pending_deposit_amount`: that amount is tradable but cannot be withdrawn, sent as a WhiteBIT Code, or moved to the collateral balance until the network confirms the deposit. To see the held amount across the whole account, and what remains withdrawable, use [Withdrawable balance](/api-reference/account-wallet/withdrawable-balance). Beyond the validation error above, this endpoint can return only the [common authentication errors](/api-reference/authentication). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Account & Wallet Source: https://docs.whitebit.com/api-reference/account-wallet/overview Endpoints for managing main balance, deposits, withdrawals, codes, crypto lending, fees, and credit lines. Manage the main account balance, deposits, withdrawals, transfers, WhiteBIT codes, crypto lending, fees, and credit lines. For general API conventions (base URL, error format, rate limits), see the [API Reference Overview](/api-reference/overview). *** ## Main Balance & Transfers Get main account balance Get deposit address for cryptocurrency Generate a fiat deposit URL and payment details Issue JWT token for authentication Issue card token for payments Create a withdrawal request Create withdrawal with specific amount (fee not included) Create a single-use payment token that charges a WhiteBIT user's balance Transfer funds between balances Get the history of transfers between balances Get deposit and withdrawal history Create a new deposit address Refund a canceled deposit Get deposit refunds with status *** ## Codes Create a new WhiteBIT code Apply a WhiteBIT code Get created codes Get codes history *** ## Crypto Lending ### Fixed Plans Get available fixed lending plans Invest in a fixed plan Close a fixed investment Get fixed investments history Get interest payments history ### Flex Plans Get available flex lending plans Get flex investments Get flex investment history Get flex payment history Create a new flex investment Withdraw from flex investment Close a flex investment Update flex auto-reinvestment settings *** ## Fees Get trading fees information *** ## Credit Line Get list of credit lines # Get WebSocket Token Source: https://docs.whitebit.com/api-reference/account-wallet/profile-websocket-token openapi/private/main_api_v4.yaml POST /api/v4/profile/websocket_token The V4 endpoint can be used to retrieve the WebSocket token for user. The token is required to authorize WebSocket connections for private API access. Beyond validation, this endpoint returns only the [common authentication errors](/api-reference/authentication). Rate limit: 10 requests/60 sec. The API does not cache the response. # Refund deposit Source: https://docs.whitebit.com/api-reference/account-wallet/refund-deposit openapi/private/main_api_v4.yaml POST /api/v4/main-account/refund-deposit Refund a deposit. The system processes refunds only for deposits with status `canceled`. Obtain `transactionId` from the `deposit.canceled` webhook (`uniqueId`) or from the deposit/withdraw history in the WhiteBIT interface after support confirms refund availability. The refund address must support the same network and asset as the original deposit. The refund address must not be a WhiteBIT address. The refund address can differ from the original deposit sender address. Rate limit: 1000 requests/10 sec. The API does not cache the response. Refund processing does not complete instantly. Use the [refund.successful](/platform/webhook#whitebit-refund-successful) and [refund.failed](/platform/webhook#whitebit-refund-failed) webhooks to receive refund status updates, or check the current status with [Get refund history](/api-reference/account-wallet/get-refund-history). ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Transfer between balances Source: https://docs.whitebit.com/api-reference/account-wallet/transfer-between-balances openapi/private/main_api_v4.yaml POST /api/v4/main-account/transfer The endpoint transfers the specified amount between [main](/glossary#balance-main), [trade](/glossary#balance-spotbalance-trade) and [collateral](/glossary#balance-collateral) balances. Rate limit: 1000 requests/10 sec. The API does not cache the response. Also, fiat currencies can't be transferred without KYC verification. # Update Flex Auto-Reinvestment Source: https://docs.whitebit.com/api-reference/account-wallet/update-flex-auto-reinvestment openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/investments/auto-invest Enable/disable automatic reinvestment for user's investment. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Withdraw from Flex Investment Source: https://docs.whitebit.com/api-reference/account-wallet/withdraw-from-flex-investment openapi/private/main_api_v4.yaml POST /api/v4/main-account/smart-flex/investments/withdraw Withdraw specified amount from user's investment. **Note:** Plan must be active and accessible to user. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Withdrawable balance Source: https://docs.whitebit.com/api-reference/account-wallet/withdrawable-balance openapi/private/main_api_v4.yaml POST /api/v4/main-account/withdrawable-balance The endpoint reports how much of the account is held back because deposits were credited before the network fully confirmed them, and how much remains withdrawable. Amounts ending in `Stable` are expressed in a stable-coin equivalent, so figures for different currencies can be summed. `assets` breaks the free amount down per currency, in that currency's own units. The held amount is tradable: it can be moved to the trade balance and traded. It cannot be withdrawn, sent as a WhiteBIT Code, or moved to the collateral balance until the network confirms the deposit. Two limits apply at once — the free amount of the currency itself, shown in `assets`, and the free value of the whole account, shown in `availableBalanceStable`. Whichever is smaller decides. `assets` lists a currency when it has a free amount, and lists it with `"0"` when the currency is fully held back. Currencies with neither a balance nor a hold are omitted. The collateral balance is excluded from every figure here, because funds moved there are already outside the hold. Beyond the [common authentication errors](/api-reference/authentication), this endpoint returns no errors of its own. Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Private HTTP API Authentication Source: https://docs.whitebit.com/api-reference/authentication Authenticate with WhiteBIT private HTTP API endpoints using API keys and HMAC-SHA512 signatures. ## Overview The Authentication guide explains how to authenticate with WhiteBIT’s private HTTP API endpoints, which require authentication for security purposes. ## Getting Started ### Setting Up API Keys Navigate to [WhiteBIT API Settings](https://whitebit.com/settings/api) Select the appropriate configuration tab for API keys Different API keys provide access to different API endpoints Generate a new API key **Recommended Security Measures:** * Enable IP restrictions (specify up to 50 trusted IPs) * Enable Endpoint access restrictions (select only necessary endpoints) Keys auto-deactivate after 14 days of inactivity — reactivate at [whitebit.com/settings/api](https://whitebit.com/settings/api). 2FA must be enabled before key creation. Use separate keys per application with minimal permissions. ## Authentication Requirements All authenticated requests must: 1. Use the `POST` HTTP method 2. Include specific body data 3. Contain required headers ### Body Data Format The request body must be a JSON object containing: | Field | Description | Example | | - | - | - | | `request` | Request path without domain name | `'/api/v4/trade-account/balance'` | | `nonce` | An incrementing number larger than previous requests | `1594297865000` | | `nonceWindow` | Optional boolean to enable time-based nonce validation | `true` | | Request-specific parameters | Additional parameters required by the endpoint | `"ticker": "BTC"` | **Example Request Body:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "request": "/api/v4/trade-account/balance", "nonce": 1594297865000, "nonceWindow": true, "ticker": "BTC" } ``` #### About Nonce Values * Use the Unix timestamp in milliseconds for nonce values * Ensure each nonce is larger than previous requests * When `nonceWindow` is enabled: * Provide Unix timestamp in milliseconds as the nonce * Timestamp must be within ±5 seconds of server time * Each nonce must be unique to prevent double processing * Useful for high-frequency trading systems with concurrent requests ### Required Headers Every authenticated request requires these headers: Create the signature using: `hex(HMAC_SHA512(payload, key=api_secret))` ## Implementation Examples For a raw HMAC-SHA512 signing walkthrough with curl and Python examples, see [First API Call](/guides/first-api-call). Official SDKs for Go, Python, and PHP are listed on the [SDKs page](/sdks). ## Common Errors For rate limits and REST error format, see [Rate limits and error codes](/api-reference/rate-limits). ## Testing in the API playground ## Related resources * [API Reference Overview](/api-reference/overview) — Base URL, rate limits, and error format * [Market Data overview](/api-reference/market-data/overview) — Public endpoints (no authentication) * [Spot Trading overview](/api-reference/trading/spot-overview) — Private trading endpoints * [OAuth Overview](/platform/oauth/overview) — Third-party application authorization for ecosystem partners ## Used in these guides * [Crypto-as-a-Service integration](/guides/caas-integration) — white-label custody and payments for platforms. * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Fast API Key integration](/guides/fast-api-key-integration) — OAuth-issued API keys created on behalf of end users. * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. * [On/Off-Ramp overview](/guides/on-off-ramp-overview) — corporate fiat ↔ crypto over EUR/SEPA rails, program-level. * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. * [Wallet-as-a-Service integration](/guides/waas-integration) — programmatic wallets and payouts for businesses. * [Yield-as-a-Service integration](/guides/yaas-integration) — offer Crypto Lending yield to end users via per-user sub-accounts. # Convert Auto Confirm Source: https://docs.whitebit.com/api-reference/convert/convert-auto-confirm openapi/private/http-trade-v4.yaml POST /api/v4/convert/auto-confirm Request and accept a currency conversion quote in a single call via the WhiteBIT V4 API. # Convert Confirm Source: https://docs.whitebit.com/api-reference/convert/convert-confirm openapi/private/http-trade-v4.yaml POST /api/v4/convert/confirm The endpoint confirms an estimated quote. An expired quote returns code `20` (`api.converter.quoteExpired`), which is distinct from a quote that could not be found (code `0`). Balance is re-checked at confirm time and can fail with code `37` even when the estimate succeeded, because balance may change within the 10-second quote window. A re-confirmed (already used) quote and a quote that never existed both return code `0` with the `quoteId` field key `frontendServerSide.converter.quoteInvalid`. The response alone does not distinguish "already used" from "never existed". Error `message` values may be returned as translation keys (for example `api.converter.quoteExpired`) rather than finalized English strings. Treat the `code` and the field name under `errors` as the stable contract. Rate limit: 10000 requests/10 sec. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Convert Estimate Source: https://docs.whitebit.com/api-reference/convert/convert-estimate openapi/private/http-trade-v4.yaml POST /api/v4/convert/estimate The endpoint creates a quote for converting one currency to another. Quote lifetime is 10 seconds, then quote will be expired. The minimum convert size is derived from the resulting proceeds, not a fixed per-pair floor: a request is rejected as too small when `rate × amount` rounds to zero in the target currency. Account balance is pre-checked at estimate time and re-checked at confirm time, because balance can change within the 10-second quote window. There is an absolute server-side maximum on the conversion amount. The endpoint can be used to obtain a pre-execution price estimate for a market order. Call the endpoint with the desired amount before placing a market order to see the approximate execution price. Error `message` values may be returned as translation keys (for example `validation.required`) rather than finalized English strings. Treat the `code` and the field name under `errors` as the stable contract. Rate limit: 10000 requests/10 sec. ## Used in these guides * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Convert History Source: https://docs.whitebit.com/api-reference/convert/convert-history openapi/private/http-trade-v4.yaml POST /api/v4/convert/history The endpoint returns convert history, sorted by `id` descending (newest first). The `from`–`to` window is capped at 30 days per request, even though data is retained for 6 months. A wider range is rejected with code `30` (`api.validation.dateTime.maxRange`). Rate limit: 10000 requests/10 sec. Error `message` values may be returned as translation keys (for example `api.validation.dateTime.maxRange`) rather than finalized English strings. Treat the `code` and the field name under `errors` as the stable contract. **Note:** The endpoint can retrieve data not older than 6 months from the current month. For older data, use the Report on the History page. # Convert Source: https://docs.whitebit.com/api-reference/convert/overview Overview of the WhiteBIT Convert endpoints — request a quote, confirm it at the quoted rate or accept it in a single call, and review conversion history. The Convert endpoints exchange one asset for another at a quoted rate: request an estimate, confirm it before the quote expires, and review completed conversions. A single call can also request and accept a quote together, skipping the expiry window. For the quoted-rate flow end to end, see [Convert](/platform/convert). For general API conventions (base URL, authentication, error format, rate limits), see the [API Reference Overview](/api-reference/overview). ## Endpoints Request a quote for converting one asset to another. Returns the rate and an id used to confirm. Execute a conversion at the quoted rate before the quote expires. Request and accept a quote in a single call, with no expiry window. Review completed conversions. ## What's next * [Convert](/platform/convert) — the quoted-rate conversion flow end to end * [Payment Integration](/guides/payment-integration) — conversion inside a payments flow # Asset status list Source: https://docs.whitebit.com/api-reference/market-data/asset-status-list openapi/public/http-v4.yaml GET /api/v4/public/assets The endpoint retrieves the deposit and withdrawal status for every supported asset. Use the response to check whether deposits and withdrawals are enabled, read per-network fee and limit details, and determine required blockchain confirmation counts. The response includes crypto assets, fiat currencies, and fiat payment methods. Asset status is reference data, re-synced approximately once per minute. Polling more frequently returns identical data. The cache is shared across all callers. Rate limit: 2000 requests/10 sec. See [Public API V4 overview](/public/http-v4/index) for rate limit details. * [Fee](/api-reference/market-data/fee) — deposit and withdrawal fee schedule per asset. * [Market info](/api-reference/market-data/market-info) — trading pair configuration and rules. ## Notes ### Asset type classification The endpoint returns three structurally distinct asset types. Use the presence or absence of the `confirmations` and `providers` fields to classify each asset. | Asset type | `confirmations` field | `providers` field | | - | - | - | | Crypto asset | Present | Absent | | Fiat currency | Absent | Present (may be empty) | | Fiat payment method | Absent | Absent | **Crypto assets** (e.g., `BTC`, `ETH`, `USDT`) include a `confirmations` object with required blockchain confirmation counts per network. **Fiat currencies** (e.g., `EUR`, `USD`, `UAH`) include a `providers` object listing available payment processors. The `providers` field is present even when the list is empty. **Fiat payment methods** (e.g., `EUR_ADVCASH`, `USD_VISAMASTER`) represent individual payment channels. These entries include neither `confirmations` nor `providers`. The network identifier in the `networks` field matches the asset ticker. ### Deposit confirmation thresholds A crypto network can have two confirmation counts, and a deposit becomes usable in two steps. | Field | Reached at | What the deposit can be used for | | - | - | - | | `confirmations_for_trading` | Earlier | Trading only. The amount cannot be withdrawn, transferred to a collateral balance, or used as collateral. | | `confirmations` | Later | Everything, including withdrawal, transfer, and collateral operations. | Both maps always carry the same network keys, so a network listed in `confirmations` is listed in `confirmations_for_trading` too. Where a network has no earlier threshold, or while the platform has early trading availability switched off, the two values are equal — trading then opens at the same point as withdrawal. Compare the values rather than checking whether the field is there, and read the values on every poll rather than caching the thresholds as a static setting. ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [On/Off-Ramp overview](/guides/on-off-ramp-overview) — the per-currency provider matrix confirmed during onboarding. * [On/Off-Ramp FAQ](/guides/on-off-ramp-faq) — provider values and `can_deposit` flags for SEPA and card deposits. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. * [Wallet-as-a-Service integration](/guides/waas-integration) — programmatic wallets and payouts for businesses. * [Wallet-as-a-Service FAQ](/guides/waas-faq) — per-asset minimums before testing signed calls. * [Embedded Trading integration guide](/guides/sub-account-integration) — per-asset minimums before placing sub-account orders. # Available futures markets list Source: https://docs.whitebit.com/api-reference/market-data/available-futures-markets-list openapi/public/http-v4.yaml GET /api/v4/public/futures The endpoint returns detailed information for all available futures markets. Use the response to read current pricing, open interest, funding rates, and leverage bracket configuration. Each entry includes the predicted next funding rate, settlement timestamps, and maximum allowed position sizes per leverage level. The `mark_price` field reports the fair value of the perpetual contract. `index_price` and `funding_rate` are sourced from the premium index that already drives liquidation; field names and the decimal-string format are unchanged. The API caches the response for 1 second Rate limit 2000 requests/10 sec. * [Premium index (WebSocket)](/websocket/market-streams/premium-index) — subscribe for a live push of mark price, index price, and funding rate instead of polling this endpoint. * [Collateral markets list](/api-reference/market-data/collateral-markets-list) — markets available for collateral trading. * [Funding history](/api-reference/market-data/funding-history) — historical funding rate records for futures markets. # Collateral markets list Source: https://docs.whitebit.com/api-reference/market-data/collateral-markets-list openapi/public/http-v4.yaml GET /api/v4/public/collateral/markets The endpoint returns the list of [market](/glossary#market) pair names available for [collateral](/glossary#collateral) trading. Use the response to determine which markets support margin positions. Each item in the result array is a market pair name in `BASE_QUOTE` format (e.g., `BTC_USDT`). The list includes TradFi futures markets that are enabled for collateral trading, alongside crypto markets. TradFi entries are ordinary market pair names in the same array — the response carries no per-market type field, so read `type` and `isTradFiFutures` from [`GET /api/v4/public/markets`](/api-reference/market-data/market-info) to tell the market types apart. TradFi futures markets stay region-gated: a TradFi market not assigned to the caller's region is omitted from that region's response, exactly as on `GET /api/v4/public/markets`. The collateral market list is reference data, re-synced approximately every 10 seconds. Polling more frequently returns identical data. The cache is shared across all callers. A market in this list is configured for collateral trading; that is not the same as the account being entitled to trade it. Placing an order on a TradFi market additionally requires TradFi futures to be enabled for the account — without it the order request is rejected with HTTP 422, `api.tradeErrors.tradFi.restricted`. Rate limit 2000 requests/10 sec. * [Available futures markets list](/api-reference/market-data/available-futures-markets-list) — futures market details including funding rates and leverage brackets. * [Market info](/api-reference/market-data/market-info) — full market configuration with the `isCollateral` flag. # Depth Source: https://docs.whitebit.com/api-reference/market-data/depth openapi/public/http-v4.yaml GET /api/v4/public/orderbook/depth/{market} The endpoint retrieves depth price levels within ±2% of the market last price. Use when lightweight order book data is needed for a narrow price band around the current market price. The ±2% constraint limits the response to price levels near the last traded price, reducing payload size compared to the full order book. The API caches the response for 1 sec Rate limit: 2000 requests/10 sec. See [Public API V4 overview](/public/http-v4/index) for rate limit details. Public depth endpoints exclude Retail Price Improvement (RPI) orders. RPI orders appear only in private active orders (private API/WebSocket) and in the exchange UI order book (web and mobile). * [Orderbook](/api-reference/market-data/orderbook) — full order book with configurable depth and price-level aggregation. * [Recent trades](/api-reference/market-data/recent-trades) — latest executed trades for a market. # Fee Source: https://docs.whitebit.com/api-reference/market-data/fee openapi/public/http-v4.yaml GET /api/v4/public/fee The endpoint retrieves the [fee](/glossary#fee) schedule and deposit/withdrawal limits for every supported asset. Use the response to display fee estimates before a user initiates a deposit or withdrawal. The response is keyed by currency ticker; each entry contains deposit and withdrawal fee amounts and min/max transfer limits. The fee schedule is reference data, re-synced approximately once per minute. Polling more frequently returns identical data. The cache is shared across all callers. Rate limit: 2000 requests/10 sec. See [Public API V4 overview](/public/http-v4/index) for rate limit details. * [Asset status list](/api-reference/market-data/asset-status-list) — deposit and withdrawal status, network details, and per-asset fee data. ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [On/Off-Ramp overview](/guides/on-off-ramp-overview) — fees and limits per fiat asset confirmed with the account manager. # Funding history Source: https://docs.whitebit.com/api-reference/market-data/funding-history openapi/public/http-v4.yaml GET /api/v4/public/funding-history/{market} The endpoint returns the funding rate history for a specified futures market. Use the response to analyze historical funding rate trends and settlement prices. Results are sorted by funding time in descending order and support offset-based pagination via `limit` and `offset` parameters. Rate limit 2000 requests/10 sec. This endpoint supports pagination. Use `limit` (default: 100, max: 100) and `offset` (default: 0, max: 1000000) to page through results. The response is a plain array with no `total`, `has_more`, or cursor — a returned count below `limit` marks the last page (an empty array means no further records). Funding history is served per request at the API layer, with no application-level cache. * [Available futures markets list](/api-reference/market-data/available-futures-markets-list) — futures market details including current predicted funding rate. # Kline Source: https://docs.whitebit.com/api-reference/market-data/kline openapi/public/http-v1.yaml GET /api/v1/public/kline The endpoint retrieves information about market kline. The API caches the response for: 1 second Rate limit 1000 requests/10 sec. The maximum number of candles per request is 1440. Use `limit` (default: 1440, max: 1440) to control the number of results. Use `start` and `end` timestamps to page through historical data. Request validation errors return HTTP `200` with `success: false`, `result: null`, and a `message` object mapping each invalid field to the corresponding messages — for example `{"market": ["Market is not available."]}` or `{"end": ["End field must be greater then start."]}`. ## Rate limit * [Recent trades](/api-reference/market-data/recent-trades) — individual trade executions for a market. * [Market activity](/api-reference/market-data/market-activity) — 24-hour pricing and volume summary per market. # Maintenance status Source: https://docs.whitebit.com/api-reference/market-data/maintenance-status openapi/public/http-v4.yaml GET /api/v4/public/platform/status The endpoint retrieves the current maintenance status of the WhiteBIT platform. Use the response to detect scheduled downtime and pause trading automation during maintenance windows. The `status` field returns `"system operational"` when all platform services are available, or `"system maintenance"` when the platform is undergoing planned maintenance. * [Server status](/api-reference/market-data/server-status) — API health check (ping/pong). * [Server time](/api-reference/market-data/server-time) — current server timestamp for clock synchronization. # Market activity Source: https://docs.whitebit.com/api-reference/market-data/market-activity openapi/public/http-v4.yaml GET /api/v4/public/ticker The endpoint retrieves a 24-hour pricing and volume summary for each market pair available on the exchange. The API caches the response for 1 second Rate limit: 2000 requests/10 sec. See [Public API V4 overview](/public/http-v4/index) for rate limit details. * [Market info](/api-reference/market-data/market-info) — market configuration, trading rules, and fee structure. * [Recent trades](/api-reference/market-data/recent-trades) — individual trade executions for a specific market. # Market info Source: https://docs.whitebit.com/api-reference/market-data/market-info openapi/public/http-v4.yaml GET /api/v4/public/markets The endpoint retrieves configuration and trading rules for all available spot, futures, and TradFi futures markets. Use the response to discover tradeable pairs, check minimum order sizes, and read fee schedules. Each entry includes precision settings, fee ratios, and order-size constraints for the market. Market configuration is reference data, re-synced from the database approximately every 10 seconds. Polling more frequently returns identical data. The cache is shared across all callers. TradFi futures markets are region-gated: markets not available in a given region are omitted from the response entirely and do not appear under any other market type. A market with an announced delisting carries the announced date in `delistedAt` and stays tradeable until the delisting runs. Once the delisting runs, the platform cancels the active orders on the market and drops the market from this response — [Query delisting and maintenance orders](/api-reference/trading/query-delisting-orders) is a signed request that returns the authenticated account's resulting spot order records. An announcement can be rescheduled or canceled, so treat `delistedAt` as the current plan rather than a settled fact and re-read the value on the next poll. Rate limit 2000 requests/10 sec. * [Market activity](/api-reference/market-data/market-activity) — 24-hour pricing and volume summary per market. * [Collateral markets list](/api-reference/market-data/collateral-markets-list) — markets available for collateral trading. * [Fee](/api-reference/market-data/fee) — deposit and withdrawal fee schedule per asset. * [Query delisting and maintenance orders](/api-reference/trading/query-delisting-orders) — order history for markets that were delisted or put into maintenance. # Orderbook Source: https://docs.whitebit.com/api-reference/market-data/orderbook openapi/public/http-v4.yaml GET /api/v4/public/orderbook/{market} The endpoint retrieves the current [order book](/glossary#order-book) as two arrays ([bids](/glossary#bid) / [asks](/glossary#ask)) with additional parameters. The API caches the response for 100 ms Rate limit 600 requests/10 sec. Public order book responses exclude Retail Price Improvement (RPI) orders. Private active order endpoints and private WebSocket streams return RPI orders. The exchange UI order book (web and mobile) displays RPI orders. * [Depth](/api-reference/market-data/depth) — lightweight order book within ±2% of the last price. * [Recent trades](/api-reference/market-data/recent-trades) — latest executed trades for a market. # Market Data Source: https://docs.whitebit.com/api-reference/market-data/overview Public market data endpoints cover server status, trading pairs, order books, and price data — no authentication required. Browse publicly available market data endpoints — no authentication required. For general API conventions (base URL, error format, rate limits), see the [API Reference Overview](/api-reference/overview). *** ## Server & Status Endpoints for checking server health and status: Check current API life-state Get current server time Check platform maintenance status *** ## Markets & Assets Endpoints for retrieving market and asset information: Get information about spot and futures markets Get 24-hour pricing and volume summary Get asset withdrawal and deposit status Get markets available for collateral trading Get available futures markets list *** ## Order Book & Trades Endpoints for order book data and recent trading activity: Get current order book with bids and asks Get depth price levels within ±2% of market price Get recently executed trades for a market *** ## Fees & Funding Endpoints for fee information and funding rates: Get deposit and withdrawal fees and limits Get funding rate history for futures markets # Recent trades Source: https://docs.whitebit.com/api-reference/market-data/recent-trades openapi/public/http-v4.yaml GET /api/v4/public/trades/{market} The endpoint retrieves the [trades](/glossary#deal-trade) that have been executed recently on the requested [market](/glossary#market). It returns up to the 100 most recent trades; the response size is fixed and there is no `limit` parameter. The API caches the response for 1 second Public trade data can include executions that originate from RPI orders. Public order book feeds (`depth`, `bookTicker`) exclude RPI orders. RPI orders appear only in private active orders and in the exchange UI order book (web and mobile). Rate limit 2000 requests/10 sec. * [Orderbook](/api-reference/market-data/orderbook) — current order book with configurable depth and aggregation. * [Market activity](/api-reference/market-data/market-activity) — 24-hour pricing and volume summary per market. # Server status Source: https://docs.whitebit.com/api-reference/market-data/server-status openapi/public/http-v4.yaml GET /api/v4/public/ping The endpoint checks API availability by returning a simple health-check response. Use the endpoint to verify network connectivity and confirm the API server is reachable. A successful response contains the string `"pong"`. The endpoint takes no parameters and has no request-validation errors; it returns HTTP 200 on success and fails only at the infrastructure level (see the API description). The health-check response is generated per request and is not cached. Rate limit 2000 requests/10 sec. * [Server time](/api-reference/market-data/server-time) — current server timestamp for clock synchronization. * [Maintenance status](/api-reference/market-data/maintenance-status) — platform operational or maintenance state. # Server time Source: https://docs.whitebit.com/api-reference/market-data/server-time openapi/public/http-v4.yaml GET /api/v4/public/time The endpoint retrieves the current server time as a Unix timestamp. Use the response to synchronize local clocks before generating HMAC signatures for authenticated requests. The endpoint takes no parameters and has no request-validation errors; it returns HTTP 200 on success and fails only at the infrastructure level (see the API description). The server time is computed per request and is not cached. Rate limit 2000 requests/10 sec. * [Server status](/api-reference/market-data/server-status) — API health check (ping/pong). # Symbols Source: https://docs.whitebit.com/api-reference/market-data/symbols openapi/public/http-v1.yaml GET /api/v1/public/symbols The endpoint retrieves information about all available markets for trading. The API caches the response for: 1 second Rate limit 1000 requests/10 sec. ## Rate limit * [Market info](/api-reference/market-data/market-info) — detailed market configuration including trading rules, fees, and precision (V4). # Account Hashrate Source: https://docs.whitebit.com/api-reference/mining-pool/account-hashrate openapi/private/main_api_v4.yaml POST /api/v4/mining/hashrate The endpoint returns hashrate of mining pool account. There is no dedicated "mining not enabled" error. An account that is administratively disabled for mining returns HTTP `200` with empty data rather than an error. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Create Mining Account Source: https://docs.whitebit.com/api-reference/mining-pool/create-mining-account openapi/private/main_api_v4.yaml POST /api/v4/mining/accounts/create Creates a new mining account for the authenticated user. The account name must be unique within the user's accounts. The number of mining accounts per user is capped (configurable server-side). Creating an account beyond the cap returns a `400` with `miningPool.validation.maxAccounts`. Rate limit: 1000 requests/10 sec. # Create Watcher Link Source: https://docs.whitebit.com/api-reference/mining-pool/create-watcher-link openapi/private/main_api_v4.yaml POST /api/v4/mining/watcher-links/create Creates a new watcher link for one or more mining accounts, granting specific permissions with a configurable expiration. The number of active watcher links per mining account is capped (configurable server-side; currently 3 by default). Exceeding the cap returns a `400` with `Limit exceeded`. Rate limit: 1000 requests/10 sec. # Get Mining Accounts Source: https://docs.whitebit.com/api-reference/mining-pool/get-mining-accounts openapi/private/main_api_v4.yaml POST /api/v4/mining/accounts Returns a list of mining accounts for the authenticated user. Supports filtering by account name. Results are ordered by account creation time, newest first. The response does not include a `total` field. Detect the last page when `data.length < limit`. Rate limit: 1000 requests/10 sec. # Get Payout Destination Source: https://docs.whitebit.com/api-reference/mining-pool/get-payout-destination openapi/private/main_api_v4.yaml POST /api/v4/mining/payout-destination Returns the current payout destination setting for a specific mining account belonging to the authenticated user. Rate limit: 1000 requests/10 sec. # Get Rewards Source: https://docs.whitebit.com/api-reference/mining-pool/get-rewards openapi/private/main_api_v4.yaml POST /api/v4/mining/rewards The endpoint returns rewards received from mining. Results are ordered by reward date, newest first. The response does not include a `total` field. Detect the last page when `data.length < limit`. The `offset` parameter is capped at 10000. To paginate reward histories beyond that, window the request by `from` and `to` (Unix timestamps). The `account` filter is not validated at the request layer. An unknown or not-owned account name is treated as an empty filter and returns HTTP `200` with an empty `data` array — the same response as a valid account with no rewards in the requested window. An account without mining access also returns empty data, so an empty response does not distinguish "no mining access" from "no rewards in range." Rate limit: 1000 requests/10 sec. The API does not cache the response. # List Watcher Links Source: https://docs.whitebit.com/api-reference/mining-pool/list-watcher-links openapi/private/main_api_v4.yaml POST /api/v4/mining/watcher-links/list Returns all active watcher links for a specific mining account. Rate limit: 1000 requests/10 sec. # Miner Info Source: https://docs.whitebit.com/api-reference/mining-pool/miner-info openapi/private/main_api_v4.yaml POST /api/v4/mining/miners/info Returns fee information and stratum connection details with worker counts for a specific mining account. Rate limit: 1000 requests/10 sec. # Mining Pool Source: https://docs.whitebit.com/api-reference/mining-pool/overview Overview of the WhiteBIT Mining Pool endpoints — accounts, pool stats, rewards, hashrate, payout destinations, workers, and watcher links. The Mining Pool endpoints manage pool mining accounts and monitor performance: create and list mining accounts, read pool stats and rewards, track account and worker hashrate, configure payout destinations, inspect miners and workers, and share read-only watcher links. For general API conventions (base URL, authentication, error format, rate limits), see the [API Reference Overview](/api-reference/overview). ## Accounts and pool Create a mining account under the main account. List the mining accounts and each account's configuration. Read aggregate pool statistics. ## Rewards and hashrate Retrieve mining rewards. Read account-level hashrate. Read per-worker hashrate. Inspect miner details. List worker names. ## Payouts and watcher links Read the configured payout destination. Configure the payout destination. Create a read-only watcher link. List existing watcher links. ## What's next * [API Reference Overview](/api-reference/overview) — base URL, authentication, and all endpoint groups # Pool Overview Source: https://docs.whitebit.com/api-reference/mining-pool/pool-overview openapi/public/http-v4.yaml GET /api/v4/public/mining-pool The endpoint returns overall information about the current mining pool state. Hash rate is expressed in H units. Rate limit 1000 requests/10 sec. # Set Payout Destination Source: https://docs.whitebit.com/api-reference/mining-pool/set-payout-destination openapi/private/main_api_v4.yaml POST /api/v4/mining/payout-destination/edit Updates the payout destination for a specific mining account belonging to the authenticated user. Can be set to main balance or an external BTC address. Rate limit: 1000 requests/10 sec. # Worker Hashrate Source: https://docs.whitebit.com/api-reference/mining-pool/worker-hashrate openapi/private/main_api_v4.yaml POST /api/v4/mining/workers/hashrate Returns hashrate performance history for a specific worker on a mining account. Rate limit: 1000 requests/10 sec. # Worker Names Source: https://docs.whitebit.com/api-reference/mining-pool/worker-names openapi/private/main_api_v4.yaml POST /api/v4/mining/workers/names Returns a paginated list of online worker names for a specific mining account. Results are ordered by worker name ascending (alphabetical). The response does not include a `total` field. Detect the last page when `data.workers.length < limit`. Rate limit: 1000 requests/10 sec. # Get Account Transactions Source: https://docs.whitebit.com/api-reference/oauth/usage/account-transactions openapi/oauth2.yaml POST /api/v4/accounts/transactions This endpoint retrieves a paginated list of account transactions. # Delete OAuth API key Source: https://docs.whitebit.com/api-reference/oauth/usage/api-key-delete openapi/oauth2.yaml DELETE /oauth2/api-key/{externalId} The endpoint deletes a partner-issued API key owned by the authenticated OAuth2 client. The deletion triggers an email notification to the user. The endpoint applies to active keys — disabled keys must be removed by the user from the WhiteBIT dashboard. **Required scope:** `apikeys.delete`. **Region availability:** The endpoint is available on the global server (`https://whitebit.com`) only. ## Authentication OAuth 2.0 Bearer token. Required scope: `apikeys.delete`. See [Authentication](/api-reference/authentication). The endpoint is available on `https://whitebit.com` only. ## Cache No caching. ## Notes The endpoint deletes only OAuth-issued API keys owned by the authenticated OAuth2 client. Keys belonging to other OAuth2 clients return `403`. Manually-created API keys are not deletable through this endpoint. Disabled keys (post-inactivity, awaiting user-side deletion) require user-initiated deletion from the WhiteBIT dashboard. Partner-initiated deletion through the endpoint triggers an email to the user. User-initiated dashboard deletion does not send an email. * Obtain the `externalId` path parameter from [Check OAuth API key existence](/api-reference/oauth/usage/api-key-info). * Automatic deletion triggers (14-day inactivity, account password change, account block, account freeze) also send an email to the user. ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Fast API Key integration](/guides/fast-api-key-integration) — OAuth-issued API keys created on behalf of end users. # Check OAuth API key existence Source: https://docs.whitebit.com/api-reference/oauth/usage/api-key-info openapi/oauth2.yaml GET /oauth2/api-key/info The endpoint returns whether a partner-issued API key already exists for the authenticated user and OAuth2 client pair. The endpoint is Bearer-authenticated, so it is reachable only once the partner holds a token for that user: a returning partner calls it before redirecting the user again, while a first-time authorization reaches it only after the authorization code has been exchanged. When a key already exists, skip the redirect and surface the appropriate message to the user. The endpoint reports absence through the payload, never through an error status. A key that was deleted, a key belonging to a different OAuth2 client, and a manually created key are all reported as `exists: false` with an empty `permissions` list. The only failure status is `401`, which covers every problem with the token itself. **Required scope:** `apikeys.read`. **Region availability:** The endpoint is available on the global server (`https://whitebit.com`) only. ## Authentication OAuth 2.0 Bearer token. Required scope: `apikeys.read`. The endpoint cannot be reached before the partner holds a token for the user, so a first-time integration calls it only after the authorization code has been exchanged. See [Authentication](/api-reference/authentication). The endpoint is available on `https://whitebit.com` only. ## Cache No caching. ## Notes Use the decision matrix below to interpret the `(exists, isEnabled)` response and choose the next action. | `exists` | `isEnabled` | Meaning | Recommended action | | - | - | - | - | | `false` | `false` | No partner-issued API key is visible for this `(user, OAuth2 client)` pair — never created, deleted, owned by another client, or created manually. | Start the OAuth API key flow. | | `true` | `true` | An active partner-issued API key already exists. | Skip the OAuth API key flow. Surface "an active API key for this partner already exists" to the user. | | `true` | `false` | A disabled partner-issued API key exists (post-inactivity, awaiting user-side deletion). | Skip the OAuth API key flow. Ask the user to delete the disabled key from the WhiteBIT dashboard, then retry. | * For a returning user whose token is still valid, call the endpoint before redirecting again — an existing key is reused rather than recreated, and a second creation attempt is rejected. See [Returning users](/guides/fast-api-key-integration#returning-users). For a first-time user no token exists yet, so the endpoint is reachable only after the authorization code has been exchanged. * Disabled keys are not deletable through the OAuth2 partner endpoint. Disabled keys are removed by the user from the WhiteBIT dashboard. * See [Retrieve OAuth API key secret](/api-reference/oauth/usage/api-key-secret) for the secret-fetch step and [Delete OAuth API key](/api-reference/oauth/usage/api-key-delete) for partner-initiated revocation. * The `permissions` array lists the permission groups the user granted on the consent screen — see [Key permissions](/guides/fast-api-key-integration#key-permissions) for the full permission model. When the user granted no permissions at all, the key is still created and the array comes back empty; the user deletes that key and re-runs the flow to grant a usable set. ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Fast API Key integration](/guides/fast-api-key-integration) — OAuth-issued API keys created on behalf of end users. # Retrieve OAuth API key secret Source: https://docs.whitebit.com/api-reference/oauth/usage/api-key-secret openapi/oauth2.yaml GET /oauth2/api-key/{externalId}/secret The endpoint retrieves the API secret for a partner-issued API key. The endpoint returns the secret exactly once per key — a subsequent call returns `409 Conflict`. **Required scope:** `apikeys.read`. **Region availability:** The endpoint is available on the global server (`https://whitebit.com`) only. Store the API secret in encrypted backend storage on first retrieval. The secret is not recoverable after this call returns. ## Authentication OAuth 2.0 Bearer token. Required scope: `apikeys.read`. See [Authentication](/api-reference/authentication). The endpoint is available on `https://whitebit.com` only. ## Cache No caching. The response carries `Cache-Control: no-store`. ## Notes Store the API secret in encrypted backend storage on first retrieval. The secret is not recoverable after this call returns. The endpoint returns the secret exactly once per key. A subsequent call for the same key returns `409 Conflict`. Recovery from `409` requires deleting the key via [Delete OAuth API key](/api-reference/oauth/usage/api-key-delete) and restarting the OAuth API key flow to issue a new key — the secret cannot be re-issued for an existing key. A `423 Locked` response indicates a concurrent secret-retrieval attempt against the same key. Retry the request after a short delay. Use exponential backoff starting at 5–10 seconds, doubling per attempt, capped at 60 seconds, with a total budget of 3–5 minutes. The platform does not currently send a `Retry-After` header. * Obtain the `externalId` path parameter from [Check OAuth API key existence](/api-reference/oauth/usage/api-key-info). * The endpoint does not return the public `apiKey` string. The WhiteBIT frontend delivers the public `apiKey` to the partner at consent completion. \[PENDING: confirm with the WhiteBIT frontend team where exactly the partner receives the public `apiKey` (callback parameter name and URL location) — update this note with the wire-level details once confirmed.] ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Fast API Key integration](/guides/fast-api-key-integration) — OAuth-issued API keys created on behalf of end users. # Authorize Source: https://docs.whitebit.com/api-reference/oauth/usage/authorize openapi/oauth2.yaml GET /auth/login The endpoint initiates the OAuth 2.0 authorization flow for user authentication and obtaining an authorization code. **Using the State Parameter (Best Practice)** The `state` parameter is crucial for security in OAuth flows: - Generate a cryptographically secure random string - Store it in the session before redirecting - Validate it matches when handling the callback - This prevents CSRF attacks **Note:** OAuth scopes are predefined during client application setup and cannot be modified during the authorization request. The access token will include all scopes that were approved during client creation. ## Used in these guides * [Fast API Key integration](/guides/fast-api-key-integration) — step 3: build the PKCE authorization URL that sends the end user to the WhiteBIT consent screen. # Get Currency Conversions Source: https://docs.whitebit.com/api-reference/oauth/usage/currency-conversions openapi/oauth2.yaml POST /api/v4/accounts/converts This endpoint retrieves the history of currency conversions. # Get Executed Deals Source: https://docs.whitebit.com/api-reference/oauth/usage/executed-deals openapi/oauth2.yaml POST /api/v4/accounts/deals This endpoint retrieves the history of executed deals. # Get Access Token Source: https://docs.whitebit.com/api-reference/oauth/usage/get-access-token openapi/oauth2.yaml POST /oauth2/token The endpoint activates an access token by exchanging an authorization code. **Important Notes:** - Access token duration is 300 seconds - The IP of the client must be added to WB Allowlist **Request Headers:** - Content-Type: application/x-www-form-urlencoded ## Used in these guides * [Fast API Key integration](/guides/fast-api-key-integration) — step 7: exchange the callback code and `code_verifier` for the per-user token pair. # Get Main Account Balance Source: https://docs.whitebit.com/api-reference/oauth/usage/main-account-balance openapi/oauth2.yaml POST /api/v4/accounts/balances/main This endpoint retrieves the main account balance information. # Get Orders History Source: https://docs.whitebit.com/api-reference/oauth/usage/orders-history openapi/oauth2.yaml POST /api/v4/accounts/orders This endpoint retrieves the history of trading orders. # Overview Source: https://docs.whitebit.com/api-reference/oauth/usage/overview Overview of the WhiteBIT OAuth 2.0 endpoints, including the recommended OAuth API key flow for partner integrations. The OAuth 2.0 endpoints documented in this section cover three integration surfaces: authorization and token exchange, OAuth-issued API keys, and account read endpoints. Partner platforms that need to issue WhiteBIT API keys on behalf of users SHOULD use the OAuth API key flow — the flow replaces manual key creation and copy-paste with a consent-driven bootstrap that issues a partner-scoped key and exposes the secret to the partner exactly once. Any IP restriction on the key is the end user's own account-level control, not a partner-managed allowlist. ## Endpoint groups Recommended partner integration. Issue, retrieve, and delete API keys on behalf of WhiteBIT users. OAuth 2.0 authorization code flow: authorize, exchange code for access token, refresh. Read account transactions, balances, orders, deals, and conversions on behalf of the authenticated user. ## OAuth API key flow The OAuth API key flow uses Authorization Code with PKCE (S256) and issues a short-lived access token together with a refresh token. The partner redirects the user to the WhiteBIT consent screen; on consent and MFA approval, the WhiteBIT platform issues a partner-issued API key for the authenticated `(user, OAuth2 client)` pair. The partner detects key creation through `GET /oauth2/api-key/info`, retrieves the secret exactly once through `GET /oauth2/api-key/{externalId}/secret`, and deletes the key when no longer needed through `DELETE /oauth2/api-key/{externalId}`. See the [Fast API Key integration guide](/guides/fast-api-key-integration) for the full integration walkthrough. ## Required scopes | Scope | Endpoint | Purpose | | - | - | - | | `apikeys.read` | `GET /oauth2/api-key/info` | Check whether a partner-issued API key already exists for this `(user, client)` pair | | `apikeys.read` | `GET /oauth2/api-key/{externalId}/secret` | Retrieve the API secret once | | `apikeys.delete` | `DELETE /oauth2/api-key/{externalId}` | Delete a partner-owned API key | ## Region availability The OAuth API key endpoints (`/oauth2/api-key/*`) are available on the global server (`https://whitebit.com`) only. The EU server (`https://whitebit.eu`) does not expose these endpoints in this release. ## Related resources ## Used in these guides * [Fast API Key integration](/guides/fast-api-key-integration) — OAuth-issued API keys created on behalf of end users. # Refresh Token Source: https://docs.whitebit.com/api-reference/oauth/usage/refresh-token openapi/oauth2.yaml POST /oauth2/refresh_token This endpoint creates a new access token using a refresh token. **Request Headers:** - Content-Type: application/x-www-form-urlencoded **Important Notes:** - Refresh token duration is 600 seconds - Rate limit: 1 request per second - The IP of the client must be added to WB Allowlist ## Used in these guides * [Fast API Key integration](/guides/fast-api-key-integration) — renew the OAuth token used to manage partner-issued API keys. * [App Builders FAQ](/guides/app-builders-faq) — access token lifetime and renewal. # Get Spot Account Balance Source: https://docs.whitebit.com/api-reference/oauth/usage/spot-account-balance openapi/oauth2.yaml POST /api/v4/accounts/balances/spot This endpoint retrieves the spot trading account balance information. # API Reference Source: https://docs.whitebit.com/api-reference/overview WhiteBIT REST API overview — base URL, authentication, quickstart examples, rate limits, and links to all endpoint groups. ## Base URL All REST API endpoints are available at: ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} https://whitebit.com/api/v4/{endpoint} ``` * **Public endpoints** use the `GET` method and accept parameters as query strings. * **Private endpoints** use the `POST` method and accept parameters as JSON in the request body. * All endpoints return time in Unix-time format and respond with JSON. *** ## Quickstart ### Prerequisites * A WhiteBIT account ([Sign up](https://whitebit.com/auth)) * An API key with appropriate permissions ([API Settings](https://whitebit.com/settings/api)) * A programming language or HTTP client (cURL, Python, JavaScript, or similar) ### Step 1: First public API call The [Server Status](/api-reference/market-data/server-status) endpoint returns the API life-state. No authentication is required. **Request:** ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X GET "https://whitebit.com/api/v4/public/ping" ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get("https://whitebit.com/api/v4/public/ping") print(response.json()) ``` ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} const response = await fetch("https://whitebit.com/api/v4/public/ping"); const data = await response.json(); console.log(data); ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} ["pong"] ``` A response of `["pong"]` confirms the API is operational. ### Step 2: Authentication setup Private endpoints require HMAC-SHA512 signed requests. See the [Authentication](/api-reference/authentication) guide for the full signing process. **Required headers for private endpoints:** | Header | Value | | - | - | | `Content-type` | `application/json` | | `X-TXC-APIKEY` | The public API key | | `X-TXC-PAYLOAD` | Base64-encoded request body | | `X-TXC-SIGNATURE` | HMAC-SHA512 signature (hex encoded) | ### Step 3: First authenticated API call The [Main Balance](/api-reference/account-wallet/main-balance) endpoint retrieves the main account balance. The request body must include `request` (the endpoint path) and `nonce` (unique identifier). **Request body:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "request": "/api/v4/main-account/balance", "nonce": 1594297865000 } ``` **Example with cURL** (replace `YOUR_API_KEY` and `YOUR_SIGNATURE` with the signed payload): ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST "https://whitebit.com/api/v4/main-account/balance" \ -H "Content-type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_ENCODED_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{"request":"/api/v4/main-account/balance","nonce":1594297865000}' ``` For a runnable signing implementation in Python, see [First API Call](/guides/first-api-call). **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "BTC": { "main_balance": "0" }, "USDT": { "main_balance": "100.50" } } ``` The response contains balance data for each asset. Omitted assets have a zero balance. *** ## Rate Limits For complete rate limits, error codes, and best practices, see [Rate Limits & Error Codes](/api-reference/rate-limits). ## Error Format All V4 endpoints return errors as JSON. The format differs slightly between public and private APIs: **Public endpoints:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "success": false, "message": "ERROR MESSAGE", "params": [] } ``` **Private endpoints:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 0, "message": "MESSAGE", "errors": { "PARAM1": ["MESSAGE"], "PARAM2": ["MESSAGE"] } } ``` ## HTTP Status Codes For retry strategies, authentication errors, and best practices, see [Rate Limits & Error Codes](/api-reference/rate-limits). *** ## Endpoint Groups Public market info, orderbook, trades, fees, server status, and more. No authentication required. See [Markets & Trading Pairs](/concepts/markets) for pair notation. Spot and collateral (margin/futures) trading: orders, order queries, positions, leverage, hedge mode, and kill-switch timers. Estimate, confirm, and review currency conversion operations. Main balance, deposits, withdrawals, transfers, codes, crypto lending, and fees. See [Balances & Transfers](/concepts/balances) for account types. VASP directory and deposit verification for Travel Rule compliance on crypto transfers. Create and manage sub-accounts, balances, transfers, and API keys. Monitor mining operations, manage payouts, track worker performance, and create watcher links. Screen blockchain addresses for AML risk before crediting deposits or sending withdrawals. Third-party authorization: token exchange, refresh, OAuth API keys, and account endpoints. ## What's next * [Authentication](/api-reference/authentication) — Full signing process and common errors * [Rate Limits & Error Codes](/api-reference/rate-limits) — Per-endpoint limits, error formats, and troubleshooting * [Market Data](/api-reference/market-data/overview) — Public endpoints for orderbook, trades, and market info * [Trading](/api-reference/trading/spot-overview) — Spot and collateral orders, queries, and positions * [WebSocket API](/websocket/overview) — Real-time market data and account streams, plus order management (global platform only) * [SDKs](/sdks) — Official Go, Python, and PHP SDKs ## Used in these guides * [Partner Solutions](/guides/partner-solutions) — the partner router that maps use cases to programs. # REST API rate limits and error codes Source: https://docs.whitebit.com/api-reference/rate-limits Reference for REST API rate limits, error formats, authentication error codes, and best practices. Reference for REST API rate limits, error formats, and error codes. ## REST API rate limits All rate limits are **per IP address**. | Scope | Limit | | - | - | | Default (all endpoints) | 10,000 requests / 10 sec | | `/api/v4/public/*` | 20,000 requests / 10 sec | | `/api/v4/trade-account/*` | 12,000 requests / 10 sec | | `/api/v4/main-account/*` | 1,000 requests / 10 sec | Scope-specific limits override the default where listed. Some endpoints have tighter limits that override the defaults above. These are documented on the respective endpoint pages. When the rate limit is exceeded, the API returns HTTP status `429` (Too Many Requests). Use exponential backoff before retrying (see Best practices below). ## REST API error format All v4 endpoints return errors as JSON. The format differs between public and private APIs. ### Public endpoints ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "success": false, "message": "ERROR MESSAGE", "params": [] } ``` ### Private endpoints ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 0, "message": "MESSAGE", "errors": { "PARAM1": ["MESSAGE"], "PARAM2": ["MESSAGE"] } } ``` ## Authentication error reference The following errors are returned by private REST endpoints when the request signature or credentials are invalid. ## HTTP status codes ## Best practices ### Retry strategy by error type | Error type | Retry? | Strategy | | - | - | - | | Rate limit (429) | Yes | Exponential backoff: start at 1s, double on each retry, cap at 30s. Add jitter. | | Authentication error | No | Fix the root cause: check API key validity, signature computation, and header names. | | Validation error | No | Fix the request parameters. Read the `errors` field for field-level feedback. | | Insufficient balance | No | Check the account balance and wait for pending operations to settle. | | Server error (5xx) | Yes | Exponential backoff. If persistent, check platform status or contact support. | ### Exponential backoff When rate limited, wait before retrying. Double the wait time after each failed attempt (1s → 2s → 4s → 8s). ### Batch requests Combine multiple operations when the API supports batch endpoints. Use [Bulk Limit Order](/api-reference/trading/bulk-limit-order) to place up to 20 orders at once, or [Cancel Bulk Orders](/api-reference/trading/cancel-bulk-order) to cancel up to 100 orders at once, instead of issuing one request per order. ### Nonce management For private endpoints, ensure each request uses a unique, incrementing nonce. Use Unix timestamp in milliseconds when `nonceWindow` is enabled. Avoid concurrent requests with the same nonce. ### Reduce REST polling * **Use WebSocket for real-time data** — Subscribe to price, orderbook, and balance channels instead of polling REST endpoints. One WebSocket connection replaces hundreds of REST requests. See [WebSocket Quickstart](/guides/websocket-quickstart). * **Cache public data** — Market info, asset statuses, and fee structures change infrequently. Cache responses and refresh periodically (for example, every 60 seconds). * **Use conditional requests** — Check local state before making API calls. Avoid redundant balance checks when no trades have executed. * **Distribute requests** — Spread requests evenly across the 10-second window instead of sending bursts. ## Related resources * [API Reference Overview](/api-reference/overview) — Base URL and endpoint groups * [Authentication](/api-reference/authentication) — Signing and header requirements * [WebSocket Rate Limits](/websocket/rate-limits) — WebSocket connection limits, error codes, and timeout behavior ## Used in these guides * [App Builders FAQ](/guides/app-builders-faq) — per-IP rate limits when many end users share one backend. * [Crypto-as-a-Service FAQ](/guides/caas-faq) — common CaaS integration questions. * [Crypto-as-a-Service integration](/guides/caas-integration) — white-label custody and payments for platforms. * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. * [Partner FAQ](/guides/partner-faq) — cross-cutting KYB, sandbox, fees, and rate-limit answers. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. * [Wallet-as-a-Service integration](/guides/waas-integration) — programmatic wallets and payouts for businesses. # Block Sub-Account Source: https://docs.whitebit.com/api-reference/sub-accounts/block-sub-account openapi/private/main_api_v4.yaml POST /api/v4/sub-account/block The endpoint blocks [sub-account](/glossary#sub-account). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Confirm Sub-Account Withdrawal Source: https://docs.whitebit.com/api-reference/sub-accounts/confirm-sub-account-withdrawal openapi/private/main_api_v4.yaml POST /api/v4/sub-account/withdraw/confirm The endpoint confirms a single withdrawal transaction created by a [sub-account](/glossary#sub-account) of the authenticated main account. Confirmation is the main account action that approves a withdrawal held in `unconfirmed_by_main_account` status and releases it for processing. Identify the target transaction by its external id, obtained from [List Unconfirmed Sub-Account Withdrawals](/api-reference/sub-accounts/list-unconfirmed-sub-account-withdrawals). Confirmation is the only main account action on an unconfirmed withdrawal; a withdrawal left unconfirmed expires after a retention period. A successful call returns an empty object. The sub-account withdrawal endpoints are not available by default. To request access, contact institutional@whitebit.com. A `404 Not Found` response indicates the endpoint is not enabled for the account. The sub-account feature must be enabled for the region. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Create Sub-Account Source: https://docs.whitebit.com/api-reference/sub-accounts/create-sub-account openapi/private/main_api_v4.yaml POST /api/v4/sub-account/create The endpoint creates new [sub-account](/glossary#sub-account). The `email` field requirement depends on the `shareKyc` parameter: - When `shareKyc` is `false` or not provided: `email` is **required** - When `shareKyc` is `true`: `email` is **optional** Crypto deposits are disabled by default. Once deposits are enabled for the account, the capability applies to the account and its sub-accounts; enablement is not available via API. To request it, contact your assigned Account Manager or email institutional@whitebit.com. Once enabled, a sub-account generates deposit addresses through the standard [deposit-address endpoint](/api-reference/account-wallet/get-cryptocurrency-deposit-address) using its own API key with deposit permission. Rate limit: 1000 requests/10 sec. The API does not cache the response. The `email` field requirement depends on the `shareKyc` parameter: * When `shareKyc` is `false` or not provided: `email` is **required** * When `shareKyc` is `true`: `email` is **optional** ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Create Sub-Account API Key Source: https://docs.whitebit.com/api-reference/sub-accounts/create-sub-account-api-key openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/create The endpoint creates a new API key for a [sub-account](/glossary#sub-account). Each sub-account supports up to 50 API keys, independent from the main account and from other sub-accounts. A `type: 2` key includes the withdrawal permission group, but its URLs default to `enable: false`. Enable the ones the key uses (for example `/api/v4/main-account/withdraw`) with [Edit Sub-Account API Key](/api-reference/sub-accounts/edit-sub-account-api-key); until then `/api/v4/main-account/withdraw` returns `401` with `{"code":4,"message":"This API Key is not authorized to perform this action."}`. Crypto deposits additionally require deposits to be enabled for the account — disabled by default, contact your assigned Account Manager or email institutional@whitebit.com. Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Create Sub-Account API Key IP Address Source: https://docs.whitebit.com/api-reference/sub-accounts/create-sub-account-api-key-ip-address openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/ip-address/create The endpoint adds a new IP address to the allowed list for a [sub-account](/glossary#sub-account) API key. Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Delete Sub-Account Source: https://docs.whitebit.com/api-reference/sub-accounts/delete-sub-account openapi/private/main_api_v4.yaml POST /api/v4/sub-account/delete The endpoint deletes [sub-account](/glossary#sub-account). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Delete Sub-Account API Key Source: https://docs.whitebit.com/api-reference/sub-accounts/delete-sub-account-api-key openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/delete The endpoint deletes a [sub-account](/glossary#sub-account) API key. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Delete Sub-Account API Key IP Address Source: https://docs.whitebit.com/api-reference/sub-accounts/delete-sub-account-api-key-ip-address openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/ip-address/delete The endpoint removes an IP address from the allowed list for a [sub-account](/glossary#sub-account) API key. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Edit Sub-Account Source: https://docs.whitebit.com/api-reference/sub-accounts/edit-sub-account openapi/private/main_api_v4.yaml POST /api/v4/sub-account/edit The endpoint edits [sub-account](/glossary#sub-account). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Edit Sub-Account API Key Source: https://docs.whitebit.com/api-reference/sub-accounts/edit-sub-account-api-key openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/edit The endpoint updates an existing [sub-account](/glossary#sub-account) API key. Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, per-customer API keys, and permissions. * [Embedded Trading FAQ](/guides/embedded-trading-faq) — enabling the withdraw endpoint on a sub-account key. # Get Sub-Account Transfer History Source: https://docs.whitebit.com/api-reference/sub-accounts/get-sub-account-transfer-history openapi/private/main_api_v4.yaml POST /api/v4/sub-account/transfer/history The endpoint returns history of transfers between main account and [sub-account](/glossary#sub-account). Rate limit: 1000 requests/10 sec. The API does not cache the response. Results are sorted by transaction id descending (newest transfer first). The response is a plain array with no `total`, `has_more`, or cursor — a returned count below `limit` marks the last page (an empty array means no further records). **No date filtering:** the endpoint does not accept `startDate` / `endDate` parameters, and pagination is capped at `offset + limit ≤ 10000` (`limit` ≤ 100). The required `id` parameter already scopes results to a single sub-account; for a complete history export beyond the cap, use the Report on the History page. # Get Sub-Account KYC URL Source: https://docs.whitebit.com/api-reference/sub-accounts/kyc-url openapi/private/main_api_v4.yaml POST /api/v4/sub-account/kyc-url The endpoint generates a temporary KYC verification link for a [sub-account](/glossary#sub-account). The sub-account must meet all of the following conditions before a KYC URL can be generated: - The sub-account must be activated (have an associated user). - The sub-account must be active (not locked or blocked). - The sub-account must not have shared KYC enabled. Rate limit: 1000 requests/10 sec. The API does not cache the response. A KYC URL can only be generated when all of the following conditions are met: * The sub-account is activated (has an associated user). * The sub-account is active (not locked or blocked). * The sub-account does not have shared KYC enabled. When shared KYC is enabled, the sub-account inherits identity verification from the main account, and a separate KYC link is not applicable. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # List of Sub-Accounts Source: https://docs.whitebit.com/api-reference/sub-accounts/list-of-sub-accounts openapi/private/main_api_v4.yaml POST /api/v4/sub-account/list The endpoint returns list of current user [sub-accounts](/glossary#sub-account). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # List Sub-Account API Key IP Addresses Source: https://docs.whitebit.com/api-reference/sub-accounts/list-sub-account-api-key-ip-addresses openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/ip-address/list The endpoint retrieves the list of IP addresses allowed for a [sub-account](/glossary#sub-account) API key. Rate limit: 1000 requests/10 sec. The API does not cache the response. # List Sub-Account API Keys Source: https://docs.whitebit.com/api-reference/sub-accounts/list-sub-account-api-keys openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/list The endpoint retrieves a list of API keys for a [sub-account](/glossary#sub-account). Note: For security reasons, the apiSecret field returns an empty string. Rate limit: 1000 requests/10 sec. The API does not cache the response. Results are sorted by api-key id descending (newest key first). The response is a plain array with no `total`, `has_more`, or cursor — a returned count below `limit` marks the last page (an empty array means no further records). For security reasons, the `apiSecret` field returns an empty string in the response. The API secret is only displayed once during the initial API key creation. # List Unconfirmed Sub-Account Withdrawals Source: https://docs.whitebit.com/api-reference/sub-accounts/list-unconfirmed-sub-account-withdrawals openapi/private/main_api_v4.yaml POST /api/v4/sub-account/withdraw/unconfirmed-list The endpoint returns a paginated list of withdrawal transactions in `unconfirmed_by_main_account` status, created by [sub-accounts](/glossary#sub-account) of the authenticated main account and awaiting main account confirmation. Results are ordered by creation time, newest first. The sub-account withdrawal endpoints are not available by default. To request access, contact institutional@whitebit.com. A `404 Not Found` response indicates the endpoint is not enabled for the account. The sub-account feature must be enabled for the region. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Sub-Accounts Source: https://docs.whitebit.com/api-reference/sub-accounts/overview Overview of sub-account management endpoints for creating, managing, and configuring sub-accounts. Sub-accounts enable creation and management of separate trading accounts under the main account. Control access with dedicated API keys, transfer funds between accounts, and monitor balances. For general API conventions (base URL, error format, rate limits), see the [API Reference Overview](/api-reference/overview). *** ## Who uses this Sub-accounts back the **partner-operated** integration model — see [Integration models](/concepts/integration-models) for the full comparison: * **Model A — partner-operated sub-accounts.** The partner creates and manages one sub-account per end user under the master account and holds the sub-account API key. This is the account-operator and managed-trading-platform pattern, and the endpoints below implement it. See [Embedded Trading sub-account integration](/guides/sub-account-integration). * **Model B — customers' own accounts (contrast).** The end user keeps a standalone WhiteBIT account and the partner connects through a [Fast API Key](/guides/fast-api-key-integration); sub-accounts are not used. Listed here so the choice between the two models is explicit. *** ## Account Management Create a new sub-account Delete a sub-account Edit sub-account details Get list of all sub-accounts Block a sub-account Unblock a sub-account *** ## Balance & Transfers Transfer funds to/from sub-account Get sub-account balances Get sub-account transfer history *** ## Withdrawals List sub-account withdrawals awaiting main account confirmation Approve a pending sub-account withdrawal by transaction id *** ## API Key Management Create API key for sub-account Edit sub-account API key Delete sub-account API key List all sub-account API keys Reset sub-account API key List IP addresses for API key Add IP address to API key whitelist Remove IP address from API key whitelist # Reset Sub-Account API Key Source: https://docs.whitebit.com/api-reference/sub-accounts/reset-sub-account-api-key openapi/private/main_api_v4.yaml POST /api/v4/sub-account/api-key/reset The endpoint resets (regenerates) an existing [sub-account](/glossary#sub-account) API key. Rate limit: 1000 requests/10 sec. The API does not cache the response. # Sub-Account Balances Source: https://docs.whitebit.com/api-reference/sub-accounts/sub-account-balances openapi/private/main_api_v4.yaml POST /api/v4/sub-account/balances The endpoint returns [sub-account](/glossary#sub-account) balances. Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Sub-Account Transfer Source: https://docs.whitebit.com/api-reference/sub-accounts/sub-account-transfer openapi/private/main_api_v4.yaml POST /api/v4/sub-account/transfer The endpoint creates transfer from main account to [sub-account](/glossary#sub-account) or vice versa. Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Unblock Sub-Account Source: https://docs.whitebit.com/api-reference/sub-accounts/unblock-sub-account openapi/private/main_api_v4.yaml POST /api/v4/sub-account/unblock The endpoint unblocks [sub-account](/glossary#sub-account). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Used in these guides * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # ADL quantile Source: https://docs.whitebit.com/api-reference/trading/adl-quantile openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/adl-quantile The endpoint returns the [Auto-Deleveraging (ADL)](/glossary#auto-deleveraging-adl) quantile for each perpetual market in which the authenticated account holds an open position. Each entry exposes the deleveraging-priority value for the long and short sides of the position, where `0` indicates the lowest deleveraging priority and `4` indicates the highest. The endpoint returns an empty array when the account has no perpetual positions. Rate limit: 12000 requests/10 sec. Only perpetual markets (markets with the `_PERP` suffix) are returned. Spot and margin markets are not included. ## Authentication **Signed (HMAC-SHA512).** Provide an API key, payload, and request signature on every call. See [Authentication](/api-reference/authentication). ## Cache No caching. ## Notes The endpoint returns entries for perpetual markets only — markets with the `_PERP` suffix. Spot and margin markets are excluded from the response. The response is `[]` when the account has no open perpetual positions. See [ADL Grade](/concepts/auto-deleveraging#adl-grade) for the meaning of the `0`–`4` quantile values and the underlying selection mechanics. * [ADL quantile (WebSocket)](/websocket/account-streams/adl-quantile) — subscribe for a live push instead of polling this endpoint * [Open positions](/api-reference/trading/open-positions) — List all currently open collateral trading positions * [Auto-Deleveraging concept](/concepts/auto-deleveraging) — Mechanism, rating formula, and grade thresholds * [Close position](/api-reference/trading/close-position) — Close an open perpetual position * [Collateral account summary](/api-reference/trading/collateral-account-summary) — Account-level margin and equity # Borrow history Source: https://docs.whitebit.com/api-reference/trading/borrow-history openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/borrow-history The endpoint returns the [collateral](/glossary#balance-collateral) account's borrow history for the authenticated account — one record per borrow position, not per underlying engine state change. Use the optional `asset` parameter to filter to a single asset; when omitted, the response covers every asset the caller's region allows to borrow. An `asset` that is unknown or blocked in the caller's region returns a validation error rather than an empty result. Records are ordered by creation time descending (newest first). Records created in the same second are ordered by `asset` ascending, then by the trading engine's sub-second creation time descending; `limit` and `offset` page over this order. Rate limit: 12000 requests/10 sec. This endpoint supports pagination via `limit` (default and max: 100) and `offset` (default: 0, max: 10000 — a value above the maximum is rejected outright). `startTime` (default: `0`) and `endTime` (default: now) filter by position time and must satisfy `endTime` > `startTime`. Independently of `offset`, a `startTime`/`endTime` window is rejected rather than scanned slowly or served partially when collecting the matching history would exceed the endpoint's budget of 10000 underlying engine records. One position spans several engine records, so that budget is reached well below 10000 positions — narrow the window instead. **Field semantics:** `amount`, `principal` and `interest` are independently computed peak values, not a running formula — `amount` does not always equal `principal` + `interest`, because funding can keep accruing after a position's balance has already peaked. Treat any apparent `amount = principal + interest` relationship as usually true, never as a guarantee. * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity * [Positions history](/api-reference/trading/positions-history) — View per-event position state changes * [Funding history](/api-reference/trading/funding-history) — Review funding payments on positions # Bulk limit order Source: https://docs.whitebit.com/api-reference/trading/bulk-limit-order openapi/private/http-trade-v4.yaml POST /api/v4/order/bulk The endpoint creates bulk [limit trading orders](/glossary#limit-order). Each order in the batch follows the same validation rules as a single limit order. The `stopOnFail` parameter controls whether processing stops at the first failure or continues through all orders. The response contains a result-or-error pair for each submitted order. **Price and amount steps:** from September 18, 2026, the `price` of each order must be a multiple of the market `tickSize` and its `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Limit: From 1 to 20 orders per request. - RPI orders do not appear in public order book feeds (`depth`, `bookTicker`). RPI orders are visible only in private active orders and in the exchange UI order book (web/mobile). - RPI orders are post-only by design and cannot be used with the IOC flag. The API returns error code `40` when both `rpi=true` and `ioc=true` are used. - RPI orders apply post-only behavior automatically — do not also send `postOnly=true`: a request combining `rpi=true` with an explicit `postOnly=true` fails validation. - `retail=true` marks the order as a retail-source taker eligible to match RPI-maker liquidity. The Retail flag must be enabled on the account; contact the account manager to enable it. - `retail=true` has no effect on a `postOnly=true` or `rpi=true` item. Post-only and RPI orders are makers and cannot be retail takers; an item with both `rpi=true` and `retail=true` matches exactly like an RPI order. * [Create limit order](/api-reference/trading/create-limit-order) — place a single limit order * [Cancel bulk orders](/api-reference/trading/cancel-bulk-order) — sibling bulk endpoint for cancelling up to 100 orders * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Cancel all orders](/api-reference/trading/cancel-all-orders) — cancel all open orders ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Cancel all orders Source: https://docs.whitebit.com/api-reference/trading/cancel-all-orders openapi/private/http-trade-v4.yaml POST /api/v4/order/cancel/all The endpoint cancels all open [orders](/glossary#orders) that match the specified filters. Use the `market` parameter to target a single trading pair, or omit the parameter to cancel across all markets. The `type` parameter filters by order type (`spot`, `margin`, `futures`). When omitted, the endpoint targets all order types. Rate limit: 10000 requests/10 sec. * [Cancel order](/api-reference/trading/cancel-order) — cancel a single order * [Cancel bulk orders](/api-reference/trading/cancel-bulk-order) — cancel up to 100 specific orders at once * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Sync kill-switch timer](/api-reference/trading/sync-kill-switch-timer) — automatic order cancellation after timeout ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Cancel bulk orders Source: https://docs.whitebit.com/api-reference/trading/cancel-bulk-order openapi/private/http-trade-v4.yaml POST /api/v4/order/cancel/bulk The endpoint cancels up to 100 [orders](/glossary#orders) in a single request. Each item identifies a target order by `market` plus exactly one of `orderId` or `clientOrderId`. The response is an array whose items match the input order one-to-one — `response[i]` corresponds to `request.orders[i]`. Rate limit: 10000 requests/10 sec. Limit: From 1 to 100 orders per request. - Provide exactly one of `orderId` or `clientOrderId` per item. Sending both, or neither, returns a per-item validation error. - The endpoint always processes every item independently. There is no `stopOnFail`-style switch. - When the caller is not authenticated, the API returns the standard authorization error and skips per-item validation. **`timestamp` and `mtime` on a successful item:** a canceled item's `result` may echo the order's `timestamp` (creation time) and `mtime` (the last time the matching engine modified the order — the moment of cancellation, since a cancellation is an order's final modification). Both are best-effort echoes: either may be omitted, so do not rely on either field's presence. For a cancel response that always includes `mtime`, use the single [Cancel order](/api-reference/trading/cancel-order) endpoint instead. * [Cancel order](/api-reference/trading/cancel-order) — cancel a single order by ID * [Cancel all orders](/api-reference/trading/cancel-all-orders) — cancel every open order in a market * [Bulk limit order](/api-reference/trading/bulk-limit-order) — sibling bulk endpoint for order creation * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders to cancel # Cancel conditional order Source: https://docs.whitebit.com/api-reference/trading/cancel-conditional-order openapi/private/http-trade-v4.yaml POST /api/v4/order/conditional-cancel The endpoint cancels an active conditional order ([OCO](/glossary#oco-orders) or [OTO](/glossary#one-triggers-the-other-oto)) on the specified market. Both legs of the conditional order are cancelled. Use the [query unexecuted conditional orders](/api-reference/trading/query-unexecuted-conditional-orders) endpoint to obtain the conditional order `id` before cancellation. Rate limit: 10000 requests/10 sec. * [Query unexecuted conditional orders](/api-reference/trading/query-unexecuted-conditional-orders) — List active conditional orders before cancellation * [Query unexecuted OCO orders](/api-reference/trading/query-unexecuted-oco-orders) — List active OCO orders * [Create collateral OCO order](/api-reference/trading/create-collateral-oco-order) — Create a new OCO order * [Open positions](/api-reference/trading/open-positions) — View current open positions # Cancel order Source: https://docs.whitebit.com/api-reference/trading/cancel-order openapi/private/http-trade-v4.yaml POST /api/v4/order/cancel The endpoint cancels an existing [order](/glossary#orders). Provide either `orderId` or `clientOrderId` to identify the target order. The response returns the final state of the cancelled order. Rate limit: 10000 requests/10 sec. - The request accepts exactly one identifier: either `orderId` or `clientOrderId`. - Sending both identifiers, or neither, returns a validation error. - `timestamp` is the order's creation time. `mtime` is the time the matching engine last modified the order, which on a cancellation is the moment the cancellation was processed. * [Cancel bulk orders](/api-reference/trading/cancel-bulk-order) — cancel up to 100 orders at once * [Cancel all orders](/api-reference/trading/cancel-all-orders) — cancel all open orders * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Create limit order](/api-reference/trading/create-limit-order) — place a new limit order ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. # Change collateral account leverage Source: https://docs.whitebit.com/api-reference/trading/change-collateral-account-leverage openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/leverage The endpoint changes the leverage level for the [collateral](/glossary#balance-collateral) trading account. Leverage determines the ratio of borrowed funds to collateral and directly affects margin requirements and liquidation thresholds. Accepted values: `1`, `2`, `3`, `5`, `10`, `20`, `50`, `100`. Each leverage level has a corresponding bracket defining the maximum position size for the tier. When a position exceeds the bracket limit, the system applies higher tiers with progressively lower leverage. Query market-specific brackets via `GET /api/v4/public/futures`. Rate limit: 1000 requests/10 sec. A market's `max_leverage` field (from `GET /api/v4/public/futures`) may be lower than `100`. Setting leverage above a market's maximum results in an error. Coming soon: the maximum accepted `leverage` can be lower than `100` for an account due to trading restrictions. A value above the account's maximum is rejected with `422` and error code `30` on `leverage`. Leverage already set above the new maximum stays in effect until the next change. Changing leverage affects **all open positions** across margin and futures trading. Decreasing leverage increases margin requirements — if available funds are insufficient to support the new level, the request returns an error. * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View current margin and equity details * [Collateral account hedge mode](/api-reference/trading/collateral-account-hedge-mode) — Check current hedge mode status * [Update collateral account hedge mode](/api-reference/trading/update-collateral-account-hedge-mode) — Enable or disable hedge mode * [Open positions](/api-reference/trading/open-positions) — View current open positions # Close position Source: https://docs.whitebit.com/api-reference/trading/close-position openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/position/close The endpoint closes an open [collateral](/glossary#balance-collateral) position at the current market price. The system places a market order in the opposite direction to fully close the specified position. Any attached take-profit or stop-loss orders are cancelled automatically. Rate limit: 10000 requests/10 sec. * [Open positions](/api-reference/trading/open-positions) — List current open positions * [Positions history](/api-reference/trading/positions-history) — View closed position history * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View margin and equity after closing * [Funding history](/api-reference/trading/funding-history) — Review funding payments on positions # Closed-position PNL Source: https://docs.whitebit.com/api-reference/trading/closed-position-pnl openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/positions/closed-pnl The endpoint returns one aggregated profit-and-loss record per closed [collateral](/glossary#balance-collateral) position for the authenticated account — the same closed-position PNL the trading terminal shows. Records are sorted by `closeDate` descending, then `positionId` descending. Use the optional `startDate` and `endDate` parameters to narrow the window; the filter applies to the position close time. The endpoint supports pagination via `limit` (default: 50, max: 100) and `offset` (default: 0); the sum of `offset` and `limit` must not exceed 10000. A response that returns fewer than `limit` records indicates the last page. **Close-time windowing:** a position opened before the requested window but closed inside the window returns complete aggregates — fees, average prices, and closed size cover the full position lifetime, not only the requested window. Rate limit: 12000 requests/10 sec. * [Positions history](/api-reference/trading/positions-history) — View per-event position state changes * [Open positions](/api-reference/trading/open-positions) — List current open positions * [Close position](/api-reference/trading/close-position) — Close an open position * [Funding history](/api-reference/trading/funding-history) — Review funding payments on positions # Collateral account balance Source: https://docs.whitebit.com/api-reference/trading/collateral-account-balance openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/balance The endpoint returns the current [collateral balance](/glossary#balance-collateral) for one or all assets. The response maps each asset ticker to its collateral balance amount. Use the optional `ticker` parameter to filter results to a single asset. The API does not cache the response. Rate limit: 12000 requests/10 sec. * [Collateral account balance summary](/api-reference/trading/collateral-account-balance-summary) — View detailed per-asset balance breakdown * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity * [Change collateral account leverage](/api-reference/trading/change-collateral-account-leverage) — Adjust account leverage # Collateral account balance summary Source: https://docs.whitebit.com/api-reference/trading/collateral-account-balance-summary openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/balance-summary The endpoint returns a detailed [collateral balance](/glossary#balance-collateral) summary with a per-asset breakdown. Each record includes the current balance, borrowed amount, and available balance with and without borrowing capacity. Use the optional `ticker` parameter to filter results to a single asset. The API does not cache the response. Rate limit: 12000 requests/10 sec. * [Collateral account balance](/api-reference/trading/collateral-account-balance) — View per-asset collateral balances * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity * [Open positions](/api-reference/trading/open-positions) — List current open positions * [Change collateral account leverage](/api-reference/trading/change-collateral-account-leverage) — Adjust account leverage # Collateral account hedge mode Source: https://docs.whitebit.com/api-reference/trading/collateral-account-hedge-mode openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/hedge-mode The endpoint returns the current [hedge mode](/glossary#hedge-mode) status for the collateral trading account. When hedge mode is enabled (`true`), the account supports simultaneous long and short positions on the same market. When disabled (`false`), the account operates in one-way mode. Rate limit: 12000 requests/10 sec. * [Update collateral account hedge mode](/api-reference/trading/update-collateral-account-hedge-mode) — Enable or disable hedge mode * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity * [Change collateral account leverage](/api-reference/trading/change-collateral-account-leverage) — Adjust account leverage * [Open positions](/api-reference/trading/open-positions) — List current open positions # Collateral account summary Source: https://docs.whitebit.com/api-reference/trading/collateral-account-summary openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/summary The endpoint returns a collateral account summary including total equity, used margin, free margin, unrealized profit and loss, and the current leverage level. The `marginFraction` field indicates the ratio of used margin to total equity. Rate limit: 12000 requests/10 sec. * [Collateral account balance](/api-reference/trading/collateral-account-balance) — View per-asset collateral balances * [Collateral account balance summary](/api-reference/trading/collateral-account-balance-summary) — View detailed per-asset balance breakdown * [Change collateral account leverage](/api-reference/trading/change-collateral-account-leverage) — Adjust account leverage * [Open positions](/api-reference/trading/open-positions) — List current open positions # Collateral bulk limit order Source: https://docs.whitebit.com/api-reference/trading/collateral-bulk-limit-order openapi/private/http-trade-v4.yaml POST /api/v4/order/collateral/bulk The endpoint creates multiple collateral [limit orders](/glossary#limit-order) in a single request. Each order in the `orders` array is validated and processed individually. The `stopOnFail` parameter controls whether processing stops at the first failure or continues through all orders. The response array contains a result or error object for each submitted order, in the same order as the request. **Price and amount steps:** from September 18, 2026, the `price` of each order and any attached `stopLoss` or `takeProfit` price must be multiples of the market `tickSize`, and its `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Collateral limit order](/api-reference/trading/collateral-limit-order) — Place a single collateral limit order * [Collateral market order](/api-reference/trading/collateral-market-order) — Place a collateral market order * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order * [Open positions](/api-reference/trading/open-positions) — List current open positions # Collateral limit order Source: https://docs.whitebit.com/api-reference/trading/collateral-limit-order openapi/private/http-trade-v4.yaml POST /api/v4/order/collateral/limit The endpoint creates a [limit order](/glossary#limit-order) using [collateral balance](/glossary#balance-collateral). The order executes at the specified price or better. Use `buy` to open or increase a long position and `sell` to open or increase a short position. To close a position, place an opposite-side order matching the position amount. **Order validation rules** (per-market, from `GET /api/v4/public/markets`): - `amount` must have at most `stockPrec` decimal places - `price` must have at most `moneyPrec` decimal places - `amount` must be ≥ `minAmount` - `amount × price` must be ≥ `minTotal` - `amount × price` must be ≤ `maxTotal` (when `maxTotal` is not `"0"`) **Price and amount steps:** from September 18, 2026, `price` and an attached `stopLoss` or `takeProfit` price must be multiples of the market `tickSize`, and `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. For open long position use **buy**, for short **sell**. To close current position, place opposite order with current position amount. - RPI orders are post-only by design and cannot be used with the IOC flag. The API returns error code `40` when both `rpi=true` and `ioc=true` are used. * [Collateral market order](/api-reference/trading/collateral-market-order) — Place a collateral market order * [Collateral stop-limit order](/api-reference/trading/collateral-stop-limit-order) — Place a collateral stop-limit order * [Collateral bulk limit order](/api-reference/trading/collateral-bulk-limit-order) — Place multiple limit orders in a single request * [Create collateral OCO order](/api-reference/trading/create-collateral-oco-order) — Create a combined limit and stop-limit order * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order # Collateral market order Source: https://docs.whitebit.com/api-reference/trading/collateral-market-order openapi/private/http-trade-v4.yaml POST /api/v4/order/collateral/market The endpoint creates a [market order](/glossary#market-order) using [collateral balance](/glossary#balance-collateral). The order executes immediately at the best available market price. Optionally attach `stopLoss` and `takeProfit` prices to create an [OTO](/glossary#one-triggers-the-other-oto) order that activates after the market order fills. **Price and amount steps:** from September 18, 2026, `amount` must be a multiple of the market `stepSize`, and an attached `stopLoss` or `takeProfit` price a multiple of `tickSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Collateral limit order](/api-reference/trading/collateral-limit-order) — Place a collateral limit order at a specified price * [Collateral stop-limit order](/api-reference/trading/collateral-stop-limit-order) — Place a collateral stop-limit order * [Collateral trigger market order](/api-reference/trading/collateral-trigger-market-order) — Place a trigger market order * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order * [Open positions](/api-reference/trading/open-positions) — List current open positions # Collateral Trading Source: https://docs.whitebit.com/api-reference/trading/collateral-overview Overview of collateral (margin) trading endpoints for managing positions, leverage, and collateral orders. Collateral trading enables leveraged trading using margin. Manage the collateral account balance, place various order types (limit, market, stop-limit, OCO), modify and query open orders, and manage positions. For general API conventions (base URL, error format, rate limits), see the [API Reference Overview](/api-reference/overview). *** ## Account & Balance Get collateral account balance Get collateral account balance summary Get complete collateral account summary Change account leverage Get hedge mode status Update hedge mode settings *** ## Order Management Create a collateral limit order Create multiple collateral limit orders Create a collateral market order Create a collateral stop-limit order Create a collateral trigger market order Create OCO (One-Cancels-Other) order Cancel a conditional order Modify an open order on spot or collateral markets Order modification uses the shared `POST /api/v4/order/modify` endpoint. There is no collateral-specific path; the `market` parameter identifies which market the order belongs to. Group legs are the exception. To change an OCO or OTO leg, cancel the group and place a new one. To change a [TPSL pair](/websocket/order-management/collateral-order-tpsl-place), which is placed over WebSocket, cancel the leg and attach a new pair. *** ## Order Queries Conditional and OCO queries are collateral-specific. Executed, canceled, unexecuted, and trade-fill history are served by shared order-query endpoints that cover spot and futures markets alike (documented under Trading → Order Queries). Get active conditional orders Get active OCO orders Open orders on spot and futures markets Executed and canceled order history (spot and futures) Full execution history Individual trade fills for an executed order *** ## Position Management Get all open positions Get deleveraging-priority values per perpetual market Close a specific position Get positions history Get PNL per closed position Get funding history Get borrow position history # Collateral stop-limit order Source: https://docs.whitebit.com/api-reference/trading/collateral-stop-limit-order openapi/private/http-trade-v4.yaml POST /api/v4/order/collateral/stop-limit The endpoint creates a collateral [stop-limit order](/glossary#stop-limit-order) using [collateral balance](/glossary#balance-collateral). The order remains inactive until the market price reaches `activation_price`, then places a limit order at `price`. Optionally attach `stopLoss` and `takeProfit` prices to create an [OTO](/glossary#one-triggers-the-other-oto) order that activates after the stop-limit order fills. **Price and amount steps:** from September 18, 2026, `price`, `activation_price` and an attached `stopLoss` or `takeProfit` price must be multiples of the market `tickSize`, and `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Collateral limit order](/api-reference/trading/collateral-limit-order) — Place a collateral limit order at a specified price * [Collateral trigger market order](/api-reference/trading/collateral-trigger-market-order) — Place a trigger market order * [Create collateral OCO order](/api-reference/trading/create-collateral-oco-order) — Create a combined limit and stop-limit order * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order * [Query unexecuted conditional orders](/api-reference/trading/query-unexecuted-conditional-orders) — List active conditional orders # Collateral trigger market order Source: https://docs.whitebit.com/api-reference/trading/collateral-trigger-market-order openapi/private/http-trade-v4.yaml POST /api/v4/order/collateral/trigger-market The endpoint creates a collateral trigger [market order](/glossary#market-order) using [collateral balance](/glossary#balance-collateral). The order remains inactive until the market price reaches `activation_price`, then executes immediately at the best available market price. Optionally attach `stopLoss` and `takeProfit` prices to create an [OTO](/glossary#one-triggers-the-other-oto) order that activates after the trigger market order fills. **Price and amount steps:** from September 18, 2026, `activation_price` and an attached `stopLoss` or `takeProfit` price must be multiples of the market `tickSize`, and `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Collateral stop-limit order](/api-reference/trading/collateral-stop-limit-order) — Place a collateral stop-limit order * [Collateral market order](/api-reference/trading/collateral-market-order) — Place a collateral market order for immediate execution * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order * [Query unexecuted conditional orders](/api-reference/trading/query-unexecuted-conditional-orders) — List active conditional orders # Create buy stock market order Source: https://docs.whitebit.com/api-reference/trading/create-buy-stock-market-order openapi/private/http-trade-v4.yaml POST /api/v4/order/stock_market The endpoint creates a [stock](/glossary#stock) market trading [order](/glossary#orders). Unlike `POST /api/v4/order/market`, the `amount` parameter always represents the quantity in the base (stock) currency for both buy and sell sides. The matching engine executes the order immediately at the best available price. Minimum and maximum values are market-dependent. Query `GET /api/v4/public/markets` for `minAmount`, `minTotal`, and `maxTotal`. **Amount step:** from September 18, 2026, `amount` must be a multiple of the market `stepSize` on both sides. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Create market order](/api-reference/trading/create-market-order) — place a market order by quote amount * [Query executed orders](/api-reference/trading/query-executed-orders) — view executed order history * [Query executed order deals](/api-reference/trading/query-executed-order-deals) — view individual trade fills # Create collateral OCO order Source: https://docs.whitebit.com/api-reference/trading/create-collateral-oco-order openapi/private/http-trade-v4.yaml POST /api/v4/order/collateral/oco The endpoint creates a collateral [OCO](/glossary#oco-orders) (one-cancels-the-other) order using [collateral balance](/glossary#balance-collateral). An OCO order combines a limit order (take-profit leg) and a stop-limit order (stop-loss leg) into a single conditional group. When one leg executes, the system cancels the other automatically. **Price and amount steps:** from September 18, 2026, `price`, `activation_price` and `stop_limit_price` must be multiples of the market `tickSize`, and `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Query unexecuted OCO orders](/api-reference/trading/query-unexecuted-oco-orders) — List active OCO orders * [Collateral limit order](/api-reference/trading/collateral-limit-order) — Place a single collateral limit order * [Collateral stop-limit order](/api-reference/trading/collateral-stop-limit-order) — Place a collateral stop-limit order * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order # Create limit order Source: https://docs.whitebit.com/api-reference/trading/create-limit-order openapi/private/http-trade-v4.yaml POST /api/v4/order/new The endpoint creates a [limit trading order](/glossary#limit-order). The order remains on the order book until filled, cancelled, or expired. Minimum and maximum values for `amount` and `price` are market-dependent — query `GET /api/v4/public/markets` for per-market constraints. **Order validation rules** (per-market, from `GET /api/v4/public/markets`): - `amount` must have at most `stockPrec` decimal places - `price` must have at most `moneyPrec` decimal places - `amount` must be ≥ `minAmount` - `amount × price` must be ≥ `minTotal` - `amount × price` must be ≤ `maxTotal` (when `maxTotal` is not `"0"`) **Price and amount steps:** from September 18, 2026, `price` must be a multiple of the market `tickSize` and `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. - RPI orders do not appear in public order book feeds (`depth`, `bookTicker`). RPI orders are visible only in private active orders and in the exchange UI order book (web/mobile). - RPI orders are post-only by design and cannot be used with the IOC flag. The API returns error code `40` when both `rpi=true` and `ioc=true` are used. - RPI orders apply post-only behavior automatically — do not also send `postOnly=true`: a request combining `rpi=true` with an explicit `postOnly=true` fails validation. - `retail=true` marks the order as a retail-source taker eligible to match RPI-maker liquidity. The Retail flag must be enabled on the account; contact the account manager to enable it. - `retail=true` has no effect on a `postOnly=true` or `rpi=true` order. Post-only and RPI orders are makers and cannot be retail takers; an order with both `rpi=true` and `retail=true` matches exactly like an RPI order. * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Cancel order](/api-reference/trading/cancel-order) — cancel an open order * [Modify order](/api-reference/trading/modify-order) — modify an existing order * [Bulk limit order](/api-reference/trading/bulk-limit-order) — place multiple limit orders ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. # Create market order Source: https://docs.whitebit.com/api-reference/trading/create-market-order openapi/private/http-trade-v4.yaml POST /api/v4/order/market The endpoint creates a [market trading order](/glossary#market-order). The matching engine executes the order immediately at the best available price. For buy orders, `amount` represents the total in quote (money) currency to spend. For sell orders, `amount` represents the quantity in base (stock) currency to sell. Minimum and maximum values are market-dependent. Query `GET /api/v4/public/markets` for `minAmount`, `minTotal`, and `maxTotal`. **Amount step:** from September 18, 2026, `amount` on a sell order must be a multiple of the market `stepSize`. A buy order carries the quote-currency total in `amount`, so the step does not apply to it. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Create buy stock market order](/api-reference/trading/create-buy-stock-market-order) — place a market order by base asset quantity * [Query executed orders](/api-reference/trading/query-executed-orders) — view executed order history * [Query executed order deals](/api-reference/trading/query-executed-order-deals) — view individual trade fills ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. # Create stop-limit order Source: https://docs.whitebit.com/api-reference/trading/create-stop-limit-order openapi/private/http-trade-v4.yaml POST /api/v4/order/stop_limit The endpoint creates a [stop-limit trading order](/glossary#stop-limit-order). The order remains inactive until the market price reaches the `activation_price`, at which point the system places a limit order at the specified `price`. For buy orders, activation triggers when the market price rises to or above `activation_price`. For sell orders, activation triggers when the market price falls to or below `activation_price`. Minimum and maximum values for `amount`, `price`, and `activation_price` are market-dependent. Query `GET /api/v4/public/markets` for `minAmount`, `minTotal`, `maxTotal`, `stockPrec` (amount precision), and `moneyPrec` (price precision). **Price and amount steps:** from September 18, 2026, `price` and `activation_price` must be multiples of the market `tickSize`, and `amount` a multiple of `stepSize`. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Create stop-market order](/api-reference/trading/create-stop-market-order) — place a stop-market order * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Cancel order](/api-reference/trading/cancel-order) — cancel an open order # Create stop-market order Source: https://docs.whitebit.com/api-reference/trading/create-stop-market-order openapi/private/http-trade-v4.yaml POST /api/v4/order/stop_market The endpoint creates a [stop-market trading order](/glossary#stop-market-order). The order remains inactive until the market price reaches the `activation_price`, at which point the system executes a market order immediately at the best available price. For buy orders, `amount` represents the total in quote currency and activation triggers when the market price rises to or above `activation_price`. For sell orders, `amount` represents the quantity in base currency and activation triggers when the market price falls to or below `activation_price`. Minimum and maximum values are market-dependent. Query `GET /api/v4/public/markets` for `minAmount`, `minTotal`, and `maxTotal`. **Price and amount steps:** from September 18, 2026, `activation_price` must be a multiple of the market `tickSize` on both sides. `amount` on a sell order must be a multiple of `stepSize`; a buy order carries the quote-currency total in `amount`, so the step does not apply to it. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. * [Create stop-limit order](/api-reference/trading/create-stop-limit-order) — place a stop-limit order * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Cancel order](/api-reference/trading/cancel-order) — cancel an open order # Funding history Source: https://docs.whitebit.com/api-reference/trading/funding-history openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/funding-history The endpoint returns the funding rate payment history for [collateral](/glossary#balance-collateral) positions. Each record includes the funding rate, settlement price, position amount, and the resulting funding payment. The `market` parameter is required — the endpoint returns funding for one market per request and has no all-markets mode. The response supports pagination via `limit` and `offset` parameters. Results are ordered by funding time (`fundingTime`), newest first. Rate limit: 12000 requests/10 sec. This endpoint supports pagination. Use `limit` (default: 100) and `offset` (default: 0) to page through results. The response does not include a `total` field — detect the last page when you receive fewer than `limit` records. When nothing matches, the response omits the `records` key entirely rather than returning an empty array, so check that the key is present before reading it. Receiving exactly `limit` records does not guarantee that another page exists. * [Open positions](/api-reference/trading/open-positions) — List current open positions * [Positions history](/api-reference/trading/positions-history) — View closed position history * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity # Modify order Source: https://docs.whitebit.com/api-reference/trading/modify-order openapi/private/http-trade-v4.yaml POST /api/v4/order/modify The endpoint modifies an existing [order](/glossary#orders) on spot, margin, and futures markets. There is no separate collateral path: collateral orders go through this endpoint, and the `market` parameter identifies which market the order belongs to. Supported order types: limit, stop limit, stop market. On collateral markets the supported types are the collateral limit, collateral stop-limit, and collateral trigger-market orders. Request must contain at least one of the following parameters: amount, total, price, activationPrice. **Price and amount steps:** from September 18, 2026, a `price` or `activationPrice` sent in the request must be a multiple of the market `tickSize`, and `amount` a multiple of `stepSize`. A buy stop-market modification sends `total` in quote currency, which the step does not apply to. See [Price and amount steps](/concepts/markets#price-and-amount-steps). Rate limit: 10000 requests/10 sec. - Use total parameter instead of amount for modify buy stop market order. `amount` and `total` are mutually exclusive — a request sending both is rejected. - The request accepts exactly one identifier: either `orderId` or `clientOrderId`. - Sending both identifiers, or neither, returns a validation error. - Group legs cannot be modified. An OCO or OTO leg returns error `155`: cancel the group and place a new one. A TPSL leg returns error `160`: cancel the leg and attach a new pair. **WebSocket impact:** Each call to the endpoint cancels the original order and creates a replacement with a **new `orderId`**. Clients subscribed to the `ordersPending_update` WebSocket channel will receive: - `event_id=3` (cancel) for the old order - `event_id=1` (new) for the replacement Update any `orderId` references after a successful modify response. Use `clientOrderId` for stable order tracking across modifications. * [Create limit order](/api-reference/trading/create-limit-order) — place a new limit order * [Collateral limit order](/api-reference/trading/collateral-limit-order) — place a new collateral limit order * [Cancel order](/api-reference/trading/cancel-order) — cancel an open order * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Open positions Source: https://docs.whitebit.com/api-reference/trading/open-positions openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/positions/open The endpoint returns all open [collateral](/glossary#balance-collateral) positions for the authenticated account. Each position includes entry price, unrealized PnL, margin allocation, liquidation price, and take-profit/stop-loss configuration. Use the optional `market` parameter to filter results to a single trading pair. Rate limit: 12000 requests/10 sec. * [Close position](/api-reference/trading/close-position) — Close an open position * [Positions history](/api-reference/trading/positions-history) — View closed position history * [Funding history](/api-reference/trading/funding-history) — Review funding payments on positions * [ADL quantile](/api-reference/trading/adl-quantile) — Per-market deleveraging-priority value for open perpetual positions * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity # Positions history Source: https://docs.whitebit.com/api-reference/trading/positions-history openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/positions/history The endpoint returns the history of [collateral](/glossary#balance-collateral) position state changes for the authenticated account. Each record represents a position event (open, partial close, full close, or liquidation) and includes the order details that triggered the change. Use the optional `market` and `positionId` parameters to filter results. Rate limit: 12000 requests/10 sec. **Date filter window:** `startDate` and `endDate` are optional and have no defaults. The endpoint enforces no maximum window and no lower-bound floor. The only ordering constraint is `startDate` ≤ `endDate` ≤ `now + 1s` — requests that violate the ordering are rejected with a validation error. **Breaking change — April 29, 2026.** The `positionSide` field is no longer returned in the Position History response. Use `side` (same enum: `LONG`, `SHORT`, `BOTH`) plus `isHedge` (boolean) instead. Integrations reading `positionSide` from `/api/v4/collateral-account/positions/history` must migrate before consuming the new response. * [Open positions](/api-reference/trading/open-positions) — List current open positions * [Close position](/api-reference/trading/close-position) — Close an open position * [Funding history](/api-reference/trading/funding-history) — Review funding payments on positions * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity # Query delisting and maintenance orders Source: https://docs.whitebit.com/api-reference/trading/query-delisting-orders openapi/private/http-trade-v4.yaml POST /api/v4/trade-account/order/history/query The endpoint returns the authenticated account's delisting- and maintenance-related order history across spot, margin, and futures markets, from the order-history index. The response combines three categories of orders: reverse close orders that the platform generates when a market is delisted (`delistingKind` = `reverse`, `clientOrderId` prefixed with `delisting-`), active orders canceled at the moment of delisting (`delistingKind` = `canceled`), and orders canceled when a market entered planned maintenance (response `status` = `maintenance`, `delistingKind` empty). The endpoint returns a flat array sorted by `finishAt` descending, then `id` descending. Set the `status` parameter to narrow the response: `filled` returns only reverse close orders that reached the `filled` outcome, `delisting` returns only orders canceled during delisting, and `maintenance` returns only orders canceled during planned market maintenance. Omit `status` to return all three categories merged in a single array. The endpoint supports pagination via `limit` (default: 500, max: 500) and `offset` (default: 0); the sum of `offset` and `limit` must not exceed 10000. A response that returns fewer than `limit` records indicates the last page. **Date filter window:** the date range filters orders by the `finishAt` timestamp. The maximum span between `startDate` and `endDate` is **31 days**. `endDate` values greater than the current time are clamped to `now`. Rate limit: 10000 requests/10 sec. * [Query executed orders](/api-reference/trading/query-executed-orders) — view executed and canceled order history * [Query executed order history](/api-reference/trading/query-executed-order-history) — view full execution history * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Market info](/api-reference/market-data/market-info) — read `delistedAt` to detect an announced delisting before it runs # Query executed order deals Source: https://docs.whitebit.com/api-reference/trading/query-executed-order-deals openapi/private/http-trade-v4.yaml POST /api/v4/trade-account/order The endpoint retrieves individual trade fills (deals) for a specific order, which may belong to a spot, margin, or futures market. Each deal represents a partial or full execution of the order against a counterparty. The response includes pagination and returns deal details such as price, amount, fee, and execution role (maker or taker). Rate limit: 12000 requests/10 sec. This endpoint supports pagination. Use `limit` (default: 500, max: 500) and `offset` (default: 0, max: 1000) to page through results. The response does not include a `total` field — detect the last page when `records.length < limit`. An empty `records` array means you have paged past the end; receiving exactly `limit` records does not guarantee that another page exists. An unknown or not-owned `orderId` is **not** an error. The endpoint always returns HTTP 200 with the paged-list envelope; a non-matching `orderId` simply filters down to an empty `records` array. The endpoint can retrieve data not older than 6 months from the current month. For older data, use the Report on the History page. An order older than this window returns an empty `records` array even when the order was filled. * [Query executed orders](/api-reference/trading/query-executed-orders) — view executed order history * [Query executed order history](/api-reference/trading/query-executed-order-history) — view full execution history ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. # Query executed order history Source: https://docs.whitebit.com/api-reference/trading/query-executed-order-history openapi/private/http-trade-v4.yaml POST /api/v4/trade-account/executed-history The endpoint retrieves executed order history for all trading types — spot, margin, and futures — across all markets. Can be filtered by a single market if needed. Results are ordered by trade time, newest first. Rate limit: 12000 requests/10 sec. Requests with `limit` values above 100 return large payloads. Use high limits only when necessary and ensure the client application can handle large response sizes. The endpoint can retrieve data not older than 6 months from the current month. For older data, use the Report on the History page. This endpoint supports pagination. Use `limit` (default and max: 500) and `offset` (default: 0) to page through results. The response does not include a `total` field — detect the last page when fewer than `limit` records are returned (sum the records across all markets when no `market` filter is set). An empty response means you have paged past the end; receiving exactly `limit` records does not guarantee that another page exists. For B2B accounts, canceled orders are not recorded in the history. To obtain canceled-order data, contact support or the assigned account manager. * [Query executed orders](/api-reference/trading/query-executed-orders) — view executed order history * [Query executed order deals](/api-reference/trading/query-executed-order-deals) — view individual trade fills ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Embedded Trading sub-account integration](/guides/sub-account-integration) — managed sub-accounts, fee-share, and partner onboarding. # Query executed orders Source: https://docs.whitebit.com/api-reference/trading/query-executed-orders openapi/private/http-trade-v4.yaml POST /api/v4/trade-account/order/history The endpoint retrieves the history of executed and cancelled orders across spot, margin, and futures markets. The response groups orders by market name. Use the `market` parameter to filter by a single trading pair, or omit the parameter to retrieve orders across all markets. The endpoint supports pagination with `limit` (default 50, max 500) and `offset` parameters. Results are ordered by time, newest first. Rate limit: 12000 requests/10 sec. Requests with `limit` values above 100 return large payloads. Use high limits only when necessary and ensure the client application can handle large response sizes. This endpoint supports pagination. Use `limit` (default: 50, max: 500) and `offset` (default: 0) to page through results. The response does not include a `total` field — detect the last page when fewer than `limit` records are returned (sum the records across all markets when no `market` filter is set). An empty response means you have paged past the end; receiving exactly `limit` records does not guarantee that another page exists. **Date filter window:** the maximum span between `startDate` and `endDate` is **31 days**, and the earliest reachable date is **6 months ago (00:00 UTC)**. Requests that exceed the 31-day window or fall below the 6-month floor are rejected with a validation error. `endDate` values greater than the current time are silently clamped to `now`. For B2B accounts, canceled orders are not recorded in the history. To obtain canceled-order data, contact support or the assigned account manager. * [Query executed order deals](/api-reference/trading/query-executed-order-deals) — view individual trade fills * [Query executed order history](/api-reference/trading/query-executed-order-history) — view full execution history * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders # Query market fees Source: https://docs.whitebit.com/api-reference/trading/query-market-fee openapi/private/http-trade-v4.yaml POST /api/v4/market/fee Returns the account's default spot and futures maker and taker fees, plus any custom per-market overrides. The `maker` and `taker` fields represent default spot trading fees. The `futures_maker` and `futures_taker` fields represent default futures trading fees. The `custom_fee` object lists per-market overrides, keyed by market name. The `rpi_maker_fee_premium` and `futures_rpi_maker_fee_premium` fields carry the [Retail Price Improvement (RPI)](/glossary#retail-price-improvement-rpi) premiums applied on top of the maker rates when RPI orders execute. The endpoint returns them for every account, regardless of whether the RPI order mode is enabled. The system calculates the effective futures fee as the lower value between the user-specific custom fee and the market-specific fee. When the market fee is lower than the assigned custom fee, the system returns the market fee. Example: If the custom futures taker fee equals `0.026` and the market fee equals `0.02`, the response returns `0.02`. * [Query market fee for a single market](/api-reference/trading/query-market-fee-single) — the effective maker and taker fee for one market * [Retail Price Improvement (RPI)](/glossary#retail-price-improvement-rpi) — what the maker fee premium applies to # Query market fee for a single market Source: https://docs.whitebit.com/api-reference/trading/query-market-fee-single openapi/private/http-trade-v4.yaml POST /api/v4/market/fee/single Returns the account's effective maker and taker fee for one market. Use this endpoint when only one market matters; `POST /api/v4/market/fee` returns the account's default fees and every custom override at once. The response reports the fee that applies to the requested market — the market's own fee, the account's default trading fee when the default is lower than the market fee, or the custom fee assigned for the market. `rpi_maker_fee_premium` carries the [Retail Price Improvement (RPI)](/glossary#retail-price-improvement-rpi) premium on spot and margin markets, and `futures_rpi_maker_fee_premium` carries it on futures markets, where `rpi_maker_fee_premium` repeats the futures value for backward compatibility and is deprecated — read `futures_rpi_maker_fee_premium` for futures markets. The endpoint returns both fields for every account, regardless of whether the RPI order mode is enabled. * [Query market fees](/api-reference/trading/query-market-fee) — default fees and every custom override in one call * [Retail Price Improvement (RPI)](/glossary#retail-price-improvement-rpi) — what the maker fee premium applies to # Query unexecuted (active) conditional orders Source: https://docs.whitebit.com/api-reference/trading/query-unexecuted-conditional-orders openapi/private/http-trade-v4.yaml POST /api/v4/conditional-orders The endpoint returns active (unexecuted) conditional orders for the authenticated account. Conditional orders include [OCO](/glossary#oco-orders) and [OTO](/glossary#one-triggers-the-other-oto) types. The response uses polymorphic structure — each record contains a `type` field (`oco` or `oto`) that determines the record shape. Use the optional `market` parameter to filter results. Rate limit: 12000 requests/10 sec. * [Query unexecuted OCO orders](/api-reference/trading/query-unexecuted-oco-orders) — List active OCO orders * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order * [Collateral stop-limit order](/api-reference/trading/collateral-stop-limit-order) — Place a collateral stop-limit order * [Create collateral OCO order](/api-reference/trading/create-collateral-oco-order) — Create a combined limit and stop-limit order # Query unexecuted (active) OCO orders Source: https://docs.whitebit.com/api-reference/trading/query-unexecuted-oco-orders openapi/private/http-trade-v4.yaml POST /api/v4/oco-orders The endpoint returns active (unexecuted) [OCO](/glossary#oco-orders) orders for the authenticated account. Each OCO order contains a `stop_loss` and `take_profit` leg. When one leg executes, the system cancels the other automatically. Use the optional `market` parameter to filter results. Rate limit: 12000 requests/10 sec. This endpoint supports pagination. Use `limit` (default: 50) and `offset` (default: 0) to page through results. The response does not include a `total` field — detect the last page when fewer than `limit` OCO orders are returned. An empty array means you have paged past the end; receiving exactly `limit` orders does not guarantee that another page exists. * [Query unexecuted conditional orders](/api-reference/trading/query-unexecuted-conditional-orders) — List active conditional orders * [Create collateral OCO order](/api-reference/trading/create-collateral-oco-order) — Create a new OCO order * [Cancel conditional order](/api-reference/trading/cancel-conditional-order) — Cancel an active conditional order * [Collateral limit order](/api-reference/trading/collateral-limit-order) — Place a collateral limit order # Query unexecuted orders Source: https://docs.whitebit.com/api-reference/trading/query-unexecuted-orders openapi/private/http-trade-v4.yaml POST /api/v4/orders The endpoint retrieves [active orders](/glossary#active-orders) (orders not yet executed) across spot, margin, and futures markets. The response includes limit, stop-limit, and stop-market orders that remain open on the order book. Use the `market` parameter to filter by trading pair, or omit the parameter to retrieve orders across all markets. The endpoint supports pagination with `limit` and `offset` parameters. Rate limit: 12000 requests/10 sec. Search across all markets is available only if clientOrderId and orderId are not provided. This endpoint supports pagination. Use `limit` (default: 50, max: 100) and `offset` (default: 0, max: 4294967295) to page through results. The response does not include a `total` field — detect the last page when fewer than `limit` orders are returned. An empty array means you have paged past the end; receiving exactly `limit` orders does not guarantee that another page exists. * [Cancel order](/api-reference/trading/cancel-order) — cancel an open order * [Cancel all orders](/api-reference/trading/cancel-all-orders) — cancel all open orders * [Query executed orders](/api-reference/trading/query-executed-orders) — view executed order history ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. # Spot Trading Source: https://docs.whitebit.com/api-reference/trading/spot-overview Endpoints for spot trading operations including order management, order queries, market fees, and kill switch. Manage spot trading on WhiteBIT — place and cancel orders, check market fees, and control kill-switch timers. For general API conventions (base URL, error format, rate limits), see the [API Reference Overview](/api-reference/overview). *** ## Market Fee Endpoints for querying market fees: Retrieve default maker and taker rates and custom per-market overrides Retrieve the effective maker and taker fee for one market *** ## Spot Trading Endpoints for spot trading operations: ### Account & Balance Get trade balance by currency ticker or all balances ### Order Management Create a limit trading order Create multiple limit orders (1-20 orders) Create a market trading order Create buy stock market trading order Create a stop-limit trading order Create a stop-market trading order Modify an existing order Cancel a specific order Cancel up to 100 orders in a single request Cancel all orders in a market ### Order Queries Get active/unexecuted orders Get executed order history Get executed order deals Get all executed orders Get delisting and maintenance order history ### Kill Switch Synchronize kill-switch timer Get kill-switch timer status ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Status kill-switch timer Source: https://docs.whitebit.com/api-reference/trading/status-kill-switch-timer openapi/private/http-trade-v4.yaml POST /api/v4/order/kill-switch/status The endpoint retrieves the status of active [kill-switch timers](/glossary#kill-switch-timer). The response returns an array of timer objects for the specified market, or for all markets if the `market` parameter is omitted. Each timer object includes the start time, scheduled cancellation time, and targeted order types. Rate limit: 10000 requests/10 sec. * [Sync kill-switch timer](/api-reference/trading/sync-kill-switch-timer) — set or reset the kill-switch timer ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Sync kill-switch timer Source: https://docs.whitebit.com/api-reference/trading/sync-kill-switch-timer openapi/private/http-trade-v4.yaml POST /api/v4/order/kill-switch The endpoint creates, updates, or deletes a [kill-switch timer](/glossary#kill-switch-timer). The kill-switch acts as a safety mechanism for automated trading systems — the timer automatically cancels all open orders for the specified market if the client fails to reset the timer before expiration. Set `timeout` to a value between `5` and `600` (seconds) to create or update a timer. Set `timeout` to `null` to delete an existing timer. Rate limit: 10000 requests/10 sec. - If timeout=null - delete existing timer by market. - If types=null - create timer by market for all order types. * [Status kill-switch timer](/api-reference/trading/status-kill-switch-timer) — check the current kill-switch timer status * [Cancel all orders](/api-reference/trading/cancel-all-orders) — cancel all open orders immediately ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Trading balance Source: https://docs.whitebit.com/api-reference/trading/trading-balance openapi/private/http-trade-v4.yaml POST /api/v4/trade-account/balance The endpoint retrieves the [trade balance](/glossary#balance-spotbalance-trade) by currency [ticker](/glossary#ticker) or all balances. When the `ticker` parameter is provided, the response contains a single currency entry. When omitted, the response contains all currencies with non-zero balances. Each entry includes the `available` balance (funds ready to trade) and the `freeze` balance (funds locked in open orders). Rate limit: 12000 requests/10 sec. * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) — list open orders * [Query executed orders](/api-reference/trading/query-executed-orders) — view executed order history # Update collateral account hedge mode Source: https://docs.whitebit.com/api-reference/trading/update-collateral-account-hedge-mode openapi/private/http-trade-v4.yaml POST /api/v4/collateral-account/hedge-mode/update The endpoint enables or disables [hedge mode](/glossary#hedge-mode) for the collateral trading account. When hedge mode is enabled (`true`), the account supports simultaneous long and short positions on the same market. When disabled (`false`), the account operates in one-way mode. Rate limit: 1000 requests/10 sec. Switching between one-way mode and hedge mode requires **no open positions**. Close all futures positions before toggling the mode. If the switch does not take effect immediately after closing positions, wait approximately 15 seconds and retry. * [Collateral account hedge mode](/api-reference/trading/collateral-account-hedge-mode) — Check current hedge mode status * [Collateral account summary](/api-reference/trading/collateral-account-summary) — View account-level margin and equity * [Change collateral account leverage](/api-reference/trading/change-collateral-account-leverage) — Adjust account leverage * [Open positions](/api-reference/trading/open-positions) — List current open positions # Get available VASPs Source: https://docs.whitebit.com/api-reference/travel-rule/get-vasps openapi/private/main_api_v4.yaml POST /api/v4/travel-rule/vasps Retrieves the list of Virtual Asset Service Providers (VASPs) that can be used when submitting travel rule data for deposits and withdrawals. Use the returned `vaspId` when submitting travel rule data if the destination/originating VASP is in this list. If the VASP is not in the list, use `vaspName` as a fallback. This endpoint returns the region error shown in the 422 response and the [common authentication errors](/api-reference/authentication). Rate limit: 1000 requests/10 sec. ## Overview This endpoint retrieves the list of VASPs that can be used when submitting travel rule data for deposits and withdrawals. For detailed Travel Rule requirements, see [Travel Rule](/concepts/travel-rule). **When to use `vaspId` vs `vaspName`:** * If the destination/originating VASP appears in this list, use its `vaspId` for accurate identification * If the VASP is not in the list, use `vaspName` as a fallback with the VASP's name as a string *** ## Usage Notes The list may vary depending on the account's region. *** ## VASP Selection Flow ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Client participant WhiteBIT API Client->>WhiteBIT API: POST /api/v4/travel-rule/vasps WhiteBIT API-->>Client: List of available VASPs Note over Client: Search for target VASP in list alt VASP found in list Note over Client: Use vaspId from response Client->>WhiteBIT API: Submit with { vaspId: "vasp-001" } else VASP not in list Note over Client: Use vaspName as fallback Client->>WhiteBIT API: Submit with { vaspName: "Famous Vasp Name" } end ``` *** ## Related * [Submit deposit verification](/api-reference/travel-rule/submit-deposit-verification) — Use VASPs when submitting deposit originator data * [Create withdraw request](/api-reference/account-wallet/create-withdraw-request) — Use VASPs when creating withdrawals with travel rule data * [Travel Rule](/concepts/travel-rule) — Detailed requirements and workflows ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [Payment Integration](/guides/payment-integration) — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. # Travel Rule Source: https://docs.whitebit.com/api-reference/travel-rule/overview API endpoints for Travel Rule compliance for cryptocurrency deposits and withdrawals. Travel Rule API endpoints enable B2B clients to submit originator and beneficiary data for cryptocurrency transactions as required by FATF and MiCA regulations. For detailed information about Travel Rule requirements, formats, and workflows, see the [Travel Rule concept page](/concepts/travel-rule). *** ## Endpoints Retrieve the list of VASPs for travel rule submissions. Submit originator data for a deposit pending verification. *** ## Related * [Create withdraw request](/api-reference/account-wallet/create-withdraw-request) — Create withdrawals with travel rule data * [Get deposit/withdraw history](/api-reference/account-wallet/get-deposit-withdraw-history) — Monitor transaction status * [Travel Rule concept](/concepts/travel-rule) — Detailed requirements, formats, and workflows *** ## Common errors **API disabled for region:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 0, "message": "Something went wrong", "errors": { "error": ["This endpoint is disabled for your region"] } } ``` The Travel Rule API is not available to all accounts. To request access, contact the assigned Account Manager or email [institutional@whitebit.com](mailto:institutional@whitebit.com). # Submit deposit verification Source: https://docs.whitebit.com/api-reference/travel-rule/submit-deposit-verification openapi/private/main_api_v4.yaml POST /api/v4/travel-rule/deposit/verification Submits originator information for a deposit that is ready for the travel rule verification. **Wallet types:** - `hosted` - VASP-hosted wallet (exchange, custodian). Requires `vaspData` object. - `unhosted` - Self-custody wallet (hardware wallet, software wallet). No VASP required. **Party types:** - `individual` - Natural person. Requires `firstName` and `lastName`. - `entity` - Legal entity. Requires `fullName`. This endpoint returns the region error shown in the 422 response and the [common authentication errors](/api-reference/authentication). Rate limit: 1000 requests/10 sec. The API does not cache the response. ## Overview When a deposit is detected as Travel Rule-eligible, it enters a "ready for verification" state. Use this endpoint to submit the required originator data. For detailed information about wallet types, party types, and field requirements, see [Travel Rule](/concepts/travel-rule). *** ## Required fields by scenario | Scenario | `walletType` | `originator.type` | VASP | Name fields | | - | - | - | - | - | | Individual from exchange | `hosted` | `individual` | `vaspId` or `vaspName` | `firstName`, `lastName` | | Entity from exchange | `hosted` | `entity` | `vaspId` or `vaspName` | `fullName` | | Individual from self-custody | `unhosted` | `individual` | Not required | `firstName`, `lastName` | | Entity from self-custody | `unhosted` | `entity` | Not required | `fullName` | Get the list of available VASPs via the [Get VASPs endpoint](/api-reference/travel-rule/get-vasps). Use `vaspId` if the originating VASP is in the list, otherwise use `vaspName`. *** ## Verification status After successful submission, the response contains a `status` field: | Status | Description | | - | - | | `submitted` | Data submitted, awaiting compliance review | | `approved` | Immediately approved (rare) | Monitor deposit status via [deposit/withdraw history](/api-reference/account-wallet/get-deposit-withdraw-history). *** ## Common errors **Transaction Not Found**: Ensure the `uniqueId` matches a transaction in the deposit history. The transaction must exist and belong to the authenticated account. **Missing VASP for hosted wallet:** When `walletType` is `"hosted"`, provide either `vaspId` or `vaspName`. *** ## Related * [Get available VASPs](/api-reference/travel-rule/get-vasps) — Fetch VASPs list before submission * [Travel Rule](/concepts/travel-rule) — Detailed requirements and workflows ## Used in these guides * [On/Off-Ramp integration](/guides/on-off-ramp-integration) — corporate fiat ↔ crypto over EUR/SEPA rails. * [On/Off-Ramp FAQ](/guides/on-off-ramp-faq) — originator-data submission for Travel Rule holds on inbound deposits. # Go-Live Checklist Source: https://docs.whitebit.com/best-practices/go-live-checklist Pre-production readiness checklist for WhiteBIT API integrations — authentication, error handling, rate limits, compliance, WebSocket, webhooks, monitoring, and testing. Complete every item in the checklist below before deploying a WhiteBIT API integration to production. Each category covers a critical integration area with specific verification items. WhiteBIT does not offer a public testnet or sandbox environment. For risk-free Spot trading practice, use Demo Tokens (DBTC/DUSDT) — see step 1 below. For all other flows, test on the live API with minimum order amounts. Use [`GET /api/v4/public/markets`](/api-reference/market-data/market-info) to find pairs with the lowest minimum order sizes. ## Authentication * [ ] API key created with the minimum required permission level. * [ ] API secret stored in environment variables or a secrets manager — not in source code. * [ ] HMAC-SHA512 signing implemented and verified against a known-good response. * [ ] IP whitelist configured with production server IPs (up to 50 per key). * [ ] 2FA enabled on the WhiteBIT account. * [ ] Nonce implementation generates strictly increasing values (Unix timestamp in milliseconds recommended). See [Authentication](/api-reference/authentication) and [Security Best Practices](/best-practices/security) for implementation details. ## Error handling * [ ] HTTP status codes handled: `200` (success), `400` (validation), `401` (auth), `403` (forbidden), `422` (unprocessable), `429` (rate limit), `500`/`503` (server error). * [ ] Rate limit responses (`429`) handled with exponential backoff and retry. * [ ] Authentication errors (`401`) do NOT trigger automatic retry — investigate the cause. * [ ] Validation errors (`400`, `422`) logged with the full response body for debugging. * [ ] Server errors (`500`, `503`) handled with retry and exponential backoff. * [ ] Error response JSON parsed for `code`, `message`, and `errors` fields. See [Errors and Error Handling](/api-reference/rate-limits) for the complete error code reference. ## Rate limits * [ ] Per-endpoint rate limits documented and enforced in the application. * [ ] Request queuing implemented to stay within rate limits. * [ ] Bulk endpoints used where available (e.g., [`/order/bulk`](/api-reference/trading/bulk-limit-order) for up to 20 orders per call). * [ ] WebSocket used for real-time data instead of REST polling where possible. * [ ] Public endpoint caching implemented for data that changes infrequently (market list, asset status). See [Rate Limits](/api-reference/rate-limits) for per-endpoint values. ## Regional compliance (EEA) * [ ] Travel Rule: `travelRule` object included in all EEA crypto withdrawal requests. * [ ] MiCA: USDT deposit/withdrawal/code operations NOT attempted for EEA accounts (blocked since December 30, 2024). * [ ] USDT alternatives: USDC and EURI used for EEA users instead of USDT. * [ ] Asset Status endpoint ([`GET /api/v4/public/assets`](/api-reference/market-data/asset-status-list)) checked dynamically for currency availability. * [ ] Travel Rule deposit freezes (status 27, 28) handled in the deposit reconciliation flow. See [Regulatory Compliance](/institutional/compliance) and [Payment Integration](/guides/payment-integration) for the full compliance reference. ## WebSocket * [ ] Automatic reconnection implemented with exponential backoff. * [ ] Channel re-subscription occurs after every reconnection. * [ ] Ping/pong heartbeat mechanism implemented to detect stale connections. * [ ] WebSocket authentication token refreshed before expiry (if using private channels). * [ ] Message ordering verified — check sequence numbers where available. See the [WebSocket Quickstart](/guides/websocket-quickstart) for connection setup. ## Webhooks * [ ] Webhook URL configured (see [Webhooks](/platform/webhook)). * [ ] Domain verification completed (DNS TXT, file, or endpoint method). * [ ] HMAC-SHA512 signature verification implemented on every incoming webhook. * [ ] Webhook nonce tracked — each nonce is strictly greater than the previous. * [ ] Idempotency implemented using `uniqueId` to prevent double-processing. * [ ] Fallback polling implemented for reconciliation. Webhook delivery is best-effort — a small number of retries spaced roughly hourly over a \~1-day window — so polling must close the gap for extended consumer outages. * [ ] Server responds with HTTP `200` for successfully processed webhooks. See [Webhooks](/platform/webhook) and [Security Best Practices](/best-practices/security) for verification implementation. ## Monitoring * [ ] Balance monitoring active — alerts on unexpected balance changes. * [ ] Order status monitoring — track open orders and detect stuck states. * [ ] Kill-switch configured for trading applications — one timer per traded market; cancels that market's open orders after a timeout if the system becomes unresponsive. * [ ] API response time monitoring — detect latency degradation. * [ ] Error rate monitoring — alert on elevated error rates (especially `429` and `500`). ## Testing WhiteBIT does not offer a public testnet. The following approach validates an integration on the live API with minimal risk. 1. **Start with Demo Tokens (risk-free):** Activate free Demo Tokens (0.5 DBTC + 1,000 DUSDT) via the [WhiteBIT Codes page](https://whitebit.com/codes) — no KYC required. Trade the `DBTC_DUSDT` spot pair via [`POST /api/v4/order/new`](/api-reference/trading/create-limit-order) to validate the full order lifecycle (place, query, cancel, fill) without risking real funds. Demo tokens support Spot trading only — Margin and Futures testing requires real assets at minimum sizes. 2. **Start with public endpoints:** Verify connectivity and parsing by calling read-only public endpoints ([`GET /api/v4/public/time`](/api-reference/market-data/server-time), [`GET /api/v4/public/markets`](/api-reference/market-data/market-info)). No authentication required. 3. **Verify authentication:** Make an authenticated call to [`POST /api/v4/trade-account/balance`](/api-reference/trading/trading-balance). If the response is `401`, debug the HMAC signing implementation before proceeding. 4. **Use minimum order sizes:** Query `GET /api/v4/public/markets` to find pairs with the lowest `minAmount`. Place test orders at minimum sizes to verify the full order lifecycle. 5. **Verify error handling:** Send intentionally malformed requests (invalid ticker, zero amount, duplicate nonce) and verify the application handles error responses correctly. 6. **Test webhook delivery:** Trigger a real (small) deposit or withdrawal and verify the webhook is received, the signature validates, and the application processes the event correctly. 7. **Confirm Travel Rule compliance:** For EEA accounts, submit a test crypto withdrawal with the `travelRule` object and verify acceptance before processing customer funds. 8. **Verify reconciliation:** Confirm that the polling fallback detects events missed by webhooks. Temporarily disable webhook processing and verify that polling catches up. # Security Best Practices Source: https://docs.whitebit.com/best-practices/security API key management, IP whitelisting, secret storage, key rotation, and webhook verification for WhiteBIT API integrations. Secure API integration requires careful management of credentials, network access, and verification mechanisms. The following practices apply to all WhiteBIT API integrations regardless of the use case. ## API key management Create separate API keys for each application, service, or environment. * **One key per application:** Do not share a single API key across multiple applications or services. If one application is compromised, revoke the compromised key without affecting other applications. * **Minimal permissions:** Assign the minimum permission set required: * `Info + Trading` — for applications that only read data and place trades * `Info + Trading + Deposit + Withdraw` — only for applications that need to move funds * **No client-side keys:** Never embed API secrets in client-side code (browser JavaScript, mobile apps). API secrets must remain server-side only. * **Environment isolation:** Use separate API keys for each application or service (e.g., one for the trading bot, one for the monitoring dashboard, one for the withdrawal service). Never expose API secrets in client-side code, version control, or log files. Store secrets in environment variables or a dedicated secrets manager. ## IP whitelisting Restrict API key usage to known IP addresses using the IP whitelist. * Each API key supports up to **50 IP addresses** in the whitelist * Configure the whitelist in the API key settings at [whitebit.com/settings/api](https://whitebit.com/settings/api) * **Production recommendation:** Always enable IP whitelisting for production API keys * If the application runs on dynamic infrastructure (e.g., autoscaling), whitelist the NAT gateway or load balancer IP range * IP whitelisting is the primary defense against stolen API credentials ## Secret storage Store API secrets using environment variables or a dedicated secrets management service. * **Environment variables:** Store the API secret in an environment variable (e.g., `WHITEBIT_API_SECRET`); load at runtime * **Secrets managers:** For production deployments, use a dedicated secrets manager (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, Azure Key Vault) * **Never commit secrets:** Add API key files and `.env` files to `.gitignore` * **No hardcoded secrets:** Secrets must not appear in source code, configuration files committed to version control, Docker images, or CI/CD logs ## Key rotation Rotate API keys regularly and monitor for inactive key auto-deactivation. * **Auto-deactivation:** API keys that remain unused for **14 consecutive days** are automatically deactivated. An IP whitelist does not exempt a key from this rule * **Reserve keys:** Send one authenticated request from each standby key every 14 days to keep it active — any authenticated endpoint resets the timer * **Rotation strategy:** 1. Create a new API key with the same permissions and IP whitelist 2. Update the application configuration to use the new key 3. Verify the application works with the new key 4. Deactivate (delete) the old key * **Zero-downtime rotation:** If the application supports multiple keys, configure the new key alongside the old key before deactivating the old one * Monitor key activity to detect unauthorized usage patterns ## Two-factor authentication Two-factor authentication (2FA) is required for API key creation and management. * 2FA must be enabled on the WhiteBIT account before creating API keys * 2FA protects against unauthorized key creation even if account credentials are compromised * Recommendation: use a hardware security key or authenticator app (not SMS) ## Webhook HMAC verification Verify the HMAC-SHA512 signature on every incoming webhook to confirm the request originated from WhiteBIT. WhiteBIT signs all webhook payloads using HMAC-SHA512. **Verification headers:** | Header | Content | | - | - | | `X-TXC-APIKEY` | WhiteBIT webhook API key | | `X-TXC-PAYLOAD` | Base64-encoded body data | | `X-TXC-SIGNATURE` | `hex(HMAC_SHA512(payload, key=api_secret))` | **Verification algorithm:** 1. Read the raw request body 2. Base64-encode the body — compare with the `X-TXC-PAYLOAD` header 3. Compute `HMAC_SHA512(base64_encoded_body, api_secret)`, where `api_secret` is the secret of the webhook key 4. Convert to hex string — compare with the `X-TXC-SIGNATURE` header 5. If the signature does not match, reject the request (return non-200 status) ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import hashlib import hmac import base64 from flask import Flask, request, jsonify app = Flask(__name__) WEBHOOK_SECRET = "YOUR_WEBHOOK_SECRET" @app.route("/webhook", methods=["POST"]) def handle_webhook(): raw_body = request.get_data() # Base64-encode the raw body encoded_payload = base64.b64encode(raw_body).decode() # Verify the payload header matches expected_payload = request.headers.get("X-TXC-PAYLOAD", "") if encoded_payload != expected_payload: return jsonify({"error": "Payload mismatch"}), 400 # Compute the HMAC-SHA512 signature computed_signature = hmac.new( WEBHOOK_SECRET.encode(), encoded_payload.encode(), hashlib.sha512, ).hexdigest() # Compare with the signature header received_signature = request.headers.get("X-TXC-SIGNATURE", "") if not hmac.compare_digest(computed_signature, received_signature): return jsonify({"error": "Invalid signature"}), 401 # Process the verified webhook data = request.get_json() print(f"Verified webhook: {data.get('method')} — ID: {data.get('id')}") return jsonify({"status": "ok"}), 200 ``` See [Webhooks](/platform/webhook) for the full webhook setup and event types. ## Environment isolation Separate API credentials by application function to limit the blast radius of any single compromise. WhiteBIT does not offer a public testnet or sandbox environment. All API calls execute against the live exchange. Use separate API keys per application and test with minimum order amounts. Create distinct API keys for distinct concerns: | Application | Permissions | Rationale | | - | - | - | | Trading application | `Info + Trading` | Cannot move funds off the exchange | | Fund management | `Info + Trading + Deposit + Withdraw` | Full access required for deposits/withdrawals | | Monitoring / analytics | `Info + Trading` | Read-only usage with no trade execution | Each key has a dedicated IP whitelist — configure the whitelist to match the application's infrastructure. Revoking one key does not affect other applications. # WhiteBIT API Changelog Source: https://docs.whitebit.com/changelog Track updates, improvements, and fixes to the WhiteBIT API platform including new endpoints and changes. ## TP/SL legs can be modified over WebSocket **`order_modify` accepts TP/SL legs; `collateral_order_tpsl_place` documented as additive** Legs created by `collateral_order_tpsl_place` can be changed with `order_modify` — send the leg's `order_id` or `client_order_id` with a new `activation_price`. Earlier documentation said `order_modify` returned error `160` for a TPSL leg; that statement was incorrect and is removed. Each `collateral_order_tpsl_place` call creates a new pair of TP/SL orders. It does not replace or cancel TP/SL orders already on the position, including those created through the REST API (`takeProfit` / `stopLoss`) or by OTO orders. To change levels, modify the existing orders with `order_modify`, or cancel those orders with `order_cancel` and place new ones. When a TP/SL order triggers and closes the position, the remaining TP/SL orders for that position are cancelled automatically. ## Trading on deposits awaiting confirmation **Deposits become tradable at the first confirmations, and the part still awaiting the network is reported separately** A crypto deposit can now be credited before the network fully confirms it, so the funds are tradable earlier. Until confirmation completes, that part of the balance is held back: it can be moved to the [trade balance](/glossary#balance-spotbalance-trade) and traded, but it cannot be withdrawn, sent as a WhiteBIT Code, or moved to the [collateral balance](/glossary#balance-collateral). [Main balance](/api-reference/account-wallet/main-balance) gains a `pending_deposit_amount` field per currency — the part of `main_balance` that is still held back. It is `0` when nothing is held. A new endpoint, [Withdrawable balance](/api-reference/account-wallet/withdrawable-balance), reports the same picture for the whole account: the total, the held value, and what remains withdrawable, in a stable-coin equivalent, plus a per-currency breakdown of the free amount. Requests that would move held funds off the platform are rejected with code `20` on the `amount` field: [Withdraw](/api-reference/account-wallet/create-withdraw-request), [Withdraw Pay](/api-reference/account-wallet/create-withdraw-request-with-specific-amount), [Express Withdraw](/api-reference/account-wallet/create-express-withdraw-token), and [WhiteBIT Code creation](/api-reference/account-wallet/create-code). [Transfer](/api-reference/account-wallet/transfer-between-balances) to the collateral balance is rejected the same way; transfers to the trade balance are never restricted. Two limits apply at once — the free amount of the currency itself and the free value of the whole account. Whichever is smaller decides, so holding a large balance in other currencies does not make a held currency withdrawable. ## Refund history and memo for deposit refunds **New `POST /api/v4/main-account/refund-history` endpoint and `memo` support for refunds** The Main Account API now returns the account's deposit refunds with the current status of each: `in_process`, `successful`, or `canceled`. The list includes refunds requested through the WhiteBIT interface and through the API. Filter by `depositId` or `ticker`, and page through results with `limit` and `offset`. Only full refunds are listed. `POST /api/v4/main-account/refund-deposit` accepts an optional `memo` for the destination address. The `refund.successful` and `refund.failed` webhooks now include `memo`, which is `null` when no memo was sent. ## RPI and retail flags on the same limit order **`POST /api/v4/order/new` and `POST /api/v4/order/bulk` accept `rpi=true` together with `retail=true`** A limit order may now set both `rpi=true` and `retail=true`; the API no longer rejects the combination with error code `41`, and code `41` is retired. The order rests as an RPI maker and matches exactly like an order with only `rpi=true` — the Retail flag has no effect on it, as on any post-only order. The account still needs both flags enabled: error codes `42` and `43` apply unchanged. ## Account-level maximum leverage on Collateral Trading **`POST /api/v4/collateral-account/leverage` can accept a lower maximum per account** Coming soon: the account-level maximum is not yet enforced by the endpoint. The accepted `leverage` values stay `1`, `2`, `3`, `5`, `10`, `20`, `50` and `100`, but trading restrictions on an account can set a lower maximum. A request above the account's maximum returns HTTP 422 with error code `30` and the message under `errors.leverage`. Leverage already set above the new maximum stays in effect until the next change, so read the current value before assuming a request will be accepted. ## ADL quantile and premium index over WebSocket **Two new push streams for data previously available only by polling** The WebSocket API adds two channels that were already implemented but undocumented: `ADLQuantile_subscribe` (private) pushes the account's ADL deleveraging-priority rank for open futures positions — immediately on subscribe, then every 30 seconds — as an alternative to polling the ADL quantile REST endpoint. `premiumIndex_subscribe` (public) pushes mark price, index price, and funding rate for futures markets every 0.5 seconds, mirroring the data on the futures markets list endpoint. ## Borrow history on Collateral Trading **New `POST /api/v4/collateral-account/borrow-history` endpoint** The Collateral Trading API now returns the borrow history for a collateral account — one record per borrow position, not per underlying engine state change. Each record carries `amount`, `principal`, and `interest` (independently computed peak values — `amount` is not always `principal` + `interest`), plus `status` (`active`, `repaid`, or `liquidated`) and `timestamp`. Filter to one asset with the optional `asset` parameter, and page through results with `startTime`/`endTime`, `limit`, and `offset`. ## Which order fields carry a step, and what a rejection looks like **Per-endpoint `tickSize` and `stepSize` rules ahead of the September 18, 2026 enforcement** The [markets concept page](/concepts/markets#price-and-amount-steps) now lists which request field each step applies to — `price`, `activation_price`, `stop_limit_price` and attached `stopLoss` / `takeProfit` prices against `tickSize`, `amount` against `stepSize` — and every order endpoint states its own rule. An order rejected for a step mismatch returns HTTP 422 with trade error code `1` and the failing field as the key in `errors` — distinct from the endpoints' own validation codes `30`, `32` and `33` — so branch on the code together with the key rather than on the localized message. The amount step does not apply to `POST /api/v4/order/market` and `POST /api/v4/order/stop_market` buy orders, where `amount` is the quote-currency total rather than a quantity. The `activation_price` of a buy stop-market order is still checked. ## Single-call currency conversion **Request and accept a conversion quote in one request** `POST /api/v4/convert/auto-confirm` requests a conversion quote and accepts it in a single call, so the 10-second quote lifetime cannot elapse between requesting a rate and executing at it. The request takes the same `from`, `to`, `direction`, and `amount` fields as [Convert Estimate](/api-reference/convert/convert-estimate), and the response returns `finalGive`, `finalReceive`, and the executed conversion's `id` — usable as the `quoteId` filter on [Convert History](/api-reference/convert/convert-history). An optional `idempotencyKey` of 8 to 128 characters deduplicates retries: the first request claims the key and converts, and a repeat returns the recorded conversion instead of converting again. The claim is short-lived and is never renewed, so review the retry-timing caveat on [Convert Auto Confirm](/api-reference/convert/convert-auto-confirm) before building retry logic. Send a key from any automated caller — without one, a retry converts a second time. The two-step [Convert Estimate](/api-reference/convert/convert-estimate) and [Convert Confirm](/api-reference/convert/convert-confirm) endpoints are unchanged and remain available. The new endpoint is additive. ## Order placement over WebSocket **Place, modify, and cancel orders on the WebSocket connection** From September 2, 2026, the WebSocket API carries order flow alongside market and account streams: 21 JSON-RPC methods place, modify, and cancel spot, margin, and futures orders over the same authorized connection that carries subscriptions. The methods are an alternative transport to the REST order endpoints for latency-sensitive integrations that hold one connection open. Authorize the connection first with the `authorize` frame; an order method on an unauthorized connection is rejected. The transport numbers its errors independently of REST — the same numeric code carries a different meaning on each surface — so branch on the codes documented on the Order Management page rather than reusing REST codes. ## WebSocket rate limits **Per-connection budgets: 10,000 order placements and 12,000 other requests per 10 seconds** The documented WebSocket request limits are updated. Per connection, order placements — the `*_place` methods — are limited to 10,000 requests per 10 seconds, and every other JSON-RPC request (subscriptions, cancellations, modifications, `ping`) counts against a separate budget of 12,000 per 10 seconds. These budgets replace the previously documented cap of 200 requests per minute per connection. The connection limit is unchanged at 1,000 new connections per minute. ## WebSocket host migration **Breaking change: the Global WebSocket host moved to `wss://wss.whitebit.com/ws`** The Global WebSocket endpoint moved from `wss://api.whitebit.com/ws` to `wss://wss.whitebit.com/ws`. Both hosts serve the same channels over the same `/ws` path during a 6-month transition window, after which the legacy host stops accepting connections. Only the host changes. The `/ws` path, the JSON-RPC message format, every market-stream, account-stream, and order-management method name, the `authorize` flow and token format, and the connection and request limits are all unchanged. **Migration guide:** * Replace `wss://api.whitebit.com/ws` with `wss://wss.whitebit.com/ws` in the WebSocket client and redeploy. * Update every hardcoded copy of the host — reconnect helpers, failover lists, client defaults, and environment configuration. A missed copy keeps working until the sunset date and fails then rather than at deploy time. * Subscription logic, message parsing, authorization, and keepalive handling need no change. **Sunset date:** March 1, 2027. **Replacement:** Connect to `wss://wss.whitebit.com/ws`. See [WebSocket API — Host migration](/websocket/overview#host-migration). **Impact:** Every integration on the Global WebSocket host is affected — public market streams, private account streams, and WebSocket order management alike. REST API integrations are not affected; the REST base URL is unchanged. ## Price and quantity steps on Market Info **Breaking change: order price and amount must align to `tickSize` and `stepSize`** `GET /api/v4/public/markets` now returns `tickSize` — the minimal price step a limit order price must be a multiple of — and `stepSize` — the minimal quantity step an order amount must be a multiple of. Both are decimal strings passed through verbatim from the trade engine, so the values follow a precision change on the market automatically. Either field is an empty string when the engine does not provide the value for the market, so handle the empty string before parsing. **Migration guide:** * Read `tickSize` and `stepSize` from `GET /api/v4/public/markets` and validate order price and amount against those two fields, instead of deriving the steps from `moneyPrec`/`stockPrec`. * Handle the empty-string case (the engine does not provide the value for the market) before parsing. **Backward compatibility:** Until September 18, 2026, WhiteBIT maintains backward compatibility for order prices and amounts that are not aligned to `tickSize` and `stepSize`. After September 18, 2026, an order whose price is not a multiple of `tickSize`, or whose amount is not a multiple of `stepSize`, is rejected. **Sunset date:** September 18, 2026. ## Market data, order history, and fee updates This release documents three API updates across market data, order history, and trading fees. ### Mark price on futures markets list **New `mark_price` field on `GET /api/v4/public/futures`** Each futures market entry carries `mark_price` — the fair value of the perpetual contract, derived from the underlying index price and the futures basis. Mark price, not `last_price`, is what a liquidation is evaluated against, so reading it lets an integration reproduce the distance to liquidation the platform itself measures instead of approximating it from the order book. The value is a decimal string taken from the latest premium index snapshot. While no fresh snapshot is available for the market, the field is returned as an empty string instead. The same release repoints `index_price` and `funding_rate` to that premium index source. Field names and the decimal-string format are unchanged, so no integration change is required. `index_price` now carries the index the contract actually tracks; while the index is unavailable it falls back to the last traded price of the corresponding spot market, then to the last traded price of the futures market itself, and returns `"0"` when neither has traded. ### Maintenance status on order history **New `maintenance` order status and status filter on `POST /api/v4/trade-account/order/history` and `POST /api/v4/trade-account/order/history/query`** When a market enters planned maintenance, the platform cancels the orders that are open on it. Those orders now carry a dedicated `maintenance` status on both order-history endpoints, so an integration can tell a maintenance cancellation from one the user or a risk rule triggered. `POST /api/v4/trade-account/order/history` accepts `MAINTENANCE` as the `status` filter and returns `MAINTENANCE` in the response, matching the uppercase status set of that endpoint. Maintenance cancellations are no longer reported as `CANCELED`, so the `CANCELED` filter excludes maintenance records. `POST /api/v4/trade-account/order/history/query` accepts `maintenance` as the `status` filter and returns the same lowercase value in the response `status` field, matching the lowercase outcomes of that endpoint. Maintenance records carry an empty `delistingKind`, so the `status` field is the discriminator, and a request that omits `status` returns maintenance records next to the delisting records. ### Single-market fee endpoint documented **New reference page for `POST /api/v4/market/fee/single`** `POST /api/v4/market/fee/single` returns the effective maker and taker fee for one market. The endpoint has been available for some time but was never documented; the new reference page covers the request body, the response fields, and the validation errors. Use it when only one market matters — `POST /api/v4/market/fee` returns the account's default fees and every custom override at once. ## bankBic parameter for SEPA and bank-rail fiat withdrawals **New `bankBic` request parameter on `POST /api/v4/main-account/withdraw` and `POST /api/v4/main-account/withdraw-pay`** The withdrawal endpoints now accept a `bankBic` parameter carrying the beneficiary bank's BIC (SWIFT) code. It is required when the fiat provider is one of `SEPA`, `SEPA_CLEAR_JUNCTION`, `SEPA_BCB_GROUP`, `FINCI`, `ZEN`, or `BANKING_CIRCLE`, and identifies the destination bank for bank-rail payouts. ## Funding cap and floor on futures markets list **New `funding_cap` and `funding_floor` fields on `GET /api/v4/public/futures`** Each futures market entry now returns the bounds that the funding rate can reach: `funding_cap` (upper) and `funding_floor` (lower). Use the fields to model worst-case funding costs in trading algorithms instead of hardcoding exchange-wide limits. Both fields are decimal strings served from the last successfully refreshed funding snapshot, so a temporary source outage does not drop the values; both return `null` only when no snapshot has been loaded since service start. ## Delisting date on Market Info **`delistedAt` field on `GET /api/v4/public/markets`** Every market entry carries `delistedAt` — the announced delisting date as a Unix timestamp in seconds, or `null` when no delisting is announced. The field has been live since June 2026; this entry marks the point it became documented. A market with an announced delisting stays tradeable until the delisting runs; once the delisting runs, the platform cancels the active orders on the market and drops the market from the response. An announcement can be rescheduled or canceled, so read the value on each poll rather than caching the value for the lifetime of an integration. ## Closed-position PNL on Collateral Trading **New `POST /api/v4/collateral-account/positions/closed-pnl` endpoint** The Collateral Trading API now returns one aggregated profit-and-loss record per closed position — the same closed-position PNL the trading terminal shows. Each record carries `grossPnl` (realized PNL with trading fees already deducted), `netPnl` (`grossPnl` minus `totalFunding`), volume-weighted average entry and exit prices, total closed size, and informational fee totals. The optional `startDate`/`endDate` window filters by position close time, and a position opened before the window still returns complete lifetime aggregates. The `amount` field always returns `"0"` for closed positions. ## RPI maker fee premiums on Query Market Fees **New `rpi_maker_fee_premium` and `futures_rpi_maker_fee_premium` fields on `POST /api/v4/market/fee`** The Query Market Fees response returns the RPI maker fee premium, an additional fee component applied on top of the maker rate when a Retail Price Improvement (RPI) order executes. `rpi_maker_fee_premium` covers spot and margin markets; `futures_rpi_maker_fee_premium` covers futures markets. The effective RPI maker rate equals the base maker rate plus the applicable premium. The endpoint returns both fields for every account, regardless of whether the RPI order mode is enabled; each field returns `null` when no premium is configured for the account, and a premium configured as zero is returned as `"0"`. ## Express Withdraw for B2B partners **New `POST /api/v4/main-account/express-withdraw/token` endpoint for B2B partners** Express Withdraw lets an approved B2B partner charge a specific amount from a WhiteBIT user's balance through a signed, single-use payment token valid for 90 seconds. The partner integrates one endpoint; the user confirms the exact ticker and amount on a WhiteBIT-hosted page, and the funds settle instantly, off-chain, and fee-free into the partner's Main balance. Express Withdraw is not available to everyone: the endpoints are available only for B2B partner services and require a separate approval process. Request access at [https://institutional.whitebit.com/](https://institutional.whitebit.com/). ## Granted permissions on OAuth API key info **New `permissions` array on `GET /oauth2/api-key/info`** `GET /oauth2/api-key/info` now returns a `permissions` array alongside `exists`, `isEnabled`, and `externalId`. Each entry is a permission group with a locale-independent `name` (for partner-side logic), a locale-dependent `title` (display only), and a `urls` list of `{ url, enable }` pairs reflecting what the user granted during the OAuth handshake. The array is empty when no key exists; for a disabled key the array still reflects the grant-time permission set, so the partner can show the original scope. ## Abbreviated Self-Trade Prevention mode values **`stp` accepts `cb`, `cn`, `co`; long-form values deprecated** The `stp` parameter on trade endpoints now uses abbreviated mode values: `cb` (cancel both), `cn` (cancel new), and `co` (cancel old); `no` is unchanged. The legacy values `cancel_both`, `cancel_new`, and `cancel_old` are deprecated. The long-form values remain accepted with identical behavior until a deprecation deadline is announced, after which the API rejects the long-form values. Responses always return the abbreviated form, regardless of which variant the request used. The parameter is documented on the five spot order endpoints (limit, market, stock market, stop-limit, stop-market) and the five collateral order endpoints (limit, market, stop-limit, trigger-market, OCO). ## Travel Rule API **New endpoints and structured format for Travel Rule compliance** The Travel Rule API enables B2B clients to submit originator and beneficiary data for cryptocurrency transactions as required by FATF and MiCA regulations. Available for accounts registered in the European Economic Area (EEA). **New endpoints:** * `POST /api/v4/travel-rule/vasps` — Retrieve the list of available VASPs for travel rule submissions. * `POST /api/v4/travel-rule/deposit/verification` — Submit originator data for deposits pending verification. **Updated `travelRule` format on withdrawals:** The `travelRule` object on `POST /api/v4/main-account/withdraw` now uses a structured format with `walletType`, `beneficiary`, and `vasp` objects. The legacy flat format is deprecated. ## TradFi Futures markets on Market Info **New `tradfiFutures` market type and `isTradFiFutures` flag on `GET /api/v4/public/markets`** `GET /api/v4/public/markets` returns traditional-finance (TradFi) futures markets, futures contracts on traditional financial assets such as equities (for example, `AAPL_USD`). A TradFi market carries `type: tradfiFutures` together with `isTradFiFutures: true`. Availability is region-gated: markets the account is not eligible to trade are omitted from the response entirely and do not appear under any other market type. ## Retail flag on Create Limit Order and Bulk Limit Order **New `retail` request parameter enables API clients to take RPI-maker liquidity** A new optional `retail` boolean parameter on `POST /api/v4/order/new` and `POST /api/v4/order/bulk` marks an order as a retail-source taker. A retail taker is eligible to match against orders submitted by RPI makers and may receive price improvement at execution. The retail designation was previously available only on non-API sources (web, mobile, TV); approved WaaS/CaaS clients can now take RPI orders via API. **Validation:** * `retail=true` requires the Retail flag enabled on the account; the API returns error code `42` otherwise. * `retail=true` cannot be combined with `rpi=true`; the API returns error code `41` otherwise. * The flag has no effect on `postOnly=true` orders, because post-only orders are makers and cannot be retail takers. ## Fast API Key via OAuth **New OAuth flow for partner-issued API keys** Partner platforms can now issue a WhiteBIT API key on behalf of a WhiteBIT user through the OAuth API key consent flow. The flow uses Authorization Code with PKCE (S256), a 4-hour access token without refresh, and partner-scoped IP restrictions on the resulting key. Three new OAuth2 endpoints support the flow. **New endpoints (global server only — `https://whitebit.com`):** * `GET /oauth2/api-key/info` — Check whether a partner-issued API key already exists for the authenticated user and OAuth2 client pair. * `GET /oauth2/api-key/{externalId}/secret` — Retrieve the API secret once. Subsequent calls return `409`. * `DELETE /oauth2/api-key/{externalId}` — Delete a partner-owned API key. Sends an email notification to the user. **New OAuth scopes:** `apikeys.create`, `apikeys.read`, `apikeys.delete`. ## Position History API update **Breaking change: `positionSide` field removed from Position History response** The `POST /api/v4/collateral-account/positions/history` endpoint no longer returns the `positionSide` field. Two new fields replace it: `side` (same enum as the removed field — `LONG`, `SHORT`, `BOTH`) and `isHedge` (a boolean indicating whether the position was opened in hedge mode). The combination lets integrations attribute closed-position records to a specific direction and account mode for P\&L tracking, compliance reporting, and strategy reconstruction. **Migration guide:** * Replace any reader of `positionSide` from `/positions/history` with `side`. The enum is unchanged: `LONG`, `SHORT`, `BOTH`. * Read `isHedge` to determine whether the record was produced under hedge mode (`true`) or one-way mode (`false`). * Other endpoints that return `positionSide` (`/positions/open`, `/conditional-orders`, order-create requests) are unchanged. **Sunset date:** April 29, 2026. **Replacement:** Use `side` and `isHedge` on the same endpoint. See [v4 - Positions history](/api-reference/trading/positions-history). **Impact:** Integrations parsing the response of `POST /api/v4/collateral-account/positions/history` and reading `positionSide` must migrate to `side` and `isHedge`. Other endpoint integrations are not affected. ## Bulk cancel orders endpoint **Cancel up to 100 spot orders in a single request** The new `POST /api/v4/order/cancel/bulk` endpoint cancels up to 100 spot orders in a single request. Each item identifies a target order by `market` plus exactly one of `orderId` or `clientOrderId`. The response array preserves the order of the input — `response[i]` corresponds to `request.orders[i]`. ## Reduce-only order parameter **Position-closing guarantee for collateral orders** A new `reduceOnly` boolean parameter for collateral order endpoints. When set to `true`, the order can only decrease or close an existing position — the order never increases the position or opens a new one. **Behavior:** * If the order amount exceeds the current position size, the system automatically reduces the order to match * The API returns error code `116` if no open position exists or the order direction matches the position direction * Pending reduce-only orders are auto-canceled with status `AUTO_CANCELED_REDUCE_ONLY` when the associated position closes **Supported on 6 collateral order creation endpoints:** The `reduceOnly` field also appears in the response of [query active orders](/api-reference/trading/query-unexecuted-orders), [query executed orders](/api-reference/trading/query-executed-orders), and [query conditional orders](/api-reference/trading/query-unexecuted-conditional-orders). **WebSocket channels:** The `reduce_only` field is added to the [Orders Pending](/websocket/account-streams/orders-pending) and [Orders Executed](/websocket/account-streams/orders-executed) channels — both in query responses and real-time update events. See [Order Types — Reduce-only orders](/concepts/order-types#reduce-only-orders) for full details. ## clientOrderId uniqueness scope change **Breaking change: `clientOrderId` is now unique only among open orders, not for a fixed time window** The uniqueness rule for `clientOrderId` on spot and collateral order creation changed. Uniqueness is now enforced only among the account's open (pending) orders on the same market. Once a previous order is filled or canceled, the same `clientOrderId` can be reused, including on the same market. The previous time-based uniqueness window no longer applies. **Impact on retry and deduplication logic:** Integrations that relied on a fixed-time uniqueness window to suppress duplicate submissions should not assume a resubmitted `clientOrderId` will be rejected after the original order leaves the open state. Before resubmitting an order whose response was not received, check whether an order with that `clientOrderId` already exists: * [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) (`POST /api/v4/orders`) — search open orders by `clientOrderId`. * [Query executed orders](/api-reference/trading/query-executed-orders) (`POST /api/v4/trade-account/order/history`) — search filled and canceled orders by `clientOrderId`. If the order is found in either result, the original submission was accepted and no retry is needed. ## Previous Changes ## Auto-Deleveraging (ADL) **Futures-market final-stage liquidation mechanism** WhiteBIT futures markets now apply Auto-Deleveraging as the final stage of liquidation, activated only when standard market liquidity cannot fully cover a liquidated position. ADL closes profitable counterparty positions on the opposite side at a calculated price, ranked by an internal Rating, ensuring no user balance becomes negative. **Integrator-relevant facts:** * ADL fills carry `source: "adl"` on the `ordersExecuted` WebSocket stream and a `client_order_id` of the form `adl__!`. Over REST order history — where the payload does not include `source` — match the `adl_` `client_order_id` prefix. The `reduce_only` flag remains `false` on ADL inserts, so do not use it for identification. * Pending reduce-only orders auto-cancel with the existing `AUTO_CANCELED_REDUCE_ONLY` status when ADL closes a counterparty position. No ADL-specific cancel status was introduced. * ADL Grade (0–4) indicates a position's place in the per-market ADL ranking, with Grade 4 corresponding to the asymptotic top 5% of ranked positions. ## Deprecation: OCO and OTO cancel endpoints **`POST /api/v4/order/oco-cancel` and `POST /api/v4/order/oto-cancel` are being retired** WhiteBIT is discontinuing support for the two dedicated conditional-cancel endpoints. Cancel OCO and OTO orders through [`POST /api/v4/order/conditional-cancel`](/api-reference/trading/cancel-conditional-order), which handles both order types on every collateral market. **Migration guide:** * Replace calls to `POST /api/v4/order/oco-cancel` and `POST /api/v4/order/oto-cancel` with `POST /api/v4/order/conditional-cancel`. * Send the conditional order `id` in place of `orderId` or `otoId`. The value is the same identifier, returned as `id` by [query unexecuted conditional orders](/api-reference/trading/query-unexecuted-conditional-orders). * An integration that cancels OCO orders by `clientOrderId` must resolve the client order id to the conditional order `id` first through [query unexecuted conditional orders](/api-reference/trading/query-unexecuted-conditional-orders). The replacement endpoint does not accept `clientOrderId`. * Expect an empty array in the response. `POST /api/v4/order/oco-cancel` returns the canceled `stop_loss` and `take_profit` legs; the replacement does not. An integration that logs the canceled legs can read the final leg state from [query executed orders](/api-reference/trading/query-executed-orders), within a 31-day request window reaching back 6 months. For B2B accounts, canceled orders are not recorded in order history; contact support or the assigned account manager to retrieve canceled-leg data. **Impact:** Integrations calling either endpoint must migrate. Integrations that cancel OCO orders by `clientOrderId`, or that read the canceled legs from the response, need an extra lookup rather than a direct swap. **Backward compatibility:** Both endpoints keep working until the sunset date. **Sunset date:** To be announced. ## Mining Pool API **Comprehensive mining pool management endpoints** Introduced a complete Mining Pool API with 10 endpoints for managing mining operations, including account monitoring, payout configuration, worker management, and watcher link generation. **Public endpoints:** * Pool statistics and connection information **Mining account management:** * Reward history with pagination * Account-level hashrate monitoring with configurable intervals (5m, 1h, 24h) * Fee and stratum connection details **Payout configuration:** * Get and set payout destination (main balance or external BTC address) * Support for all standard Bitcoin address formats **Worker monitoring:** * List online workers with pagination * Individual worker hashrate history **Watcher links:** * Create read-only access links with granular permissions (dashboard, rewards, workers) * Configurable expiration periods (1h, 24h, 7d, always) * List active watcher links All authenticated endpoints require the MINING\_POOL feature to be enabled on the API key. ## Mining Account Management **Create and list mining accounts** Added endpoints to create and manage mining pool accounts programmatically. **Account creation:** * Create named mining accounts with optional referral codes * Unique account names with alphanumeric and underscore support * Automatic validation for duplicate names **Account listing:** * Retrieve all mining accounts or filter by name * Results sorted by creation date (newest first) All endpoints require the MINING\_POOL feature to be enabled on the API key. ## API Documentation Updates **Sub-account transfer endpoints: add transactionId for correlation** The response of `/api/v4/sub-account/transfer` and `/api/v4/sub-account/transfer/history` includes the `transactionId` field. Use `transactionId` to correlate transfer operations with transfer history records. The `id` field in transfer history is deprecated. Replace `id` with `transactionId`. ## Documentation Updates **Clarified Book Ticker stream update interval** Refined the description of the Book Ticker WebSocket stream to explicitly state instant BBO snapshot with incremental updates. ## Flex Earn Endpoints **Introduced Smart Flex private endpoints** Added documentation for Smart Flex (Flex Earn) endpoints: list plans, manage investments, view histories, and configure auto-reinvestment. ## API Documentation Updates **Enhanced Query executed orders documentation** Updated documentation for `/api/v4/trade-account/order/history` endpoint to clarify date range filtering capabilities with `startDate` and `endDate` parameters. ## Public API Update **New Funding History endpoint** Added new endpoint `/api/v4/public/funding-history/{market}` to retrieve funding rate history for futures markets. ## Private API Update **Issue JWT Token for Private API** New endpoint to issue JWT token for private API access. **Issue card token using JWT** New endpoint to issue a card token using JWT for secure transactions. **Withdraw endpoint update** Address now accepts card tokens for withdrawals. ## Public WebSocket Update **Added BookTicker WebSocket stream** New bookTicker stream added to WebSocket API, providing real-time updates of best bid/ask prices and quantities for markets. Includes subscription (bookTicker\_subscribe) and unsubscription (bookTicker\_unsubscribe) methods for managing the data feed. ## Trade Engine Update **Event time and update id introduced in WebSocket events** WebSocket events now include `event_time` and `update_id` fields. The `event_time` field provides the timestamp of the event, while the `update_id` field is a unique identifier for each update, allowing for better tracking and synchronization of events. **Hedge mode support** The Hedge mode is now available for all users. This mode allows holding both long and short positions in the same asset simultaneously, providing greater flexibility in managing trades. **Queries Limited to the Last 6 Months** To enhance performance and focus on the most relevant data, the API limits data queries to the past 6 months. Data can be retrieved up to six months old from the current date. ## Withdraw update **HTTP Main V4 API - Withdraw** The `paymentDescription` field is now mandatory for withdrawal requests from whitebit-tr.com. ## Travel Rule Update **HTTP Main V4 API - Travel Rule** Added new statuses DEPOSIT\_TRAVEL\_RULE\_FROZEN (27) and DEPOSIT\_TRAVEL\_RULE\_FROZEN\_PROCESSING (28) to the deposit endpoint. ## Convert History Update **HTTP Trade V4 API - Convert** Added 30 days date range limit for convert history and default values for `from` and `to` parameters. ## Deposit and Withdrawal Updates **HTTP Main V4 API - Birth Date Addition** Added beneficiary.birthDate field (Format: YYYY-MM-DD) to withdrawal requests and customer.birthDate (Format: YYYY-MM-DD) to deposit requests. # Auto-Deleveraging (ADL) Source: https://docs.whitebit.com/concepts/auto-deleveraging Final-stage liquidation mechanism on WhiteBIT futures markets — closes profitable counterparty positions when standard market liquidity cannot cover a liquidated position. Auto-Deleveraging (ADL) is the final stage of the WhiteBIT futures liquidation flow. Activation occurs only when standard market liquidity cannot fully absorb a liquidated position. ADL closes a portion of profitable counterparty positions on the opposite side of the market at a calculated price, ensuring no user balance becomes negative. ## How liquidation reaches ADL WhiteBIT futures liquidation runs in two stages. The trigger price, maintenance margin schedule, and liquidation sequence that precede both stages are covered in [Liquidation and margin requirements](/concepts/liquidation). * **Stage 1 — Market liquidity.** The liquidation order matches against existing order-book depth, primarily liquidity-provider depth. Under normal market conditions Stage 1 absorbs the order, and the position closes without engaging counterparty user positions. * **Stage 2 — ADL.** When Stage 1 cannot fully absorb the liquidation order, ADL activates to close the residual portion. ADL never runs before Stage 1 is exhausted. ## How ADL closes the residual position ADL places post-only limit orders in the order book at the bankruptcy price — the level at which the liquidated user's collateral approaches zero without crossing into negative. Order properties: * **Owner.** Each ADL order is owned by the selected counterparty's user account, not by the platform, an insurance fund, or the liquidated user. * **Type.** Post-only limit orders. Public order-book visibility applies while the orders are unfilled, although the small price offset usually results in fast fills. * **Volume per order.** Every ADL order matches the full counterparty position size, except the last selected order, which may be smaller to match the exact required volume. ## Identifying liquidation and ADL fills Both the liquidation close order (on the liquidated account) and any ADL fills (on a counterparty account) arrive through the normal execution surfaces. The reliable discriminator differs by delivery channel: * **WebSocket — [`ordersExecuted`](/websocket/account-streams/orders-executed) stream.** Use the `source` field: `"liquidation"` when the account's own position is being liquidated, `"adl"` when the account's position is closed as the counterparty of another user's liquidation. * **REST — order and executed history.** The history payloads do not include `source`. Match the `clientOrderId` prefix instead. | | Liquidation (account's own position) | ADL (as counterparty) | | - | - | - | | `source` (WebSocket) | `"liquidation"` | `"adl"` | | `clientOrderId` prefix | `liquidation__!` | `adl__!` | | Order type | Market, `ioc: true` | Post-only limit | | Terminal status | `FILLED`, or `PARTIALLY_FILLED` if book depth is insufficient | `FILLED` | Do not use `reduceOnly` to identify these fills — it remains `false` on ADL-inserted orders despite the position-reducing effect. When the account's own position is liquidated, the account's other pending orders on that market are swept with the `AUTO_CANCELED_LIQUIDATION` status. ## How counterparties are selected Selection runs on per-market lists, separately for the long and short sides: * A **Short liquidation** draws counterparties from the **Long** list. * A **Long liquidation** draws counterparties from the **Short** list. Selection rules: * **Hedge Mode.** A user holding both long and short positions on the same perpetual market receives a Grade computed independently for each side. Selection on one side never considers the other. * **Positive Rating only.** Only positions with a positive Rating are selected as counterparties. Losing positions are filtered out at selection time. * **Highest first.** Selection walks the list from highest Rating downward until cumulative volume covers the liquidated position. ## Rating formula Each candidate position receives a Rating value. Higher Rating means earlier selection. ``` Rating = % profit × effective leverage % profit = unrealized PnL / |position size in money| effective leverage = |position size in money| / account equity ``` Account equity refers to the user's collateral-account equity figure as defined in [Balances](/concepts/balances). Negative-Rating positions are still ranked and receive a Grade for the indicator (see [ADL Grade](#adl-grade)), but selection filters those positions out — only positive-Rating positions become ADL counterparties. ## Execution price ADL fills execute at a price derived from **Last Price** (not Mark Price). The formula: ``` d = Margin Fraction − 2 × taker_fee_rate Long position : Price_ADL = LastPrice × (1 − d) Short position : Price_ADL = LastPrice × (1 + d) ``` Where: * `LastPrice` — the current last-traded price at the time of liquidation. * `Margin Fraction` — the system parameter from the published execution-price formula. The canonical publication is the [WhiteBIT help-center article on ADL](https://help.whitebit.com/hc/ru/articles/35218885148445). * `taker_fee_rate` — the **liquidated user's** taker fee rate. ## Worked example A 10 BTC short position on a perpetual market is liquidated at `LastPrice = $42,000`. The system computes Ratings for the long-side candidates: | Trader | Rating | Position | PnL | Selection result | | - | - | - | - | - | | A | 0.26 | 5 BTC | +\$35,000 | Full position closed (5 BTC) | | B | 0.167 | 8 BTC | +\$8,000 | Partial close (5 BTC) — 3 BTC remain open | | C | −0.05 | 6 BTC | −\$3,000 | Not selected — losing position | Price calculation for the Short liquidation: * Margin Fraction (of liquidated position) ≈ 0.02 * `taker_fee_rate` = 0.0005 (0.05%) * `d` = 0.02 − 2 × 0.0005 = 0.019 * `Price_ADL` = 42,000 × (1 + 0.019) = **\$42,798** Source: WhiteBIT help-center article. ## ADL Grade ADL Grade is an indicator value from 0 to 4 reflecting a position's place in the per-market ranking. Higher Grade signals higher likelihood of selection as an ADL counterparty. Computation: * Position lists are ordered ascending by Rating. * Each position's index converts to `k = i / n`, where `i` is the 1-based position in the list and `n` is the list size. * Grade is assigned by the threshold table below. | Range of k | Grade | Risk | | - | - | - | | k \< 0.5 | 0 | Minimal | | k \< 0.73 | 1 | Low | | k \< 0.87 | 2 | Medium | | k \< 0.95 | 3 | Elevated | | k ≥ 0.95 | 4 | Highest priority | Grade depends on Rating and on the number of other traders on the same market. As prices and unrealized PnL change, Grade values update accordingly. Fetch the current Grade for open positions via [`POST /api/v4/collateral-account/adl-quantile`](/api-reference/trading/adl-quantile), or subscribe to [ADL quantile](/websocket/account-streams/adl-quantile) over WebSocket for a live push instead of polling. ### Grade 4 in thin markets Grade 4 corresponds to the asymptotic top 5% of ranked positions on the market. For thin markets, the actual Grade 4 fraction is `(n − ⌈0.95n⌉ + 1) / n`: | List size n | Grade 4 count | % of list | | - | - | - | | 10 | 1 | 10% | | 100 | 6 | 6% | | 1000 | 51 | 5.1% | Integrators modeling ADL base rates numerically should account for thin-market discretization rather than assuming a flat 5%. ## What happens when ADL closes a position Effects on the selected counterparty: * The position closes at `Price_ADL`. * A notification is delivered with the closure details (volume and price). * All open orders on the affected market are cancelled. * Pending [reduce-only](/concepts/order-types#reduce-only-orders) orders auto-cancel with the existing `AUTO_CANCELED_REDUCE_ONLY` status. No ADL-specific cancel status was introduced. ## Reducing ADL exposure Three approaches lower a position's ADL exposure: * **Reduce leverage.** Lower configured leverage reduces effective leverage, which reduces Rating and therefore Grade. * **Use stop-loss.** Losing positions are excluded from selection. Setting a stop-loss to convert a profitable position into a losing one before potential ADL selection removes the position from the queue. * **Maintain margin.** Adequate collateral reduces the user's own liquidation risk, which limits exposure to the market conditions under which ADL activates. ## What's Next Perpetual contracts up to 100x, Hedge Mode, funding rates. All order types and execution flags, including reduce-only. Definitions for ADL, ADL Grade, and effective leverage. # Balances & Transfers Source: https://docs.whitebit.com/concepts/balances Understand WhiteBIT's three account types — Main, Trade, and Collateral — and how funds move between accounts. WhiteBIT uses three account types to separate funds by purpose: Main, Trade, and Collateral. Funds must be transferred between accounts before use — deposits arrive in Main, trading requires Trade or Collateral. ## Account types **Main balance** — The primary holding account. Deposits arrive here. Withdrawals leave from here. Creating a U EARN (lending) investment debits funds from Main and moves the assets into a separate investment account; the platform UI surfaces the investment as a virtual Earn balance. Main balance is not used for direct trading. * Endpoint: `POST /api/v4/main-account/balance` — [API Reference](/api-reference/account-wallet/overview) **Trade balance (Spot)** — Holds funds for spot trading. Transfer funds from Main to Trade before placing spot orders. Each currency has an `available` amount (ready to trade) and a `freeze` amount (locked in open orders). * Endpoint: `POST /api/v4/trade-account/balance` — [API Reference](/api-reference/account-wallet/overview) **Collateral balance (Margin & Futures)** — Holds funds for both margin and futures trading. Transfer funds from Main to Collateral before opening leveraged positions. The same Collateral balance serves both products — the market pair determines whether the position is Margin or Futures. * Endpoint: `POST /api/v4/collateral-account/balance` — [API Reference](/api-reference/trading/collateral-account-balance) **API naming convention:** WhiteBIT's API uses "collateral" endpoints for both Margin and Futures trading. The market pair determines the product: spot pairs (e.g., `BTC_USDT`) for Margin, perpetual pairs (e.g., `BTC_PERP`) for Futures. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. ## Fund flow Transfers between account types use a single endpoint and are instant and fee-free. ``` Main ↔ Trade (for spot trading) Main ↔ Collateral (for margin and futures trading) Trade ↔ Collateral (executed as two steps through Main) ``` Every transfer is stored with Main on one side. A direct Trade ↔ Collateral transfer is accepted — the platform executes such a transfer as two steps through Main, so transfer history returns two records, `spot → main` and `main → collateral`, each carrying the full amount. The platform UI exposes the same direct Trade ↔ Collateral transfer, and the same Main-routed steps happen under the hood. * Transfer endpoint: `POST /api/v4/main-account/transfer` — [API Reference](/api-reference/account-wallet/transfer-between-balances) * Transfer history endpoint: `POST /api/v4/main-account/transfer/history` — [API Reference](/api-reference/account-wallet/get-transfer-history) Transfer direction is controlled via the `method` parameter: * `deposit` — Main → Trade * `withdraw` — Trade → Main * `collateral-deposit` — Main → Collateral * `collateral-withdraw` — Collateral → Main ## Available vs. frozen balance Each balance entry includes two fields: | Field | Description | | - | - | | `available` | Funds ready to use for new orders or transfers | | `freeze` | Funds locked by open orders or pending operations | Total balance = `available` + `freeze`. Only `available` funds can be transferred or used to place orders. ## USDTB (bonus collateral) USDTB is a bonus collateral token used for futures trading. USDTB cannot be deposited or withdrawn — the platform grants USDTB as a bonus asset. USDTB appears in the Collateral balance and counts toward futures margin requirements. ## Deposit flow 1. Generate a deposit address. Use `POST /api/v4/main-account/create-new-address` ([API Reference](/api-reference/account-wallet/create-new-address-for-deposit)) to generate a unique address per request, or `POST /api/v4/main-account/address` ([API Reference](/api-reference/account-wallet/get-cryptocurrency-deposit-address)) to retrieve a persistent reusable address. Alternatively, create an address through the platform UI. 2. Send crypto to the generated address. 3. Funds arrive in Main balance after blockchain confirmations. Confirmation requirements vary by asset. 4. Transfer from Main to Trade (for spot orders) or to Collateral (for margin/futures positions). ## Withdrawal flow 1. Ensure funds are in Main balance — transfer from Trade or Collateral if needed. 2. (Optional) If the held currency differs from the withdrawal currency, transfer to Trade balance, convert via the [Convert](/platform/convert) feature, and transfer back to Main balance. See [Payment Integration](/guides/payment-integration) for the full withdrawal-with-conversion flow. 3. Submit a withdrawal request via `POST /api/v4/main-account/withdraw`. 4. Withdrawal processes after security checks complete. **EEA users:** Crypto withdrawals require a `travelRule` object with beneficiary information (name, address, VASP). Deposits may be held for Travel Rule verification (status codes 27, 28). See [Regulatory Compliance](/institutional/compliance) for full details. ## What's Next Generate API keys and sign requests. Choose an integration path. Full endpoint documentation for balances, deposits, and withdrawals. # Integration models Source: https://docs.whitebit.com/concepts/integration-models How WhiteBIT partner programs connect end users: partner-operated sub-accounts (Model A), customers' own accounts via Fast API Key (Model B), and why a pooled account is not offered. An integration model defines who holds each end user's WhiteBIT account and who performs end-user identity verification (KYC). WhiteBIT partner programs offer more than one model because partners differ: some operate accounts on behalf of customers, and others connect customers who already hold personal WhiteBIT accounts. The chosen model sets the account structure, the counterparty relationship, and where compliance responsibility sits. Program overviews and integration guides link to the models below rather than restating the trade-off. ## Model A — partner-operated sub-accounts Model A places each end user in a dedicated sub-account under the partner's master account. WhiteBIT provides per-customer isolation, per-customer API keys, and fee-free internal transfers between the master account and the sub-accounts. WhiteBIT is the end user's counterparty and, by default, verifies (KYC) each end user. Model A suits partners operating accounts for customers: Embedded Trading partners, [Wallet-as-a-Service](/guides/waas-overview) backends — where the model is called *managed sub-accounts* — and platforms managing customer funds. A gated variant, KYC reliance, lets an eligible partner perform end-user verification instead, subject to a WhiteBIT Compliance assessment. The eligibility conditions are documented on the [Embedded Trading overview](/guides/embedded-trading-overview) and the [WaaS overview](/guides/waas-overview). Build Model A with [Sub-Accounts](/products/sub-accounts/overview); the [Embedded Trading integration guide](/guides/sub-account-integration) covers per-customer setup end to end. ## Model B — customers' own accounts (Fast API Key) Model B connects end users who each hold a personal WhiteBIT account. WhiteBIT holds custody and performs KYC. The partner acts on the account through an OAuth-issued API key granted by the user on the WhiteBIT consent screen — see [Fast API Key via OAuth](/guides/fast-api-key-integration) for the flow and [OAuth 2.0](/platform/oauth/overview) for the concept. The user selects the key's permission scope, so partner access is bounded by the granted permissions. In Wallet-as-a-Service terms, Model B is *attribution*: the end user is a direct WhiteBIT customer, and attribution or fee-share is arranged separately. Model B fits more partner types than embedded trading alone — a long tail of applications where the end user keeps a personal account. Model B partner types group by the permission scope required: * **Read-only** — portfolio trackers and aggregators, tax and accounting tools, and referral apps reading a user's own activity. No fund movement. * **Trade-execute** — trading bots and signal execution, copy and social trading, charting and analytics with on-chart execution, algorithmic and quant platforms, and education platforms with in-app execution. Order placement only; withdrawal remains a separate, user-controlled grant. Compliance review scales with the permission scope, not the partner label. ## Comparison | Dimension | Model A — sub-accounts | Model B — Fast API Key | | - | - | - | | Account holder | Partner (a sub-account per end user under a master account) | End user (a personal WhiteBIT account) | | KYC | WhiteBIT by default; the partner under gated KYC reliance | WhiteBIT | | Counterparty | WhiteBIT, via the partner's master account | WhiteBIT, direct to the end user | | Best fit | Account operators, WaaS backends, platforms operating customer accounts | Bots, copy trading, portfolio and tax tools, and other apps on customers' own accounts | | Where to build | [Sub-Accounts](/products/sub-accounts/overview), [Embedded Trading](/guides/sub-account-integration) | [Fast API Key via OAuth](/guides/fast-api-key-integration) | ## Why not a pooled account A single pooled (omnibus) account holding all end users' funds together — sometimes called Model C — is not offered. Pooled custody conflicts with MiCA client-fund segregation and with [Travel Rule](/concepts/travel-rule) requirements, both of which depend on funds and transfers being attributable to an identified end user. Segregated sub-accounts (Model A) and customers' own accounts (Model B) preserve attribution, while a master account acts only as a settlement hub. Client-fund segregation also became the market baseline after the 2022 collapse of FTX, where customer funds were commingled. See [Regulatory Compliance](/institutional/compliance) for the MiCA specifics. ## What's next Build Model A: per-customer sub-accounts, per-customer API keys, and reconciliation. Build Model B: the OAuth API key flow on customers' own accounts. What Embedded Trading is and how enrollment works. # Liquidation and margin requirements Source: https://docs.whitebit.com/concepts/liquidation How liquidation is evaluated on WhiteBIT margin and futures positions — mark price as the trigger, the maintenance margin schedule, leverage brackets, and the API fields that report liquidation state. Liquidation force-closes a leveraged position when the maintenance margin requirement is breached. Margin Trading and Futures Trading draw on the same [Collateral balance](/concepts/balances), so both products share one maintenance margin schedule, one account-wide leverage setting, and one liquidation sequence. The sections below cover the trigger price, the margin threshold, the order in which exposure closes, and the API fields that report liquidation state. ## Trigger price On perpetual markets, liquidation is evaluated against the **mark price**, not `last_price`. A temporary wick in the order book does not by itself trigger a liquidation. Mark price is the fair value of the perpetual contract, derived from the underlying index price and the futures basis. The value is a point-in-time reading from the latest premium index snapshot, exposed as `mark_price` on [`GET /api/v4/public/futures`](/api-reference/market-data/available-futures-markets-list). While no fresh snapshot is available for a market, `mark_price` returns an empty string. The `index_price` field on the same endpoint carries the index the contract tracks, read from the same snapshot. While the index is unavailable, `index_price` falls back to the last traded price of the spot market, then of the futures market, and returns `"0"` when neither has traded. Auto-Deleveraging fills are priced from **Last Price**, not mark price. See [Auto-Deleveraging](/concepts/auto-deleveraging) for the execution-price formula. ## Maintenance margin and leverage brackets The Maintenance Margin Rate (MMR) is **3% for leverage 1x–10x**. Per-market leverage limits and collateral brackets are published on the [collateral brackets page](https://whitebit.com/trading-data/collateral-brackets). | | Margin | Futures | | - | - | - | | Instrument | Spot pairs (`BTC_USDT`) | Perpetual pairs (`BTC_PERP`) | | Maximum leverage | 10x | 100x | | Documented MMR | 3% for 1x–10x | 3% for 1x–10x | The [leverage endpoint](/api-reference/trading/change-collateral-account-leverage) accepts `1`, `2`, `3`, `5`, `10`, `20`, `50`, and `100`. Leverage is an account-level setting — a change affects all open positions across both products. A market's `max_leverage` field may be lower than `100`, and setting leverage above a market maximum returns an error. The `brackets` object on `GET /api/v4/public/futures` maps each leverage multiplier to the **maximum open position size in USDT equivalent** at that level. Brackets are position-size limits, not MMR percentages. A position that exceeds a bracket limit moves to higher tiers with progressively lower leverage. ## Liquidation sequence Partial liquidation is the primary mechanism: a portion of the position (for example, 20–30%) closes first to restore margin. Full liquidation follows only when partial liquidation is insufficient. Collateral allocated to a liquidated position is lost. Exposure closes in a fixed order: 1. Margin positions, from smallest to largest initial margin value 2. Crypto borrowings 3. Futures positions On futures markets, [Auto-Deleveraging](/concepts/auto-deleveraging) is the final stage, reached only when order-book liquidity cannot absorb the liquidation order. ## Liquidation state in API responses | Field | Surface | Meaning | | - | - | - | | `liquidationPrice` | [Open positions](/api-reference/trading/open-positions) | Liquidation price for the current position state. Nullable — a position already under a margin call can return `null` | | `liquidationState` | [Open positions](/api-reference/trading/open-positions) | `margin_call` or `liquidation`. Nullable while neither state applies | | `marginFraction` | [Collateral account summary](/api-reference/trading/collateral-account-summary) | Ratio of used margin to account equity, returned alongside `equity`, `margin`, `freeMargin`, and `pnl` | | `liq_price`, `liq_stage` | [Positions](/websocket/account-streams/positions) stream | Liquidation price and stage per position, pushed every second. `liq_stage` is `margin_call`, `liquidation`, or `null` when healthy | | `liq_price` | [Borrows](/websocket/account-streams/borrows) stream | Liquidation price of an individual borrow | | Event type | [Borrows events](/websocket/account-streams/borrows-events) stream | `1` = margin call, `2` = liquidation | | `liq_stage` | [Margin positions events](/websocket/account-streams/margin-positions-events) stream | Event-driven margin call and liquidation notifications; no snapshot on subscribe | Because `liquidationPrice` is nullable, a risk monitor treats a missing value as "not yet computed" rather than "no liquidation risk", and tracks `marginFraction` alongside. ## Cost of borrowed funds A commission applies to borrowed funds on margin positions, charged only when an order is at least partially executed. Unexecuted orders incur no borrowing fee. Current rates are published on the [trading fees page](https://whitebit.com/trading-data/trading-fees). No public endpoint returns the borrowing rate itself. Accrued borrowing cost per open borrow is available as `unrealized_funding` on the [Borrows](/websocket/account-streams/borrows) stream — the funding due at the next borrow stage change. > **Coming soon:** the full mark price calculation method (snapshot cadence and basis handling), the trigger price for margin positions on spot pairs, MMR values for leverage brackets above 10x, and per-position liquidation price formulas. For institutional risk-modelling requirements, contact [institutional@whitebit.com](mailto:institutional@whitebit.com). **API naming convention:** WhiteBIT's API uses "collateral" endpoints for both Margin and Futures trading. The market pair determines the product: spot pairs (e.g., `BTC_USDT`) for Margin, perpetual pairs (e.g., `BTC_PERP`) for Futures. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. ## What's Next The final liquidation stage, counterparty selection, and the ADL Grade indicator. Main, Trade, and Collateral accounts, and how funds move between accounts. Open a first leveraged position and read position risk fields. # Markets & Trading Pairs Source: https://docs.whitebit.com/concepts/markets Understand market types, trading pair notation, and how to fetch market data from the WhiteBIT API. WhiteBIT organizes trading around **market pairs** — combinations of a base asset and a quote asset, written as `BASE_QUOTE` (for example, `BTC_USDT`). The base asset (left side) is what gets bought or sold. The quote asset (right side) is what gets paid with. ## Market types WhiteBIT supports four market types, each using different account balances and leverage settings. | Type | Pairs | Balance | Leverage | Example | | - | - | - | - | - | | **Spot** | 800+ | Trade | None (1×) | `BTC_USDT` | | **Margin** | Spot pairs | Collateral | Up to 10× | `BTC_USDT` | | **Futures** | 270+ perpetuals | Collateral | Up to 100× | `BTC_PERP` | | **TradFi Futures** | Region-gated | Collateral | — | `AAPL_USD` | **Spot** — Direct buy/sell. Orders execute against the spot orderbook. Funds held in the [Trade balance](/concepts/balances). **Margin** — Leveraged trading on spot pairs with up to 10× leverage. Pair names are identical to spot (e.g., `BTC_USDT`). Funds held in the [Collateral balance](/concepts/balances). Isolated margin mode available. **Futures** — Perpetual contracts with up to 100× leverage. Pairs use the `_PERP` suffix (e.g., `BTC_PERP`). Funds held in the [Collateral balance](/concepts/balances). Hedge Mode allows simultaneous long and short positions. **TradFi Futures** — Futures markets on traditional-finance assets such as equities (e.g., `AAPL_USD`), identified in the [markets response](/api-reference/market-data/market-info) by `type: tradfiFutures` and `isTradFiFutures: true`. Funds are held in the [Collateral balance](/concepts/balances). Availability is region-gated — markets not available in a given region are omitted from `GET /api/v4/public/markets` entirely. TradFi markets enabled for collateral trading also appear in the [collateral markets list](/api-reference/market-data/collateral-markets-list); placing an order on a TradFi market additionally requires TradFi futures to be enabled for the account. Availability is also gated per account: placing or modifying an order on a TradFi market requires the account to hold the TradFi futures permission. The account gate is separate from the region gate, so a TradFi market can be listed in `GET /api/v4/public/markets` and still reject order placement with HTTP 422 and error code `10011` on the [collateral order endpoints](/api-reference/trading/collateral-overview). Canceling an existing order on a TradFi market is never restricted. **API naming convention:** WhiteBIT's API uses "collateral" endpoints for both Margin and Futures trading. The market pair determines the product: spot pairs (e.g., `BTC_USDT`) for Margin, perpetual pairs (e.g., `BTC_PERP`) for Futures. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. ## How to fetch market info Public endpoints — no authentication required: * **All markets (spot, margin, perpetual, TradFi futures):** `GET /api/v4/public/markets` — [API Reference](/api-reference/market-data/market-info) * **Perpetual futures markets:** `GET /api/v4/public/futures` — [API Reference](/api-reference/market-data/available-futures-markets-list) ## Key market fields Each market returned by `GET /api/v4/public/markets` includes: | Field | Description | | - | - | | `stock` | Base asset ticker (e.g., `BTC`) | | `money` | Quote asset ticker (e.g., `USDT`); perpetual futures pairs report `USDT` | | `minAmount` | Minimum order quantity in the base asset | | `minTotal` | Minimum order total in the quote asset | | `makerFee` | Default maker fee as a percentage value (`"0.1"` means 0.1%) | | `takerFee` | Default taker fee as a percentage value (`"0.1"` means 0.1%) | | `tradesEnabled` | Whether trading is active on the pair | | `stockPrec` | Maximum decimal places for base asset quantity | | `moneyPrec` | Maximum decimal places for quote asset amount | | `tickSize` | Minimal price step a limit order price must be a multiple of; empty string when not provided | | `stepSize` | Minimal quantity step an order amount must be a multiple of; empty string when not provided | ## Price and amount steps From September 18, 2026, the matching engine rejects an order whose price is not a multiple of `tickSize` or whose amount is not a multiple of `stepSize`. Read both values from `GET /api/v4/public/markets` on every poll instead of deriving the steps from `moneyPrec` and `stockPrec` — both values follow the market settings in the trade engine and may differ from the precision-derived values. | Request field | Step | Where it applies | | - | - | - | | `price` | `tickSize` | limit, stop-limit, bulk and modify orders, spot and collateral | | `activation_price`, spelled `activationPrice` on modify | `tickSize` | stop-limit, stop-market, trigger-market, OCO and modify orders | | `stop_limit_price` | `tickSize` | the stop-loss leg of an OCO order | | `stopLoss`, `takeProfit` | `tickSize` | prices attached to a collateral order; a position take-profit / stop-loss request spells the same prices `take_profit_activation_price` and `stop_loss_activation_price` | | `amount` | `stepSize` | every order endpoint except the cases below | The amount step does not apply to `POST /api/v4/order/market` and `POST /api/v4/order/stop_market` buy orders: there `amount` is the total in quote currency, not a quantity. The `activation_price` of a buy stop-market order is still checked. A standalone order rejected for a step mismatch returns HTTP 422 with trade error code `1` and the failing field in `errors`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 1, "message": "Validation failed", "errors": { "price": ["Price must be a multiple of 0.01."] } } ``` The bulk endpoints answer HTTP 200 instead and carry the same object in the array entry of the order that failed. A step rejection keys `errors` on `price`, `amount`, `activationPrice`, `stopLimitPrice`, `takeProfit` or `stopLoss`, whatever spelling the request uses for the field. The endpoint's own validation errors — codes `30`, `32` and `33` — key on the request field instead, so `activation_price` appears there. Branch on the code together with the key, never on the message text: the message is localized. An empty `tickSize` or `stepSize` means the trade engine does not provide the value for that market. Fall back to `10^-moneyPrec` for the price step and `10^-stockPrec` for the amount step, and re-read the market on the next poll. ## Market statuses The `tradesEnabled` field indicates whether a market is actively accepting orders. The `/api/v4/public/markets` response only includes markets enabled for trading, so a disabled market disappears from the list rather than appearing with `tradesEnabled: false`. Markets can be temporarily disabled by the platform without prior notice. The platform announces a permanent removal in advance instead. The market carries the announced delisting date in `delistedAt` — a Unix timestamp in seconds, `null` when no delisting is announced. The market keeps trading until the delisting runs, then the platform cancels the active orders and drops the market from the response. An announcement can be rescheduled or canceled, so re-read `delistedAt` on each poll. For platform-wide maintenance status, call `GET /api/v4/public/platform/status` — [API Reference](/api-reference/market-data/maintenance-status). ## What's Next Learn about the 7 order types available on WhiteBIT. Understand Main, Trade, and Collateral account types. Fetch live prices and orderbooks — no auth required. # Matching engine Source: https://docs.whitebit.com/concepts/matching-engine How the WhiteBIT matching engine sequences and executes orders — price-time priority and participant fairness across spot, margin, and futures markets. The matching engine is the core system that pairs buy and sell orders across WhiteBIT spot, margin, and futures markets. A single engine serves every market: every order — regardless of account, product, or order type — enters the same order book and follows the same matching rules. Understanding how the engine sequences orders helps integrators reason about fill probability and execution timing. ## Order matching The engine runs continuous matching — each incoming order is evaluated for a match on arrival, with no batch-auction window, speed bump, or arrival-time randomization. Resting orders match on **[price-time priority](/glossary#price-time-priority)**: better-priced orders fill first, and orders at the same price fill in arrival sequence. At a given price level, non-RPI orders form a priority queue ahead of [RPI](/glossary#retail-price-improvement-rpi) orders. FIFO holds within each segment, but the entire non-RPI queue at that price drains before any RPI order at the same price executes — even if the RPI order arrived first. Each fill triggers re-evaluation of resting [stop and trigger orders](/concepts/order-types#stop-market-orders). Any stop or trigger whose condition is met by the new trade price enters the matching pipeline immediately, in the same engine cycle as the originating fill. Time priority is determined by **matching-engine arrival**, not by arrival at the API gateway. Order modification does not preserve queue position — the engine cancels the original order and creates a replacement with a new `orderId` at the back of the price level's queue. See [order modification in the Market Maker Guide](/guides/market-maker-integration) and the [modify order endpoint](/api-reference/trading/modify-order). ## Participant fairness All participants are subject to identical matching logic and the same latency rules. No account type, VIP tier, or market-making agreement grants matching priority, a separate venue, or a preferential queue. Internal liquidity follows the same rules as external order flow — no priority lane and no separate aggregation layer. The engine applies no prioritization by request type (submit, cancel, modify, bulk), order type (limit, market, IOC, post-only), or product (spot versus margin). The unified-path design is deliberate: a single prioritization model across every flow sustains the engine's throughput at high request rates. [Self-Trade Prevention](/platform/self-trade-prevention) and [order type](/concepts/order-types) flags change how an individual order behaves, not where the order sits in the matching sequence. ## What's Next Execution flags — IOC, post-only, reduce-only — and how each behaves. Colocation, quoting strategy, and the matching-engine-zone endpoint subset. STP modes for accounts running two-sided quotes. # Order Types Source: https://docs.whitebit.com/concepts/order-types All 7 order types supported by WhiteBIT, each type's availability across market types, and time-in-force options. WhiteBIT supports 7 order types across spot, margin, and futures markets. Every order operation requires authentication. The REST endpoints listed on this page all use the `POST` method; the same order types become reachable over the WebSocket transport as JSON-RPC methods (global platform only) — see [WebSocket Order Management](/websocket/order-management/overview). ## Order types overview | Order Type | Spot | Margin | Futures | Description | | - | - | - | - | - | | Market | Yes | Yes | Yes | Execute immediately at best available price | | Limit | Yes | Yes | Yes | Execute at a specified price or better | | Advanced-Limit | Yes | No | No | Limit order with IOC or post-only conditions (spot only) | | Stop-Market | Yes | Yes | Yes | Trigger at stop price, execute as market order | | Stop-Limit | Yes | Yes | Yes | Trigger at stop price, place limit order | | Multi-Limit (Bulk) | Yes | Yes | Yes | Place up to 20 limit orders in a single API call | | OCO | No | Yes | Yes | One-Cancels-Other: two linked orders (margin/futures only) | Verify availability per market type in the [API Reference](/api-reference/trading/spot-overview). ## Market orders A market order executes at the best available price immediately. No price parameter is needed. Orders fill immediately subject to available liquidity. Market orders are useful for exiting positions quickly when price precision matters less than execution speed. * Spot endpoint: `POST /api/v4/order/market` — [API Reference](/api-reference/trading/create-market-order) * Spot stock market endpoint: `POST /api/v4/order/stock_market` — always denominated in the base (stock) currency * Collateral endpoint: `POST /api/v4/order/collateral/market` **Slippage protection (taker band).** The matching engine caps how far a market order can sweep the book. If the order would execute beyond the taker band, it is partially filled up to the band and the remainder is canceled, and the order returns the status `CANCELED_TAKER_BAND`. This protects against excessive slippage during thin liquidity or volatility spikes — handle this status as a partial fill plus a canceled remainder rather than a failure. ## Limit orders A limit order specifies an exact price. The order rests on the orderbook until filled or canceled. Maker fees apply when the order provides liquidity rather than consuming it. Limit orders are the most common order type for automated trading. **Post-only mode:** Setting `postOnly: true` ensures the order is placed as a maker order. If the order would immediately match an existing order, the API rejects the request instead of allowing a taker fill. * Spot endpoint: `POST /api/v4/order/new` — [API Reference](/api-reference/trading/create-limit-order) * Collateral endpoint: `POST /api/v4/order/collateral/limit` ## Advanced-Limit orders An Advanced-Limit order is a spot limit order with additional execution conditions. Setting `ioc: true` (Immediate-or-Cancel) causes the order to fill what it can immediately and cancel any unfilled portion. IOC is available on spot markets only. See `POST /api/v4/order/new` with the `ioc` flag — [API Reference](/api-reference/trading/create-limit-order). The `ioc` flag and `postOnly` flag are mutually exclusive. Setting both to `true` returns error code `37`. ## Stop-Market orders A stop-market order uses a trigger price as a condition. When the market reaches the trigger price, a market order is placed immediately. Stop-market orders are common for stop-loss scenarios where immediate execution at market price is preferred over price control. * Spot endpoint: `POST /api/v4/order/stop_market` * Collateral endpoint: `POST /api/v4/order/collateral/trigger-market` ## Stop-Limit orders A stop-limit order uses two prices — a trigger price and a limit price. When the market reaches the trigger price, a limit order is placed at the specified limit price. Stop-limit orders provide more price control than stop-market orders but may not execute if the market moves past the limit price. * Spot endpoint: `POST /api/v4/order/stop_limit` * Collateral endpoint: `POST /api/v4/order/collateral/stop-limit` ## Multi-Limit orders (Bulk) Multi-Limit allows placing up to 20 limit orders in a single API call. Available on spot and collateral (margin/futures) markets. Designed for market makers managing many price levels simultaneously without issuing separate requests per order. * Spot endpoint: `POST /api/v4/order/bulk` — [API Reference](/api-reference/trading/bulk-limit-order) * Collateral endpoint: `POST /api/v4/order/collateral/bulk` ## OCO orders An OCO (One-Cancels-Other) order pairs two linked orders — typically a take-profit limit and a stop-loss stop-limit. When one leg executes, the system automatically cancels the other. Available on margin and futures markets only (collateral balance required). * Collateral endpoint: `POST /api/v4/order/collateral/oco` ## Reduce-only orders A reduce-only order guarantees that the order only decreases or closes an existing position — the order cannot increase the position or open a new one in the opposite direction. Available on collateral (margin and futures) markets only. **Behavior** * If the order amount exceeds the current position size, the system automatically reduces the order to match the position — the response returns the adjusted amount. * The reduction applies on placement and execution. * `reduceOnly` is set at order creation and cannot be changed via order modification. * Cannot be combined with `stopLoss` or `takeProfit` parameters (the API returns error code `30`). * Set `reduceOnly: true` in the request body of any collateral order creation endpoint. **Rejection** The API returns error code `116` synchronously if: * No open position exists for the specified market * The order direction matches the position direction (e.g., a buy reduce-only order on a long position) ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 116, "errors": { "reduceOnly": [ "Reduce-only: Position doesn't exist or wrong side" ] }, "message": "Validation failed" } ``` **Auto-cancellation** If a position closes while a reduce-only limit order is still pending, the backend auto-cancels the order with status `AUTO_CANCELED_REDUCE_ONLY`. The same status applies whether the position closes through a standard close path or through [Auto-Deleveraging](/concepts/auto-deleveraging) — no ADL-specific cancel status was introduced. **Supported endpoints** | Endpoint | Path | | - | - | | Collateral limit order | [`POST /api/v4/order/collateral/limit`](/api-reference/trading/collateral-limit-order) | | Collateral bulk limit order | [`POST /api/v4/order/collateral/bulk`](/api-reference/trading/collateral-bulk-limit-order) | | Collateral market order | [`POST /api/v4/order/collateral/market`](/api-reference/trading/collateral-market-order) | | Collateral stop-limit order | [`POST /api/v4/order/collateral/stop-limit`](/api-reference/trading/collateral-stop-limit-order) | | Collateral trigger market order | [`POST /api/v4/order/collateral/trigger-market`](/api-reference/trading/collateral-trigger-market-order) | | Collateral OCO order | [`POST /api/v4/order/collateral/oco`](/api-reference/trading/create-collateral-oco-order) | For OCO orders, `reduceOnly` is a single top-level parameter that applies to both the take-profit and stop-loss legs simultaneously. ## Execution flags | Flag | Behavior | Available on | | - | - | - | | Default (neither flag) | GTC — order remains active until filled or manually canceled | All limit-type orders | | `ioc: true` | IOC — fills immediately what it can; cancels the unfilled remainder | Limit orders (spot only via `order/new`) | | `postOnly: true` | Post-only — rejects the order if it would match immediately (ensures maker) | All limit-type orders | | `reduceOnly: true` | Reduce-only — order can only decrease or close an existing position | Collateral orders only | ## Regional restrictions In some regions the set of available order types and execution flags is narrower than the global default. The restriction is applied at order creation: a request for an order type, flag, or BBO role that is not available in the active region is rejected synchronously with HTTP status `453`. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": 30, "errors": { "orderType": [ "This order type is not available" ] }, "message": "Validation failed" } ``` These limits currently apply to the **EU** region only. Every other region keeps the full set of order types described above. ### EU region In the EU region, the available order types are restricted to meet applicable regulatory requirements. As a result: * **Spot** exposes only `market`, `advanced-limit`, and `stop-market`. On `advanced-limit` the `ioc` flag is forced (`required: true`) and the BBO role is locked to `counterparty` — a maker (post-only / queue) order cannot be placed. * **`limit`, `multi-limit`, `stop-limit`, and `oco` are not available** on spot. * **Margin and futures are not available** — requesting order types for these trade types returns an empty list, and order creation is rejected. ### New-listing window Independent of region, while a market has not yet been fully listed (its trading-open time is still in the future) only a single **post-only limit** order is accepted. Every other order type and flag combination returns `453` until the market is fully listed. This applies because a maker order cannot rest against the empty order book of a not-yet-listed asset. ## Related features * **Client Order ID** — Attach a custom identifier to orders for tracking. See [Client Order ID guide](/guides/client-order-id). * **Kill-switch** — Emergency cancellation mechanism that cancels a market's active orders after a configurable timeout, one timer per market. Endpoints: `POST /api/v4/order/kill-switch` (activate) and `POST /api/v4/order/kill-switch/status` (check). * **Self-Trade Prevention** — Prevents an account's orders from matching against each other. See [Self-Trade Prevention](/platform/self-trade-prevention). * **Reduce-only** — Guarantees an order only decreases or closes an existing position. See [Reduce-only orders](#reduce-only-orders) above. ## What's Next Place orders on 800+ spot pairs. Leveraged trading up to 10×. Full endpoint documentation for all order types. # Travel Rule Source: https://docs.whitebit.com/concepts/travel-rule Regulatory requirement for VASPs to share originator and beneficiary information for cryptocurrency transfers. The Travel Rule requires Virtual Asset Service Providers (VASPs) to share originator and beneficiary information for cryptocurrency transfers above certain thresholds. This regulatory requirement, mandated by frameworks like FATF and MiCA, helps prevent money laundering and terrorist financing. WhiteBIT provides API endpoints for Travel Rule compliance, enabling B2B clients to submit required data for deposits and withdrawals. *** ## When Travel Rule applies Travel Rule verification is required when: * The transaction involves cryptocurrency deposits or withdrawals * The account is registered in the [European Economic Area (EEA)](/glossary#european-economic-area-eea) * The transaction meets regional threshold requirements * The Travel Rule API is enabled for the account The Travel Rule API is not available to all accounts. To request access, contact the assigned Account Manager or email [institutional@whitebit.com](mailto:institutional@whitebit.com). *** ## Wallet types | Type | Description | VASP required | | - | - | - | | `hosted` | VASP-hosted wallet (exchange, custodian) | Yes — provide `vaspData` object | | `unhosted` | Self-custody wallet (hardware, software) | No | *** ## Party types | Type | Description | Required fields | | - | - | - | | `individual` | Natural person | `firstName`, `lastName`, `residenceCountry`, `address` | | `entity` | Legal entity | `fullName`, `residenceCountry`, `address` | *** ## VASP identification When the destination or originating wallet is hosted: * **VASP in list** — Use `vaspId` from the [Get VASPs endpoint](/api-reference/travel-rule/get-vasps) response * **VASP not in list** — Use `vaspName` with the VASP's name as a string fallback *** ## Country codes All country fields use [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) codes (3-letter): | Code | Country | | - | - | | `DEU` | Germany | | `GBR` | United Kingdom | | `NLD` | Netherlands | | `FRA` | France | | `USA` | United States | *** ## Deposit verification ### Flow ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Client participant WhiteBIT API participant Compliance Note over Client,Compliance: Deposit arrives and is detected as Travel Rule-eligible Client->>WhiteBIT API: GET /api/v4/main-account/history WhiteBIT API-->>Client: Deposit with status "ready for verification" Client->>WhiteBIT API: POST /api/v4/travel-rule/vasps WhiteBIT API-->>Client: List of available VASPs Client->>WhiteBIT API: POST /api/v4/travel-rule/deposit/verification Note right of Client: Submit originator data
(walletType, originator, vaspData) WhiteBIT API->>Compliance: Review originator data alt Approved Compliance-->>WhiteBIT API: Approved WhiteBIT API-->>Client: status: "approved" Note over Client,Compliance: Deposit credited to account else Rejected Compliance-->>WhiteBIT API: Rejected WhiteBIT API-->>Client: status: "rejected" Note over Client,Compliance: Deposit canceled end ``` Verification is performed against the originator (sender) address the deposit came from, not the generated deposit address. Status 28 means the submitted data is under review; it resolves either to a successful credit or to a rejection. A rejected deposit is canceled rather than refunded automatically. To return the funds, submit a separate refund request via [Refund deposit](/api-reference/account-wallet/refund-deposit) (`POST /api/v4/main-account/refund-deposit`). Deposits canceled under Travel Rule are eligible for refund. ### Deposit examples **Individual from hosted wallet (VASP in list):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "uniqueId": "550e8400-e29b-41d4-a716-446655440000", "walletType": "hosted", "originator": { "type": "individual", "firstName": "Alice", "lastName": "Johnson", "residenceCountry": "NLD", "walletAddress": "0x9876543210fedcba9876543210fedcba98765432", "address": { "country": "NLD", "city": "Amsterdam", "addressLine1": "Damrak 1" } }, "vaspData": { "vaspId": "vasp-002" } } ``` **Entity from hosted wallet (VASP not in list):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "uniqueId": "550e8400-e29b-41d4-a716-446655440000", "walletType": "hosted", "originator": { "type": "entity", "fullName": "Acme Corporation Ltd", "residenceCountry": "GBR", "walletAddress": "0xabcdef1234567890abcdef1234567890abcdef12", "address": { "country": "GBR", "city": "London", "postCode": "EC2A 4BX", "addressLine1": "123 Finsbury Square" } }, "vaspData": { "vaspName": "Famous Vasp Inc" } } ``` **Individual from unhosted wallet:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "uniqueId": "550e8400-e29b-41d4-a716-446655440000", "walletType": "unhosted", "originator": { "type": "individual", "firstName": "Bob", "lastName": "Smith", "residenceCountry": "DEU", "walletAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", "address": { "country": "DEU", "city": "Berlin", "addressLine1": "Alexanderplatz 1" } } } ``` *** ## Withdrawal with Travel Rule ### Flow ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Client participant WhiteBIT API participant Compliance Client->>WhiteBIT API: POST /api/v4/travel-rule/vasps WhiteBIT API-->>Client: List of available VASPs Client->>WhiteBIT API: POST /api/v4/main-account/withdraw Note right of Client: Include travelRule object
(walletType, beneficiary, vaspData) WhiteBIT API->>Compliance: Review beneficiary data alt Approved Compliance-->>WhiteBIT API: Approved WhiteBIT API-->>Client: Withdrawal processed Note over Client,Compliance: Funds sent to destination else Rejected Compliance-->>WhiteBIT API: Rejected WhiteBIT API-->>Client: Withdrawal canceled Note over Client,Compliance: Funds returned to account end ``` ### Withdrawal examples **Individual to hosted wallet (VASP in list):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "ticker": "BTC", "amount": "0.5", "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", "uniqueId": "withdraw-tr-001", "travelRule": { "walletType": "hosted", "beneficiary": { "type": "individual", "firstName": "John", "lastName": "Doe", "residenceCountry": "DEU", "address": { "country": "DEU", "city": "Berlin", "addressLine1": "Alexanderplatz 1" } }, "vaspData": { "vaspId": "vasp-001" } } } ``` **Entity to hosted wallet (VASP not in list):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "ticker": "USDT", "amount": "10000", "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f8a2B1", "network": "ERC20", "uniqueId": "withdraw-tr-002", "travelRule": { "walletType": "hosted", "beneficiary": { "type": "entity", "fullName": "Acme Trading Ltd", "residenceCountry": "GBR", "address": { "country": "GBR", "city": "London", "postCode": "EC2A 4BX", "addressLine1": "123 Finsbury Square" } }, "vaspData": { "vaspName": "Famous Vasp Inc" } } } ``` **Individual to unhosted wallet:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "ticker": "ETH", "amount": "2.5", "address": "0xabcdef1234567890abcdef1234567890abcdef12", "uniqueId": "withdraw-tr-003", "travelRule": { "walletType": "unhosted", "beneficiary": { "type": "individual", "firstName": "Jane", "lastName": "Smith", "residenceCountry": "NLD", "address": { "country": "NLD", "city": "Amsterdam", "addressLine1": "Damrak 1" } } } } ``` *** ## Legacy format (withdrawals only) The API still accepts the legacy flat format for withdrawals, but it will **not pass Travel Rule verification**. To complete Travel Rule compliance, use the new structured format. **Field mapping:** | Legacy field | New field | | - | - | | `type` | `beneficiary.type` | | `vasp` | `vaspData.vaspId` or `vaspData.vaspName` | | `name` | `beneficiary.firstName` (individual) or `beneficiary.fullName` (entity) | | `address` | `beneficiary.lastName` (individual) or `beneficiary.address` (entity) | **Legacy format example (will not pass verification):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "ticker": "BTC", "amount": "0.5", "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", "uniqueId": "withdraw-tr-legacy", "travelRule": { "type": "individual", "vasp": "Binance", "name": "John", "address": "Doe" } } ``` *** ## What's next Retrieve the list of VASPs for travel rule submissions. Submit originator data for a deposit pending verification. Create withdrawals with travel rule data. European Economic Area countries where Travel Rule applies. # FAQ Source: https://docs.whitebit.com/faq Find answers to common questions about the WhiteBIT API, trading, deposits and withdrawals, webhooks, institutional onboarding, compliance, and integration. ## Rate limits and errors Rate limit 429 errors occur when an endpoint exceeds the rate limit. To resolve: * Wait for the rate limit window to reset * Check the specific rate limit value in the endpoint documentation * Implement rate limiting in code For more details, see the [API v4 overview](/api-reference/market-data/overview). CORS requests to the ticker endpoint are forbidden for security reasons. Make the request from a backend server instead of client-side code. For endpoint details, see the [Market activity endpoint](/api-reference/market-data/market-activity). Nonce errors occur when timestamps or request ordering are invalid. To resolve: 1. Debug the code implementation 2. Recreate API keys 3. Ensure system time is properly synchronized For details on nonce requirements, see the [Authentication guide](/api-reference/authentication). For full details on HMAC-SHA512 signing and nonce requirements, see [Authentication](/api-reference/authentication). Lending endpoints require B2B partner permissions. This applies to both Fixed (`/api/v4/main-account/smart/`) and Flex (`/api/v4/main-account/smart-flex/`) endpoints. Until access is granted, these endpoints return `403` with the message `You don't have permission to use this endpoint. Please contact support for more details`. To gain access: * Fill the institutional services form at [https://whitebit.com/institutional-services/b2b](https://whitebit.com/institutional-services/b2b) * Provide use case details For endpoint details, see the [Crypto Lending documentation](/api-reference/account-wallet/get-plans). The most frequent API errors and corresponding causes: `422` — validation failed (check required parameters); `429` — rate limit exceeded (wait for window reset); `401` — authentication failed (check API key and HMAC signature); `403` — insufficient permissions (verify API key permissions). See [Errors and Error Handling](/api-reference/rate-limits) for the complete error code reference. ## WebSocket Multiple time periods for pairs are available through multiple WebSocket connections or the HTTP method. Two solutions: 1. Open multiple WebSocket connections 2. Use the equivalent HTTP method instead For more details, see the [Kline documentation](/websocket/market-streams/kline). The system shows only the last 100 deals by default. To access more: * Subscribe to the WebSocket feed * Accumulate and store the data * Process the data as needed For more details, see the [Trades channel documentation](/websocket/market-streams/trades). WhiteBIT offers colocation across EEA/EMEA and APAC regions. Colocation provides access to a subset of 35 trading endpoints. See [Colocation](/platform/colocation) for infrastructure details and the [Market Maker Guide](/guides/market-maker-integration) for the full endpoint list. ## Transfers and withdrawals Transfers may take up to 2 seconds to complete. When making transfers and withdrawals: * Wait for transfers to complete (approximately 2 seconds) * Avoid initiating withdrawals before transfer completion * Implement proper error handling for transfer states For endpoint details, see the [Transfer between balances](/api-reference/account-wallet/transfer-between-balances) documentation. For details on account types (Main, Trade, Collateral), see [Balances & Transfers](/concepts/balances). Withdrawal amount plus fee must not exceed the available balance. Calculate the total required using the [fee endpoint](/api-reference/account-wallet/get-fees). Check the withdrawable amount before initiating a withdrawal. If the issue persists, review open orders possibly reserving funds. See [Balances & Transfers](/concepts/balances) for explanation of available vs. frozen balances. Each cryptocurrency network requires a specific number of block confirmations before a deposit is credited. The webhook payload includes `confirmations.actual` and `confirmations.required` fields. Check the [Asset Status endpoint](/api-reference/market-data/asset-status-list) for per-currency confirmation requirements. Since December 30, 2024, EEA users cannot deposit, withdraw, or create WhiteBIT Codes in USDT. Use USDC (Circle holds an EU e-money license) or EURI (euro-pegged, MiCA-compliant) as alternatives. See [Regulatory Compliance](/institutional/compliance) for details. Deposits below the minimum amount for a currency are not credited to the account balance. Check the minimum deposit amount via the [Asset Status endpoint](/api-reference/market-data/asset-status-list) before generating deposit addresses. No mechanism exists to recover below-minimum deposits. ## Webhooks HTTPS is required for Webhook API communication: * Communication occurs over port 443 * SSL/TLS encryption is mandatory * HTTP connections are not supported For more details, see the [Webhook documentation](/platform/webhook). Each webhook request includes an `X-TXC-APIKEY` header and an `X-TXC-PAYLOAD` + `X-TXC-SIGNATURE` for verification. Verify the HMAC-SHA512 signature using the webhook secret key to confirm the request originates from WhiteBIT. See the [Webhook](/platform/webhook) reference for the full verification flow. WhiteBIT retries failed webhook deliveries 5 times at 10-minute intervals, providing up to 50 minutes of coverage. There is no replay mechanism after the retry window expires. Implement polling of the deposit and withdrawal history endpoints as a fallback for outages exceeding 50 minutes. See [Webhook](/platform/webhook) for details. ## API and assets Check currency status through the assets endpoint: * URL: [https://whitebit.com/api/v4/public/assets](https://whitebit.com/api/v4/public/assets) * The endpoint provides real-time status of all currencies * Check the currency-specific enabled/disabled flags For endpoint details and response schema, see the [Asset status list](/api-reference/market-data/asset-status-list) documentation. ## Trading The API uses "collateral" as a shared prefix for both Margin Trading (up to 10x leverage on spot pairs like `BTC_USDT`) and Futures Trading (up to 100x leverage on perpetual pairs like `BTC_PERP`). The market pair determines the product — not the endpoint path. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. See [Margin Trading](/products/margin/overview) and [Futures Trading](/products/futures/overview). Each market has a minimum order amount (`minAmount`) and minimum order value (`minTotal`). Retrieve these values from `GET /api/v4/public/markets` (spot) or `GET /api/v4/public/futures` (futures). Orders below the minimum are rejected. See [Markets & Trading Pairs](/concepts/markets). The kill-switch automatically cancels all active orders after a configurable timeout. Activate via `POST /api/v4/order/kill-switch` with a `timeout` parameter (in seconds). Use `POST /api/v4/order/kill-switch/status` to check the current state. Designed as a safety mechanism for automated trading strategies. See the [Market Maker Guide](/guides/market-maker-integration) for usage patterns. The bulk order endpoint (`POST /api/v4/order/bulk`) accepts up to 20 limit orders in a single request. All orders in the batch must be for the same market pair. The collateral bulk endpoint (`POST /api/v4/order/collateral/bulk`) follows the same 20-order limit. The price returned in a market order response may reflect an internal limit price, not the actual execution price. To obtain the true fill price, check the trade history via `POST /api/v4/trade-account/executed-history` or subscribe to the WebSocket deals channel. See [Order Types](/concepts/order-types) for market order execution details. A reduce-only order guarantees that the order only decreases or closes an existing position — the order cannot increase the position or open a new one. Set `reduceOnly: true` on any collateral order creation endpoint. Available on margin and futures markets only. If no open position exists or the order direction matches the position direction, the API returns error code `116`. If the order amount exceeds the current position size, the system reduces the order to match automatically. Pending reduce-only orders are auto-canceled with status `AUTO_CANCELED_REDUCE_ONLY` when the associated position closes. See [Order Types — Reduce-only orders](/concepts/order-types#reduce-only-orders) for full details. ## Security and API keys Store API keys securely using environment variables, restrict IP access, and use minimum required permissions. Never commit keys to version control. For details, see the [Authentication guide](/api-reference/authentication). For comprehensive security guidance, see [Security Best Practices](/best-practices/security). Immediately delete the compromised key, review account activity for unauthorized actions, and create new API keys. Contact support if unauthorized activity is detected. For details, see the [Authentication guide](/api-reference/authentication). The platform automatically deactivates an API key that receives no requests for 14 consecutive days. An IP whitelist does not exempt a key from this rule — whitelisted and non-whitelisted keys deactivate on the same schedule. Reactivate a deactivated key at [whitebit.com/settings/api](https://whitebit.com/settings/api). See [Key rotation](/best-practices/security#key-rotation). Send at least one authenticated request from each spare key every 14 days. Any authenticated endpoint resets the inactivity timer — a balance check via `POST /api/v4/main-account/balance` is sufficient. Keys held in reserve without periodic traffic deactivate on the same schedule as unused keys. See [Main balance](/api-reference/account-wallet/main-balance). An API key becomes disabled after 14 consecutive days without requests, or when deactivated from the account settings. Check the key status at [whitebit.com/settings/api](https://whitebit.com/settings/api), resolve the cause, then re-enable the key. See [Security best practices](/best-practices/security). ## API usage Use WebSocket for real-time data, batch requests when possible, implement proper rate limiting, and cache frequently accessed data. For details, see the [WebSocket API](/websocket/market-streams/overview). For rate limit tiers and endpoint-specific limits, see [Rate Limits](/api-reference/rate-limits). For colocation infrastructure, see the [Market Maker Guide](/guides/market-maker-integration). Implement automatic reconnection with exponential backoff. Maintain local order state and set up monitoring and alerts for connection issues. For details, see the [WebSocket API](/websocket/market-streams/overview). For a pre-launch readiness checklist including reconnection testing, see the [Go-Live Checklist](/best-practices/go-live-checklist). Start with the [First API Call](/guides/first-api-call) guide for an orientation. The recommended path: create an API key, make a public endpoint call (no auth required), then authenticate a private endpoint call. Official SDKs exist for Go, Python, and PHP. See the [SDKs page](/sdks) for installation instructions and GitHub links. For raw HMAC-SHA512 signing without an SDK, see [First API Call](/guides/first-api-call). WhiteBIT does not offer a public testnet or sandbox. For risk-free Spot testing, activate Demo Tokens (DBTC + DUSDT) from the [WhiteBIT Codes page](https://whitebit.com/codes) — no KYC required. Trade the `DBTC_DUSDT` pair via the standard API to validate the full order lifecycle without real funds. For Margin, Futures, and fund-movement testing, use minimum order sizes on the live API. See the [Go-Live Checklist](/best-practices/go-live-checklist) for the complete testing strategy. Use the REST API for one-time request–response calls: checking balances, fetching trade history, and placing orders. Use the WebSocket API for real-time streaming data: live orderbook updates, trade feeds, and balance changes. Order placement, modification, and cancellation are also available over WebSocket as an alternative transport, on the global platform only — the [order methods](/websocket/order-management/overview) run on the same authorized connection as the streams, which suits low-latency placement without opening and re-authenticating a connection per request. REST polling at high frequency consumes rate limits — switch to WebSocket for data that updates continuously. See [Rate Limits](/api-reference/rate-limits) for REST constraints, [WebSocket Rate Limits](/websocket/rate-limits) for the per-connection WebSocket request budgets, [WebSocket Quickstart](/guides/websocket-quickstart) for streaming setup, and [Order Management](/websocket/order-management/overview) for the WebSocket order methods. Official SDKs are available for Go, Python, and PHP. Check the [SDKs page](/sdks) for current version, maintenance status, and whether each SDK handles HMAC signing automatically. Public endpoints (market data, tickers, orderbook) require no account or authentication. Private endpoints (trading, account management) require API keys — create these keys in account Settings. Institutional features (colocation, OTC, Embedded Trading) require [institutional onboarding](/institutional/onboarding). See [First API Call](/guides/first-api-call) for the recommended integration path. ## Institutional and partner onboarding WhiteBIT offers Market-Making Programs, Embedded Trading (up to 40% fee share), Sub-Account management, OTC trading, Crypto Lending for business, colocation, and Liquidity Provision. See the [Institutional Overview](/institutional/overview) for the full catalog. Onboarding has two phases: Phase 1 (crypto access) requires account registration, KYC for the director, and KYB verification. Phase 2 (fiat/SEPA access) requires additional documentation through the fiat processing partner. See [Institutional Onboarding](/institutional/onboarding) for the step-by-step process. Base trading fees are 0.1% maker / 0.1% taker. The Market-Making Program offers rebates up to -0.012% maker. Embedded Trading provides up to 40% fee share on referred user trading fees; the applicable rate is agreed individually during enrollment. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) for volume-based arrangements. WhiteBIT does not offer a public testnet or sandbox. However, free Demo Tokens (0.5 DBTC + 1,000 DUSDT) are available for risk-free Spot trading via the [WhiteBIT Codes page](https://whitebit.com/codes) — no KYC required. The `DBTC_DUSDT` pair works with all standard Spot API endpoints. For Margin, Futures, and deposit/withdrawal testing, use minimum order sizes on the live API. See the [Go-Live Checklist](/best-practices/go-live-checklist) for the complete testing strategy. WhiteBIT holds licenses in multiple EU jurisdictions and maintains ISO 27001, PCI DSS, and CCSS security certifications, with the CCSS Level 3 assessment conducted by Hacken. GDPR compliance is maintained for data processing. For specific VASP authorization details and jurisdiction information, contact [institutional@whitebit.com](mailto:institutional@whitebit.com). See [Regulatory Compliance](/institutional/compliance). Colocation is available across EEA/EMEA and APAC regions. Access is limited to a subset of 35 trading endpoints. See [Colocation](/platform/colocation) for setup details and the [Market Maker Guide](/guides/market-maker-integration) for the full endpoint list. A sub-account created with its own email address (dedicated KYC, `shareKyc: false`) must have that email confirmed before permissions can be configured. The end customer confirms it by opening the personal link from [`POST /api/v4/sub-account/kyc-url`](/api-reference/sub-accounts/kyc-url) and completing verification, which covers both identity verification and email confirmation. Permissions configured before that confirmation are not retained. Re-apply the permission set with [`POST /api/v4/sub-account/edit`](/api-reference/sub-accounts/edit-sub-account) once the sub-account is active, and send the full `permissions` object on every edit: flags omitted from an edit request are turned off without a warning. A sub-account created with `shareKyc: true` accepts permissions immediately at creation. See the [Sub-account integration guide](/guides/sub-account-integration) for the full flow. ## Compliance and regulatory Since December 30, 2024, EEA accounts cannot deposit, withdraw, or create WhiteBIT Codes in USDT under MiCA regulation. USDC and EURI are available as compliant alternatives. See [Regulatory Compliance](/institutional/compliance) for the full list of affected operations and recommended alternatives. Since May 19, 2025, crypto withdrawals from EEA accounts require a `travelRule` object in the withdrawal request body. The object uses a structured format: `walletType` (hosted or unhosted destination), `beneficiary` (receiver details), and `vaspData` (destination platform identification). See [Regulatory Compliance](/institutional/compliance) for the field reference and code examples. WhiteBIT holds ISO 27001, PCI DSS, and CCSS security certifications, with the CCSS Level 3 assessment conducted by Hacken. GDPR is a regulation (not a certification) — WhiteBIT processes data in accordance with GDPR requirements. For audit reports or verification details, contact [institutional@whitebit.com](mailto:institutional@whitebit.com). ## What's Next First steps for API integration — account setup, API keys, and the first authenticated call. Find the recommended integration path for market makers, account operators, bot platforms, wallet backends, payment providers, prop firms, and institutional clients. # Glossary Source: https://docs.whitebit.com/glossary Comprehensive glossary of trading terms, cryptocurrency concepts, and WhiteBIT platform terminology. ## A [Orders](#orders) running for the duration of the trading day. An indicator value from 0 to 4 reflecting a position's place in the per-market [Auto-Deleveraging](#auto-deleveraging-adl) ranking. Higher Grade signals higher likelihood of selection as an ADL counterparty. Grade 4 corresponds to the asymptotic top 5% of the ranked list. See [ADL Grade](/concepts/auto-deleveraging#adl-grade). Anti-Money Laundering. Controls and checks to detect and prevent money laundering. WhiteBIT runs AML checks on deposit and withdrawal flows. Sell [order](#orders). A digital representation of value transferable, storable, or tradable electronically. In Model B (customers' own accounts), the mechanism that links an end user's WhiteBIT account and activity to the partner that onboarded the user, so fee-share and reporting apply without the partner holding the account. See [Integration models](/concepts/integration-models). Final-stage liquidation mechanism on the futures market. Activates only when standard market liquidity cannot fully cover a liquidated position. Closes profitable counterparty positions on the opposite side at a calculated price, ensuring no user balance becomes negative. See [Auto-Deleveraging](/concepts/auto-deleveraging). ## B An account designation for business-to-business (B2B) institutional partner services. Certain endpoint groups require a B2B partner account — for example fixed [lending](/products/lending/overview) plans and the [Travel Rule](#travel-rule) API — and canceled orders are not recorded in order history. Request access through the [institutional services form](https://whitebit.com/institutional-services/b2b). Balance for [margin](#margin-trading) and [futures trading](#futures-trading) A balance accepting deposits and withdrawals of cryptocurrency and national currency. Balance for [spot trading](#spot-trading). This balance supports non-marginal trading ([order](#orders) placement) and currency exchange. Best-bid-offer (BBO) determines [limit order](#limit-order) prices based on market conditions. In the counterparty method, for buy orders the system uses the lowest ask price in the [order book](#order-book); for sell orders, the highest bid price. The queue method uses the highest current buy price (Bid) for buy orders and the highest ask price for sell orders. Buy [order](#orders). ## C A unique identifier for a card, used to facilitate payments and manage subscriptions without exposing the actual card information. See [WhiteBIT Codes](#whitebit-codes) The cryptocurrency [asset](#assets) pledged by the borrower as a guarantee of loan repayment. The practice of placing trading servers in close physical proximity to an exchange's [matching engine](#matching-engine) to minimize [latency](#latency). Colocation is crucial for [high-frequency trading (HFT)](#high-frequency-trading-hft) operations. "Conditional orders" is a collective term for [orders](#orders) with conditions. Currently, these include [OTO](#one-triggers-the-other-oto) (One Triggers the Other) and [OCO](#oco-orders) (One Cancels the Other) orders. Crypto Lending enables earning passive income by lending funds to the exchange in a chosen cryptocurrency for a set period. ## D A transaction where two parties buy or sell an [asset](#assets) at an agreed-upon price. The trade record includes the price, amount, date, and any [fees](#fee). Test assets for risk-free Spot trading on the live platform. WhiteBIT has no public testnet — activate free demo tokens (0.5 DBTC + 1,000 DUSDT) from the [WhiteBIT Codes page](https://whitebit.com/codes) with no KYC required, and trade the `DBTC_DUSDT` pair through the standard API endpoints. Demo tokens support Spot trading only. Crypto derivatives are contracts deriving value from a primary underlying [asset](#assets). The primary asset is a cryptocurrency such as Bitcoin. See [Order book](#order-book). ## E A position-level metric used in the [Auto-Deleveraging](#auto-deleveraging-adl) Rating formula. Defined as `|position size in money| / account equity`. Distinct from configured account [leverage](#leverage) — effective leverage scales with position size relative to the account's [collateral balance](#balance-collateral), not with the leverage setting alone. See [Rating formula](/concepts/auto-deleveraging#rating-formula). The EEA is an international agreement enabling the extension of the European Union's single market to non-EU member states. The EEA consists of the EU member states and three EFTA states (Iceland, Liechtenstein, and Norway). A gated B2B payment feature that charges a specific amount from a WhiteBIT user's [Main balance](#balance-main) to the partner's Main balance through a signed, single-use payment token valid for 90 seconds. The transfer settles instantly, off-chain, and without a [fee](#fee). See the [Payment Integration guide](/guides/payment-integration#express-withdraw-payments). ## F An OAuth-issued WhiteBIT API key that a partner platform obtains on behalf of an end user through the OAuth API key consent flow, replacing manual key creation and copy-paste. The API secret is retrievable by the partner exactly once through a Bearer-authenticated endpoint. Any IP restriction on the key is the end user's own account-level control, not a partner-managed allowlist. See the [Fast API Key integration guide](/guides/fast-api-key-integration). The platform charges a fee for crypto transactions. A currency (a medium of exchange) established by government regulation as [money](#money) but without intrinsic value (value independent of the nominal value, such as a precious metal might have). A list of all completed (executed) [orders](#orders) including order ID, date, amount, price, conditions, and other relevant data. See [Perpetual futures](#perpetual-futures) Futures trading supports opening Long and Short positions and using [leverage](#leverage). Traders pay a [fee](#fee) for using borrowed funds to each other, not to the exchange. ## G An automated strategy that places [limit orders](#limit-order) at fixed price intervals around a center price. When a buy order fills, the strategy places a sell order one grid level above; when a sell order fills, the strategy places a buy order one level below. Profit comes from price oscillation within the grid range. See the [Trading Bot guide](/guides/building-a-trading-bot) for the strategy walkthrough. ## H An account-level setting for collateral trading accounts that allows simultaneous long and short [positions](#position-side) on the same market; when disabled, the account operates in one-way mode. Toggling requires zero open positions. See [Collateral account hedge mode](/api-reference/trading/collateral-account-hedge-mode) and [Update collateral account hedge mode](/api-reference/trading/update-collateral-account-hedge-mode). An automated trading strategy involving executing a large number of [orders](#orders) at extremely high speeds, typically utilizing [colocation](#colocation) services to minimize [latency](#latency). A keyed hash algorithm that signs private REST API requests: the client computes `hex(HMAC_SHA512(payload, key=api_secret))` and sends the result in the `X-TXC-SIGNATURE` header. See [Authentication](/api-reference/authentication) for the full signing scheme. ## I Restricting an API key to accept requests only from pre-approved IP addresses, with up to 50 addresses per key. Configure the whitelist at the API settings page. See [Security Best Practices](/best-practices/security) for key-management guidance. ## J ## K A function to cancel all [orders](#orders) on a specific market automatically when the timer expires. Each timer covers a single market and can be restricted to spot, margin, or futures order types. Know Your Business. Verification of a business entity's identity and ownership, the corporate counterpart of [KYC](#kyc). Part of [Institutional Onboarding](/institutional/onboarding). Know Your Customer. Identity verification of an individual customer before trading or withdrawing. ## L The time delay between sending a trading order and order execution. In [high-frequency trading](#high-frequency-trading-hft), traders measure latency in milliseconds or microseconds. See [Crypto Lending](#crypto-lending) The ratio of [margin](#margin-trading) to borrowed funds shows how many times credit exceeds available [assets](#assets). A limit order specifies a fixed price for buying or selling an [asset](#assets). ## M A maker is a trader who places [limit orders](#limit-order) on the [order book](#order-book), setting the price and quantity of the [trade](#deal-trade), and waits for another trader to accept the [order](#orders). The use of exchange's funds to trade [assets](#assets) enables placing [orders](#orders) for sums exceeding the initial deposit several times. The initial deposit is called "margin," and the margin size depends on the [leverage](#leverage). [Assets](#assets) tradable for each other on an exchange. [Market](#market) information (last price, [volume](#volumetrade-volume), high, low, change) for the last 24 hours. A market order specifies an [asset](#assets) for immediate purchase or sale at the best available price. See [Market](#market) The core system of an exchange pairing buy and sell [orders](#orders). In [colocation](#colocation) setups, exchanges position trading servers close to the matching engine to minimize execution time. A special identifier some cryptocurrency networks require for transactions. Depositing and withdrawing some cryptocurrencies, such as Ripple (XRP) and Stellar (XLM), requires specifying a memo. Markets in Crypto-Assets. The European Union's regulatory framework for crypto-asset service providers. See [Regulatory Compliance](/institutional/compliance). The partner-operated sub-account model: the partner creates and manages one WhiteBIT sub-account per end user under a master account and holds the sub-account API key. Used by account operators and managed-trading platforms. See [Integration models](/concepts/integration-models). The customers'-own-accounts model: each end user holds a standalone WhiteBIT account and the partner connects through a [Fast API Key](#fast-api-key); WhiteBIT runs the KYC, and activity is linked to the partner by [attribution](#attribution). See [Integration models](/concepts/integration-models). The currency used to buy and sell [assets](#assets) on a trading platform. Cryptocurrency like USDT exists on different networks (e.g. OMNI, Tron, Ethereum). Traders select the network when making a deposit or withdrawal. ## N An arbitrary number used only once in a request. ## O An OCO order combines a [limit order](#limit-order) with a [stop-limit](#stop-limit-order); only one executes. When one order fills, the platform automatically cancels the other. A single pooled account holding multiple end users' funds together. WhiteBIT does not offer a pooled omnibus model for partner integrations — pooled custody conflicts with MiCA client-fund segregation and Travel Rule requirements, so each model keeps segregated sub-accounts. See [Integration models](/concepts/integration-models). OTO is a trading feature where fulfilling a primary [order](#orders) automatically sets corresponding stop loss and take profit orders. OTO allows specifying prices for stop loss and take profit when creating the primary order. A separated list of buy (bids) and sell (asks) [active orders](#active-orders) for a specific [market](#market). Simple contracts specifying the crypto to buy or sell, the quantity, and the price. Orders consist of [trades (deals)](#deal-trade). The execution of all deals executes the order. There are different types of orders: [Market order](#market-order), [Limit order](#limit-order), [Stop market order](#stop-market-order), [Stop limit order](#stop-limit-order), [OCO order](#oco-orders). Orders have either [executed (finished)](#finished-orders) or [unexecuted (active)](#active-orders) status. [Orders](#orders) requesting an exchange to buy or sell an [asset](#assets) at a set price and conditions. ## P See [Market](#market) A type of [derivative](#derivative) contract for trading cryptocurrencies with no expiration date and daily rollover. Profit and loss on a position. `grossPnl` is the realized profit and loss before funding, with trading fees already deducted; `netPnl` is `grossPnl` minus total funding. See [Closed-position PNL](/api-reference/trading/closed-position-pnl). Defines the position direction for a trade when hedge mode is enabled, and only for [perpetual futures](#perpetual-futures) trading [Market](#market). "LONG": Represents a long (buy) position. "SHORT": Represents a short (sell) position. "BOTH": Applies to both long and short positions, typically used in query contexts. The number of digits to the right of the decimal point. The order-matching rule used by the [matching engine](#matching-engine): better-priced [orders](#orders) fill first, and orders resting at the same price fill in the sequence of arrival at the engine. [Fiat](#fiat) currencies have different providers facilitating deposits and withdrawals by bank transfers. ## Q ## R Refund returns funds for a canceled [deposit](#whitebit-deposit-to-main-balance). The refund address must support the same network and [asset](#assets) as the original deposit. The refund address cannot be a WhiteBIT address. Use the [Refund deposit endpoint](/api-reference/account-wallet/refund-deposit) to request a refund. Retail Price Improvement (RPI) defines a [limit order](#limit-order) mode improving execution for retail users and keeping the order out of public market data feeds. RPI is a two-sided feature: makers submit RPI orders with `rpi=true`, and takers eligible to match against those orders set [`retail=true`](#retail-flag). **Visibility** Public `depth` and `bookTicker` feeds exclude RPI orders in both WebSocket and REST responses. Private active order endpoints and private WebSocket streams return RPI orders. The exchange UI [order book](#order-book) (web and mobile) displays RPI orders. **IOC compatibility** RPI orders use post-only behavior by design. An RPI order does not support the IOC flag. The API returns error code `40` when a request sets both `rpi=true` and `ioc=true`. **Fees** RPI executions apply a specific [fee](#fee) or rebate model defined for the account. When a user trades through a [sub-account](#sub-account), the system applies the effective sub-account fee configuration. Use [`Query Market Fees`](/api-reference/trading/query-market-fee) to retrieve account-wide fees, or [`Query Market Fee For A Single Market`](/api-reference/trading/query-market-fee-single) to retrieve the effective fee for one market. The `retail` request parameter on the [Create Limit Order](/api-reference/trading/create-limit-order) and [Bulk Limit Order](/api-reference/trading/bulk-limit-order) endpoints marks a [limit order](#limit-order) as a retail-source taker eligible to match against orders submitted by [Retail Price Improvement (RPI)](#retail-price-improvement-rpi) makers. The Retail flag is the taker-side counterpart to the `rpi` flag, which marks the maker side of the same feature. **Eligibility** The Retail flag must be enabled on the account before `retail=true` can be sent from a private-API source. Contact the account manager to enable the Retail flag. **Behavior** A retail taker is eligible to match against RPI-maker liquidity and may receive price improvement at execution. The flag has no effect when combined with `postOnly=true` — post-only orders are makers, never takers. **Combination with RPI** The Retail flag can be sent together with the `rpi` flag. An order with both `retail=true` and `rpi=true` is an RPI maker and matches exactly like an order with only `rpi=true`: the Retail flag has no effect on it, as on any post-only order. See [Order Parameter Rules](/guides/order-parameter-rules) for the complete list of unsupported parameter combinations. Reduce-only is an order parameter that guarantees an order only decreases or closes an existing position — never increases the position or opens a new one in the opposite direction. **Behavior** If the order amount exceeds the current position size, the system automatically reduces the order to match — the response returns the adjusted amount. This applies on placement and execution. **Rejection** The API returns error code `116` if no open position exists or the order direction matches the position direction. This is a synchronous rejection — the order is never created. **Auto-cancellation** If a position closes while a reduce-only [limit order](#limit-order) is still pending, the backend auto-cancels the order with status `AUTO_CANCELED_REDUCE_ONLY`. [Auto-Deleveraging](#auto-deleveraging-adl)-triggered closure also auto-cancels pending reduce-only orders with the same `AUTO_CANCELED_REDUCE_ONLY` status — no ADL-specific cancel status was introduced. **Availability** Available on collateral (margin and futures) markets only. See [Order Types — Reduce-only orders](/concepts/order-types#reduce-only-orders) for details and endpoint links. ## S STP is a mechanism preventing traders from executing trades against own [orders](#orders). STP helps avoid unintentional self-trading and ensures market integrity by automatically canceling or modifying orders resulting in a self-match. See [Crypto Lending](#crypto-lending) See [Crypto Lending](#crypto-lending) Buying and selling [assets](#assets) for immediate settlement. An [asset](#assets) tradable on an exchange. A stop-limit [order](#orders) has both the [stop](#stop-price) and the limit prices. When the market price at the [pair](#market) reaches the [stop price](#stop-price), the order activates and executes as a basic [limit order](#limit-order). A stop-market [order](#orders) executes when the market price reaches the [stop price](#stop-price). Traders use stop-market orders to limit losses during market volatility. A price set in advance to trigger a stop order. A main account manages a sub-account. The main account assigns specific permissions to the sub-account (for example, the main account disables [margin trading](#margin-trading)). Crypto deposits are a separately enabled capability and are disabled by default. Once enabled for the account, the capability applies to the account and its sub-accounts; to request it, contact the assigned Account Manager or email [institutional@whitebit.com](mailto:institutional@whitebit.com). A sub-account can use a custom trading [fee](#fee) or rebate model defined for the sub-account. Use [`Query Market Fees`](/api-reference/trading/query-market-fee) to retrieve effective fees when an API key belongs to a sub-account. [RPI](#retail-price-improvement-rpi) trading uses account-specific fees or rebates. When a user places RPI orders through a sub-account, the system applies the effective sub-account fees. Use [`Query Market Fees`](/api-reference/trading/query-market-fee) to verify fees for RPI executions. ## T A risk management feature to automatically close positions at predefined price levels. Take Profit (TP) closes at a higher price; Stop Loss (SL) closes at a lower price. These [orders](#orders) help traders manage risk and lock in profits automatically. A taker accepts an existing [order](#orders) from the [order book](#order-book), taking liquidity from the [market](#market). An alphabetic and/or numeric abbreviation of the name of a digital [asset](#assets). (BTC - Bitcoin ticker). See [Deal](#deal-trade) See [Volume](#volumetrade-volume) Traditional-finance (TradFi) futures contracts on assets such as equities (for example, `AAPL_USD`). These contracts carry `type: tradfiFutures` and `isTradFiFutures: true` in the [markets](/api-reference/market-data/market-info) response, and availability is region-gated. Placing or modifying an order on a TradFi market additionally requires the account to hold the TradFi futures permission — see [Markets & Trading Pairs](/concepts/markets) for both gates. See [Perpetual futures](#perpetual-futures) for crypto-settled contracts. A regulatory requirement for Virtual Asset Service Providers (VASPs) to share originator and beneficiary information for cryptocurrency transfers above certain thresholds, mandated by frameworks such as the Financial Action Task Force (FATF) recommendations and Markets in Crypto-Assets (MiCA). WhiteBIT can hold deposits under statuses 27 (awaiting verification) and 28 (confirmation in progress) until verifying the required data. See [Travel Rule](/concepts/travel-rule) for when the rule applies and the API workflow. ## U ## V The total number of shares or contracts buyers and sellers exchange in a [market](#market) on a given day. ## W An HTTP callback the platform sends to a partner-configured URL when an event occurs, such as a deposit or withdrawal status change. WhiteBIT signs each delivery so the consumer can verify the origin. See [Webhooks](/platform/webhook) for setup, the event catalog, and retry behavior. WhiteBIT Codes enable converting funds into a unique alphanumeric code. Easy and free to use. ## X ## Y ## Z # Account Monitoring Source: https://docs.whitebit.com/guides/account-monitoring Monitor balances, deposits, withdrawals, and order activity across Main, Trade, and Collateral accounts using REST polling and WebSocket streams. Monitor account state across Main, Trade, and Collateral balances using REST endpoints and WebSocket streams. Payment processing backends and trading systems consume the same account state through different mechanisms. * **Payment processing integrations** (deposit/withdrawal monitoring) — focus on balance monitoring and deposit/withdrawal tracking; Main balance does not support WebSocket streaming, so webhooks and REST polling are the primary mechanisms. * **Trading integrations** (bots, dashboards) — focus on balance monitoring and order activity monitoring via WebSocket for real-time state. ## Prerequisites * A WhiteBIT API key and HMAC-SHA512 request signing — see [First API Call](/guides/first-api-call) for key creation and [Authentication](/api-reference/authentication) for the signing scheme * For WebSocket sections: the token-based authorization flow from the [WebSocket Quickstart](/guides/websocket-quickstart) * For webhook-based tracking: a publicly reachable consumer endpoint — see [Webhooks](/platform/webhook) ## Balance monitoring WhiteBIT separates funds into three account types. Each has a dedicated balance endpoint: | Account type | Endpoint | Doc page | | - | - | - | | Main | `POST /api/v4/main-account/balance` | [Main Balance](/api-reference/account-wallet/main-balance) | | Trade (Spot) | `POST /api/v4/trade-account/balance` | [Trading Balance](/api-reference/trading/trading-balance) | | Collateral | `POST /api/v4/collateral-account/balance` | [Collateral Balance](/api-reference/trading/collateral-account-balance) | For an explanation of account types and how funds move between accounts, see [Balances & Transfers](/concepts/balances). Every endpoint and stream in this guide operates on the account that owns the API key — to monitor a sub-account, use the sub-account's dedicated key. A master-account key can also query a sub-account's Main, Spot, and Collateral balances via [`POST /api/v4/sub-account/balances`](/api-reference/sub-accounts/sub-account-balances). See [Sub-Accounts](/api-reference/sub-accounts/overview) for key management. ### Fetch Trade balance Store API keys securely and never commit keys to version control. Use IP whitelisting and grant keys only the minimum required permissions. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # See /api-reference/authentication for signing details. curl -X POST https://whitebit.com/api/v4/trade-account/balance \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"request":"/api/v4/trade-account/balance","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64, hashlib, hmac, json, time, requests API_KEY = "YOUR_API_KEY" API_SECRET = "YOUR_API_SECRET" BASE_URL = "https://whitebit.com" def send_request(path, data=None): if data is None: data = {} data["request"] = path data["nonce"] = int(time.time() * 1000) data_json = json.dumps(data) payload_b64 = base64.b64encode(data_json.encode()).decode() signature = hmac.new( API_SECRET.encode(), payload_b64.encode(), hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload_b64, "X-TXC-SIGNATURE": signature, } return requests.post(BASE_URL + path, headers=headers, data=data_json).json() balance = send_request("/api/v4/trade-account/balance") for asset, info in balance.items(): if float(info["available"]) > 0 or float(info["freeze"]) > 0: print(f"{asset}: available={info['available']}, freeze={info['freeze']}") ``` For Go and PHP examples, see [SDKs](/sdks). **Response fields:** * `available` — funds ready for trading or withdrawal * `freeze` — funds locked in open orders or pending operations ## Real-time balance via WebSocket REST polling provides point-in-time snapshots. To receive a push message each time a balance changes, subscribe to WebSocket account streams: | Channel | Subscribe method | Use case | | - | - | - | | [Balance Spot](/websocket/account-streams/balance-spot) | `balanceSpot_subscribe` | Trade (Spot) balance changes | | [Balance Margin](/websocket/account-streams/balance-margin) | `balanceMargin_subscribe` | Collateral balance changes (Margin + Futures) | Main balance does not have a WebSocket subscription channel. Use webhooks for real-time notification of the transaction types in the [webhook event catalog](/platform/webhook#webhook-methods), with `POST /api/v4/main-account/history` polling as a fallback. For a complete view of Main balance state, poll `POST /api/v4/main-account/balance`. ### Subscribe to balance updates The following example assumes an authenticated WebSocket session. Private channels require authorization before subscribing — see [WebSocket authentication](/websocket/authentication) for the full authentication flow. Subscribing to a private channel without authorization fails with an authorization error — check the `error` field on the subscription response. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import json, websockets, asyncio async def monitor_balance(): async with websockets.connect("wss://wss.whitebit.com/ws") as ws: # Authenticate first — see "Authenticate for private channels" # in the WebSocket Quickstart. Private channels require # authorization before subscribing. # Subscribe to spot balance changes. # params: [] subscribes to all assets. # Pass specific tickers (e.g., ["USDT", "BTC"]) to filter updates. await ws.send(json.dumps({ "id": 1, "method": "balanceSpot_subscribe", "params": [] })) async for message in ws: data = json.loads(message) # Subscription confirmation has a "result" key. # Balance updates have a "method" key set to "balanceSpot_update", # with "params" as an array of asset-keyed update objects. if data.get("method") == "balanceSpot_update": for update in data["params"]: for asset, info in update.items(): print(f"Balance change: {asset} available={info['available']} freeze={info['freeze']}") asyncio.run(monitor_balance()) ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > {"id": 1, "method": "balanceSpot_subscribe", "params": []} ``` ## Deposit and withdrawal tracking ### REST polling Query deposit and withdrawal history using the main account history endpoint: **Endpoint:** [`POST /api/v4/main-account/history`](/api-reference/account-wallet/get-deposit-withdraw-history) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/main-account/history \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"transactionMethod":1,"request":"/api/v4/main-account/history","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Uses the send_request helper from the "Fetch Trade balance" example. # Fetch recent deposits (transactionMethod: 1 = deposits, 2 = withdrawals) deposits = send_request("/api/v4/main-account/history", { "transactionMethod": 1, "limit": 50 }) for record in deposits.get("records", []): print(f"{record['ticker']}: {record['amount']} — status {record['status']}") ``` The `status` field is a numeric code — for example `3` and `7` mean credited, and deposits can sit frozen under [Travel Rule](/glossary#travel-rule) statuses `27`/`28`. See the status state machines in [Payment Integration](/guides/payment-integration). The endpoint paginates with `limit` (default 50, max 500) and `offset` — page until fewer than `limit` records return. It accepts no date filters, and pagination is capped at `offset + limit ≤ 10000`. For reconciliation, page from `offset` 0 until reaching the last processed transaction. ### Webhook-based monitoring For real-time deposit and withdrawal notifications, configure webhooks. Webhook delivery is best-effort — a small number of retries spaced roughly an hour apart over a window of about one day. Treat the exact cadence as not contractually guaranteed. **Recommended reconciliation approach:** * **Primary:** Webhooks — process events on arrival * **Fallback:** REST polling — periodically query the history endpoint to catch any events missed during webhook downtime or after the retry window expires See [Webhooks](/platform/webhook) for setup, signature verification, and event types. For the full deposit/withdrawal lifecycle including status state machines and fee calculation, see [Payment Integration](/guides/payment-integration). ## Order activity monitoring ### Open orders Query active orders across all markets or filter by a specific market: **Endpoint:** [`POST /api/v4/orders`](/api-reference/trading/query-unexecuted-orders) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/orders \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","request":"/api/v4/orders","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Uses the send_request helper from the "Fetch Trade balance" example. open_orders = send_request("/api/v4/orders", {"market": "BTC_USDT"}) print(f"Open orders: {len(open_orders)}") for order in open_orders: print(f" {order['side']} {order['amount']} @ {order['price']} (ID: {order['orderId']})") ``` ### Executed orders Query order history for filled and canceled orders: **Endpoint:** [`POST /api/v4/trade-account/order/history`](/api-reference/trading/query-executed-orders) For [B2B](/glossary#b2b-partner-account) accounts, canceled orders are not recorded in order history — to obtain canceled-order data, contact support or the assigned account manager. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/trade-account/order/history \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","request":"/api/v4/trade-account/order/history","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Uses the send_request helper from the "Fetch Trade balance" example. history = send_request("/api/v4/trade-account/order/history", {"market": "BTC_USDT"}) for market, orders in history.items(): for order in orders[:5]: print(f" {order['side']} {order['amount']} @ {order['price']} — {order.get('type', 'unknown')}") ``` Order history paginates with the same `limit` (default 50, max 500) and `offset` parameters. Date filtering is limited to a 31-day window between `startDate` and `endDate`, with the earliest reachable date 6 months back — see [Query Executed Orders](/api-reference/trading/query-executed-orders). ### Real-time order updates via WebSocket To receive an event on order placement, partial fill, or cancellation, subscribe to account streams: | Channel | Subscribe method | Events | | - | - | - | | [Orders Pending](/websocket/account-streams/orders-pending) | `ordersPending_subscribe` | Order placed, partially filled, canceled | | [Deals](/websocket/account-streams/deals) | `deals_subscribe` | Trade executions (fills) | For final order state with aggregate data (fully filled or canceled), see also [Orders Executed](/websocket/account-streams/orders-executed). The two channels use different `params` shapes: `ordersPending_subscribe` accepts a flat list of markets (`["BTC_USDT"]`), while `deals_subscribe` accepts a list of market lists (`[["BTC_USDT"]]`). ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Add these calls inside monitor_balance() after the # balanceSpot_subscribe message. Subscribe to order updates and trade fills. await ws.send(json.dumps({ "id": 2, "method": "ordersPending_subscribe", "params": ["BTC_USDT"] })) await ws.send(json.dumps({ "id": 3, "method": "deals_subscribe", "params": [["BTC_USDT"]] })) ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > {"id": 2, "method": "ordersPending_subscribe", "params": ["BTC_USDT"]} > {"id": 3, "method": "deals_subscribe", "params": [["BTC_USDT"]]} ``` ## Polling vs WebSocket decision matrix | Use case | Recommended approach | Reason | | - | - | - | | Balance snapshot | REST | One-time check, no persistent connection needed | | Live balance changes | WebSocket | Push notification on every change | | Deposit/withdrawal status | Webhook + REST fallback | Reliability — webhooks for speed, REST for reconciliation | | Open order monitoring | WebSocket | Real-time state changes (fills, cancellations) | | Historical trades | REST | Paginated query over a time range | **General guidance:** Combine WebSocket and REST — WebSocket for the primary real-time flow, REST for startup state hydration and periodic reconciliation. WebSocket streams do not replay messages that arrived during a disconnection. After a reconnect, re-authorize, re-subscribe, and re-sync state from the REST endpoints — see [WebSocket Quickstart — State recovery after reconnect](/guides/websocket-quickstart#state-recovery-after-reconnect) and [Building a Trading Bot — Auto-resubscription after reconnect](/guides/building-a-trading-bot#auto-resubscription-after-reconnect). ### Recommended polling intervals When using REST polling, align the interval with the use case and the endpoint rate budget. See [Rate Limits & Error Codes](/api-reference/rate-limits) for per-scope request limits. | Use case | Endpoint | Suggested interval | | - | - | - | | Balance dashboard | `POST /api/v4/trade-account/balance` | 5–30 seconds | | Deposit detection (fallback) | `POST /api/v4/main-account/history` | 5 minutes | | Order history reconciliation | `POST /api/v4/trade-account/order/history` | 30–60 seconds | `POST /api/v4/main-account/history` has a much smaller rate budget (200 requests/10 s) than the trade endpoints (12,000 requests/10 s) — keep its polling interval in minutes, not seconds. Polling loops need failure handling. On HTTP `429`, back off and resume — see [Building a Trading Bot — Rate limit backoff](/guides/building-a-trading-bot#rate-limit-backoff); retried requests need a new, larger `nonce` (see [Authentication](/api-reference/authentication)). On WebSocket, check the `error` field on every response before treating a subscription as active. ## What's next Full deposit/withdrawal lifecycle, fee calculation, and reconciliation. Token-based authorization for private channels and state recovery after reconnect. End-to-end automated trading with order management and error handling. # Docs page AI menu Source: https://docs.whitebit.com/guides/ai-context-menu Copy page content for AI tools or open documentation directly in ChatGPT, Claude, Perplexity, or Grok. Access AI-optimized content and AI tool integrations via the **Copy page** dropdown on any WhiteBIT documentation page. The **Copy page** dropdown is available at the top of every documentation page. The menu provides options to copy page content for AI consumption, open pages directly in AI chat tools, and connect development environments to the full documentation via MCP. ## Access the contextual menu Select the **Copy page** dropdown next to the document title on any page. The menu opens with all available options grouped by function. ## Page content options ### Copy page Copies the current page content as standard Markdown. Use when sharing documentation content or pasting into a text editor. ### Copy page as Markdown for LLMs Copies the current page content in an AI-optimized Markdown format with additional context for language models. Use when feeding page content to an AI tool for analysis or asking questions about a specific page. ### View as Markdown Opens a plain-text Markdown view of the current page. Use when previewing the raw content of a documentation page. ## Open in AI tool Each option opens the current page content in the selected AI chat tool with the page pre-loaded as context. | Option | AI tool | Best for | | - | - | - | | Open in ChatGPT | ChatGPT (OpenAI) | Quick questions about the current page | | Open in Claude | Claude (Anthropic) | Detailed analysis or code generation from the current page | | Open in Perplexity | Perplexity | Research-oriented questions about the current page | | Open in Grok | Grok (xAI) | Questions and analysis with the current page as context | ## MCP and IDE quick connect The contextual menu includes one-click options to connect a development environment to the WhiteBIT documentation MCP server at `https://docs.whitebit.com/mcp`. | Option | Action | | - | - | | Copy MCP Server URL | Copies `https://docs.whitebit.com/mcp` to the clipboard for manual configuration | | Connect to Cursor | Opens Cursor with the WhiteBIT documentation MCP server pre-configured | | Connect to VS Code | Opens VS Code with the WhiteBIT documentation MCP server pre-configured | For manual configuration steps in Cursor, VS Code, and Claude Desktop, see the [Docs search via MCP](/guides/ai-ide-setup) guide. ## Full documentation context The following URLs provide the complete WhiteBIT documentation in AI-optimized formats for use with any AI tool that accepts pasted or linked content. | Resource | URL | Use when | | - | - | - | | Documentation index | `https://docs.whitebit.com/llms.txt` | Discovering all available pages before exploring further | | Full documentation | `https://docs.whitebit.com/llms-full.txt` | Providing comprehensive documentation context across the entire API reference | ## Common workflows ### Ask questions about the current page 1. Navigate to any WhiteBIT documentation page. 2. Select the **Copy page** dropdown next to the document title. 3. Select **Open in ChatGPT**, **Open in Claude**, **Open in Perplexity**, or **Open in Grok**. 4. The AI tool opens with the page content pre-loaded. Ask questions about the current page. ### Copy content for a local AI tool 1. Navigate to any WhiteBIT documentation page. 2. Select the **Copy page** dropdown next to the document title. 3. Select **Copy page as Markdown for LLMs**. 4. Paste the content into the preferred AI tool and ask questions. ### Get comprehensive documentation context 1. Navigate to `https://docs.whitebit.com/llms-full.txt`. 2. Copy the URL or file content. 3. Use when questions span multiple areas of the API documentation. ### Connect an IDE to the documentation 1. Navigate to any WhiteBIT documentation page. 2. Select the **Copy page** dropdown next to the document title. 3. Select **Connect to Cursor** or **Connect to VS Code**. 4. For manual configuration or Claude Desktop setup, see [Docs search via MCP](/guides/ai-ide-setup). ## Best practices **Provide context** Include relevant details when asking AI questions: * Mention the specific API endpoint or feature in scope. * Include code snippets when asking about implementation. * For questions that span multiple pages, use `llms-full.txt` for comprehensive context. **Combine approaches** * Use the contextual menu for quick, page-specific questions and one-off tasks. * Use the [Docs search via MCP](/guides/ai-ide-setup) for ongoing development with full documentation search. * Both approaches work together for optimal AI assistance. ## What's next * [Docs search via MCP](/guides/ai-ide-setup) — Manual configuration for Cursor, VS Code, and Claude Desktop * [API Reference Overview](/api-reference/overview) — Base URL, quickstart examples, and endpoint groups * [WebSocket Overview](/websocket/overview) — Connection details, quickstart, and channel index # AI tools FAQ Source: https://docs.whitebit.com/guides/ai-faq Common questions about the WhiteBIT MCP server and CLI — API key safety, supported clients, account setup, and automation. Answers to common questions about the WhiteBIT MCP server and CLI. ## MCP server and CLI capabilities The MCP server provides 115 tools covering market data, spot trading, collateral trading, wallet operations, lending, sub-accounts, mining pool, and currency conversion. All tools are available to any connected AI client using natural language. The CLI provides 110+ commands covering the same API surface, designed for terminal use, scripting, and CI/CD pipelines. See [MCP server](/guides/mcp-server) and [CLI](/guides/cli) for the full tool and command listings. ## Supported AI clients The MCP server works with any client that supports the Model Context Protocol. Supported clients include: * **Claude Code** — global or project-scoped registration via `claude mcp add` * **Cursor** — configuration via `~/.cursor/mcp.json` * **Claude Desktop** — configuration via the application config file * **Codex** — configuration via `~/.codex/config.toml` * **OpenClaw** — configuration via the agent config file See [MCP server — Connect an AI client](/guides/mcp-server#connect-an-ai-client) for setup instructions for each client. ## API key security API keys are supplied at connection time — as `WHITEBIT_API_KEY` and `WHITEBIT_SECRET_KEY` environment variables on the stdio transport, or as `X-WB-Api-Key` and `X-WB-Secret-Key` request headers on the HTTP transport — and are used only to sign outgoing WhiteBIT API requests. No tool takes an API key as a parameter. The MCP server does not store, log, or cache credentials. All processing happens locally — no data is sent to external services beyond WhiteBIT. Public market data tools (tickers, order book, market info) query public endpoints and need no account credentials. See [Authentication](/api-reference/authentication) for instructions on generating and managing API keys. ## Trading MCP server vs documentation MCP The WhiteBIT documentation portal has two separate MCP integrations that serve different purposes: | MCP | Purpose | Endpoint | | - | - | - | | Trading MCP (`whitebit-mcp`) | Execute trades, query balances, manage orders | `http://localhost:8080/mcp` (self-hosted) | | Documentation MCP | Search the WhiteBIT API documentation | `https://docs.whitebit.com/mcp` (hosted) | The trading MCP is a self-hosted server that requires cloning the [whitebit-mcp](https://github.com/whitebit-exchange/whitebit-mcp) repository and starting a local Docker container. See [MCP server](/guides/mcp-server). The documentation MCP is a Mintlify-hosted service. See [Docs search via MCP](/guides/ai-ide-setup). ## Public market data without API keys Public market data tools do not require a WhiteBIT account. On the stdio transport these tools answer with no credentials configured, so a market-data-only setup can leave the key variables empty. Example questions: * "What is the current BTC\_USDT price?" * "Show the order book for ETH\_USDT" * "List all available trading pairs" The CLI market module also requires no authentication: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} whitebit market list whitebit market ticker BTC_USDT ``` ## CLI use in automation The CLI is designed for scripting and automation: * `--json` flag on every command outputs machine-readable JSON, compatible with `jq` and any data pipeline. * `--dry-run` flag previews the exact API request payload without sending it — useful for validating scripts. * Exit codes (`0` success, `2` auth error, `5` rate limit, etc.) allow precise error handling in shell scripts. * Multi-profile support enables switching between API keys with `--profile`. See [CLI — JSON output and scripting](/guides/cli#examples) for examples. ## Safe account practices Before connecting AI tools to a live account: * Create a dedicated sub-account with a separate API key for AI tool access. * Fund the sub-account with only the amount allocated for AI-assisted trading. * Generate API keys with the minimum permissions required — read-only keys are sufficient for balance and order queries. * Enable IP whitelisting on the API key to restrict access to the machine running the MCP server. * Test with small amounts before executing larger trades. * Never provide API keys in the AI conversation — credentials belong in the AI client configuration that the setup command writes. See [MCP server — Safe account practices](/guides/mcp-server#safe-account-practices) for the full checklist. ## Report an issue Report bugs or request features by opening an issue on the relevant GitHub repository: * [whitebit-mcp issues](https://github.com/whitebit-exchange/whitebit-mcp/issues) — MCP server bugs and feature requests * [whitebit-cli issues](https://github.com/whitebit-exchange/whitebit-cli/issues) — CLI bugs and feature requests Include the full error output when reporting a bug. For MCP errors, include the structured error block from the AI client. For CLI errors, include the full stderr output. ## Related resources * [MCP server](/guides/mcp-server) — Full setup guide for the WhiteBIT trading MCP server * [CLI](/guides/cli) — Full setup and command reference for the WhiteBIT CLI * [Docs search via MCP](/guides/ai-ide-setup) — Connect Cursor, VS Code, or Claude Desktop to the documentation search MCP * [Authentication](/api-reference/authentication) — How to generate and manage WhiteBIT API keys # Docs search via MCP Source: https://docs.whitebit.com/guides/ai-ide-setup Configure Cursor, VS Code, or Claude Desktop to search the full WhiteBIT documentation using the Model Context Protocol (MCP). This page covers the **documentation search MCP** — searching WhiteBIT API reference pages inside an AI client. For the **trading MCP** (115 tools for placing orders, checking balances, and querying market data), see the [MCP server guide](/guides/mcp-server). Configure Cursor, VS Code, or Claude Desktop to connect to the WhiteBIT documentation MCP server. Once connected, AI tools gain direct, searchable access to all documentation pages and generate accurate code and answers from current documentation. **MCP server URL**: `https://docs.whitebit.com/mcp` ## Prerequisites * Cursor, VS Code, or Claude Desktop installed * An active internet connection ## What MCP provides The Model Context Protocol (MCP) gives AI tools direct access to the WhiteBIT documentation. Instead of relying on training data, the AI tool searches current documentation pages to generate accurate API code, answer integration questions, and surface the correct endpoint parameters. ## Cursor ### Automatic setup 1. Navigate to any WhiteBIT documentation page. 2. Select the **Copy page** dropdown next to the document title. 3. Select **Connect to Cursor**. 4. Cursor opens with the WhiteBIT MCP server configured automatically. ### Manual setup 1. Open the command palette with **Cmd+Shift+P** (macOS) or **Ctrl+Shift+P** (Windows/Linux). 2. Search for **Open MCP settings** and select the result. The `mcp.json` file opens. 3. Add the WhiteBIT documentation server configuration: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcpServers": { "whitebit-docs": { "url": "https://docs.whitebit.com/mcp" } } } ``` 4. Save the file. 5. Restart Cursor. To verify the connection, ask Cursor: `What MCP tools do you have available?` The WhiteBIT documentation search tool appears in the response. ## VS Code ### Automatic setup 1. Navigate to any WhiteBIT documentation page. 2. Select the **Copy page** dropdown next to the document title. 3. Select **Connect to VS Code**. 4. VS Code opens with the WhiteBIT MCP server configured automatically. ### Manual setup 1. Install an MCP-compatible extension in VS Code. 2. Open the extension's MCP server settings. 3. Add the server URL: `https://docs.whitebit.com/mcp`. 4. Save the configuration and restart VS Code. VS Code MCP support varies by extension. Check the extension documentation for specific configuration instructions. ## Claude Desktop 1. Navigate to [claude.ai/settings/connectors](https://claude.ai/settings/connectors) in a browser. 2. Select **Add custom connector**. 3. Enter the following details: * **Name**: `WhiteBIT Docs` * **URL**: `https://docs.whitebit.com/mcp` 4. Select **Add**. 5. When starting a Claude chat, select the attachments button and choose **WhiteBIT Docs** to activate the connector. ## Test the connection After configuration, test the MCP connection by asking the AI tool: ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} What MCP tools do you have available? ``` The WhiteBIT documentation search tool appears in the response. Then verify search access: ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} Search for information about authentication in the WhiteBIT documentation. ``` The AI tool returns relevant content directly from the WhiteBIT API documentation. ## Troubleshooting ### MCP server connection failure Verify the server URL is exactly `https://docs.whitebit.com/mcp`. Check the internet connection, then restart the AI tool after making configuration changes. ### Search tool not listed Confirm the MCP server was added correctly by reviewing the configuration. Remove the server entry, re-add it, and restart the AI tool. Check the AI tool's MCP support documentation for version requirements. ### Search returns no results Try more general search terms. Use `authentication` instead of `HMAC-SHA512 private endpoint auth`. Confirm the MCP connection is active by asking `What MCP tools do you have available?` before searching. ## What's next * [Docs page AI menu](/guides/ai-context-menu) — Copy page content and open pages in AI chat tools directly from the browser * [API Reference Overview](/api-reference/overview) — Base URL, quickstart examples, and endpoint groups * [Authentication](/api-reference/authentication) — Sign and authenticate private API requests * [Model Context Protocol documentation](https://modelcontextprotocol.io/docs/tutorials/use-remote-mcp-server) — MCP protocol reference for advanced configuration * [Mintlify MCP documentation](https://mintlify.com/docs/ai/model-context-protocol) — Mintlify-specific MCP server details # App Builders FAQ Source: https://docs.whitebit.com/guides/app-builders-faq Common questions about building over customers' own WhiteBIT accounts: key types and permissions, rate limits, revocation, onboarding, and compliance. Answers to common questions about building trading and portfolio apps over customers' own WhiteBIT accounts (Model B). ## Scope and delivery ### Delivery model App Builders build over customers' own WhiteBIT accounts: each end user keeps a personal account and grants the partner a scoped API key through the [Fast API Key](/guides/fast-api-key-integration) flow. WhiteBIT holds custody and performs KYC. See the [App Builders overview](/guides/app-builders-overview). ### App Builders and Embedded Trading App Builders is WhiteBIT's Model B — end users keep personal accounts. Embedded Trading is Model A — the partner operates a dedicated sub-account per end customer instead. See [Integration models](/concepts/integration-models). ## Copy trading ### Copy-trading availability Copy trading is a partner use case built on the Fast API Key flow. Access is approval-gated — not available by default and subject to an internal review; attribution and commercial terms are confirmed with WhiteBIT at enrollment. See the [Copy Trading guide](/guides/copy-trading). ### Order execution in copy trading The partner places orders with each follower's OAuth-issued key, and execution happens inside the follower's own account; the account acted on is determined by which key signs the request. See [Copy Trading architecture](/guides/copy-trading#architecture). ## Integration ### Key types and permissions A key's type sets its maximum permissions — Read-only, Trade, or Custom (the only type that can include external withdrawal, gated on WhiteBIT approval and partner KYB). The end user picks permissions within that maximum on the consent screen; the partner cannot influence the choice. See [Key permissions](/guides/fast-api-key-integration#key-permissions). ### Rate limits with many end users behind one backend REST rate limits are enforced per IP address, not per end user. A backend serving many users from one IP shares a single request budget across every user's signed requests. Pace requests and handle `429` with backoff — see [Rate limits](/api-reference/rate-limits). ### Key revocation An OAuth-issued key is revoked when the end user changes the account password, the account is blocked or frozen, or the key has no API activity for 14 days. Signed requests then fail; re-run the consent flow to reissue. See [Lifecycle and revocation](/guides/fast-api-key-integration#lifecycle-and-revocation). ### Access token lifetime The OAuth access token used for key management is short-lived and is issued together with a refresh token — read `expires_in` from the token response and renew through [`POST /oauth2/refresh_token`](/api-reference/oauth/usage/refresh-token) instead of re-running consent. See the [Integration flow](/guides/fast-api-key-integration#integration-flow). ### Test environment availability WhiteBIT does not offer a public testnet or sandbox. Test on the live API with minimum order sizes, or activate Demo Tokens (`DBTC`/`DUSDT`) for risk-free spot practice. See the [Go-Live Checklist](/best-practices/go-live-checklist). ## Onboarding and access ### Partner enrollment Partner enrollment is approval-gated. Apply via `institutional@whitebit.com` with the intended use cases; a partner agreement and KYB review are part of onboarding before a `client_id` is issued. See [Prerequisites](/guides/fast-api-key-integration#prerequisites). ### Attribution and fee-share Attribution and any fee-share for apps built on customers' own accounts are arranged separately from the account relationship, since the end user is a direct WhiteBIT customer. See [Program terms](/guides/app-builders-overview#program-terms). ## Compliance ### Withdrawal permission and MFA Step-up MFA is enforced after consent for every Fast API Key creation, regardless of which permissions were selected. If the end user selects withdrawal permission, the consent screen adds an extra confirmation step. KYC, AML, and fraud monitoring apply on every call through the end user's own account status. ### Regional restrictions The OAuth API key endpoints are available on the global server (`https://whitebit.com`) only. For EEA end users, MiCA restricts USDT deposits, withdrawals, and WhiteBIT Codes — USDC and EURI are the documented alternatives. See [Regulatory Compliance](/institutional/compliance). ## Support ### Support contacts Partner enrollment and attribution questions go to `institutional@whitebit.com`. Platform questions are answered at [help.whitebit.com](https://help.whitebit.com), and API documentation is on docs.whitebit.com. ## What's next What App Builders can build, who it is for, and how to get started. The OAuth API key flow for acting on customers' own accounts. Mirror a lead trader's orders into followers' own accounts. Cross-cutting answers shared across programs — KYB, sandbox, fees, and rate limits. # App Builders Source: https://docs.whitebit.com/guides/app-builders-overview Build trading and portfolio apps over customers' own WhiteBIT accounts with a partner-held API key issued through the Fast API Key flow (Model B). App Builders build over customers' own WhiteBIT accounts: each end user keeps a personal account and grants the partner a scoped API key through the [Fast API Key](/guides/fast-api-key-integration) flow. WhiteBIT holds custody and performs identity verification; the partner acts within the permissions the user grants. This is WhiteBIT's [Model B](/concepts/integration-models), and it fits far more than embedded trading alone — any app that reads or trades on a user's own account. ## What App Builders can build * **Portfolio and analytics apps** — read a user's balances and activity to present holdings, performance, and tax reporting ([Model B](/concepts/integration-models)). * **Trading bots and signal execution** — place orders on a user's account under a trade-scoped key ([building a trading bot](/guides/building-a-trading-bot)). * **Copy and social trading** — mirror a lead trader's orders into followers' own accounts ([Copy trading](/guides/copy-trading)). * **Charting and education tools** — add on-chart or in-app execution over the user's own account. ## Who App Builders is for * **Read-only apps** — portfolio trackers and aggregators, tax and accounting tools, and referral apps that read a user's own activity without moving funds. * **Trade-execute apps** — trading bots, copy and social trading, charting with execution, algorithmic and quant platforms, and education platforms with in-app execution. ## How it works The end user authorizes the partner on the WhiteBIT consent screen, which issues an OAuth-based API key scoped to the permissions the user selects — so partner access is bounded by the grant. Order placement and withdrawal are separate permissions; a trade-scoped key cannot move funds off the account. The [Fast API Key integration](/guides/fast-api-key-integration) documents the authorization flow, and the [integration models](/concepts/integration-models) concept compares Model B with the partner-operated sub-account model (Model A). ## Program terms Attribution and any fee-share for apps built on customers' own accounts are arranged separately from the account relationship, since the end user is a direct WhiteBIT customer. Revenue-share terms depend on the program. Embedded Trading partners earn a share of the trading fees that referred customers generate across all products, with payouts initiated by the partner, most commonly once per month — see [WhiteBIT Embedded Trading](https://institutional.whitebit.com/broker-program) for current rates. Other partner programs confirm commercial terms during onboarding. ## How to get started Review the [integration models](/concepts/integration-models) concept to confirm Model B is the right fit, then build against the [Fast API Key integration](/guides/fast-api-key-integration). Partner enrollment and attribution go to `institutional@whitebit.com`. ## What's next The OAuth API key flow for acting on customers' own accounts. Mirror a lead trader's orders into followers' own accounts. Model A vs Model B — account holder, KYC, and best fit. Key types, rate limits, revocation, onboarding, and compliance questions. # Price Dashboard Source: https://docs.whitebit.com/guides/building-a-price-dashboard Build a live price dashboard on WhiteBIT public market data — a REST snapshot for the initial paint, a WebSocket stream for continuous updates, no account or API key required. Build a live price dashboard on WhiteBIT public market data: one REST call paints the initial board, and a single WebSocket subscription keeps every displayed price current. The full flow runs without an account or API key. The guide targets price aggregators and market-data consumers. ## Prerequisites * A terminal with curl, or any HTTP client * Python 3 with the `websocket-client` package, or `wscat` for interactive testing — for the streaming step * No WhiteBIT account or API key needed — every endpoint in this guide is public ## Architecture The dashboard combines two data paths: a REST snapshot for the initial paint and a WebSocket stream for continuous updates. A REST polling loop substitutes for the stream while a dropped connection recovers. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant App as Dashboard backend participant REST as REST API participant WS as WebSocket API Note over App,REST: Initial paint App->>REST: GET /api/v4/public/markets — pair list App->>WS: lastprice_subscribe — tracked pairs App->>REST: GET /api/v4/public/ticker — price snapshot loop Live updates WS-->>App: lastprice_update — replace the displayed price end Note over App,WS: Fallback WS--xApp: connection drops App->>REST: poll GET /api/v4/public/ticker App->>WS: reconnect and resubscribe ``` ## Select markets to track Market discovery comes first. [`GET /api/v4/public/markets`](/api-reference/market-data/market-info) returns configuration and trading rules for every market enabled for trading. Read `name` for the pair identifier and filter by `type` (`spot`, `futures`, or `tradfiFutures`) to scope the board — a spot-only dashboard keeps `type: spot` entries. Market configuration is reference data: the server re-syncs the response approximately every 10 seconds, so fetch the list once at startup and refresh on a slow cycle. For a step-by-step first call against each public market-data endpoint, see the [Market Data Quickstart](/products/market-data/quickstart). ## Fetch the price snapshot [`GET /api/v4/public/ticker`](/api-reference/market-data/market-activity) returns a 24-hour pricing and volume summary for every market pair in a single response — one call fills the whole board. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl https://whitebit.com/api/v4/public/ticker ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests ticker = requests.get("https://whitebit.com/api/v4/public/ticker").json() board = { pair: entry["last_price"] for pair, entry in ticker.items() if pair in ("BTC_USDT", "ETH_USDT") } print(board) ``` For Go and PHP examples, see [SDKs](/sdks). **Response (BTC\_USDT entry, trimmed):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "BTC_USDT": { "last_price": "62741.43", "base_volume": "1653.886345", "quote_volume": "104493656.92108444", "isFrozen": false, "change": "-0.55" } } ``` Key fields for a dashboard: `last_price` (most recent trade price in the quote currency), `change` (percentage change against the rolling 24-hour open), `quote_volume` (24-hour volume in the quote currency), and `isFrozen` (`true` when trading is disabled for the pair — flag or hide the entry). The API caches the response for 1 second, so polling faster than once per second returns identical data. ## Stream price updates Polling covers one-shot lookups; a live board needs continuous updates. Subscribe to the [Last Price channel](/websocket/market-streams/lastprice) — the server pushes an update every second when the price changes, and each update replaces the displayed value. One connection carries the full watchlist: the subscription accepts an array of market names. A single connection maintains subscriptions across 200 or more markets (see [WebSocket Rate Limits](/websocket/rate-limits)). ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import json import websocket ws = websocket.create_connection("wss://wss.whitebit.com/ws") ws.send(json.dumps({ "id": 1, "method": "lastprice_subscribe", "params": ["BTC_USDT", "ETH_USDT"] })) print(ws.recv()) # subscribe confirmation while True: message = json.loads(ws.recv()) if message.get("method") == "lastprice_update": market, price = message["params"] print(f"{market}: {price}") # replace the displayed price ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > {"id": 1, "method": "lastprice_subscribe", "params": ["BTC_USDT", "ETH_USDT"]} ``` **Subscribe confirmation:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} {"id": 1, "result": {"status": "success"}, "error": null} ``` **Update message:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} {"id": null, "method": "lastprice_update", "params": ["BTC_USDT", "62708.25"]} ``` The `params` array contains the market name (index 0) and the last traded price (index 1). For an [order book](/glossary#order-book) widget next to the price board, add the [Depth channel](/websocket/market-streams/depth) — a snapshot-plus-delta stream with recovery rules of its own, covered in [State recovery after reconnect](/guides/websocket-quickstart#state-recovery-after-reconnect). The [WebSocket Quickstart](/guides/websocket-quickstart) covers connection setup, keepalive pings, and the 60-second inactivity timeout; the dashboard reuses the same connection pattern. ## Reconcile snapshot and stream Last price updates follow a replacement model: each `lastprice_update` fully replaces the previous value for the market, so the board needs no gap handling. Three rules keep the board consistent: 1. **Startup ordering.** Subscribe first, then fetch the [ticker](/glossary#ticker) snapshot. Apply snapshot values only to pairs without a streamed value yet — the snapshot response can lag behind the stream by its 1-second cache. With replacement semantics, even the reverse order self-corrects within one update interval. 2. **Liveness.** Do not infer connection health from update frequency alone. Send a `ping` every 50 seconds or less — the server closes a connection after 60 seconds of client inactivity — and treat a missed pong as a dropped connection. Reconnection with backoff and resubscription follows the standard pattern in [Reconnection and state recovery](/guides/websocket-quickstart#reconnection-and-state-recovery). 3. **Polling fallback.** While a connection recovers, keep the board live by polling [`GET /api/v4/public/ticker`](/api-reference/market-data/market-activity). The 1-second server-side cache makes one request per second the effective polling ceiling. Stop polling once resubscription confirms. ## Rate limits The endpoints and channels used on this page carry the following limits: | Surface | Limit | | - | - | | `GET /api/v4/public/markets` | 2,000 requests per 10 seconds | | `GET /api/v4/public/ticker` | 2,000 requests per 10 seconds | | WebSocket connections | 1,000 new connections per minute | | WebSocket requests | 12,000 JSON-RPC requests per 10 seconds per connection | Full reference: [Rate Limits & Error Codes](/api-reference/rate-limits) and [WebSocket Rate Limits & Error Codes](/websocket/rate-limits). ## Complete example The two snippets above cover the critical path — the ticker snapshot and the price stream. The remaining assembly (multi-pair state, staleness flags, reconnection, the polling fallback) is standard application code. A complete runnable dashboard is planned as a clone-and-run starter repository. ## What's next First calls against each public market-data endpoint — ping, markets, ticker, orderbook, trades. Connection setup, keepalive, reconnection, and state recovery patterns. Integration routes by use case — trading bots, payments, account monitoring. # Trading Bot Source: https://docs.whitebit.com/guides/building-a-trading-bot Build an automated trading bot in Python against the WhiteBIT v4 API — signed REST orders, WebSocket fill monitoring, kill-switch heartbeat, reconnection, and a grid-bot worked example. Build an automated trading bot on the WhiteBIT API in Python, using `requests` for signed REST calls and `websockets` for streaming market data and fills. The guide assumes Python 3.9+ and a WhiteBIT account with a Trading-permission API key (see Prerequisites below). ## Prerequisites * A WhiteBIT account ([register](https://whitebit.com/auth/register)) * An API key with **Trading** permission ([create one](https://whitebit.com/settings/api)) * Funds in the **Trade** balance — transfer from Main balance if needed (see [Balances & Transfers](/concepts/balances)). Grid strategies require both the quote currency (for buy orders) and the base currency (for sell orders). * Familiarity with HMAC-SHA512 signing — see [Authentication](/api-reference/authentication) for the contract and [First API Call](/guides/first-api-call) for a worked signing example with troubleshooting * Python 3.9+ with `requests` and `websockets` packages installed (the production guidance in the worked example relies on `asyncio.to_thread`, added in Python 3.9) WhiteBIT has no public testnet or sandbox. All orders execute against the live orderbook. For risk-free testing, use Demo Tokens (DBTC/DUSDT) — activate from the [WhiteBIT Codes page](https://whitebit.com/codes). Test with the `DBTC_DUSDT` market pair before switching to real assets. ## Architecture overview A trading bot operates as a continuous loop: ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} ┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ Market Data │────▶│ Signal / Logic │────▶│ Order Execution │ │ (WS + REST) │ │ (Strategy) │ │ (REST API) │ └─────────────────┘ └──────────────────┘ └──────────────────┘ ▲ │ │ ┌──────────────────┐ │ └───────────│ Fill Monitoring │◀─────────────────┘ │ (WebSocket) │ └──────────────────┘ ``` 1. **Market data** — receive prices and orderbook updates via WebSocket (or REST polling for lower-frequency strategies) 2. **Signal generation** — apply strategy logic to determine when and what to trade 3. **Order execution** — place orders via REST API (single or bulk), or over the WebSocket connection 4. **Fill monitoring** — track order fills and state changes via WebSocket 5. **Position management** — update internal state, replace filled orders, manage risk Signal generation (step 2) is strategy-specific. The grid bot example at the end of the guide demonstrates one concrete strategy. ## Market data ingestion ### REST polling For strategies that do not require sub-second data, poll market data via REST: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Fetch ticker data for BTC_USDT curl -X GET "https://whitebit.com/api/v4/public/ticker" # Fetch orderbook for BTC_USDT (depth: 20 levels) curl -X GET "https://whitebit.com/api/v4/public/orderbook/BTC_USDT?limit=20" ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests BASE_URL = "https://whitebit.com" # Fetch ticker data ticker = requests.get(f"{BASE_URL}/api/v4/public/ticker").json() btc_price = ticker.get("BTC_USDT", {}) print(f"BTC_USDT last price: {btc_price.get('last_price')}") # Fetch orderbook orderbook = requests.get( f"{BASE_URL}/api/v4/public/orderbook/BTC_USDT", params={"limit": 20} ).json() best_bid = orderbook["bids"][0] if orderbook.get("bids") else None best_ask = orderbook["asks"][0] if orderbook.get("asks") else None print(f"Best bid: {best_bid}, Best ask: {best_ask}") ``` For Go and PHP examples, see [SDKs](/sdks). **Endpoints:** * [`GET /api/v4/public/ticker`](/api-reference/market-data/market-activity) — 24h ticker statistics for all markets * [`GET /api/v4/public/orderbook/{market}`](/api-reference/market-data/orderbook) — orderbook snapshot with configurable depth ### WebSocket streaming For real-time data, subscribe to WebSocket market streams: | Channel | Subscribe method | Data | | - | - | - | | [Last Price](/websocket/market-streams/lastprice) | `lastprice_subscribe` | Price updates on every trade | | [Depth](/websocket/market-streams/depth) | `depth_subscribe` | Orderbook depth updates | ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import json, asyncio, websockets async def stream_market_data(): async with websockets.connect("wss://wss.whitebit.com/ws") as ws: # Subscribe to last price updates await ws.send(json.dumps({ "id": 1, "method": "lastprice_subscribe", "params": ["BTC_USDT"] })) # Subscribe to orderbook depth await ws.send(json.dumps({ "id": 2, "method": "depth_subscribe", # params: [market, limit, price_interval, multi_subscription_flag] "params": ["BTC_USDT", 20, "0", True] })) async for message in ws: data = json.loads(message) method = data.get("method") if method == "lastprice_update": print(f"Price: {data['params']}") elif method == "depth_update": print(f"Orderbook update: {len(data['params'][1].get('bids', []))} bids") ``` See the [WebSocket Quickstart](/guides/websocket-quickstart) for connection setup and authentication. Incremental `depth_update` deltas chain via `past_update_id`. If a delta's `past_update_id` does not match the last-seen `update_id` for this subscription, a message was missed — resnapshot by unsubscribing and re-subscribing. Keepalive snapshots (`params[0]` is `true`, `past_update_id` absent) are full resets, not gap signals — the snapshot `update_id` may exceed the last delta's. See [WS Quickstart — State recovery after reconnect](/guides/websocket-quickstart#state-recovery-after-reconnect) for the full pattern. ## Order placement Every private endpoint in this guide is signed with HMAC-SHA512. The `send_request` helper below handles the signing and a thread-safe nonce; the rest of the guide reuses it. `send_request` uses a millisecond nonce. If multiple threads call the helper in the same millisecond, the server rejects the duplicate via its nonceWindow (±5 seconds). The helper below uses a monotonic counter protected by a lock — safe under concurrent callers (for example, the kill-switch heartbeat thread and the strategy thread placing orders simultaneously). ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64, hashlib, hmac, json, threading, time, requests API_KEY = "YOUR_API_KEY" API_SECRET = "YOUR_API_SECRET" BASE_URL = "https://whitebit.com" _nonce_lock = threading.Lock() _last_nonce = 0 def _next_nonce(): """Monotonic millisecond nonce — safe under concurrent callers.""" global _last_nonce with _nonce_lock: n = max(int(time.time() * 1000), _last_nonce + 1) _last_nonce = n return str(n) def send_request(path, data=None): """Send a signed request. Returns the decoded JSON body. Raises requests.HTTPError on HTTP 4xx/5xx — caller can inspect `.response.status_code` and `.response.json()`.""" data = dict(data or {}) data["request"] = path data["nonce"] = _next_nonce() data_json = json.dumps(data) payload_b64 = base64.b64encode(data_json.encode()).decode() signature = hmac.new( API_SECRET.encode(), payload_b64.encode(), hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload_b64, "X-TXC-SIGNATURE": signature, } resp = requests.post(BASE_URL + path, headers=headers, data=data_json) resp.raise_for_status() return resp.json() ``` Private WebSocket channels require an `authorize` handshake. The helper below fetches a token via REST (rate limit: 10 requests / 60 s) and sends the `authorize` message. Call it once per WebSocket connection, before any private subscribe: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} async def authenticate_ws(ws): """Fetch a WebSocket token via REST and authorize the WS connection.""" token_resp = send_request("/api/v4/profile/websocket_token") token = token_resp["websocket_token"] await ws.send(json.dumps({ "id": 999, "method": "authorize", "params": [token, "public"], })) ack = json.loads(await ws.recv()) if ack.get("id") != 999 or ack.get("result", {}).get("status") != "success": raise RuntimeError(f"WS authorize failed: {ack}") ``` See [Authentication](/api-reference/authentication) for the full signing walkthrough. ### Single order Place a limit order using the order creation endpoint: **Endpoint:** [`POST /api/v4/order/new`](/api-reference/trading/create-limit-order) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/new \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","side":"buy","amount":"0.001","price":"60000","request":"/api/v4/order/new","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} order = send_request("/api/v4/order/new", { "market": "BTC_USDT", "side": "buy", "amount": "0.001", "price": "60000" }) print(f"Order placed: {order.get('orderId')}") ``` For bot integrations, include `clientOrderId` in the request to map fills back to internal strategy state without depending on the server-assigned `orderId`. The identifier is preserved across `order/modify` calls (modify issues a new `orderId` but retains the caller-supplied `clientOrderId`), which makes it the right key for order reconciliation. See [Client Order ID](/guides/client-order-id) for usage patterns. ### Bulk orders Place up to 20 limit orders in a single request — one round trip instead of up to 20 for multi-order strategies. **Endpoint:** [`POST /api/v4/order/bulk`](/api-reference/trading/bulk-limit-order) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/bulk \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"orders":[{"market":"BTC_USDT","side":"buy","amount":"0.001","price":"59900"},{"market":"BTC_USDT","side":"buy","amount":"0.001","price":"59800"}],"request":"/api/v4/order/bulk","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Place 5 buy orders at descending prices. # Note: `market` goes on each order item, not at the top level. orders = [ {"side": "buy", "amount": "0.001", "price": str(60000 - i * 100), "market": "BTC_USDT"} for i in range(5) ] result = send_request("/api/v4/order/bulk", {"orders": orders}) # Bulk response is an array of {result, error} pairs. `result` is null on failure. for i, item in enumerate(result): if item.get("result"): print(f"Order {i}: placed (ID {item['result']['orderId']})") else: err = item.get("error") or {} print(f"Order {i}: failed — code {err.get('code')}, {err.get('message', 'unknown')}") ``` The bulk endpoint accepts up to **20 limit orders** per request. All orders in a batch must target the same market pair. Partial failures are possible — always check each order result individually, or set `stopOnFail: true` to stop processing at the first failed order. ### Placing orders over WebSocket The [WebSocket Order Management](/websocket/order-management/overview) methods place, modify, and cancel orders as JSON-RPC calls on the same authorized WebSocket connection used for [fill monitoring](#websocket-fill-monitoring) — an alternative to the REST order endpoints. Placing over the open socket removes the per-request HTTP round trip and the per-request HMAC signature: the connection authorizes once, and every later order frame rides that session. REST `/order/bulk` places up to 20 orders in one request, while the WebSocket methods place one order per frame, so keep REST bulk for atomic batches; the kill-switch deadman below stays on REST. A placement is one JSON-RPC frame; the server answers with a single frame carrying the same `id`, interleaved with the subscription pushes, so correlate answers by `id`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 201, "method": "order_limit_place", "params": [ { "market": "BTC_USDT", "side": "buy", "amount": "0.01", "price": "60000", "client_order_id": "bot-1" } ] } ``` The transport numbers its errors independently of REST — see the [error reference](/websocket/order-management/overview#error-codes). Order placement requires an authorized connection; the parameter set for each method is on the [Order Management](/websocket/order-management/overview) reference. ## Kill-switch setup The kill-switch cancels every active order on the configured market after a timeout that the bot must refresh. If the bot crashes or loses connectivity to the API, the timer expires and the API cancels every stale order automatically. **Endpoints:** * [`POST /api/v4/order/kill-switch`](/api-reference/trading/sync-kill-switch-timer) — activate or refresh the timer * [`POST /api/v4/order/kill-switch/status`](/api-reference/trading/status-kill-switch-timer) — check current timer state ### Activate kill-switch ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/kill-switch \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","timeout":"60","request":"/api/v4/order/kill-switch","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Activate kill-switch with 60-second timeout. # Note: the API expects `timeout` as a STRING, not an integer. ks = send_request("/api/v4/order/kill-switch", { "market": "BTC_USDT", "timeout": "60" # seconds as string, valid range: "5"–"600" }) print(f"Kill-switch active, cancellationTime: {ks.get('cancellationTime')}") ``` The kill-switch scope defaults to **all order types** (spot, margin, futures). To scope it to just spot orders — for example, when the same account runs futures positions that must not be canceled by a spot kill-switch — pass `"types": ["spot"]` in the request. ### Heartbeat refresh loop The bot must refresh the kill-switch before the timer expires. If the bot fails to refresh, all orders cancel automatically. Retry a failed refresh after a short delay instead of waiting the full interval — with a 45-second interval and a 60-second timeout, one skipped refresh expires the timer before the next scheduled attempt. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import threading def kill_switch_heartbeat(market, timeout_seconds, refresh_interval): """Refresh kill-switch on a regular interval. If this thread stops, the kill-switch expires and all orders are canceled automatically.""" timeout_str = str(timeout_seconds) # API requires timeout as string while True: try: send_request("/api/v4/order/kill-switch", { "market": market, "timeout": timeout_str, }) except Exception as e: print(f"Kill-switch refresh failed: {e} — retrying in 5s") time.sleep(5) continue time.sleep(refresh_interval) # Refresh every 45 seconds with a 60-second timeout (15-second safety margin). # Runs as a daemon thread (not an asyncio task) so refreshes continue even # when the event loop is busy processing WebSocket messages. heartbeat = threading.Thread( target=kill_switch_heartbeat, args=("BTC_USDT", 60, 45), daemon=True ) heartbeat.start() ``` ### Deactivate kill-switch ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/kill-switch \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","timeout":null,"request":"/api/v4/order/kill-switch","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Deactivate by setting timeout to null (None in Python → null in JSON) send_request("/api/v4/order/kill-switch", { "market": "BTC_USDT", "timeout": None }) ``` ## WebSocket fill monitoring Subscribe to account streams to receive real-time notifications for order state changes and trade executions: | Channel | Subscribe method | Events | | - | - | - | | [Deals](/websocket/account-streams/deals) | `deals_subscribe` | Trade executions (fills) | | [Orders Pending](/websocket/account-streams/orders-pending) | `ordersPending_subscribe` | Order placed, partially filled, canceled | ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} async def monitor_fills(ws): # Subscribe to trade fills await ws.send(json.dumps({ "id": 10, "method": "deals_subscribe", "params": [["BTC_USDT"]] })) # Subscribe to order state changes await ws.send(json.dumps({ "id": 11, "method": "ordersPending_subscribe", "params": ["BTC_USDT"] })) async for message in ws: data = json.loads(message) method = data.get("method") if method == "deals_update": # params is a flat 11-element tuple — not an array of objects. # Elements: [deal_id, time, market, order_id, price, amount, fee, # client_order_id, side_int, role_int, fee_asset] p = data["params"] deal_id, ts, market, order_id, price, amount, fee, client_oid, side_int, role_int, fee_asset = p side = "sell" if side_int == 1 else "buy" print(f"Fill: {side} {amount} @ {price} (order {order_id})") elif method == "ordersPending_update": # params is [event_id, order_object]. # event_id: 1=new, 2=update, 3=finish (cancel or execute) event_id, order = data["params"] event_label = {1: "new", 2: "update", 3: "finish"}.get(event_id, "?") print(f"Order {event_label}: {order['id']} — remaining: {order.get('left', 'N/A')}") ``` ## Error handling Unattended bots must handle three failure modes: HTTP 429 rate limits, transient HTTP 5xx responses, and HTTP 4xx validation errors that should not be retried. ### Rate limit backoff ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import random def send_request_with_retry(path, data=None, max_retries=5): """Send a request with exponential backoff on HTTP 429 or 5xx. Requires `send_request` to raise on HTTP errors (via resp.raise_for_status()).""" for attempt in range(max_retries): try: return send_request(path, data) except requests.HTTPError as e: status = e.response.status_code if status == 429 or 500 <= status < 600: delay = min(30, 2 ** attempt) + random.uniform(0, 1) print(f"HTTP {status}, retrying in {delay:.1f}s...") time.sleep(delay) continue raise # 4xx other than 429 — don't retry raise Exception(f"Max retries exceeded for {path}") ``` ### Error classification | Signal | Example | Action | Auto-retry? | | - | - | - | - | | HTTP `429` | — | Exponential backoff (1s → 2s → 4s → max 30s, with jitter) | Yes | | HTTP `401` | — | Stop trading, investigate — never auto-retry auth failures | No | | HTTP `422` + body `code: 5` | Not enough balance | Log, skip order, re-check balance | No | | HTTP `422` + body `code: 30/31/32/33` | Validation failed (field-specific) | Fix the request — inspect the `errors` map | No | | HTTP `422` + body `code: 10` | Market not found or disabled | Skip market, check status via REST | No | | HTTP `5xx` | — | Backoff and retry | Yes | Never auto-retry `401` authentication errors. A failed auth indicates an incorrect signature, expired key, or IP whitelist mismatch — retrying floods the API without resolving the root cause. See [Rate Limits & Error Codes](/api-reference/rate-limits) for the complete error reference. ## Reconnection and recovery WebSocket connections drop due to network issues, server maintenance, or idle timeouts. A production bot must handle disconnections without losing state. ### Ping/pong keepalive Send periodic ping messages to detect stale connections before a timeout occurs. The server closes idle connections after 60 seconds of inactivity; send a ping every 50 seconds and treat a pong that takes longer than 10 seconds as a dead connection (see [WebSocket rate limits](/websocket/rate-limits)). A longer pong wait delays disconnect detection — long enough for the kill-switch timer to expire and cancel the working orders before the bot even notices the drop: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} PING_INTERVAL = 50 # seconds between pings PONG_TIMEOUT = 10 # reconnect if no pong arrives within 10 seconds async def keepalive(ws): """Send ping messages and monitor for pong responses.""" while True: try: await ws.send(json.dumps({"id": 0, "method": "ping", "params": []})) pong = await asyncio.wait_for(ws.recv(), timeout=PONG_TIMEOUT) data = json.loads(pong) if data.get("result") != "pong": # Not a pong — process as regular message and wait for pong pass except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed): print("Connection lost — triggering reconnection") break await asyncio.sleep(PING_INTERVAL) ``` The keepalive function above is shown in isolation. In production, integrate ping/pong handling into the main message loop — running a separate `recv()` consumer conflicts with the primary message loop and causes missed messages. ### Reconnection with exponential backoff ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} async def connect_with_retry(url, max_delay=60): """Connect to WebSocket with exponential backoff.""" delay = 1 while True: try: ws = await websockets.connect(url) print("WebSocket connected") return ws except Exception as e: jitter = random.uniform(0, 1) print(f"Connection failed: {e}. Retrying in {delay + jitter:.1f}s...") await asyncio.sleep(delay + jitter) delay = min(max_delay, delay * 2) ``` ### Auto-resubscription after reconnect After reconnecting, the bot must re-authenticate (for private channels) and re-subscribe to all channels. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} async def run_bot(): """Main bot loop with automatic reconnection and resubscription.""" subscriptions = [ {"method": "lastprice_subscribe", "params": ["BTC_USDT"]}, {"method": "depth_subscribe", "params": ["BTC_USDT", 20, "0", True]}, {"method": "deals_subscribe", "params": [["BTC_USDT"]]}, {"method": "ordersPending_subscribe", "params": ["BTC_USDT"]}, ] while True: ws = await connect_with_retry("wss://wss.whitebit.com/ws") try: # Private channels require authentication first await authenticate_ws(ws) # Re-subscribe to all channels for i, sub in enumerate(subscriptions): await ws.send(json.dumps({"id": i + 1, **sub})) # Process messages — `handle_message` is a strategy-specific # callback the caller provides. The grid-bot walkthrough below # shows the strategy-specific replacement trigger. async for message in ws: data = json.loads(message) await handle_message(data) except websockets.exceptions.ConnectionClosed: print("Disconnected — reconnecting...") continue ``` ### State reconciliation WebSocket streams do not replay messages that arrived during a disconnection. After reconnecting and re-authenticating, reconcile local state against the authoritative server state: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} def reconcile_state(market, local_orders): """Query active orders; reconcile against local state.""" # 1. Active orders on the exchange right now active = send_request("/api/v4/orders", {"market": market}) server_ids = {o["orderId"] for o in active} # 2. Drop any local order that the server no longer knows about disappeared = set(local_orders) - server_ids for oid in disappeared: local_orders.pop(oid) print(f"Reconcile: {oid} vanished — assuming filled or canceled") # 3. Orders the server knows about that are missing from local state # (e.g., after a restart) unknown_locally = server_ids - set(local_orders) for oid in unknown_locally: print(f"Reconcile: adopting server-side order {oid}") ``` Call `reconcile_state(MARKET, grid_orders)` after `authenticate_ws(ws)` and before re-subscribing. For a per-fill audit trail, also query [`POST /api/v4/trade-account/executed-history`](/api-reference/trading/query-executed-order-history) to see fills that happened during the disconnect. ## Worked example: Grid bot A grid bot places buy and sell orders at fixed price intervals around a center price. When a buy fills, a sell is placed one grid level above. When a sell fills, a buy is placed one grid level below. The strategy profits from price oscillation within the grid range. The bot assembles the building blocks from the previous sections — the signed `send_request` helper, `authenticate_ws`, the kill-switch heartbeat, and the reconnection loop — around one strategy-specific piece: the fill-replacement trigger. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Bot as Grid bot participant REST as REST API participant WS as WebSocket API Note over Bot,REST: Startup Bot->>REST: GET /api/v4/public/ticker — read center price Bot->>REST: POST /api/v4/order/kill-switch — arm the timer Bot->>REST: POST /api/v4/order/cancel/all — clean slate Bot->>REST: POST /api/v4/order/bulk — place buy/sell grid Bot->>WS: authorize, deals_subscribe, ordersPending_subscribe loop Trading loop WS-->>Bot: ordersPending_update — order finished Bot->>REST: POST /api/v4/order/new — opposite side, one level away Bot->>REST: POST /api/v4/order/kill-switch — heartbeat refresh end Note over Bot,WS: Recovery WS--xBot: connection drops Bot->>WS: reconnect + authorize Bot->>REST: POST /api/v4/orders — detect vanished grid orders Bot->>WS: re-subscribe ``` The lifecycle, mapped to the sections above: 1. **Center the grid** — fetch the market's `last_price` from [`GET /api/v4/public/ticker`](/api-reference/market-data/market-activity) and snap to the grid spacing. 2. **Arm the kill-switch first** — activate the timer and start the [heartbeat refresh loop](#heartbeat-refresh-loop) before any order exists, so a crash mid-startup still cleans up. 3. **Clean slate** — cancel leftovers from a previous run with `POST /api/v4/order/cancel/all` scoped to the market. The call removes every open order on the market regardless of type, including manually placed ones. 4. **Place the grid** — buy levels below center, sell levels above, batched through the [bulk endpoint](#bulk-orders) in groups of 20. Track `orderId → {side, price, level}` in a local dict (`grid_orders` below). 5. **Monitor and replace** — subscribe to the [account streams](#websocket-fill-monitoring); each fully executed grid order triggers an opposite order one level away. 6. **Recover** — on disconnect, [reconnect with backoff](#reconnection-with-exponential-backoff), re-authorize, [reconcile](#state-reconciliation) against `POST /api/v4/orders` (a grid order missing from the server filled or was canceled during the gap), then re-subscribe. The replacement trigger is the only strategy-specific code — and the step bots most often get wrong: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} async def handle_message(data): """Replacement trigger. deals_update fires per PARTIAL execution — log fills there, never replace. Replace only on ordersPending event 3 (finish) with left == 0 (fully executed, not canceled).""" if data.get("method") == "ordersPending_update": event_id, order = data["params"] if event_id == 3 and float(order.get("left", "0")) == 0: filled = grid_orders.pop(order["id"], None) if filled is None: return # not a grid order up = filled["side"] == "buy" send_request("/api/v4/order/new", { "market": MARKET, "side": "sell" if up else "buy", "amount": ORDER_AMOUNT, "price": str(float(filled["price"]) + (GRID_SPACING if up else -GRID_SPACING)), }) ``` Inside the async message loop, wrap synchronous REST calls in `asyncio.to_thread()` — blocking calls (including the backoff sleeps in `send_request_with_retry`) delay WebSocket message processing. When reconciling after a reconnect, confirm a vanished order's outcome via [`POST /api/v4/trade-account/executed-history`](/api-reference/trading/query-executed-order-history) before treating the disappearance as a fill. Before running against real funds: validate all order parameters against the market's `minAmount` and `minTotal` from [`GET /api/v4/public/markets`](/api-reference/market-data/market-info), and add proper logging. The startup `order/cancel/all` call removes every open order on the configured market regardless of type, including orders placed manually, so run the bot on a dedicated account or sub-account. ## What's next Monitor balances, deposits, and order activity across all account types. Attach custom identifiers to orders for tracking across systems. Per-endpoint rate limits, error codes, and retry strategies. # Crypto-as-a-Service FAQ Source: https://docs.whitebit.com/guides/caas-faq Common questions about WhiteBIT Crypto-as-a-Service: scope and delivery, onboarding and access, integration, security and compliance, and support. Answers to common questions about WhiteBIT Crypto-as-a-Service (CaaS). ## Scope and delivery ### Delivery model CaaS is a white-label offering delivered as a dedicated, custom-branded instance integrated through the WhiteBIT API, with WhiteBIT operating the exchange, custody, and compliance infrastructure. See the [CaaS overview](/guides/caas-overview). ### End-customer capabilities End customers can create crypto wallets, store crypto in institutional custody, buy and sell with fiat, and send and receive crypto. See [What end customers can do](/guides/caas-overview#what-end-customers-can-do). ### CaaS and Wallet-as-a-Service CaaS is the full white-label exchange offering; Wallet-as-a-Service is the wallet and deposit-address building block that CaaS uses for end-customer wallets. See [Wallet-as-a-Service](/guides/waas-overview). ## Onboarding and access ### Onboarding phases Institutional onboarding has two phases: Phase 1 grants crypto operations access after KYC of the director or responsible person and KYB of the company; optional Phase 2 adds fiat access ([Fiat access via SEPA](#fiat-access-via-sepa)). See [Institutional Onboarding](/institutional/onboarding). ### Crypto deposit enablement Crypto deposits are disabled by default on institutional accounts and cannot be enabled via API. Once enabled, the capability applies to the account and its sub-accounts. Request it through the assigned account manager or `institutional@whitebit.com`. See [Institutional Onboarding](/institutional/onboarding). ### Fiat access via SEPA EUR/SEPA fiat access is added in Phase 2 of institutional onboarding and covers API-generated deposit invoices and SEPA withdrawals. See the [On/Off-Ramp guide](/guides/on-off-ramp-integration). ### Crypto Lending access Fixed and Flex lending endpoints are restricted to B2B partners and return a permission error until access is granted. Request access through the [institutional services form](https://whitebit.com/institutional-services/b2b). See [Crypto Lending](/products/lending/overview). ## Integration ### API base URL and regions The global REST base URL is `https://whitebit.com`. Regional environment options are confirmed during onboarding. See [First API Call](/guides/first-api-call). ### Test environment availability WhiteBIT does not offer a public testnet or sandbox. Test on the live API with minimum order sizes and low-minimum assets; Demo Tokens are available for risk-free spot practice. See the [Go-Live Checklist](/best-practices/go-live-checklist). ### OAuth and Fast API Key Partners issue user-scoped API keys through the OAuth-based Fast API Key flow. The classic OAuth 2.0 Authorization Code Grant flow for direct account-data access is deprecated and will be removed on November 1, 2026. See [Fast API Key via OAuth](/guides/fast-api-key-integration). ### Rate limits Rate limits are set per scope and per endpoint rather than as a single global value. See [Rate limits](/api-reference/rate-limits). ## Security and compliance ### Security certifications WhiteBIT holds ISO 27001, CCSS Level 3, and PCI DSS Level 1 certifications, with the CCSS Level 3 assessment conducted by Hacken; 96% of platform digital assets are held in cold storage, with Fireblocks on the custody side. See [Regulatory Compliance](/institutional/compliance). ### MiCA and Travel Rule for EEA end users For EEA users, MiCA restricts some stablecoin operations — USDT deposits, withdrawals, and WhiteBIT Codes are unavailable, and USDC and EURI are the documented alternatives. The Travel Rule governs crypto transfers for EEA and Turkey accounts. See [Regulatory Compliance](/institutional/compliance) and [Travel Rule](/concepts/travel-rule). ### Restricted jurisdictions Which jurisdictions are restricted or prohibited for the partner and its end customers is confirmed case by case with `compliance@whitebit.com`; bring the target regions to the first onboarding conversation so the applicable regime (including MiCA and Travel Rule scope) can be assessed. See [Restricted jurisdictions](/institutional/compliance#restricted-jurisdictions). ### Data Processing Agreement A Data Processing Agreement (DPA) is available on request; WhiteBIT processes data in the European Union. Request it via `compliance@whitebit.com`. See [Regulatory Compliance](/institutional/compliance). ## Support ### Support contacts The assigned account manager is the primary contact. Programs and onboarding go to `institutional@whitebit.com`; compliance, VASP, and DPA matters go to `compliance@whitebit.com`. Platform questions are answered at [help.whitebit.com](https://help.whitebit.com), and API documentation is on docs.whitebit.com. ## What's next What Crypto-as-a-Service provides and the segments it fits. How a CaaS integration is assembled from the documented API surface. Cross-cutting answers shared across programs — KYB, sandbox, fees, and rate limits. # Crypto-as-a-Service integration Source: https://docs.whitebit.com/guides/caas-integration How a CaaS integration is assembled from WhiteBIT's documented API building blocks. **For developers.** This page routes each CaaS capability to the guide that documents it. For what CaaS is, the segments it fits, and the path to launch, see the [CaaS overview](/guides/caas-overview). A CaaS integration is assembled from the same documented API surface used across WhiteBIT's B2B products. It does not restate the schemas — each linked guide carries the endpoint and field detail. ## Prerequisites * **A CaaS engagement scoped with WhiteBIT** — see the [CaaS overview](/guides/caas-overview) for what the model delivers and the path to launch. * **Architecture alignment** — the instance, branding, and asset scope agreed during onboarding (see [Architecture alignment during onboarding](#architecture-alignment-during-onboarding)). * **API access** — [HMAC-signed requests](/api-reference/authentication); each capability's endpoint and field detail lives in the linked product guide. ## Integration building blocks ### Core API access * **REST and WebSocket.** 100+ authenticated REST endpoints and 14 public endpoints, plus WebSocket market data and private account streams. Requests are signed with HMAC-SHA512 using the `X-TXC-APIKEY`, `X-TXC-PAYLOAD`, and `X-TXC-SIGNATURE` headers. See [First API Call](/guides/first-api-call). [Order placement, modification, and cancellation](/websocket/order-management/overview) over the same connection are available (global platform only), authorized once on the connection rather than per request. * **SDKs and tooling.** Official Go, Python, and PHP SDKs, plus an MCP server and a CLI for AI-assisted integration. See [SDKs](/sdks) and [AI tools](/guides/use-with-ai). * **API keys.** Two-factor authentication is required before key creation; the secret is shown only once at creation; up to 50 trusted IPs can be whitelisted per key; keys auto-deactivate after 14 days of inactivity and are revoked on an account password change, block, or freeze. See [Authentication](/api-reference/authentication). * **Rate limits.** Limits are set per scope and per endpoint. See [Rate limits](/api-reference/rate-limits) for current values rather than assuming a single figure. API keys grant account access. Restrict each key to the minimum scope and to known IPs, and store secrets outside application code. See [Authentication](/api-reference/authentication). ### Wallets and payments * **Deposit addresses.** Generate a unique address per end user with `POST /api/v4/main-account/create-new-address`; incoming funds are reconciled by webhook. See the [Payment Integration guide](/guides/payment-integration) and the [Wallet-as-a-Service developer guide](/guides/waas-integration). * **Withdrawals.** Fee-inclusive (`/withdraw`) and fee-on-top (`/withdraw-pay`) variants, plus withdrawal after conversion using the Convert service — request a quote, confirm at the quoted rate, then withdraw in the destination currency. See [Payment Integration](/guides/payment-integration) and [Convert](/platform/convert). * **Fiat rails (EUR/SEPA).** Available after Phase 2 onboarding — API-generated deposit invoices and SEPA withdrawals. See the [On/Off-Ramp guide](/guides/on-off-ramp-integration). * **WhiteBIT Codes.** Fee-free internal crypto transfers between WhiteBIT accounts, useful for settlement flows. See [WhiteBIT Codes](/platform/whitebit-codes). * **Crypto Lending.** Fixed and Flex lending endpoints are restricted to B2B partners and require access to be granted through the [institutional services form](https://whitebit.com/institutional-services/b2b). See [Crypto Lending](/products/lending/overview). Travel Rule affects deposits and withdrawals for EEA and Turkey accounts — the primary CaaS segments (banks, EMIs, fintechs). The Travel Rule API for programmatic verification is enabled per account via [institutional@whitebit.com](mailto:institutional@whitebit.com); see [Regulatory Compliance](/institutional/compliance). For transfers in scope of the Travel Rule, originator and beneficiary information is required. See [Travel Rule](/concepts/travel-rule) for the field requirements and the transfer flow. ### Account architecture * **Sub-accounts.** Create and manage thousands of separate accounts under one umbrella, each with independent balances, API keys, and IP whitelists, with fee-free instant transfers between the main account and its sub-accounts. See [Sub-Accounts](/products/sub-accounts/overview). * **Fast API Key via OAuth.** For flows where end users hold personal WhiteBIT accounts, a partner can issue user-scoped API keys through the OAuth API key flow. New partner integrations use this flow. See [Fast API Key via OAuth](/guides/fast-api-key-integration) and the [OAuth overview](/platform/oauth/overview). * **Trading and conversion.** Spot markets across 800+ pairs, and the Convert service for instant conversion at a quoted rate without placing orders on the order book. See [Convert](/platform/convert). The classic OAuth 2.0 Authorization Code Grant flow for direct account-data access is deprecated and will be removed on November 1, 2026. New integrations use the Fast API Key flow. See the [OAuth overview](/platform/oauth/overview). ## Architecture alignment during onboarding The public documentation covers the API surface, but not the full dedicated-instance model behind CaaS. The items below define the integration architecture and are agreed and documented with WhiteBIT during onboarding, before development starts. * **Instance model** — how the dedicated, custom-branded instance relates to the public API surface, and which base URL and credentials the environment uses. * **End-user account mapping** — how end customers map onto the WhiteBIT account model (for example, one sub-account per end user, versus a pooled account with the partner's own internal ledger), and the reconciliation and limit trade-offs of each. * **KYC and KYB split** — which party verifies end customers, at which levels, and how verification status is exchanged between the partner and WhiteBIT. * **Data residency and privacy** — where end-customer data is processed and stored, and the Data Processing Agreement (available via [compliance@whitebit.com](mailto:compliance@whitebit.com)). * **Operational roles** — which staff hold which permissions (API key scopes, sub-account administration, withdrawal approval). * **Support model** — support tiers, response targets, and incident channels beyond the public status page. * **Fee and settlement terms.** There is no public sandbox. Integrate against the live API with minimum amounts, run a limited pilot cohort, then scale to production. The [Go-Live Checklist](/best-practices/go-live-checklist) gates each stage. ## Operating the integration * **Webhooks.** Real-time notifications for deposits, withdrawals, code redemptions, and refunds, verified with an HMAC-SHA512 signature. Pair webhooks with periodic history polling as a reconciliation fallback. See [Webhooks](/platform/webhook). * **Monitoring.** [status.whitebit.com](https://status.whitebit.com) reports platform, API, and blog status; [whitebit.com/system-page](https://whitebit.com/system-page) reports per-asset deposit, withdrawal, and transfer availability. * **Testing.** WhiteBIT does not offer a public testnet. Test on the live API with minimum order sizes and low-minimum assets; Demo Tokens are available for risk-free spot practice. * **Go-live.** Work through the [Go-Live Checklist](/best-practices/go-live-checklist) — covering authentication, error handling, rate limits, compliance, WebSocket, webhooks, monitoring, and testing. ## Support * **Primary contact:** the assigned account manager, plus the support channels agreed during onboarding. * **Programs and onboarding:** [institutional@whitebit.com](mailto:institutional@whitebit.com). * **Compliance, VASP, and DPA:** [compliance@whitebit.com](mailto:compliance@whitebit.com). * **Self-service:** [help.whitebit.com](https://help.whitebit.com) for platform questions; docs.whitebit.com for API documentation. ## What's next What CaaS is, who it is for, and the path to launch. Common questions on scope, onboarding, regions, and support. KYB and the two-phase onboarding process. Pre-launch verification across every integration concern. # Crypto-as-a-Service Source: https://docs.whitebit.com/guides/caas-overview Put WhiteBIT behind a partner's product as the exchange, custody, and compliance backend for a white-label crypto offering. Crypto-as-a-Service (CaaS) lets a partner offer digital-asset functionality under its own brand while WhiteBIT operates the exchange, custody, and compliance infrastructure behind it. For how the integration is assembled, see the [Integration guide](/guides/caas-integration). Launching a full branded exchange fits CaaS. Adding wallets or payouts to an existing product instead fits [Wallet-as-a-Service](/guides/waas-overview), the building block CaaS uses for end-customer wallets. CaaS orchestrates existing WhiteBIT building blocks rather than adding new API surface. The [Integration guide](/guides/caas-integration) routes each capability — wallets, payments, accounts, and compliance — to the guide that documents it. ## What CaaS provides * A dedicated, custom-branded instance, integrated into the partner's platform through the API. * End-customer crypto capabilities — wallets, custody, fiat buy and sell, and cross-border transfers — delivered under the partner's brand. * The security and compliance posture of the underlying exchange: institutional custody, certifications, and regulated operation. * Coverage across 80+ blockchain networks and hundreds of digital assets. Asset and market coverage and program terms are confirmed during onboarding — see the [CaaS product page](https://institutional.whitebit.com/crypto-as-a-service). ## Who CaaS is for | Segment | Typical use | | - | - | | Banks and EMIs (electronic money institutions) | Embed digital-asset functionality — wallets, custody, buy and sell, transfers — into an existing regulated product. | | Fintechs and neobanks | Let end customers accept, store, and move digital assets across borders inside the partner app. | | Telecom operators | Offer crypto buy and sell to subscribers. One implemented pattern is access through a USSD code (a carrier menu dialed as a short code). | | Core banking and Banking-as-a-Service (BaaS) providers | Integrate CaaS into the product suite and resell it as a white-label option to corporate customers. | ## What end customers can do * **Create crypto wallets** — a unique deposit address per end user across 80+ networks. See [Wallet-as-a-Service](/guides/waas-overview) for the wallet-level integration. * **Store crypto in institutional custody** — 96% of platform digital assets are held in cold storage, with Fireblocks on the custody side. * **Buy and sell with fiat** — fiat access over EUR/SEPA rails, added in optional Phase 2 onboarding, with [Convert](/platform/convert) and spot markets for the crypto side. See the [On/Off-Ramp guide](/guides/on-off-ramp-integration). * **Send and receive crypto** — on-chain transfers, plus fee-free internal transfers with [WhiteBIT Codes](/platform/whitebit-codes). ## Onboarding and launch path The path from first conversation to a live offering has four stages. Review and agree the business case with the WhiteBIT team. Complete institutional onboarding — KYC for the director or responsible person and KYB for the company (Phase 1, crypto operations), with an optional Phase 2 for fiat operations via SEPA. See [Institutional Onboarding](/institutional/onboarding). Connect the partner platform to WhiteBIT through the API. See the [Integration guide](/guides/caas-integration). Go live with the crypto functionality embedded in the partner product — typically around four weeks from approval, depending on integration scope. Crypto deposits are disabled by default on institutional accounts. Once enabled, the capability applies to the account and its [sub-accounts](/products/sub-accounts/overview); enablement is not available via API. Request it through the assigned account manager or [institutional@whitebit.com](mailto:institutional@whitebit.com). ## Security and compliance End customers inherit the security and compliance posture of the underlying platform. * **Certifications:** ISO 27001, CCSS Level 3, and PCI DSS Level 1; the CCSS Level 3 assessment is conducted by Hacken. See [Regulatory Compliance](/institutional/compliance). * **Custody:** 96% cold wallet storage, with Fireblocks integration on the custody side. * **Regional compliance (EEA):** MiCA restricts some stablecoin operations for EEA users, and the Travel Rule governs EEA and Turkey transfers. Both affect the assets and flows available to those end users. See [Regulatory Compliance](/institutional/compliance) and [Travel Rule](/concepts/travel-rule). * **Data and licensing:** WhiteBIT processes data in the European Union and provides a Data Processing Agreement (DPA) on request. VASP registrations and DPA requests are handled by [compliance@whitebit.com](mailto:compliance@whitebit.com). The instance model, end-user account mapping, the KYC/KYB split, and commercial terms are agreed and documented with WhiteBIT during onboarding, before development starts. See [Architecture alignment during onboarding](/guides/caas-integration#architecture-alignment-during-onboarding) for the full list. ## How to get started 1. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) with the business case, target segment, and target regions. 2. Prepare for [Institutional Onboarding](/institutional/onboarding) — KYB, plus optional fiat access (Phase 2). 3. Build against the [Integration guide](/guides/caas-integration) and clear the [Go-Live Checklist](/best-practices/go-live-checklist) before real volume. For compliance, VASP, and DPA matters, contact [compliance@whitebit.com](mailto:compliance@whitebit.com). ## What's next Route each capability to its guide, align the dedicated-instance architecture, and operate in production. Common questions on scope, onboarding, regions, and support. KYB and the two-phase onboarding process. Program overview, segments, and figures on institutional.whitebit.com. # CLI Source: https://docs.whitebit.com/guides/cli Trade, manage accounts, and query market data from the terminal using the WhiteBIT CLI. Built for scripting, CI/CD pipelines, and automated workflows. The WhiteBIT CLI provides 110+ commands covering the full WhiteBIT API surface — market data, spot trading, collateral trading, lending, sub-accounts, deposits, and withdrawals — directly from the terminal. ## Prerequisites * A WhiteBIT account with an API key for authenticated commands — see [Authentication](/api-reference/authentication) Public market data commands (`market`, `server`) require no account or API key. | Feature | Detail | | - | - | | **110+ commands** | Full API surface: spot, collateral, lending, sub-accounts, deposits, withdrawals | | **Multi-profile** | Named profiles in `~/.whitebit/config.toml`, switch with `--profile` | | **`--dry-run` mode** | Preview the exact request payload before sending | | **JSON output** | `--json` flag on every command — pipe into `jq` or any automation tool | | **Shell completion** | Tab-completion for Bash, Zsh, and Fish | | **Cross-platform** | macOS (ARM + x64), Linux, and Windows | ## Install the CLI ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} brew install whitebit-exchange/tap/whitebit ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} npm install -g whitebit-cli ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} git clone https://github.com/whitebit-exchange/whitebit-cli cd whitebit-cli bun install bun src/cli.ts --help ``` Requires [Bun](https://bun.sh) ≥ 1.0.0. ## Quick start ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # 1. Set credentials (required for account and trading commands) export WHITEBIT_API_KEY="YOUR_API_KEY" export WHITEBIT_API_SECRET="YOUR_SECRET" # 2. Verify setup — no authentication required whitebit market info # 3. Check the spot balance whitebit spot balance # 4. Place a limit order whitebit spot limit-order --market BTC_USDT --side buy --amount 0.001 --price 50000 ``` ## Authentication Credentials are resolved in priority order (highest first): | Method | Best for | Persistence | Security note | | - | - | - | - | | CLI flags (`--api-key`, `--api-secret`) | Quick testing | None | Visible in process list | | Environment variables | CI/CD, Docker, one-off scripts | Per-session | Depends on environment | | Config file (`~/.whitebit/config.toml`) | Daily use, multiple profiles | Permanent | Set `chmod 600` on the file | Store API keys securely. Do not commit `~/.whitebit/config.toml` to version control. Avoid `--api-key` flags in production scripts — the value is visible in the process list. ### Config file Create `~/.whitebit/config.toml` with one or more named profiles: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [default] api_key = "YOUR_API_KEY" api_secret = "YOUR_SECRET" default_format = "table" # or "json" [work] api_key = "WORK_API_KEY" api_secret = "WORK_SECRET" ``` Switch profiles with `--profile`: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} whitebit spot balance --profile work ``` ## Commands | Module | Commands | Auth | Description | | - | - | :-: | - | | `server` | 3 | No | Server ping, time, and maintenance status | | `market` | 11 | No | Markets, order book, trades, depth, funding rates, assets | | `spot` | 14 | Yes | Limit, market, stop orders; cancel, modify, kill-switch | | `collateral` | 16 | Yes | Margin: leverage, positions, OCO, conditional orders | | `account` | 7 | Yes | Main balance, history, deposit address, withdraw, transfer, fees | | `convert` | 3 | Yes | Estimate and execute asset conversions | | `lending` | 11 | Yes | Fixed and flexible staking, interest history | | `mining` | 6 | Yes | Rewards, hashrate, worker stats, payout destination | | `sub-account` | 10 | Yes | Sub-account management, balances, transfers | | `config` | 2 | No | Manage CLI credentials and profiles | ## Examples ### Market data ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # List all available markets whitebit market info # Get 24h pricing and volume for all markets whitebit market activity # Get order book whitebit market orderbook --market BTC_USDT # Get recent trades whitebit market trades --market BTC_USDT ``` ### Account and balance ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Check spot balance whitebit spot balance # Check main account balance whitebit account main-balance # Transfer 100 USDT from main to spot whitebit account transfer --from main --to spot --ticker USDT --amount 100 ``` ### Spot trading ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Place a limit buy order whitebit spot limit-order --market BTC_USDT --side buy --amount 0.001 --price 50000 # Place a market sell order whitebit spot market-order --market BTC_USDT --side sell --amount 0.001 # List open orders whitebit spot active-orders --market BTC_USDT # Cancel an order whitebit spot cancel --market BTC_USDT --order-id ORDER_ID ``` ### JSON output and scripting ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Output as JSON whitebit spot balance --json # Pipe into jq whitebit spot balance --json | jq '.[] | {currency: .currency, balance: .available}' # Dry run — preview the request without sending whitebit spot limit-order --market BTC_USDT --side buy --amount 0.001 --price 50000 --dry-run ``` ## Shell completion ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} whitebit completion --shell bash >> ~/.bash_completion ``` To load automatically, add `source ~/.bash_completion` to `~/.bashrc`. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} mkdir -p ~/.zfunc whitebit completion --shell zsh > ~/.zfunc/_whitebit ``` Add `fpath=(~/.zfunc $fpath)` and `autoload -Uz compinit && compinit` to `~/.zshrc`. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} whitebit completion --shell fish > ~/.config/fish/completions/whitebit.fish ``` ## Global options | Option | Description | | - | - | | `--profile ` | Use a named config profile (default: `default`) | | `--api-key ` | Override the API key for this command | | `--api-secret ` | Override the API secret for this command | | `--api-url ` | Override the API base URL | | `--format ` | Output format | | `--json` | Shorthand for `--format json` | | `--verbose`, `-V` | Show raw API responses | | `--dry-run` | Show the request payload without sending | ## Exit codes | Code | Meaning | | - | - | | `0` | Success | | `1` | General error | | `2` | Authentication or credential error | | `3` | Network error | | `4` | Usage or bad arguments | | `5` | Rate limit (HTTP 429) | ## Security best practices * Never commit credentials to version control. * Use environment variables for CI/CD pipelines. * Set restrictive file permissions: `chmod 600 ~/.whitebit/config.toml`. * Use API key restrictions in the WhiteBIT dashboard — IP whitelist and read-only scope when appropriate. * Avoid `--api-key` and `--api-secret` flags in production scripts — values are visible in the process list. ## What's next * [MCP server](/guides/mcp-server) — Use natural language to trade and query data via an AI client * [AI tools FAQ](/guides/ai-faq) — Common questions about the CLI, API keys, and automation * [AI tools overview](/guides/use-with-ai) — All WhiteBIT AI tools in one place * [Authentication](/api-reference/authentication) — How to generate and manage WhiteBIT API keys * [API Reference Overview](/api-reference/overview) — Full REST API endpoint listing # Client Order ID Source: https://docs.whitebit.com/guides/client-order-id This guide provides information about using `clientOrderId` in trading operations, including best practices and common use cases. ## Overview The `clientOrderId` is an optional identifier for tracking and managing orders with custom identifiers. It provides an additional layer of order management and tracking capabilities alongside the exchange-provided `orderId`. ## Specifications * Type: String * Mandatory: No * Uniqueness: enforced only among open (pending) orders on the same market — the identifier can be reused once the previous order fills or cancels * Latin letters * Numbers * Dashes (-) * Dots (.) * Underscores (\_) * Recommended length: 32 characters * Case-sensitive: “Order1” and “order1” are different IDs * Leading/trailing spaces are not allowed * Cannot be an empty string if provided ## Best Practices **Structured Naming Convention** ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Format: strategy-pair-type-timestamp const clientOrderId = "scalp-btcusdt-limit-1678234567"; // Format: botId-strategy-sequence const clientOrderId = "bot123-grid-0001"; // Format: userAccount-orderType-customSequence const clientOrderId = "trade15-market-a7b8c9"; ``` **Timestamp Integration** ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}} const getClientOrderId = (prefix: string) => { const timestamp = Date.now(); return `${prefix}-${timestamp}`; }; // Usage const orderId = getClientOrderId("btc-dca"); // "btc-dca-1678234567890" ``` **Strategy Identification** ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}} const generateStrategyOrderId = ( strategy: string, pair: string, action: string ) => { const sequence = Math.floor(Math.random() * 1000) .toString() .padStart(3, "0"); return `${strategy}-${pair}-${action}-${sequence}`; }; // Usage const orderId = generateStrategyOrderId("grid", "btcusdt", "buy"); ``` * • spot-btcusdt-buy-001 * • dca-ethusdt-sell-002 * • grid-solusdt-buy-003 * • bot1-grid-btc-h4-001 * • arb-eth-ftm-cross-002 * • hedge-btc-perp-003 ## Common Use Cases **Basic Limit Order** ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Simple limit order with clientOrderId const limitOrderRequest = { market: "BTC_USDT", side: "buy", amount: "0.01", price: "40000", clientOrderId: "limit-btc-buy-001" }; ``` **Market Order with Strategy Tag** ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Market order for DCA strategy const marketOrderRequest = { market: "BTC_USDT", side: "buy", amount: "50", // Buy BTC for 50 USDT clientOrderId: "dca-btc-market-002" }; ``` **Stop-Limit Order with Position Tracking** ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Stop-limit order with position tracking const stopLimitOrderRequest = { market: "BTC_USDT", side: "sell", amount: "0.01", price: "39000", activation_price: "39500", clientOrderId: "pos1-sl-btc-001" }; ``` **OTO (One-Triggers-Other) Orders** ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Main order with stop loss and take profit const otoOrderRequest = { market: "BTC_USDT", side: "buy", amount: "0.01", price: "40000", clientOrderId: "oto-btc-main-001", stopLoss: "38000", takeProfit: "42000" }; ``` ## Order Management Track orders using `clientOrderId` through the following endpoints: **1. Query Active Orders** Use the [Query Active Orders endpoint](/api-reference/trading/query-unexecuted-orders) (`/api/v4/orders`) to get all unexecuted orders: ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Request const queryActiveOrders = { market: "BTC_USDT", clientOrderId: "dca-btc-market-002" }; ``` Example response includes order details such as ID, status, and execution information: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "orderId": 4180284841, "clientOrderId": "dca-btc-market-002", "market": "BTC_USDT", "side": "buy", "type": "limit", "timestamp": 1595792396.165973, "dealMoney": "0", "dealStock": "0", "amount": "0.001", "price": "40000", "status": "NEW" } ``` **2. Query Order History** Use the [Query Order History endpoint](/api-reference/trading/query-executed-orders) (`/api/v4/trade-account/order/history`) to get executed orders: ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Request const queryOrderHistory = { market: "BTC_USDT", clientOrderId: "grid-btc-sell-003", limit: 50, offset: 0 }; ``` Example response showing execution details and final order status. The response groups orders by market name: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "BTC_USDT": [ { "id": 4180284841, "clientOrderId": "grid-btc-sell-003", "side": "sell", "type": "limit", "ctime": 1595792396.165973, "ftime": 1595792396.999999, "dealMoney": "41.258268", "dealStock": "0.001", "amount": "0.001", "price": "41258.27", "status": "FILLED" } ] } ``` **3. Cancelling Orders Using ClientOrderId** Use the [Cancel Order endpoint](/api-reference/trading/cancel-order) (`/api/v4/order/cancel`) to cancel an order by its `clientOrderId`: ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Request const cancelOrderRequest = { market: "BTC_USDT", clientOrderId: "dca-btc-market-002" }; ``` **Important notes about order cancellation:** * Use either `orderId` or `clientOrderId`, but not both in the same request * A request specifying both identifiers, or neither, returns a validation error ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} // Example response { "orderId": 4180284841, "clientOrderId": "dca-btc-market-002", "market": "BTC_USDT", "side": "buy", "type": "limit", "timestamp": 1595792396.165973, "mtime": 1595792412.443301, "dealMoney": "0", "dealStock": "0", "amount": "0.001", "left": "0.001", "price": "40000", "status": "CANCELED" } ``` ## Error Handling #### Common Error Cases The clientOrderId only has to be unique among the account's open (pending) orders on the same market. Once a previous order is filled or canceled, the same identifier can be reused on the same market. The same identifier can also be used in parallel on different markets. Ensure the ID only contains allowed characters. The recommended length is 32 characters, with a maximum permissible length of 64 characters. Handle cases where an order with the specified clientOrderId does not exist. #### Example error handling: ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} try { const order = await queryOrderByClientId("dca-btc-market-002"); // Process order } catch (error) { if (error.code === 36) { console.error("Invalid clientOrderId format"); } else if (error.code === 2) { console.error("Order not found"); } else { console.error("Unexpected error:", error); } } ``` ## Example: Account-operator implementation For the full Embedded Trading integration guide — program enrollment, sub-account setup, fee share model, and revenue monitoring — see [Embedded Trading integration](/guides/sub-account-integration). **ClientOrderId Structure** Format: ` acct-{clientId}-{orderType}-{purpose}-{timestamp} ` Example: `acct-ind123-limit-spot-1678234567` **Components:** * `acct`: Account-operator prefix * `clientId`: Internal client identifier * `orderType`: Order type (market/limit) * `purpose`: Trading purpose/strategy * `timestamp`: Keeps each identifier distinct across submissions `acct-ind123-market-spot-1678234567` `acct-corp789-limit-hedge-1678234567` `acct-port555-market-dca-1678234567` ### Trading Purpose Examples `acct-ind123-market-spot-1678234567` `acct-port555-market-dca-1678234567` `acct-ind123-limit-grid-1678234567` `acct-port555-limit-rebal-1678234567` ### API Usage Example ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Create an order for a client const createClientOrder = { market: "BTC_USDT", side: "buy", amount: "0.01", price: "40000", clientOrderId: "acct-ind123-limit-spot-1678234567" }; // Query client's active orders const queryClientOrders = { market: "BTC_USDT", clientOrderId: "acct-ind123-limit-spot-1678234567" }; // Cancel client's order using clientOrderId const cancelClientOrder = { market: "BTC_USDT", clientOrderId: "acct-ind123-limit-spot-1678234567" }; // Get historical data for client orders const getClientOrderHistory = { market: "BTC_USDT", clientOrderId: "acct-ind123-limit-spot-1678234567", limit: 50, offset: 0 }; ``` **This structured approach lets an account operator:** * Track orders for multiple clients * Identify order types and purposes * Maintain unique identifiers * Query and manage orders efficiently ### Order management for account operators **Client Order Management** #### Cancelling Client Orders An account operator can efficiently cancel orders for any client using the structured clientOrderId: ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Function to cancel a client's order async function cancelClientOrder(clientId, orderPurpose, orderId) { const cancelRequest = { market: "BTC_USDT", clientOrderId: `acct-${clientId}-limit-${orderPurpose}-${orderId}` }; try { const response = await api.post('/api/v4/order/cancel', cancelRequest); return response.data; } catch (error) { console.error(`Failed to cancel order for client ${clientId}:`, error); throw error; } } // Example usage await cancelClientOrder('ind123', 'spot', '1678234567'); ``` #### Retrieving Historical Client Orders The [Query Order History endpoint](/api-reference/trading/query-executed-orders) (`/api/v4/trade-account/order/history`) supports exact `clientOrderId` lookup only: pass the full identifier to retrieve a single order. When `clientOrderId` is supplied, the endpoint switches to single-order lookup mode and ignores the `startDate`, `endDate`, and `status` filters. Pattern or prefix matching on `clientOrderId` is not supported. ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Exact lookup of one client order (single-order mode) const lookupClientOrder = { market: "BTC_USDT", clientOrderId: "acct-ind123-limit-spot-1678234567" }; ``` For reporting across many client orders, retrieve history in list mode — filtered by `market`, `startDate`, and `endDate` (Unix seconds) — and parse the structured identifiers client-side, as shown below. ### Analytics and reporting With structured clientOrderId patterns, an account operator can reconstruct per-client reporting from order history without a separate order database — each ID segment maps to a report dimension: | ID segment | Encodes | Analytics use | | - | - | - | | `acct` | Account-operator prefix | Separates operator flow from other orders | | `clientId` | Internal client identifier | Groups orders and volume per client | | `orderType` | Order type (market/limit) | Order-type mix per client | | `purpose` | Trading purpose/strategy (spot, dca, grid, rebal) | Order count and volume per strategy | | `timestamp` | Submission time | Keeps IDs distinct; submission-time analysis | The critical path is the parser — split the ID and validate its shape. Aggregating parsed segments into per-client totals (order counts, `dealMoney` volume, per-purpose breakdowns) is standard reporting code on top of it: ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} // Parse clientOrderId back into its metadata segments // Format: acct-{clientId}-{orderType}-{purpose}-{timestamp} function parseClientOrderId(clientOrderId) { const parts = clientOrderId.split('-'); if (parts.length !== 5 || parts[0] !== 'acct') { throw new Error('Invalid account-operator clientOrderId format'); } return { clientId: parts[1], orderType: parts[2], purpose: parts[3], timestamp: parseInt(parts[4]) }; } ``` # Copy Trading Source: https://docs.whitebit.com/guides/copy-trading How a copy-trading platform mirrors a lead trader's orders into followers' own WhiteBIT accounts using OAuth-issued Fast API Keys. Architecture, permissions, and order-placement schema. Copy trading is a partner use case, not a WhiteBIT product feature. A partner platform decides which orders to mirror and places each order, through an OAuth-issued API key, on the follower's own WhiteBIT account. Execution happens inside the follower's account. This use case builds on the [Fast API Key via OAuth](/guides/fast-api-key-integration) integration — the prerequisite flow for consent, key issuance, one-time secret retrieval, signing, and revocation. Complete that integration first. Copy-trading access is granted on top of an approved Fast API Key integration. ## Architecture Each follower keeps a personal WhiteBIT account — WhiteBIT performs KYC and holds custody — and grants the partner an OAuth-issued API key on the consent screen. One key is issued per follower. The partner backend computes the copy logic — which lead-trader orders to mirror, position sizing, and timing. The backend then places the resulting orders on the follower's account, signing each request with that follower's key. The account an order lands on is determined by which follower's key signs the request. The V4 trade API has no account-selector parameter — a request always acts on the account that owns the API key in the `X-TXC-APIKEY` header. Mirroring the same lead trade across many followers means placing one signed order per follower, each with that follower's own key. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Follower participant Partner as Partner backend participant WhiteBIT Follower->>WhiteBIT: Authorize partner on the consent screen WhiteBIT-->>Follower: API key created (2FA confirmed) Partner->>WhiteBIT: GET /oauth2/api-key/info WhiteBIT-->>Partner: externalId Partner->>WhiteBIT: GET /oauth2/api-key/{externalId}/secret WhiteBIT-->>Partner: apiSecret (returned once) Note over Partner: Lead trader places an order Partner->>WhiteBIT: POST /api/v4/order/new (signed with the follower's key) WhiteBIT-->>Partner: Order accepted Note over Follower,WhiteBIT: Execution happens in the follower's account ``` ## Permissions and scope Copy trading requires order placement and cancellation on the follower's account. The follower selects the key's permissions on the WhiteBIT consent screen — the partner does not pass a permission set in the authorization request and cannot influence the follower's choice (see [Key permissions](/guides/fast-api-key-integration#key-permissions)). To mirror orders, the follower must grant trade-level access: order placement and cancellation, convert, and internal transfer between the follower's own balances. External withdrawal is a separate, user-controlled grant behind an additional consent-screen confirmation and is not needed for copy trading. Named [API key types](/guides/fast-api-key-integration#api-key-types) — Read-only, Trade, and Custom — are being introduced for the Fast API Key flow. Once available, the operations above map to the **Trade** type, which caps a key at trade-level access and excludes external withdrawal. The partner reads the permissions a follower actually granted from the `permissions` array on `GET /oauth2/api-key/info`, and branches on the locale-independent `name` value. See [Key permissions](/guides/fast-api-key-integration#key-permissions) for the full permission model. The OAuth-issued key places live orders on the follower's account. Store each follower's `apiSecret` in encrypted server-side storage. The follower selects permissions on the consent screen — external withdrawal is not required for copy trading, so followers grant trade-level access only. See the [Security checklist](/guides/fast-api-key-integration#security-checklist). ## Order placement The partner places each mirrored order on the follower's account through the V4 trade API, signing with the follower's OAuth-issued key. Requests are authenticated by the `X-TXC-APIKEY`, `X-TXC-PAYLOAD`, and `X-TXC-SIGNATURE` headers — `externalId` is the value sent in `X-TXC-APIKEY`. The signing process is the same as for a manually-created key; see [Private HTTP API authentication](/api-reference/authentication). The fields below are the copy-trading-relevant subset of the limit-order request. The full request and response schemas, including all order types and the signed-payload fields, are on the API Reference pages linked at the end of each table. **Request — [Create Limit Order](/api-reference/trading/create-limit-order) (`POST /api/v4/order/new`):** | Field | Type | Required | Notes for copy trading | | - | - | - | - | | `market` | string | Yes | Trading pair (`BASE_QUOTE`, e.g. `BTC_USDT`) — mirror the lead trade's market. | | `side` | string | Yes | `buy` or `sell` — mirror the lead trade's side. | | `amount` | string | Yes | Quantity in base currency, sized per follower by the copy logic. | | `price` | string | Conditional | Limit price in quote currency. Required unless a best-bid/offer execution method is used. | | `clientOrderId` | string | No | Partner-assigned identifier, useful to reconcile a mirrored order back to its lead trade and follower. | For market and stop variants, see [Create Market Order](/api-reference/trading/create-market-order) and the other [order endpoints](/api-reference/trading/spot-overview). **Response — order confirmation (subset of the shared order shape):** | Field | Type | Notes for copy trading | | - | - | - | | `orderId` | integer | Matching-engine order id; store it against the follower and lead trade. | | `clientOrderId` | string | Echoes the request value; empty string when not supplied. | | `status` | string | Order lifecycle status; the value tracks order fills and cancellations. | | `dealStock` | string | Filled amount in base currency; `"0"` while unfilled. | | `dealMoney` | string | Filled amount in quote currency; `"0"` while unfilled. | | `left` | string | Remaining unfilled quantity. | Full field list: [Create Limit Order](/api-reference/trading/create-limit-order). ## Endpoints Copy trading composes the Fast API Key management endpoints with the standard V4 spot trading and monitoring endpoints. Every trade request acts on the account whose key signs it. A copy-trading backend calls the endpoints below, grouped by role. **Key management, per follower** (from the [Fast API Key flow](/guides/fast-api-key-integration)): | Purpose | Endpoint | Reference | | - | - | - | | Check whether a follower key exists and read the granted permissions | `GET /oauth2/api-key/info` | [API key info](/api-reference/oauth/usage/api-key-info) | | Retrieve the follower's API secret once | `GET /oauth2/api-key/{externalId}/secret` | [API key secret](/api-reference/oauth/usage/api-key-secret) | | Revoke a follower key on unfollow or offboarding | `DELETE /oauth2/api-key/{externalId}` | [Delete API key](/api-reference/oauth/usage/api-key-delete) | **Order placement and management, signed with the follower's key:** | Purpose | Endpoint | Reference | | - | - | - | | Place a limit order | `POST /api/v4/order/new` | [Create limit order](/api-reference/trading/create-limit-order) | | Place a market order | `POST /api/v4/order/market` | [Create market order](/api-reference/trading/create-market-order) | | Modify an open order | `POST /api/v4/order/modify` | [Modify order](/api-reference/trading/modify-order) | | Cancel one order | `POST /api/v4/order/cancel` | [Cancel order](/api-reference/trading/cancel-order) | | Cancel every order on a market for one follower | `POST /api/v4/order/cancel/all` | [Cancel all orders](/api-reference/trading/cancel-all-orders) | | List a follower's open orders | `POST /api/v4/orders` | [Query unexecuted orders](/api-reference/trading/query-unexecuted-orders) | **Fill monitoring and reconciliation, per follower:** | Purpose | Where | | - | - | | Order updates in real time | [Orders Executed](/websocket/account-streams/orders-executed) WebSocket stream | | Fills in real time | [Deals](/websocket/account-streams/deals) WebSocket stream | | Executed-order history, as a polling fallback | [Query executed order history](/api-reference/trading/query-executed-order-history) (`POST /api/v4/trade-account/executed-history`) | | Trade-level deals for an order | [Query executed order deals](/api-reference/trading/query-executed-order-deals) | Subscribing to a follower's private WebSocket streams requires a WebSocket authentication token from `POST /api/v4/profile/websocket_token`. Confirm that an OAuth-issued key can obtain this token for the follower's account before making the WebSocket streams the primary fill-monitoring path; until then, poll [executed-order history](/api-reference/trading/query-executed-order-history) as the reliable per-follower fallback. ## Operational pitfalls Copy trading fans one lead trade out to many independent accounts, which introduces failure modes a single-account integration does not have. * **No batch or account selector.** The V4 trade API acts only on the account that owns the signing key. Mirroring one lead trade means one signed request per follower; no endpoint places an order across multiple accounts. * **Rate limits apply per IP address, not per follower.** REST rate limits are enforced per IP — the default is 10,000 requests per 10 seconds, and `/trade-account/executed-history` allows 12,000 per 10 seconds. A backend that serves many followers from one IP shares a single budget across every follower's signed requests, so per-IP sharing — not a per-follower budget — is the fan-out constraint to design around. Pace requests across the window, handle `429` with backoff, and consider spreading a large follower base across egress IPs — see [Rate limits](/api-reference/rate-limits). * **Follower keys are revoked outside the partner's control.** An OAuth-issued key is revoked when the follower changes the account password or the account is blocked or frozen, and it is disabled after 14 days of inactivity. Signed requests then fail; re-run the consent flow to reissue. The OAuth access token used for key management is short-lived and comes with a refresh token — renew it server-side rather than re-running consent. See [Fast API Key via OAuth](/guides/fast-api-key-integration). * **Permission grants vary per follower.** The follower chooses permissions on the consent screen, so a follower can grant less than trade-level access. Read the `permissions` array on `GET /oauth2/api-key/info` before mirroring, and skip followers without order-placement permission. External withdrawal is never required for copy trading — do not request it. * **Balances and market minimums differ per follower.** Size each mirrored order to the follower's own balance and the market's minimum order size. Expect per-follower rejections for insufficient balance and partial fills rather than uniform execution. * **Regional restrictions apply per follower.** For EEA followers, USDT deposits, withdrawals, and WhiteBIT Codes are unavailable under MiCA — USDC and EURI are the documented alternatives — which constrains how those followers are funded and which stablecoins those followers hold. Account for per-follower differences rather than assuming a uniform asset set. See [Regulatory Compliance](/institutional/compliance). * **Retries can double-place.** Set a `clientOrderId` on each mirrored order so a retried request reconciles to the same lead trade and follower instead of creating a duplicate. * **The API secret is returned once.** Capture and encrypt `apiSecret` at issuance. A re-fetch returns `409 Conflict` and requires deleting and re-issuing the key. ## Common questions Common questions from copy-trading partners, beyond the eligibility and gating covered in the [Embedded Trading FAQ](/guides/embedded-trading-faq). ### Copy-trading API availability There is no copy-specific endpoint. Copy trading is an orchestration of the [Fast API Key](/guides/fast-api-key-integration) flow and the standard spot order endpoints — the partner backend supplies the copy logic. ### Follower connection and revocation A follower grants an OAuth-issued key on the WhiteBIT consent screen; the partner captures `externalId` and the one-time secret. To disconnect, revoke the key with `DELETE /oauth2/api-key/{externalId}` — the platform emails the follower on revocation. `DELETE` is authenticated with a short-lived Bearer access token, so revocation depends on holding a valid token: renew it with the stored refresh token, or obtain a fresh pair through a new consent flow once the refresh token has expired too. A dormant follower's key still winds down without action — an OAuth-issued key auto-deactivates after 14 days without API activity, and is revoked when the follower changes the account password or the account is blocked or frozen. If revoking a dormant follower's key without fresh consent is required, confirm the available management path with WhiteBIT. ### Per-follower fill tracking Poll [Query executed order history](/api-reference/trading/query-executed-order-history) for per-follower fills, and subscribe to each follower's [Orders Executed](/websocket/account-streams/orders-executed) and [Deals](/websocket/account-streams/deals) account streams for real-time updates where an OAuth-issued key can obtain a WebSocket token (see the monitoring note under [Endpoints](#endpoints)). Reconcile each fill to its lead trade and follower with the `clientOrderId` set at placement. ### Sandbox-free testing WhiteBIT has no public testnet. Validate the flow on the live API with a small follower cohort and minimum order sizes; Demo Tokens (`DBTC`/`DUSDT`) allow risk-free spot practice. Work through the [Go-Live Checklist](/best-practices/go-live-checklist) before scaling. ## Approval and commercial terms Copy-trading access is approval-gated — it is not available by default and requires an internal review in addition to Fast API Key approval. To request it, contact `institutional@whitebit.com` with the intended use case, the jurisdiction where the partner's legal entity is registered, and the licenses it holds. Whether attribution or commercial terms apply is confirmed with WhiteBIT during enrollment. ## What's next The prerequisite flow: consent, key issuance, secret retrieval, signing, and revocation. Full request and response schema for order placement. What App Builders can build, who it is for, and how to get started. Key types, rate limits, revocation, and copy-trading gating questions. # Embedded Trading FAQ Source: https://docs.whitebit.com/guides/embedded-trading-faq Common questions about WhiteBIT Embedded Trading: eligibility and approval, revenue share, the two integration models, sub-account limits, and copy-trading availability. Answers to common questions about WhiteBIT Embedded Trading. ## Eligibility and approval ### Embedded Trading eligibility Embedded Trading is open to partners that operate trading for end customers, and enrollment is approval-gated — every application is individually reviewed before provisioning is enabled. Apply by emailing `institutional@whitebit.com`; see [Eligibility and approval](/guides/sub-account-integration#eligibility-and-approval). ### KYC reliance for account operators KYC reliance — WhiteBIT relying on the partner's own customer verification — may be available to eligible licensed partners under a written agreement, assessed case by case and never enabled by default. The eligibility criteria are on the [Integration guide](/guides/sub-account-integration#eligibility-and-approval). ### End-customer KYC branding The end-customer KYC verification flow is WhiteBIT-branded and cannot be white-labeled. See [Eligibility and approval](/guides/sub-account-integration#eligibility-and-approval). ## Program terms ### Revenue share The revenue share is up to 40% of the trading fees generated by referred customers; the applicable rate and any additional commercial terms are agreed individually at enrollment. The canonical terms are on the [Embedded Trading program page](https://institutional.whitebit.com/broker-program); see also [Program terms](/guides/sub-account-integration#program-terms). ### Revenue reporting Earnings are reported through the WhiteBIT Analytical Dashboard; the program does not expose a dedicated fee-share endpoint. Programmatic reconciliation combines the sub-account list with per-sub-account trade history — see [Revenue monitoring](/guides/sub-account-integration#revenue-monitoring). ## Integration models ### Sub-account or Fast API Key Partner-operated sub-accounts (this program) and customers' own accounts via Fast API Key are two separate architectures for two different personas. The [Embedded Trading overview](/guides/embedded-trading-overview) compares both; the Fast API Key path — copy trading, trading bots, and portfolio apps — is documented under [App Builders](/guides/app-builders-overview). ### Sub-account API key limits Each sub-account supports up to 50 API keys, independent from the main account and from other sub-accounts, each with its own IP whitelist and permission scope. See [Account architecture](/guides/sub-account-integration#account-architecture). ### Sub-account withdrawal returns 401 "This API Key is not authorized to perform this action" A newly created `type: 2` key has its withdraw endpoints disabled by default (`enable: false`), so withdrawals return this 401 until the URL is enabled with [Edit Sub-Account API Key](/api-reference/sub-accounts/edit-sub-account-api-key). See [Sub-account withdrawal approval](/products/sub-accounts/quickstart#sub-account-withdrawal-approval) for the step. ## What's next What Embedded Trading provides and the two integration architectures. Per-customer sub-accounts, API keys, and revenue reconciliation. Cross-cutting answers shared across programs — KYB, sandbox, fees, and rate limits. # Embedded Trading Source: https://docs.whitebit.com/guides/embedded-trading-overview What WhiteBIT Embedded Trading is, the two integration architectures (partner-operated sub-accounts and customers' own accounts via Fast API Key), and how enrollment works. WhiteBIT Embedded Trading lets a partner offer trading to its own customers on WhiteBIT's exchange infrastructure. A partner integrates through one of two architectures depending on who holds the trading account — the partner, or the end customer. Both are approval-gated and share the same enrollment channel. ## Integration architectures The account-holding question separates the two models: partner-operated accounts use the sub-account architecture; customers' own accounts use the Fast API Key architecture. The partner operates a dedicated sub-account per end customer under a master account. WhiteBIT provides per-customer isolation, per-customer API keys, and fee-free internal transfers. WhiteBIT performs end-customer KYC, unless KYC reliance is agreed. End customers keep personal WhiteBIT accounts and grant the partner an OAuth-issued API key on the consent screen. WhiteBIT holds custody and performs KYC. Fits copy trading, trading bots, and portfolio apps. The two architectures are WhiteBIT's **Model A** (partner-operated sub-accounts) and **Model B** (customers' own accounts via Fast API Key). The [integration models](/concepts/integration-models) page compares the two models side by side — account holder, KYC responsibility, and best fit — plus the *managed sub-accounts* / *attribution* / *KYC reliance* vocabulary. Model B fits more use cases than embedded trading alone: copy-trading, trading-bot, and portfolio apps built over users' own accounts route to [App Builders](/guides/app-builders-overview). ## Eligibility and approval Embedded Trading enrollment is approval-gated. Every application is individually reviewed before provisioning is enabled. To apply, email `institutional@whitebit.com` with a description of the service, the registered legal entity, licenses held, the intended account structure, who performs end-customer KYC, and the countries served. The full application question list is on the [Partner Solutions](/guides/partner-solutions#how-to-apply) page. **KYC reliance eligibility:** KYC reliance — WhiteBIT relying on the partner's own customer verification — may be available, but is not enabled by default. It is never automatic, and operates as a delegation: responsibility for customer verification is never transferred. Eligibility is assessed case by case. Reliance is available only to partners that are supervised AML-obligated entities (for example EMI, PI, VASP, or MiCA-CASP license holders) in an adequate jurisdiction, applying broadly equivalent customer due diligence, under a written agreement and an individual WhiteBIT Compliance assessment. A confirmed entry on the relevant public register establishes the licensing basis; a confirmed EU/MiCA entity is additionally required when EU users are in scope. Licensing regimes and entity structures vary, and the examples above may not capture every case. Describe your licence(s), jurisdiction, and customer due-diligence approach in full in your application so the WhiteBIT Compliance team can review your specific situation and make a determination. ## Program terms The revenue share is up to **40%** of the trading fees generated by referred customers. The applicable rate and any additional commercial terms are agreed individually during enrollment; the canonical program terms are published on the [Embedded Trading program page](https://institutional.whitebit.com/broker-program). Commercial terms for the Fast API Key architecture — including attribution — are confirmed with WhiteBIT at enrollment. ## What's next Eligibility, per-customer sub-account setup, per-customer API keys, and revenue reconciliation. The OAuth API key flow for partners acting on customers' own accounts. A Fast API Key use case: mirror a lead trader's orders into followers' own accounts. Eligibility, revenue share, integration models, and copy-trading gating. # Fast API Key via OAuth Source: https://docs.whitebit.com/guides/fast-api-key-integration Integration guide for partner platforms that issue WhiteBIT API keys on behalf of users through the OAuth API key flow. The OAuth API key flow lets a partner platform issue a WhiteBIT API key for an authenticated WhiteBIT user without the user manually copying credentials between sites. The user authorizes the partner on the WhiteBIT consent screen, the WhiteBIT platform issues a partner-scoped API key, and the partner backend reads the API secret once through a Bearer-authenticated endpoint and persists it. The flow uses Authorization Code with PKCE (S256); the authorization server issues a short-lived access token together with a refresh token. See the [Fast API Key](/glossary#fast-api-key) glossary entry for the short definition. ## Partner use cases The flow fits partners whose end users keep personal WhiteBIT accounts: WhiteBIT performs KYC and holds custody, and the partner operates on the user's account through the OAuth-issued key. * **Copy trading** — the copy-trading platform mirrors lead-trader positions into followers' accounts. Each follower connects a personal WhiteBIT account through the consent screen, and the partner platform places orders with the issued key; execution happens inside the follower's own account. See the [Copy Trading guide](/guides/copy-trading) for the architecture and order-placement schema. * **Trading bots** — the service runs strategies on the user's account. The user approves the permission set on the consent screen — trading scopes for execution, with withdrawal remaining a separate, user-controlled grant behind an additional confirmation (see [Key permissions](#key-permissions)). * **Portfolio and aggregator apps** — the app aggregates balances and transaction history through a read-scoped key and places no orders. Partners operating accounts *for* customers — a dedicated sub-account per end customer under a partner master account — integrate via [Embedded Trading](/guides/embedded-trading-overview) instead; the [Partner Solutions](/guides/partner-solutions) page maps all partner types. Whether [attribution](/guides/waas-overview) or commercial terms apply for own-account partners is confirmed with WhiteBIT during enrollment. ## Prerequisites Partner enrollment is approval-gated. New partners apply via `institutional@whitebit.com` with the details listed under [How to apply](/guides/partner-solutions#how-to-apply); a partner agreement and KYB review are part of onboarding; client registration is then coordinated through the same channel, as described below. * Partner-registered OAuth2 client (`client_id`, `client_secret`, redirect URIs). Contact `institutional@whitebit.com` to enroll a client; the OAuth API key feature must be approved for the partner platform before a `client_id` is issued. * End user with a WhiteBIT account, 2FA enabled, the required verification level passed, and operating in a region where the feature is available. A user who meets none of these can still start the flow — WhiteBIT walks the user through registration, 2FA, and KYC on its own pages, as described under [Account status and eligibility](#account-status-and-eligibility). The OAuth API key endpoints are available on the global server (`https://whitebit.com`) only. * Partner backend that supports HTTPS, server-side secret storage, and OAuth 2.0 Authorization Code with PKCE (S256). ### What to prepare for client registration WhiteBIT registers the OAuth2 client manually, so the request to `institutional@whitebit.com` should carry everything the administrator needs in one message. The company-level items are the ones listed under [How to apply](/guides/partner-solutions#how-to-apply); the integration-level items below are specific to this flow. | Item | Provided by | Notes | | - | - | - | | Redirect URI(s) | Partner | Exact HTTPS URLs where the authorization code is delivered. Matching is exact: no wildcards and no path prefixes, so each environment's callback URL is registered on its own. | | Scopes | Partner | Which of `apikeys.create`, `apikeys.read`, `apikeys.delete` the client needs — see [Scopes](#scopes). Fixed at registration. | | Partner display name and logo | Partner | Shown to the user on the WhiteBIT consent screen as "Create an API key for \[Partner Name]". | | Intended use case and key type | Partner | Copy trading, bot, aggregator, or other, and the [key type](#api-key-types) requested. Withdrawal access requires the Custom type and KYB. | | Technical contact | Partner | Email WhiteBIT uses for questions about the OAuth2 client. | | `client_id` | WhiteBIT | Permanent identifier, sent as the `clientId` query parameter. | | `client_secret` | WhiteBIT | Server-side only. Used in the token exchange and never sent to the browser. | ## Endpoint surface | Method | Path | Auth | Required scope | Purpose | | - | - | - | - | - | | `GET` | [`/oauth2/api-key/info`](/api-reference/oauth/usage/api-key-info) | Bearer | `apikeys.read` | Check whether a key exists for the `(user, OAuth2 client)` pair | | `GET` | [`/oauth2/api-key/{externalId}/secret`](/api-reference/oauth/usage/api-key-secret) | Bearer | `apikeys.read` | Retrieve the API secret once | | `DELETE` | [`/oauth2/api-key/{externalId}`](/api-reference/oauth/usage/api-key-delete) | Bearer | `apikeys.delete` | Delete a partner-owned key | ### Scopes Three scopes govern the flow, and the consent screen names the ones the OAuth2 client holds: * `apikeys.create` — permits key creation. The scope authorizes the consent screen the user completes in step 8; no partner-facing endpoint consumes it, which is why it carries no row above. * `apikeys.read` — permits reading key state and retrieving the secret once. * `apikeys.delete` — permits deleting a key the OAuth2 client owns. Holding at least one of the three admits a client to the flow; holding all three is not required. A client that issues keys and retrieves the secrets needs `apikeys.create` and `apikeys.read`, and adds `apikeys.delete` to revoke keys from its own side. Scopes are fixed when the OAuth2 client is registered and cannot be varied per authorization request. ## Integration flow ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant User participant Partner as Partner backend participant WhiteBIT Note over User,WhiteBIT: Steps 1-8 — the partner holds no OAuth token yet User->>Partner: Start "Connect WhiteBIT" Partner->>User: Redirect to /auth/login (clientId, redirect_uri, state, PKCE challenge) User->>WhiteBIT: Open the WhiteBIT authorization page WhiteBIT->>WhiteBIT: Eligibility gate — login, 2FA, existing key, verification, availability alt Not eligible WhiteBIT-->>User: Blocking screen — flow stops, no authorization code is issued else Eligible WhiteBIT-->>User: Consent screen (apikeys.create, apikeys.read, apikeys.delete) User->>WhiteBIT: Approve WhiteBIT-->>Partner: Callback to redirect_uri with the authorization code Partner->>WhiteBIT: POST /oauth2/token (client_id, client_secret, code, code_verifier) WhiteBIT-->>Partner: access_token + refresh_token for this (user, partner) pair User->>WhiteBIT: Select key permissions, confirm with 2FA WhiteBIT->>WhiteBIT: Create the partner key — secret withheld from the browser Note over User,WhiteBIT: Steps 9-12 — the partner backend can now call /oauth2/api-key/* loop poll until exists and isEnabled Partner->>WhiteBIT: GET /oauth2/api-key/info end WhiteBIT-->>Partner: externalId Partner->>WhiteBIT: GET /oauth2/api-key/{externalId}/secret alt 423 Locked Note over Partner: Retry with backoff (5-10s, doubling, cap 60s) else 409 Conflict Partner->>WhiteBIT: DELETE /oauth2/api-key/{externalId} Note over Partner: Restart from step 2 else success WhiteBIT-->>Partner: apiSecret (returned once) end end Note over Partner,WhiteBIT: Partner signs V4 requests with HMAC using externalId + apiSecret ``` For the remaining failure modes (401, 403, 404) and both consent-screen error codes, see [Error handling](#error-handling) below. Every `/oauth2/api-key/*` endpoint is Bearer-authenticated, so none of the three can be called until the partner backend holds an OAuth token for that specific user. Steps 1 through 8 cover everything that runs before that point — client registration, and the consent journey WhiteBIT hosts on its own pages. The partner writes code for steps 1, 2, 3, 6, 7, and 9 through 12; steps 4, 5, and 8 happen on WhiteBIT's side and are observable to the partner only as an authorization code on the callback, or as no callback at all. A WhiteBIT administrator creates the OAuth2 client after enrollment and issues a permanent `client_id`, a `client_secret`, and the exact redirect URIs. Partners cannot self-register a client. See [Prerequisites](#prerequisites) for the enrollment channel. Applies to a returning user whose token from an earlier authorization is still valid — a first-time user has no token yet, so the flow starts at step 3. Call `GET /oauth2/api-key/info` and interpret the `(exists, isEnabled)` response using the decision matrix on the endpoint page: `(false, false)` proceeds to step 3; `(true, true)` reuses the existing key instead of running the flow again; `(true, false)` asks the user to delete the disabled key from the WhiteBIT dashboard first. See [Returning users](#returning-users). The user starts the connection in the partner's app ("Connect WhiteBIT"). Generate a cryptographically secure `code_verifier` (43–128 characters, unreserved alphabet) and derive `code_challenge = BASE64URL(SHA256(code_verifier))`. Store `code_verifier` and `state` in a server-side session keyed by a short-lived cookie, then redirect the browser to [`GET /auth/login`](/api-reference/oauth/usage/authorize) with the following query parameters: | Parameter | Required | Description | | - | - | - | | `clientId` | Yes | The `client_id` issued at registration. | | `redirect_uri` | Yes | One of the registered redirect URIs, character-for-character. | | `state` | Optional in the spec; always send it | Opaque random string, at least 32 bytes of entropy, bound to the user's session. Returned unchanged on the callback. | | `code_challenge` | Yes | `BASE64URL(SHA256(code_verifier))`, without padding. | | `code_challenge_method` | Yes | Always `S256`. | Scopes are not passed in the URL. The scopes registered on the OAuth2 client apply (see [Scopes](#scopes)). ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} https://whitebit.com/auth/login ?clientId=YOUR_CLIENT_ID &redirect_uri=https%3A%2F%2Fpartner.example%2Foauth%2Fwhitebit%2Fcallback &state=Zm9vYmFyLXN0YXRlLTMyLWJ5dGVz &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM &code_challenge_method=S256 ``` Before showing the consent screen, WhiteBIT checks the account behind the request — sign-in state, 2FA, verification level, and whether the feature is available for the OAuth2 client and for the account's region. Each blocking outcome renders as a variant of the same screen and stops the flow on WhiteBIT's page: no authorization code is issued and the partner receives no callback. Whether a key already exists is enforced separately, at the moment key creation is attempted. [Account status and eligibility](#account-status-and-eligibility) lists every outcome and what the partner can observe. The consent screen names the partner and the `apikeys.*` scopes the OAuth2 client holds — see [Scopes](#scopes). The user approves or declines. Approval is what produces the short-lived authorization code on the registered `redirect_uri`. On the redirect back to the registered `redirect_uri`, validate the returned `state` matches the stored value (anti-CSRF). Capture the `code` query parameter. Reject the callback when `state` is missing, mismatched, or expired. ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} https://partner.example/oauth/whitebit/callback ?code=AUTHORIZATION_CODE &state=Zm9vYmFyLXN0YXRlLTMyLWJ5dGVz ``` The code is single-use and short-lived; exchange it immediately in step 7. POST to [`/oauth2/token`](/api-reference/oauth/usage/get-access-token) with `client_id`, `client_secret`, `code`, and `code_verifier`, server-to-server, as `application/x-www-form-urlencoded`. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "access_token": "MZM1MDBMMJYTNWM4MI0ZNTIYLTKXNDATNZY1MZHKM2Y2MJY3", "expires_in": 300, "refresh_token": "ODK5ZTVKZDUTYTI5ZC01NWJHLTGZZDMTYWFKYTNMNJHHMGZM", "scope": "apikeys.create,apikeys.read,apikeys.delete", "token_type": "Bearer" } } ``` The response carries a short-lived access token and a refresh token; read the lifetime from `expires_in` rather than hardcoding it. The token pair is bound to the `(user, OAuth2 client)` pair, not to the partner as a whole: a partner serving 1,000 users holds 1,000 token pairs. WhiteBIT does not store the mapping between its user and the partner's own account — persist the token alongside the partner-side user record. Renew through [`POST /oauth2/refresh_token`](/api-reference/oauth/usage/refresh-token) and replace the stored pair on every refresh. Re-run the consent flow only when the refresh token itself has expired. The user selects the key permissions on WhiteBIT's own page, reviews the selection in a confirmation modal, and confirms with a second factor — a passkey or an authenticator-app code. A key cannot be created without 2FA, and the partner never calls the creation endpoint. WhiteBIT creates the key and withholds the secret from the browser by design, which is why the secret is fetched server-side in step 10. Poll `GET /oauth2/api-key/info` with the OAuth access token until `exists=true` and `isEnabled=true`, then capture `externalId` (short backoff, 1–2 second intervals, total budget under 30 seconds). Call `GET /oauth2/api-key/{externalId}/secret`. The response returns `apiSecret` exactly once; persist `(externalId, apiSecret)` in encrypted server-side storage immediately — `externalId` is the public key value sent in the `X-TXC-APIKEY` header. On `423 Locked`, retry with exponential backoff starting at 5–10 seconds, doubling per attempt, capped at 60 seconds, total budget 3–5 minutes. On `409 Conflict`, the secret has already been retrieved for this key — delete the key via `DELETE /oauth2/api-key/{externalId}` and restart the flow from step 2. Sign V4 trade API requests with HMAC: send `externalId` as the `X-TXC-APIKEY` value and use `apiSecret` for the signature. The OAuth-issued key follows the same signing rules as a manually-created key. See [Private HTTP API authentication](/api-reference/authentication) for the canonical signing process. Call `DELETE /oauth2/api-key/{externalId}` to revoke the key. The platform sends a notification email to the user. The endpoint applies to active keys — disabled keys (post-inactivity) require user-initiated deletion from the WhiteBIT dashboard. ## Account status and eligibility The flow assumes an end user who already holds a WhiteBIT account with 2FA and the required verification level. A user who meets none of that is not turned away: WhiteBIT hosts registration, 2FA setup, and KYC on its own pages, and the gate in step 4 routes the user to whichever one is missing. The partner does not implement any of these screens. | Account state | What the user sees on WhiteBIT | What the partner observes | | - | - | - | | No WhiteBIT account, or not signed in | The WhiteBIT sign-in page, where the user signs in or registers before the authorization request continues | Nothing until the user finishes; the callback arrives only after consent | | 2FA disabled | A blocking screen — "2FA is required. To proceed with API key creation, please enable 2FA" — offering Decline or Enable 2FA | No callback | | Verification level not met, KYC available | An instruction screen: sign in to the WhiteBIT main account, pass KYC under Verification, return to the partner app, and reconnect the account | No callback | | Verification level not met, KYC not available for the account | The same instructions without a verification link — the case for a sub-account that inherits KYC from its main account — plus a Go to Homepage action | No callback | | Active key already exists for this partner | A notice that an API key for this partner already exists on the account, and that the existing key must be deleted in platform settings before a new one can be created | No callback | | Feature unavailable — region restriction, or API keys disabled for the account | "API key creation is not available. Please contact support for more details" | No callback | An abandoned flow is indistinguishable from a blocked one, because the gate runs before any token exists. Treat a missing callback as "not connected yet": keep the Connect WhiteBIT entry point available so the user can retry after fixing the account, rather than blocking the partner-side account on a timeout. ### Checking status from the partner side Nothing about the user is readable before consent. The `/oauth2/api-key/*` endpoints are Bearer-authenticated and the token is issued only after the user approves, so the first partner-observable signal is the callback itself. Nothing needs to be read after consent either. A callback means a registered, 2FA-enabled, verified user who approved the consent screen, so the account statuses the gate checks are already settled by the time the partner holds a token. [`GET /oauth2/api-key/info`](/api-reference/oauth/usage/api-key-info) covers what remains — key state for the `(user, OAuth2 client)` pair — and needs only `apikeys.read`. The account-data scopes belong to the [deprecated classic OAuth flow](/platform/oauth/overview) and are not part of this integration. ## Returning users A `(user, OAuth2 client)` pair holds one partner key at a time, whatever state that key is in. Re-running the authorization flow does not produce a second key: the creation attempt is rejected with `partner_key_active_exists` when the existing key is active and `partner_key_expired_exists` when it is disabled after inactivity. The path for a returning user starts at step 2 instead. `GET /oauth2/api-key/info` returns `exists`, `isEnabled`, `externalId`, and `permissions` for the existing key, which is enough to skip creation entirely and keep using the key already issued — the stored `externalId` and secret remain valid, and the `permissions` array shows the scope the user originally granted. A lost secret has no recovery path. The secret is released once, a repeat call returns `409 Conflict`, and no endpoint re-issues it. Delete the key with `DELETE /oauth2/api-key/{externalId}` and take the user through the flow again from step 2. ## Key permissions The user picks API key permissions on the WhiteBIT consent screen from the same list shown when creating a manual API key in the dashboard — read, spot, collateral, withdrawal, and the other granular scopes. The partner does not pass the permission set in the authorization request and cannot influence the user's choice. The issued key carries those permissions for its lifetime; changing the permission set requires deleting the key and re-running the OAuth API key flow. The partner reads the granted permission set through the `permissions` array on [`GET /oauth2/api-key/info`](/api-reference/oauth/usage/api-key-info). Each entry is a permission group with a locale-independent `name` (use for partner-side logic), a locale-dependent display `title`, and per-endpoint `enable` flags that reflect the user's choices on the consent screen. The array also covers disabled keys — the grant-time permission set stays readable so the partner can show the original scope. If the user selects withdrawal permission, the consent modal adds a warning block and a confirmation checkbox before the user can accept. Step-up MFA is enforced after consent for every Fast API Key creation, regardless of which permissions were selected. After issuance the key behaves the same as a manually-created key with matching permissions. Trade and withdrawal endpoints are authorized by the HMAC signature on each request — see [Private HTTP API authentication](/api-reference/authentication). KYC for fiat withdrawals, AML and fraud monitoring, and withdrawal limits apply on every call. ### API key types Named API key types are being introduced for the Fast API Key flow. The model below describes how key access is scoped once the types are available. A key's type sets the maximum permissions it can carry; the user chooses within that maximum on the consent screen. Every type requires WhiteBIT approval — the flow is not available by default. Until the types ship, the consent screen offers the full permission list described under [Key permissions](#key-permissions). * **Read-only** — read access to balances, orders, deals, and history. No fund movement. * **Trade** — read access plus order placement and cancellation, convert, and internal transfer between the user's own balances. Excludes external withdrawal. * **Custom** — a configurable type, and the only one that can include external withdrawal. Requires WhiteBIT approval and business verification (KYB) of the partner. To request Fast API Key access, contact `institutional@whitebit.com` with the intended use cases, the jurisdiction where the partner's legal entity is registered, and the licenses it holds. Partner KYB is part of the review. ## Lifecycle and revocation OAuth-issued API keys are revoked or deleted by any of the following events: * The user changes the account password. * The user account is blocked (AML / fraud / compliance) or frozen. * The key has no API activity for 14 days (cron-driven auto-deactivation). * The partner calls `DELETE /oauth2/api-key/{externalId}`. * The partner's authorization for that user is revoked. * The user removes the key from the WhiteBIT dashboard. All revocation events except user-initiated dashboard deletion send an email notification to the user. ## Error handling | Status | Endpoint | Cause | Recommended action | | - | - | - | - | | `401` | All three | Missing, invalid, or expired Bearer token, or a token that lacks the required `apikeys.*` scope — an insufficient scope is not reported separately. | Refresh the access token, or restart the OAuth authorization flow when the refresh token has expired too. | | `403` | `secret`, `delete` | The key belongs to a different OAuth2 client, or the key was created manually rather than through OAuth. | Verify `externalId` came from `GET /info` issued by the same OAuth2 client. | | `404` | `secret`, `delete` | No key with that `externalId`, or the key is not owned by the user the token identifies. A key deleted by the system (inactivity, account freeze, password change) returns the same `404` as one the user deleted. | Re-query `GET /info` to confirm the current state of the `(user, client)` pair; treat the key as gone and re-run the flow. | | `409` | `secret` | Secret already retrieved. | Delete the key via `DELETE /oauth2/api-key/{externalId}` and restart the OAuth API key flow. | | `423` | `secret` | Concurrent secret-retrieval attempt holds the lock. | Retry with exponential backoff (5–10s start, cap 60s, budget 3–5 minutes). | `GET /oauth2/api-key/info` is the exception to the table: it never answers with `403` or `404`. Every absence — a deleted key, a key owned by another OAuth2 client, a manually created key — comes back as `200 OK` with `exists: false` and an empty `permissions` list, so partner-side logic branches on the payload rather than on the status code. Two application-level error codes can surface during key creation on the WhiteBIT consent screen. Each code is observable to the partner only indirectly — when one of the codes fires, the consent flow terminates and the partner detects the failure as the absence of a created key on the subsequent `GET /info` poll: * `partner_key_active_exists` — An active partner-issued key already exists for the `(user, OAuth2 client)` pair. The partner SHOULD re-run `GET /info` before starting the flow. * `partner_key_expired_exists` — A disabled (post-inactivity) partner-issued key exists. The user must remove the disabled key from the WhiteBIT dashboard before a new key can be issued. ## Security checklist * Store `client_secret` and `apiSecret` server-side only. Never embed in mobile, desktop, single-page, or browser-side code. * Validate the `state` parameter on every callback to prevent CSRF. * Use the exact registered `redirect_uri` — wildcards and open redirects are rejected. * Use Authorization Code with PKCE (S256) on every authorization request. * Rotate `apiSecret` by deleting and re-issuing keys. The secret cannot be retrieved a second time for an existing key. * No IP check applies to the OAuth API key flow itself — the partner is identified by the OAuth token, which cannot be obtained without the user personally approving the consent screen. The IP-allowlist restriction available on manually created keys (exact-match addresses only; ranges and subnets are not supported, and a request from an unlisted address flags the key as compromised) is not part of this flow: the WhiteBIT dashboard exposes no allowlist control on an OAuth-issued key, and the partner manages no allowlist of its own. ## Limits * One OAuth-issued API key per `(user, partner)` pair, whatever state the key is in. A second creation attempt is rejected — see [Returning users](#returning-users) — and the existing key is never invalidated automatically. * A global limit of 50 API keys per user, shared between manually created and OAuth-issued keys. Partner keys have no separate quota. * A user can have OAuth-issued keys from an unlimited number of partners. ## What's next Full list of OAuth endpoints in the API Reference, with required scopes per endpoint. HMAC signing process for the V4 trade API once the partner holds the api key and secret pair. Sign a `POST /api/v4/main-account/balance` request with HMAC-SHA512 and read the response. Key types, rate limits, revocation, onboarding, and compliance questions. ## Related resources # Fireblocks Source: https://docs.whitebit.com/guides/fireblocks Step-by-step guide to connect a WhiteBIT account to Fireblocks Network for secure digital asset transfers. ## Overview The Fireblocks Network is a secure transfer system enabling immediate discovery, connection, and transfer of digital assets among exchanges, fiat providers, liquidity partners, and counterparties. To connect a WhiteBIT account to Fireblocks, generate a unique API key and an API secret. These are the credentials required to use an API Hook. The standard WhiteBIT API key is unsuitable for Fireblocks integration. Generate a specific Fireblocks API key following the instructions below. *** ## Generate Fireblocks API Key Follow these steps to generate a Fireblocks API key in WhiteBIT: ### Step 1: Navigate to API Integrations Log in to WhiteBIT and open the "API" page in the account settings. In the "API" section, choose "Integrations". Navigate to API Integrations *** ### Step 2: Generate the API Key Press the "Generate API key" button on the Integrations page. Two-factor authentication (2FA) confirmation is required to complete the key generation process. Enter the 2FA code from the Authenticator app. 2FA Confirmation Enable 2FA on the account before proceeding with API key generation. *** ### Step 3: Save credentials After successfully entering 2FA, the system will automatically generate a unique API key and API secret. Generated API Key and Secret **Important Security Notice:** The API secret will only be visible once. Store the generated API secret immediately in a secure location. If the API secret is lost, generate a new API key. Unique API key identifier viewable anytime Private secret key - only shown once during generation *** ### Step 4: Name the API key Give a descriptive name to the API key. This helps identify the key's purpose later. Confirm the completion of the key generation process by following the on-screen instructions. Name and Confirm API Key *** ## Important Limitations **Key Generation Limit:** The Fireblocks system allows generating a maximum of **one API key** per account. Plan accordingly and store credentials securely. *** ## Quick Configuration Guide To connect a WhiteBIT account to Fireblocks: On the "API" page, choose "Integrations" and click "Generate API Key" Confirm the operation with the 2FA code from the Authenticator app The system will automatically generate an API key and an API secret. Keep track of both the API key and the API secret Give a title to the generated key Confirm the key generation Remember: Only one key can be generated per account. *** ## Best Practices Store the API secret in a secure password manager or encrypted vault Limit access to API credentials to authorized personnel only Monitor API activity regularly for any unauthorized usage Keep secure backups of credentials in multiple safe locations *** ## What's next After generating and saving the Fireblocks API key and secret, proceed to: 1. Configure the Fireblocks account with the WhiteBIT credentials 2. Set up transfer policies and workflows 3. Begin transferring digital assets securely For more information about Fireblocks integration, refer to the Fireblocks documentation. *** ## Support Contact WhiteBIT support for assistance Explore WhiteBIT API documentation # First API Call Source: https://docs.whitebit.com/guides/first-api-call Make a first WhiteBIT API call — public market data with no authentication, then an authenticated balance check with HMAC-SHA512 signing. Make a first WhiteBIT API call — public data with no authentication, then a private request with HMAC-SHA512 signing. The walkthrough is for developers integrating the v4 REST API for the first time and includes curl and Python examples for each API call. WhiteBIT does not offer a public testnet or sandbox environment — all API calls in this guide execute against the live API. Steps 1 and 2 are read-only public calls, safe to run freely. Step 4 only reads account balances — it places no orders and moves no funds. ## Prerequisites * curl or Python 3.x installed * Steps 1–2: No account required * Steps 3–4: WhiteBIT account ([register](https://whitebit.com/auth/register)), 2FA enabled, API key with **Info + Trading** permissions ([create key](https://whitebit.com/settings/api)) Verify connectivity by calling the public server time endpoint — no authentication needed. **Endpoint:** `GET https://whitebit.com/api/v4/public/time` ([API Reference](/api-reference/market-data/server-time)) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X GET https://whitebit.com/api/v4/public/time ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get("https://whitebit.com/api/v4/public/time") print(response.json()) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "time": 1700000000 } ``` The `time` field is a Unix timestamp in seconds. For Go and PHP examples, see [SDKs](/sdks). Retrieve the list of available markets — spot and futures (including TradFi futures). The endpoint requires no authentication. **Endpoint:** `GET https://whitebit.com/api/v4/public/markets` ([API Reference](/api-reference/market-data/market-info)) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X GET https://whitebit.com/api/v4/public/markets ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get("https://whitebit.com/api/v4/public/markets") markets = response.json() # Print first 3 markets for market in markets[:3]: print(market["name"], market["minAmount"], market["tradesEnabled"]) ``` **Expected response (truncated — the full response contains 900+ markets):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "name": "BTC_USDT", "stock": "BTC", "money": "USDT", "stockPrec": "6", "moneyPrec": "2", "makerFee": "0.1", "takerFee": "0.1", "minAmount": "0.00001", "minTotal": "1", "tradesEnabled": true } ] ``` Key fields: `name` (pair), `minAmount` (minimum order size in base asset), `tradesEnabled` (pair active status). For risk-free Spot trading practice, activate Demo Tokens (DBTC + DUSDT) from the [WhiteBIT Codes page](https://whitebit.com/codes). The `DBTC_DUSDT` pair supports the same API endpoints as any Spot market — place, query, and cancel orders without risking real funds. No KYC required. All private endpoints require an API key. Skip this step if a key is already available. 1. Navigate to [API key settings](https://whitebit.com/settings/api). 2. Enable 2FA if not already active — key creation requires active 2FA. 3. Create a new key with **Info + Trading** permissions. 4. Optionally whitelist the current IP address (up to 50 addresses per key). 5. Save the API key and secret immediately — the portal displays the secret only once and offers no way to retrieve it later. Store the API secret securely in an environment variable or secrets manager. Never commit secrets to version control or embed credentials in client-side code. Read the Trade account balance. This call requires HMAC-SHA512 signing. **Endpoint:** `POST https://whitebit.com/api/v4/trade-account/balance` ([API Reference](/api-reference/trading/trading-balance)) Every private request requires three headers computed from the request body: * `X-TXC-APIKEY` — the API key string * `X-TXC-PAYLOAD` — Base64-encoded JSON request body * `X-TXC-SIGNATURE` — HMAC-SHA512 of the Base64 payload, hex-encoded, signed with the API secret The JSON request body must include `request` (the endpoint path) and `nonce` (an ever-increasing integer — use Unix milliseconds). See [Authentication](/api-reference/authentication) for the full signing walkthrough. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests import hmac import hashlib import base64 import json import time API_KEY = "YOUR_API_KEY" # Replace with actual API key API_SECRET = "YOUR_API_SECRET" # Replace with actual API secret url = "https://whitebit.com/api/v4/trade-account/balance" payload = { "request": "/api/v4/trade-account/balance", "nonce": int(time.time() * 1000) } # Use compact separators: the server validates the body against a # canonical (no-whitespace) serialization and rejects spaced JSON # with HTTP 400 `{"code":9,"message":"Invalid payload."}`. payload_json = json.dumps(payload, separators=(",", ":")) payload_base64 = base64.b64encode(payload_json.encode()).decode() signature = hmac.new( API_SECRET.encode(), payload_base64.encode(), hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload_base64, "X-TXC-SIGNATURE": signature, } response = requests.post(url, headers=headers, data=payload_json) print(response.json()) ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # The payload and signature must be computed before calling curl. # Use the Python example for a complete signing implementation. # Replace BASE64_PAYLOAD and HMAC_SIGNATURE with computed values. curl -X POST https://whitebit.com/api/v4/trade-account/balance \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"request":"/api/v4/trade-account/balance","nonce":1700000000000}' ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "BTC": { "available": "0.00100000", "freeze": "0" }, "USDT": { "available": "100.00000000", "freeze": "0" } } ``` Each key is an asset ticker. `available` is the amount ready to trade; `freeze` is the amount locked in open orders. An empty response (`{}`) means the Trade balance holds no assets — transfer funds from Main first. See [Balances & Transfers](/concepts/balances) for details on Main, Trade, and Collateral account types. ## Troubleshooting The payload used for Base64 encoding must be the exact same JSON string sent as the request body. Verify: * The `request` field matches the endpoint path exactly (e.g., `"/api/v4/trade-account/balance"`). * The `nonce` is an integer larger than the previous request's nonce — use Unix milliseconds. * The API secret is current — regenerating the key invalidates the old secret. * The HMAC uses the Base64-encoded string as input, not the raw JSON. See [Authentication](/api-reference/authentication) for the complete signing walkthrough. Verify: * Copy the API key exactly — no leading or trailing spaces. * The key is active. Keys auto-deactivate after 14 days of inactivity. Reactivate at [whitebit.com/settings/api](https://whitebit.com/settings/api). * The key has **Info + Trading** permissions for balance endpoints. If the API key has IP whitelisting enabled, the request must come from a whitelisted IP address. Add the current IP at [whitebit.com/settings/api](https://whitebit.com/settings/api). The `nonce` must be greater than the previous request's nonce for the same API key. Use `int(time.time() * 1000)` to generate a millisecond-precision Unix timestamp. Avoid reusing nonces across requests. ## What's next Place a first order on a spot market. Stream real-time prices over WebSocket. Browse the 14 public endpoints for tickers, orderbooks, trades, and funding rates. # Market-Making Program FAQ Source: https://docs.whitebit.com/guides/market-maker-faq Common questions about the WhiteBIT Market-Making Program: eligibility and onboarding, program terms, colocation, and safety mechanisms. Common questions about the WhiteBIT Market-Making Program. ## Eligibility and onboarding ### Market-Making Program eligibility The program is intended for professional liquidity providers, and access is arranged during onboarding. Apply by emailing `institutional@whitebit.com` with trading-volume history and target markets. See the [Market-Making Program overview](/guides/market-maker-overview). ### Colocation access Colocation is provisioned by the dedicated account manager, who supplies the AWS region, availability zone, and connection endpoints during onboarding. See [Colocation](/platform/colocation). ## Program terms ### Maker-fee rebates Maker fees are tiered by 30-day rolling volume, with separate breakpoints for spot and futures; a negative maker fee is a rebate paid on filled maker orders. Rates and breakpoints change over time — see the [Market-Making Program page](https://institutional.whitebit.com/market-making-program) and the [trading fees page](https://whitebit.com/trading-data/trading-fees). ### Program benefits beyond fees The program adds colocation, a dedicated account manager, cross-marketing support, and sub-accounts for strategy separation. See the [overview](/guides/market-maker-overview). ## Integration ### Colocation endpoint coverage Colocation exposes a subset of the API — spot trading, collateral trading, and utility endpoints — reachable from inside the matching-engine zone; other endpoints use the standard API. See the [Market Maker integration guide](/guides/market-maker-integration#available-colocation-endpoints). ### Bulk quoting Up to 20 limit orders can be placed in a single request for atomic quote-ladder placement, and orders can be requoted by client order identifier. See [Quoting strategy](/guides/market-maker-integration#quoting-strategy). ### Placing and canceling orders over WebSocket On the global platform, orders can be placed, modified, and canceled over the same authorized WebSocket connection that carries market data, as an alternative to the REST order endpoints. REST stays preferred for atomic bulk quote-ladder placement and the kill-switch deadman timer; the socket suits low-latency single-order placement on one connection. See [Placing and canceling orders over WebSocket](/guides/market-maker-integration#placing-and-canceling-orders-over-websocket). ## Safety mechanisms ### Disconnect protection WhiteBIT provides no automatic cancel-on-disconnect; the per-market kill-switch is the safeguard. See [Monitoring and safety](/guides/market-maker-integration#monitoring-and-safety). ### Self-trade prevention Two-sided quoters can match resting orders on the same account; the STP mode set at order placement determines which side is canceled. See [Self-Trade Prevention](/platform/self-trade-prevention). ## What's next What the Market-Making Program provides and who it is for. The quoting loop, colocation, and safety mechanisms. Cross-cutting answers shared across programs — KYB, sandbox, fees, and rate limits. # Market Maker Integration Guide Source: https://docs.whitebit.com/guides/market-maker-integration Guide for professional market makers — Market-Making Program terms, colocation setup, available endpoints, quoting strategy, and safety mechanisms. The Market-Making Program provides dedicated infrastructure for professional liquidity providers: maker-fee rebates, [colocation](/platform/colocation), and a 35-endpoint API subset reachable from inside the matching-engine zone. ## Market-Making Program overview Maker-fee rebates are tiered by 30-day rolling trading volume, with separate tiers for spot and futures. Negative maker fees are rebates — the exchange pays the market maker for each maker order filled. Rates and volume breakpoints change over time and are not duplicated here. For current fees and tier requirements, see the [Market-Making Program page](https://institutional.whitebit.com/market-making-program), the [trading fees page](https://whitebit.com/trading-data/trading-fees), or the [VIP program](https://whitebit.com/vip-program). **Program benefits beyond fees:** * [Colocation](/platform/colocation) access * Dedicated account manager * Cross-marketing support * [Sub-accounts](/products/sub-accounts/overview) for strategy separation * Access to [Liquidity Provision program](https://whitebit.com/m/liquidity-provision) for non-MM liquidity partnerships ## Prerequisites * **Approved Market-Making Program enrollment** — contact `institutional@whitebit.com` with trading-volume history and target markets (see [How to apply](#how-to-apply)); the [Market-Making overview](/guides/market-maker-overview) covers program terms. * **Colocation connection details** — provisioned by the account manager for latency-sensitive strategies (see [Colocation setup](#colocation-setup)). * **API access** — [HMAC-signed requests](/api-reference/authentication). ## Colocation setup Colocation provides low-latency API access from AWS infrastructure co-located with the WhiteBIT matching engine. The account manager provides the specific AWS region, availability zone, and connection endpoints during onboarding. **EC2 sizing recommendations:** * Network: up to **10Gbit bandwidth** * CPU: minimum **4 vCPU cores** * Low-performance VPS instances result in higher latency Both REST API and WebSocket connections are available via colocation. Contact the designated account manager for connection details including base URLs and availability zone placement. Colocation endpoints are a SUBSET of the full WhiteBIT API. Only the 35 endpoints listed below are available via colocation infrastructure. All other API endpoints must be accessed through the standard public API. See the [Colocation](/platform/colocation) page for additional infrastructure details. ## Available colocation endpoints The colocation infrastructure exposes 35 endpoints organized into three categories: spot trading (17), collateral trading for both Margin and Futures (14), and utility (4). ### Spot trading (17 endpoints) | Endpoint | Description | | - | - | | `POST /api/v4/trade-account/balance` | Trade account balance | | `POST /api/v4/trade-account/executed-history` | Executed order history | | `POST /api/v4/trade-account/order` | Single order details | | `POST /api/v4/trade-account/order/history` | Order history | | `POST /api/v4/orders` | Active orders list | | `POST /api/v4/order/cancel` | Cancel an order | | `POST /api/v4/order/cancel/bulk` | Cancel up to 100 orders in one request | | `POST /api/v4/order/cancel/all` | Cancel all open orders (optional `market` and `type` scope) | | `POST /api/v4/order/new` | Place a limit order | | `POST /api/v4/order/bulk` | Place up to 20 limit orders | | `POST /api/v4/order/modify` | Modify an existing order | | `POST /api/v4/order/market` | Place a market order | | `POST /api/v4/order/stock_market` | Place a stock market order | | `POST /api/v4/order/stop_limit` | Place a stop-limit order | | `POST /api/v4/order/stop_market` | Place a stop-market order | | `POST /api/v4/order/kill-switch` | Set or cancel the kill-switch timer | | `POST /api/v4/order/kill-switch/status` | Check kill-switch status | ### Collateral / Margin and Futures trading (14 endpoints) | Endpoint | Description | | - | - | | `POST /api/v4/collateral-account/balance` | Collateral account balance | | `POST /api/v4/collateral-account/balance-summary` | Collateral balance summary | | `POST /api/v4/collateral-account/summary` | Collateral account summary | | `POST /api/v4/collateral-account/leverage` | Set leverage | | `POST /api/v4/collateral-account/positions/open` | Open positions | | `POST /api/v4/collateral-account/positions/history` | Position history | | `POST /api/v4/collateral-account/funding-history` | Funding history | | `POST /api/v4/oco-orders` | OCO orders | | `POST /api/v4/order/collateral/limit` | Collateral limit order | | `POST /api/v4/order/collateral/market` | Collateral market order | | `POST /api/v4/order/collateral/stop-limit` | Collateral stop-limit order | | `POST /api/v4/order/collateral/trigger-market` | Collateral trigger-market order | | `POST /api/v4/order/collateral/oco` | Collateral OCO order | | `POST /api/v4/order/collateral/bulk` | Collateral bulk orders | **API naming convention:** WhiteBIT's API uses "collateral" endpoints for both Margin and Futures trading. The market pair determines the product: spot pairs (e.g., `BTC_USDT`) for Margin, perpetual pairs (e.g., `BTC_PERP`) for Futures. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. ### Utility (4 endpoints) | Endpoint | Description | | - | - | | `POST /api/v4/profile/websocket_token` | Generate WebSocket authentication token | | `GET /api/v4/public/ping` | Server health check | | `GET /api/v4/public/time` | Server time | | `POST /api/v4/market/fee` | Query maker and taker fees for all markets | For endpoints not listed above, use the standard WhiteBIT API at `https://whitebit.com`. ## Quoting strategy Quoting on WhiteBIT uses limit orders placed via individual endpoints or `POST /api/v4/order/bulk` (up to 20 limit orders per request), paired with the `depth` and `bookTicker` WebSocket channels for price input. Orders can be placed over REST — covered in this section — or over the WebSocket order methods on the same connection (global platform only); see [Placing and canceling orders over WebSocket](#placing-and-canceling-orders-over-websocket) for the trade-offs. **Bulk vs individual:** bulk reduces wire and auth overhead and gives atomic same-timestamp placement of a quote ladder. The bulk response only returns once every leg in the batch is processed. Pipelined individual orders give faster per-leg acknowledgment for clients optimized for that pattern. Use bulk for atomic quote refreshes and less-optimized clients; use individual orders when lowest per-leg ack latency matters most. **RPI mode:** Each order item in `/order/bulk` can set `rpi: true` to enable Retail Price Improvement (RPI) mode. RPI orders are post-only and hidden from public `depth` and `bookTicker` feeds. RPI orders remain visible in the exchange UI order book (web/mobile) — capturing UI-driven retail flow rather than algorithmic flow consuming the public feed. RPI executions use an account-specific fee or rebate model. Incompatible with `ioc`. RPI is a flow-segmentation tool, not a default MM primitive — fit depends on volume targets and the account's fee arrangement. See the [API Reference](/api-reference/trading/bulk-limit-order) and [glossary entry](/glossary#retail-price-improvement-rpi). **Real-time orderbook:** Subscribe to the `depth` WebSocket channel for real-time orderbook updates. See the [WebSocket Quickstart](/guides/websocket-quickstart). **Order modify:** `POST /api/v4/order/modify` — change an existing order's price, amount, or activation price. The matching engine internally cancels the original order and creates a replacement with a **new `orderId`**, so modify does NOT preserve queue priority. Use `clientOrderId` as the stable identifier across modifications. Identify the target by `orderId` OR `clientOrderId` — never both. See the [API Reference](/api-reference/trading/modify-order). For how the engine sequences orders — price-time priority, participant fairness, and latency factors — see [Matching engine](/concepts/matching-engine). **Kill-switch (circuit breaker):** `POST /api/v4/order/kill-switch` — sets a per-market timeout of 5–600 seconds; if the endpoint is not called again before it expires, the kill-switch cancels every open order on that market. Quoting several markets requires one timer per market. The deadman trigger for process crashes, lost connectivity, and operator absence. See the [API Reference](/api-reference/trading/sync-kill-switch-timer). * Configuration: set the timeout (5–600 seconds); each call to the endpoint resets the timer; `timeout: null` deletes it * Scope: pass the optional `types` array (`"spot"`, `"margin"`, `"futures"`) to restrict the breaker to a subset of order types — useful when spot market-making runs alongside futures positions whose protective orders must stay on the book * Check status: `POST /api/v4/order/kill-switch/status` — see the [API Reference](/api-reference/trading/status-kill-switch-timer) **Self-Trade Prevention:** Market makers providing two-sided quotes (bid + ask) must understand STP behavior to avoid self-trades. When a new order would match against an existing order from the same account, the STP mechanism cancels the new order, the existing order, both, or neither — depending on the `stp` mode passed at order placement. The default mode (`no`) allows self-trades, which is usually not what a two-sided quoter wants. See [Self-Trade Prevention](/platform/self-trade-prevention) for the available modes. The examples below assume an API key with trade permissions. Payload signing (`X-TXC-PAYLOAD`, `X-TXC-SIGNATURE`) is covered in the [request-signing setup](/guides/first-api-call). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Place a bulk order — the "orders" array carries 1–20 limit orders. # Each order item has its own "market" field; there is no top-level # market parameter. curl -X POST "https://whitebit.com/api/v4/order/bulk" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "orders": [ {"market": "BTC_USDT", "side": "buy", "amount": "0.01", "price": "60000", "clientOrderId": "quote-bid-1"} ], "request": "/api/v4/order/bulk", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Request bodies for the quoting loop. To send each one: add "request" # (the endpoint path) and "nonce", sign with HMAC-SHA512, and send with # the X-TXC-* headers — implementation in the First API Call guide # linked above. # POST /api/v4/order/bulk — 1–20 limit orders; each item carries its own # "market". The response is a list of {"result": ..., "error": ...} pairs — # check each item individually; per-order failures do not fail the # HTTP request. bulk_body = { "orders": [ {"market": "BTC_USDT", "side": "buy", "amount": "0.01", "price": "60000", "clientOrderId": "quote-bid-1"}, ], } # POST /api/v4/order/modify — requote by clientOrderId. The response # carries a new orderId; clientOrderId is preserved so local tracking # survives the modify. modify_body = { "market": "BTC_USDT", "clientOrderId": "quote-bid-1", "price": "60050", } ``` For Go and PHP examples, see [SDKs](/sdks). The kill-switch rides the same loop: arm one timer per quoted market, reset it on every quote refresh, and let expiry cancel that market's open orders if the bot stops calling in. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Bot as MM bot participant WB as WhiteBIT API Bot->>WB: POST /api/v4/order/kill-switch (arm timer) WB-->>Bot: timer confirmed loop every quote refresh — before the timeout expires Bot->>WB: POST /api/v4/order/kill-switch (reset timer) WB-->>Bot: timer reset end Bot->>WB: POST /api/v4/order/kill-switch/status (verify active timers) WB-->>Bot: active timers for the market Note over Bot,WB: bot crashes or loses connectivity — resets stop WB->>WB: timeout expires — open orders on the market are canceled ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # POST /api/v4/order/kill-switch — arm or reset the deadman timer. # "timeout" is a string, "5"–"600" seconds; null deletes the timer. # The optional "types" array restricts scope, e.g. ["spot"]. # Sign and send as above. kill_switch_body = { "market": "BTC_USDT", "timeout": "60", } ``` ## WebSocket workflow for market making The market-making loop runs on real-time WebSocket data, not REST polling. Quote inputs arrive on `depth` (deep book) or `bookTicker` (top of book); inventory state arrives on `balanceSpot`; fill confirmations arrive on `deals` (executions) and `ordersPending` (state transitions including partial fills and cancels). Wire those four channels together to close the loop: market data drives the quote, REST `order/bulk` or `order/modify` places it, `ordersPending` confirms the state transition, `deals` confirms the fill, `balanceSpot` confirms the inventory delta, and the loop recomputes. The protocol primitives — connect, ping/pong, `authorize`, exponential-backoff reconnection, and the query-then-subscribe recovery pattern — are covered end-to-end in the [WebSocket Quickstart](/guides/websocket-quickstart). | Channel | Carries | Recovery model | Where to learn the protocol | | - | - | - | - | | `depth` | Full orderbook (1/5/10/20/30/50/100 levels per market) | Snapshot on subscribe, then incremental updates; detect gaps via the `past_update_id` chain on deltas (keepalive snapshots are full resets, not gaps) | [Depth channel](/websocket/market-streams/depth) | | `bookTicker` | Best bid + best ask only — lighter than depth, ideal for top-of-book quoting | Simple replacement on every change | [Book Ticker channel](/websocket/market-streams/book-ticker). Note: `bookTicker_update` excludes RPI orders. Track RPI quotes via the private active-orders state. | | `balanceSpot` | Available + frozen balances per asset | Query-then-subscribe (`balanceSpot_request` then `balanceSpot_subscribe`) | [WS Quickstart — State recovery](/guides/websocket-quickstart#state-recovery-after-reconnect) | | `ordersPending` | Active order state transitions: placed, partially filled, canceled | Query first (`ordersPending_request` or REST `POST /api/v4/orders`), then subscribe | [Bot Guide — WebSocket fill monitoring](/guides/building-a-trading-bot#websocket-fill-monitoring) | | `deals` | Trade execution events with price, amount, fee, deal-id | Query first (`deals_request` or REST `POST /api/v4/trade-account/executed-history`), then subscribe | [Bot Guide — WebSocket fill monitoring](/guides/building-a-trading-bot#websocket-fill-monitoring) | **Futures additions.** When quoting perpetuals (e.g. `BTC_PERP`), add two more channels: | Channel | Carries | Recovery model | Where to learn the protocol | | - | - | - | - | | `positions` | Snapshot of open collateral positions (size, entry price, liquidation price, PnL) | Periodic full snapshot — full state arrives shortly after subscribing | [WS Quickstart — State recovery table](/guides/websocket-quickstart#state-recovery-after-reconnect) | | `marginPositionsEvents` | Position-change events (open, update, close, liquidation) | Event-only — pair with `positions` for complete state | [WS Quickstart — State recovery table](/guides/websocket-quickstart#state-recovery-after-reconnect) | **Canonical subscribe set (spot MM).** Send these messages after the [`authorize` handshake](/websocket/authentication) — the three private subscriptions will be rejected on an unauthenticated socket. For multi-symbol MM, repeat each `*_subscribe` per market or use the multiple-subscription flag where supported (see the [depth subscribe parameters](/websocket/market-streams/depth)). To stop quoting on one pair without disrupting the others, send `depth_unsubscribe` or `bookTicker_unsubscribe` with that market name in `params` — only that market's feed drops; an empty array unsubscribes from all markets on the stream. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ {"id": 10, "method": "depth_subscribe", "params": ["BTC_USDT", 20, "0", true]}, {"id": 11, "method": "balanceSpot_subscribe", "params": ["USDT", "BTC"]}, {"id": 12, "method": "ordersPending_subscribe", "params": ["BTC_USDT"]}, {"id": 13, "method": "deals_subscribe", "params": [["BTC_USDT"]]} ] ``` Note the asymmetry: `ordersPending_subscribe` takes a flat array of markets, `deals_subscribe` takes a single-element array containing the array of markets. The full schema lives in `asyncapi/private/deals.yaml` (rendered as the [Deals channel](/websocket/account-streams/deals) page). For the full reconnect-with-fresh-token + auto-resubscribe pattern that wraps these subscriptions in production, see [WS Quickstart — Reconnection and state recovery](/guides/websocket-quickstart#reconnection-and-state-recovery) and the worked grid-bot example in the [Bot Guide](/guides/building-a-trading-bot#auto-resubscription-after-reconnect). ## Placing and canceling orders over WebSocket The subscriptions above feed the quoting loop with market data and fill events, while the [Quoting strategy](#quoting-strategy) section places orders over REST. The same authorized socket can carry the write side too: the [WebSocket Order Management](/websocket/order-management/overview) methods place, modify, and cancel orders as JSON-RPC calls on the connection already open for market data — an alternative transport to the REST order endpoints for latency-sensitive flow. The loop runs on one connection — authorize once, place with an order method, then read the acknowledgment and the fills off the same socket: ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Bot as MM bot participant WS as WhiteBIT WebSocket Bot->>WS: authorize (token) WS-->>Bot: result: success Bot->>WS: order_limit_place (id 101) WS-->>Bot: result (id 101 — order object) WS-->>Bot: ordersPending push — state change WS-->>Bot: deals push — fill Note over Bot,WS: correlate the ack by id; fills arrive as id-less pushes Bot->>WS: order_modify or order_cancel — requote ``` A placement carries the order parameters in a single-object `params` array — prices and amounts as decimal strings, `side` as `"buy"` or `"sell"`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 101, "method": "order_limit_place", "params": [ { "market": "BTC_USDT", "side": "buy", "amount": "0.01", "price": "60000", "client_order_id": "quote-bid-1" } ] } ``` The server answers with one frame echoing `id`: `result` holds the order object — with `side` inverted to `1` for sell or `2` for buy — and `error` is `null` on success. The full parameter set, the flag rules, and every method live on the [Order Management](/websocket/order-management/overview) reference and the [Place limit order](/websocket/order-management/order-limit-place) page. **When the socket wins.** Placing over the open connection removes the per-request HTTP round trip and the per-request HMAC signature that each REST order carries: the connection authorizes once, and every later order frame rides that session. For a quoter refreshing one price at a time, the socket is the shortest path to the book. **When REST still wins.** Two market-making primitives run over REST, so a socket-first quoter keeps a REST client alongside the connection: * **Atomic ladder placement.** `POST /api/v4/order/bulk` places up to 20 limit orders in one request with same-timestamp atomicity. The WebSocket methods place one order per frame — the per-connection budget of 10,000 order placements per 10 seconds absorbs a 20-level requote easily, but the levels land as separate engine events rather than at one timestamp. Refresh a full ladder over REST bulk when same-timestamp placement matters; place and cancel individual quotes over the socket. * **The deadman timer.** The kill-switch (`POST /api/v4/order/kill-switch`) that cancels a market's orders when the client stops calling in is a REST endpoint. Arm it over REST no matter which transport places the quotes — the WebSocket `order_cancel_all` method cancels one market on demand but does not run a timer. **Correlation and errors.** Each order method answers with a single frame carrying the request `id`; responses interleave with subscription pushes, so match answers by `id`, not by arrival order. `order_modify` over the socket is cancel-and-replace exactly as the REST modify is — a new engine order id, `client_order_id` preserved, queue priority lost. The `rpi` flag is accepted on `order_limit_place`, so RPI quoting works over either transport. The WebSocket transport numbers its errors independently of REST — code `40` is `order is not post only`, `41` is `order is not ioc`, and `43` a duplicate `client_order_id`, each different from the REST code for the same condition. Branch on the WebSocket codes in the [error reference](/websocket/order-management/overview#error-codes); never carry a REST code across. ## Infrastructure best practices Three pieces are load-bearing in production: how the account is partitioned across strategies, how the socket recovers when it drops, and how requests stay under per-endpoint limits. **Sub-accounts for strategy separation:** Use [sub-accounts](/products/sub-accounts/overview) to isolate different trading strategies or pair groups. Each sub-account has independent balances and can have dedicated API keys; transfers between sub-accounts are fee-free. Worked example: run the BTC\_USDT spot MM book in one sub-account funded with its own USDT balance, and a directional ETH\_USDT swing book in a second sub-account with its own balance and leverage limit. A drawdown that wipes the swing book's collateral cannot pull capital from the MM book — the MM bot keeps quoting on its untouched balance, and the swing book's API key has no authority over the MM sub-account. **WebSocket connection management:** * Authenticate after connecting: fetch a token via `POST /api/v4/profile/websocket_token` (rate limit: **10 requests per 60 seconds** — cache the token across reconnects within its lifetime), then send `{"id": N, "method": "authorize", "params": ["", "public"]}` on the socket. On `{"result": {"status": "success"}}`, subscribe to private channels such as `balanceSpot`, `ordersPending`, and `deals` * Implement automatic reconnection with exponential backoff * Re-subscribe to all channels after reconnection * Use the ping/pong mechanism to detect stale connections * After reconnecting, reconcile local state: call `POST /api/v4/orders` for the current active set and `POST /api/v4/trade-account/executed-history` for fills since the last-seen ID. Do not assume in-memory state survived the disconnect * See the [WebSocket Quickstart](/guides/websocket-quickstart) for a full connection + auth example **Rate limit management:** All limits are per IP address. Order placement, cancellation, and modification sit at 10,000 requests per 10 seconds per endpoint; `trade-account` reads allow 12,000. The outlier is `POST /api/v4/profile/websocket_token` at 10 requests per 60 seconds. Full reference: [Rate Limits](/api-reference/rate-limits). * Use bulk orders (`/order/bulk`) to reduce request count: 20 orders per call vs. 20 individual calls * Use WebSocket for market data instead of polling REST endpoints * Maintain a per-endpoint token bucket sized to the table above; back off when the bucket empties rather than retrying after a 429 ## Monitoring and safety Set the kill-switch first; everything below is the loop that keeps it reset, the manual cancel that overrides it, and the balance and fee surfaces the loop reads from. **Kill-switch configuration:** Set a kill-switch timer for every quoted market as the first action after connecting — each timer covers only its own market. Configure the timeout based on the maximum acceptable unmonitored period for the system. Reset the timers with each regular API call to the kill-switch endpoint. If the system crashes or loses connectivity, the kill-switch cancels each covered market's open orders as its timeout expires. **Disconnect protection:** WhiteBIT provides no automatic cancel-on-disconnect for WebSocket clients — resting orders persist when the socket drops. The per-market kill-switch is the disconnect safeguard: set a timer for each quoted market and reset it on the connection heartbeat, so a dropped or crashed client has its open orders canceled when the timer lapses. The kill-switch is a REST endpoint — arm it over REST whether quotes are placed over REST or the WebSocket order methods. **Emergency cancel:** `POST /api/v4/order/cancel/all` — cancel every open order synchronously; the response returns after the cancellations complete. Use the optional `market` field to scope to a single pair and the `type` array to scope to `"spot"`, `"margin"`, or `"futures"`; omit both to cancel everything on the account. This is the "big red button" for live traders; the kill-switch is the deadman timer for unattended operation. `order/cancel/all` is available on colocation as well as through the standard public API. See the [API Reference](/api-reference/trading/cancel-all-orders). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Cancel all spot orders on BTC_USDT curl -X POST "https://whitebit.com/api/v4/order/cancel/all" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "market": "BTC_USDT", "type": ["spot"], "request": "/api/v4/order/cancel/all", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # POST /api/v4/order/cancel/all — request body; sign and send per the # First API Call guide (see Quoting strategy above). cancel_all_body = { "market": "BTC_USDT", "type": ["spot"], } ``` **Balance monitoring:** Use the WebSocket `balanceSpot` channel for real-time balance updates, or poll `POST /api/v4/trade-account/balance` for periodic checks. Monitor for unexpected balance changes. **Fee tracking:** Use `POST /api/v4/market/fee` to pull the account's global maker and taker fees plus any per-pair custom fees — the `market` request parameter is currently ignored, so the endpoint returns fees for all markets regardless. Filter the per-pair `custom_fee` map client-side. Fee tiers are based on 30-day rolling volume — monitor tier changes as volume accumulates. Look up tier breakpoints on the [VIP program page](https://whitebit.com/vip-program) or the [trading fees page](https://whitebit.com/trading-data/trading-fees). **Self-Trade Prevention:** Understand the STP mode active on the account. Two-sided quoters hit STP frequently when bid and ask orders overlap. See [Self-Trade Prevention](/platform/self-trade-prevention) for the available modes and behavior. ## How to apply Contact **[institutional@whitebit.com](mailto:institutional@whitebit.com)** with trading volume history and target markets. The dedicated account manager provides colocation connection details — AWS region, availability zone, and connection endpoints — during onboarding. ## What's next AWS regions, EC2 sizing, and availability-zone placement for colocation onboarding. Full endpoint documentation for all spot trading endpoints. STP modes and behavior for two-sided quoting. # Market-Making Program Source: https://docs.whitebit.com/guides/market-maker-overview What the WhiteBIT Market-Making Program provides for professional liquidity providers — maker-fee rebates, colocation, and the trading capabilities used to quote at scale. The WhiteBIT Market-Making Program provides dedicated infrastructure for professional liquidity providers: maker-fee rebates tiered by trading volume, [colocation](/platform/colocation) inside the matching-engine zone, and the trading capabilities a quoting engine relies on. This overview covers fit, capabilities, and program terms; the integration detail lives on the [Market Maker integration guide](/guides/market-maker-integration). ## What the Market-Making Program provides * **Maker-fee rebates** — negative maker fees paid on filled maker orders, tiered by 30-day rolling volume with separate spot and futures tiers ([trading fees](https://whitebit.com/trading-data/trading-fees)). * **Colocation** — low-latency REST and WebSocket access from AWS infrastructure co-located with the matching engine ([details](/platform/colocation)). * **Bulk and atomic quoting** — place a full quote ladder in a single request and requote by client order identifier ([integration guide](/guides/market-maker-integration)). * **Safety mechanisms** — a per-market kill-switch for unattended operation and [Self-Trade Prevention](/platform/self-trade-prevention) for two-sided quotes. * **Strategy isolation** — [sub-accounts](/products/sub-accounts/overview) with independent balances and API keys, and fee-free transfers between the master account and sub-accounts. ## Who the Market-Making Program is for * **Professional market makers** — firms providing two-sided liquidity across spot and perpetual markets. * **Proprietary trading firms** — desks running latency-sensitive strategies that benefit from colocation. * **Quantitative and algorithmic desks** — teams operating automated quoting and hedging systems at scale. ## How it works A market maker streams orderbook and balance data over WebSocket, places and requotes orders over REST, and protects the book with a per-market kill-switch. [WebSocket order placement](/guides/market-maker-integration#placing-and-canceling-orders-over-websocket) is available (global platform only) as an alternative to the REST order endpoints. The program adds maker-fee rebates on top of the standard trading surface and, for latency-sensitive strategies, colocation inside the matching-engine zone. The [Market Maker integration guide](/guides/market-maker-integration) documents the quoting loop, the colocation endpoint subset, and the WebSocket channels end to end. ## Program terms Maker-fee rebates are tiered by 30-day rolling volume, with separate breakpoints for spot and futures. Rates and volume breakpoints change over time and are not restated here — the current schedule is on the [Market-Making Program page](https://institutional.whitebit.com/market-making-program), the [trading fees page](https://whitebit.com/trading-data/trading-fees), and the [VIP program](https://whitebit.com/vip-program). The applicable tier and any additional terms — including colocation and the dedicated account manager — are confirmed individually during onboarding. ## How to get started Contact `institutional@whitebit.com` with trading-volume history and target markets. The dedicated account manager provides colocation connection details — AWS region, availability zone, and connection endpoints — during onboarding. Then build against the [Market Maker integration guide](/guides/market-maker-integration). ## What's next The quoting loop, colocation endpoint subset, kill-switch, and WebSocket channels. Eligibility, program terms, colocation, and safety mechanisms. Low-latency infrastructure co-located with the matching engine. # MCP server Source: https://docs.whitebit.com/guides/mcp-server Connect Claude Code, Cursor, Claude Desktop, Codex, or OpenClaw to 115 WhiteBIT trading tools using the Model Context Protocol. The WhiteBIT MCP server exposes the full WhiteBIT API as AI tools over the Model Context Protocol. Connect a supported AI client and interact with markets, trading, balances, wallets, and sub-accounts using natural language. * **115 tools** across market data, spot trading, collateral trading, wallet, lending, sub-accounts, mining pool, and currency conversion * Runs locally — API keys never leave the machine * Credentials are passed per tool call and are not stored or logged by the server The MCP server documented on this page enables **trading** via AI clients. For documentation search via MCP (searching the WhiteBIT API docs in Cursor or VS Code), see [Docs search via MCP](/guides/ai-ide-setup). ## Prerequisites * A WhiteBIT account with an API key (for trading tools) — see [API key generation](/api-reference/authentication) * A supported AI client: Claude Code, Cursor, Claude Desktop, Codex, or OpenClaw * [uv](https://docs.astral.sh/uv/getting-started/installation/) **or** [Docker](https://docs.docker.com/get-docker/) ## Quick start One command configures the MCP server for every supported AI client at once. No Docker, no manual config editing. `uv` is a Python package manager that provides the `uvx` command used to run the server. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -LsSf https://astral.sh/uv/install.sh | sh source $HOME/.local/bin/env ``` ```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}} powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} uvx --from whitebit-mcp whitebit-mcp-setup --public=YOUR_API_KEY ``` Keep `--from whitebit-mcp`. `whitebit-mcp-setup` is a command inside the `whitebit-mcp` package, not a package of its own — running `uvx whitebit-mcp-setup` downloads and executes an unrelated third-party package that happens to hold that name on PyPI, and passes the API credentials to it. Omitting `--secret` makes the script prompt for the secret key without echoing it, which keeps it out of the shell history. To run non-interactively, add `--secret=YOUR_SECRET_KEY`. The script writes the server configuration and credentials into the config of each AI tool it finds: | AI tool | Config file | | - | - | | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) / `%APPDATA%\Claude\…` (Windows) | | Claude Code | `~/.claude/mcp.json` | | Cursor | `~/.cursor/mcp.json` | | OpenAI Codex | `~/.codex/config.toml` | | OpenClaw | `~/.openclaw/openclaw.json` | Existing configs are updated in place — other configured MCP servers are not affected. The MCP server is started automatically by the AI client — there is no separate server process to run manually. Under the hood, the setup command registered the following as the server entry in each config: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} uvx whitebit-mcp ``` The AI client executes this command on startup and keeps the server running in the background as long as the client is open. Restart the AI client so it picks up the new config and launches the server. * **Claude Desktop** — quit and reopen the app * **Claude Code** — run `claude mcp list` to reload, or start a new session * **Cursor** — open the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) and run **MCP: Reload Servers** * **Codex** — start a new Codex session * **OpenClaw** — restart the agent Ask the AI client something like: ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} What is the current BTC_USDT price? ``` If the WhiteBIT MCP server is connected, the AI client calls the tool and returns live data. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} git clone https://github.com/whitebit-exchange/whitebit-mcp cd whitebit-mcp ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} docker compose up -d ``` The MCP endpoint is available at `http://localhost:8080/mcp`. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} docker compose ps ``` The `whitebit-mcp` container status shows `Up`. Stop the server at any time: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} docker compose down ``` Then follow the [Connect an AI client](#connect-an-ai-client) section below to register the server in the AI tool. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} pip install mcp whitebit-python-sdk mcp run server.py ``` The server listens on `http://0.0.0.0:8000`. Use port `8000` in place of `8080` in all client configurations below. Then follow the [Connect an AI client](#connect-an-ai-client) section below to register the server in the AI tool. ## Connect an AI client Skip this section if the auto-setup tab above was used — the AI clients are already configured. **Global registration (all projects):** ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} claude mcp add --transport http --scope user whitebit http://localhost:8080/mcp ``` Verify the connection: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} claude mcp list # whitebit: http://localhost:8080/mcp (http) ``` **Project-scoped registration:** The repository includes a `.mcp.json` file at the project root. Running `claude` from inside the cloned `whitebit-mcp` directory registers the server automatically at project scope. Use `/mcp` inside a Claude Code session to see live server status and available tools. Create or edit `~/.cursor/mcp.json`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcpServers": { "whitebit": { "url": "http://localhost:8080/mcp" } } } ``` Open the Command Palette (`Cmd+Shift+P` on macOS, `Ctrl+Shift+P` on Windows/Linux) and run **MCP: Reload Servers**. Edit the Claude Desktop configuration file: * **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json` * **Windows:** `%APPDATA%\Claude\claude_desktop_config.json` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcpServers": { "whitebit": { "type": "http", "url": "http://localhost:8080/mcp" } } } ``` Restart Claude Desktop. Add to `~/.codex/config.toml`: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [mcp_servers.whitebit] url = "http://localhost:8080/mcp" ``` Start a Codex session — the server connects automatically. Add to the OpenClaw agent configuration: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcp_servers": { "whitebit": { "url": "http://localhost:8080/mcp" } } } ``` ## API keys Generate API keys at [whitebit.com](https://whitebit.com) → **Profile** → **API Keys**. Use the minimum permissions required for the intended use case — read-only keys are sufficient for balance and order queries. Never paste API keys into the AI conversation. Credentials are supplied at connection time — the setup command writes the keys into the AI client configuration, and the client passes the credentials to the server on every connection. The server uses keys only to sign outgoing WhiteBIT API requests — keys are not stored, logged, or cached. **Credential handling:** credentials are read from the transport, never from tool parameters. | Transport | Where credentials come from | | - | - | | stdio / `uvx` | `WHITEBIT_API_KEY` and `WHITEBIT_SECRET_KEY` environment variables | | HTTP / Docker | `X-WB-Api-Key` and `X-WB-Secret-Key` request headers | **Public market data tools** (market info, tickers, order book) query public endpoints and need no credentials. On the HTTP transport the `/mcp` endpoint still answers `401` to a connection that carries no credentials at all, so the client must be configured with keys even for public data. ## Example prompts ### Market data — no API key required These tools query public endpoints and return data without credentials. * "What is the current BTC\_USDT price?" * "Show the order book for ETH\_USDT" * "List all available markets" * "What are the deposit fees for USDT?" * "What is the funding rate history for BTC\_USDT?" * "Is WhiteBIT in maintenance mode?" ### Spot trading — API key required * "Show the spot balance" * "List open orders on BTC\_USDT" * "Place a limit buy order for 0.001 BTC at 90000 on BTC\_USDT" * "Cancel all open orders on ETH\_USDT" * "Show order history for the last 30 days" ### Wallet — API key required * "What is the deposit address for USDT on TRC20?" * "Show recent deposits and withdrawals" * "Transfer 100 USDT from the main account to spot trading" * "Create a WhiteBIT code for 50 USDT" ### Collateral trading — API key required * "List open collateral positions" * "Place a collateral limit buy for 0.01 BTC on BTC\_USDT" * "What is the current leverage?" * "Close the BTC\_USDT position" ### Sub-accounts — API key required * "List all sub-accounts" * "Show the balance of sub-account ID 123" * "Transfer 200 USDT to sub-account ID 456" ## Configuration reference | Variable | Default | Description | | - | - | - | | `WHITEBIT_BASE_URL` | `https://whitebit.com` | API base URL — override for custom deployments | Set in `docker-compose.yml` or as a shell variable: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} WHITEBIT_BASE_URL=https://whitebit.com docker compose up ``` ## Safe account practices Before using the MCP server with a live account: * Create a dedicated sub-account with a separate API key for AI tool access. * Fund the sub-account with only the amount allocated for AI-assisted trading. * Generate API keys with the minimum required permissions — use read-only keys for monitoring. * Use IP whitelisting on the API key to restrict access to the machine running the server. * Test with a small amount before executing larger trades. ## What's next * [CLI](/guides/cli) — Trade and query account data directly from the terminal without an AI client * [AI tools FAQ](/guides/ai-faq) — Answers to common questions about API key safety, supported clients, and account practices * [AI tools overview](/guides/use-with-ai) — All WhiteBIT AI tools in one place * [Authentication](/api-reference/authentication) — How to generate and manage WhiteBIT API keys * [API Reference Overview](/api-reference/overview) — Full REST API endpoint listing # On/Off-Ramp FAQ Source: https://docs.whitebit.com/guides/on-off-ramp-faq Common questions on the WhiteBIT on/off-ramp integration: endpoint activation, SEPA deposit matching, withdrawal fee semantics, reconciliation, identifier casing, and EEA compliance. Answers to common questions on the WhiteBIT on/off-ramp integration. For the flows and code, see the [Integration guide](/guides/on-off-ramp-integration); for access, onboarding, and positioning, see the [Overview](/guides/on-off-ramp-overview). ## Access and activation The `POST /api/v4/main-account/fiat-deposit-url` endpoint requires per-account activation and is not enabled by default. Contact WhiteBIT support and provide the API key to request access. Fiat operations also depend on completed Phase 2 institutional onboarding — see [How to get started](/guides/on-off-ramp-overview#how-to-get-started). Fiat withdrawals require KYC verification; an account without KYC verification cannot process a fiat withdrawal. In exceptional, documented cases the institutional team can arrange a per-account override that permits fiat withdrawal without standard KYC. The override is exception-only, not a default capability — contact [institutional@whitebit.com](mailto:institutional@whitebit.com) with the documented case. See [Fiat withdrawal](/guides/payment-integration#fiat-withdrawal). ## Fiat deposits The `uniqueId` submitted in the `fiat-deposit-url` request must appear in the SEPA payment-reference field of the bank transfer. WhiteBIT uses that string to match the incoming settlement to the original deposit request. If the end user omits or alters the reference, the deposit may settle unmatched and require manual reconciliation through institutional support. Validate the reference field in the payment UX. See [SEPA payment reference](/guides/payment-integration#sepa-payment-reference). Take the request `provider` value from the [Asset Status](/api-reference/market-data/asset-status-list) response, and confirm the enabled provider for SEPA EUR deposits on the account with the account manager. The exact provider value for SEPA EUR deposits is confirmed per account during onboarding; read the current options from the [Asset Status](/api-reference/market-data/asset-status-list) response rather than hardcoding a value. For the VISAMASTER provider, the browser must send the `Referer` header when opening the invoice link. Messengers and email clients often strip the header, and without it WhiteBIT redirects the end user to the homepage instead of the payment provider. Test the redirect in the real delivery surface — mobile app, email link, or in-app web view — before go-live. See [Card-provider flows](/guides/payment-integration#card-provider-flows). Not every fiat ticker is depositable via API. Check `can_deposit` in the [Asset Status](/api-reference/market-data/asset-status-list) response before generating an invoice; tickers without API deposit support run through the WhiteBIT web interface. ## Fiat withdrawals Both endpoints submit a withdrawal but differ in fee handling. `POST /api/v4/main-account/withdraw` treats `amount` as **including** the fee, so the recipient receives `amount - fee`. `POST /api/v4/main-account/withdraw-pay` charges the fee **on top**, so the recipient receives the exact amount specified. Select the endpoint that matches whether the specified amount is the debit or the credit. Setting `partialEnable: true` raises the maximum limit for fiat withdrawals. The withdrawal can then complete partially, surfacing as the `Partially successful` status (18). The application must reconcile `requestAmount` against `processedAmount` in the history record and surface the remainder to operations. See the [failure and exception paths](/guides/on-off-ramp-integration#failure-and-exception-paths). ## Reconciliation and monitoring Treat webhook delivery as best-effort. Failed deliveries are retried a small number of times spaced roughly an hour apart over a window of about one day, and there is no replay mechanism once that window closes. Pair webhooks with polling: query `POST /api/v4/main-account/history` (`transactionMethod: 1` for deposits, `2` for withdrawals) on a regular cycle, and deduplicate against received events. See [Webhooks](/platform/webhook) and the [reconciliation pattern](/guides/payment-integration#webhook-reconciliation). The identifier is named differently across the API surface: | Field | Where it appears | Meaning | | - | - | - | | `uniqueId` | `fiat-deposit-url` and withdrawal requests | Client-side transaction identifier, up to 255 characters | | `unique_id` | History filter and records | The deposit/withdraw identifier in history responses | | `transactionId` | `refund-deposit` request, refund webhooks | Deposit transaction UUID, sourced from the `deposit.canceled` webhook | | `id` | `refund-deposit` response | The same deposit transaction UUID, echoed back — not a refund identifier | | `depositId` | `refund-history` filter and records | The same deposit transaction UUID | | `refundId` | `refund-history` records | The refund's own UUID, returned only by refund history | | `transaction_id` | History records | System-wide transaction UUID, never reused | Match on the correct casing per surface when reconciling across webhooks, history, and refunds. Configure the webhook endpoint over HTTPS and authenticate each delivery by verifying the HMAC-SHA512 signature rather than by source IP. See [Webhooks](/platform/webhook) for the verification flow. Whether the outbound delivery IP addresses are stable and publishable for allowlisting is confirmed with the account manager; the portal does not publish a fixed list. Settlement windows and cutoff behavior depend on the fiat rail in use, including weekends and holidays. The account manager confirms the applicable windows for the account during onboarding. No fixed settlement time is published; the timing for the specific rails enabled on the account is confirmed by the account manager. ## Conversion In both on/off-ramp flows, fiat enters and exits through the fiat deposit and withdrawal endpoints, and conversion runs on the crypto side of the balance — request a quote with `POST /api/v4/convert/estimate`, then execute it with `POST /api/v4/convert/confirm` before the quote expires. The convert service routes balances internally; no manual Main↔Trade transfers are required. See [Convert](/platform/convert). Whether Convert accepts a fiat ticker directly as the conversion leg is confirmed per account; the conversion pairs available to the account are set with the account manager. ## Compliance Inbound crypto deposits for EEA and Turkey accounts are held until Travel Rule verification completes — status 27 (awaiting originator data) and status 28 (data submitted, under review). No webhook fires for Travel Rule transitions, so the hold surfaces via history polling. Where the Travel Rule API is enabled, submit originator data through the [deposit verification endpoint](/api-reference/travel-rule/submit-deposit-verification); otherwise complete verification on the platform. See [Travel Rule](/concepts/travel-rule). Under MiCA, EEA accounts cannot deposit, withdraw, or create WhiteBIT Codes in USDT since December 30, 2024. Use USDC or EURI for the crypto leg. See [Regulatory Compliance](/institutional/compliance). ## What's next Positioning, the two-phase access model, enablement gates, and how to apply. The on-ramp and off-ramp flows, code, reconciliation, and failure paths. Endpoint-level lifecycle reference: statuses, fees, fiat operations, refunds. # On/Off-Ramp Integration Guide Source: https://docs.whitebit.com/guides/on-off-ramp-integration Technical integration for corporate on/off-ramp clients: the fiat EUR/SEPA and crypto flows in both directions, the conversion leg, code snippets, reconciliation, and the failure paths to handle before go-live. **For developers.** Fiat access is gated: it is the second phase of institutional onboarding and is not automatic after KYB. For positioning, the access gates, onboarding, and how to apply, see the [On/Off-Ramp overview](/guides/on-off-ramp-overview). All fiat operations run at the partner's main account, over v4 endpoints, in both directions: fiat in to crypto out, and crypto back to EUR. Each direction pairs a fiat leg with a conversion step and a crypto leg. ## Prerequisites * **Completed institutional onboarding with approved fiat access** — a separate, non-automatic phase after KYB; see [How to get started](/guides/on-off-ramp-overview#how-to-get-started) on the overview page. * **Per-account enablement gates** — the fiat deposit invoice endpoint, dedicated deposit addresses, and Express Withdraw are enabled per account; confirm each with the account manager. * **API access** — [HMAC-signed requests](/api-reference/authentication) on the main account. Since December 30, 2024, EEA accounts cannot deposit, withdraw, or create WhiteBIT Codes in USDT under MiCA. Use USDC or EURI for the crypto leg — see [Regulatory Compliance](/institutional/compliance). ## On-ramp flow: fiat in, crypto out ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant User as End user participant Partner as Partner backend participant WhiteBIT as WhiteBIT API Partner->>WhiteBIT: POST /api/v4/main-account/fiat-deposit-url WhiteBIT-->>Partner: Hosted payment URL Partner->>User: Open the payment URL User->>WhiteBIT: Complete the payment (SEPA transfer or card checkout) WhiteBIT-->>Partner: Deposit status change (webhook / history record) Partner->>WhiteBIT: POST /api/v4/convert/estimate → /convert/confirm Partner->>WhiteBIT: POST /api/v4/main-account/withdraw (crypto leg) ``` The `fiat-deposit-url` endpoint works on demand. Contact WhiteBIT support and provide the API key to get access to the functionality. Without activation, the endpoint returns a permission error. Generate a deposit invoice with a client-side `uniqueId` (any string up to 255 characters). The `ticker` must be a [fiat](/glossary#fiat) currency with `can_deposit: true`, and the `provider` value comes from the Asset Status response — see the [provider](/glossary#provider) glossary entry: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Generate a fiat deposit invoice (provider value from Asset Status) curl -X POST "https://whitebit.com/api/v4/main-account/fiat-deposit-url" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "EUR", "provider": "PROVIDER", "amount": "100", "uniqueId": "deposit-2026-000123", "request": "/api/v4/main-account/fiat-deposit-url", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64, hashlib, hmac, json, time, requests API_KEY, API_SECRET = "YOUR_API_KEY", "YOUR_SECRET" endpoint = "/api/v4/main-account/fiat-deposit-url" # provider value from the Asset Status response body = json.dumps({ "ticker": "EUR", "provider": "PROVIDER", "amount": "100", "uniqueId": "deposit-2026-000123", "request": endpoint, "nonce": int(time.time() * 1000), }) payload = base64.b64encode(body.encode()).decode() signature = hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha512).hexdigest() response = requests.post( "https://whitebit.com" + endpoint, headers={"Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload, "X-TXC-SIGNATURE": signature}, data=body, ) print(response.json()) # {"url": "..."} ``` For Go and PHP examples, see [SDKs](/sdks). The signing process is documented in [Private HTTP API authentication](/api-reference/authentication). Operational rules for the deposit leg: * **SEPA payment reference.** The `uniqueId` must appear in the SEPA payment-reference field of the bank transfer. If the end user omits or alters it, the deposit may settle unmatched and require manual reconciliation through institutional support — see [SEPA payment reference](/guides/payment-integration#sepa-payment-reference). * **Redirect links.** `successLink` and `failureLink` require feature activation through WhiteBIT support, which validates the destination domain; `returnLink` needs no activation. * **Card flows.** Card funding (the VISAMASTER provider) requires a `customer` billing block, and the browser must send the `Referer` header when opening the invoice link — messengers and email clients often strip it. See [Card-provider flows](/guides/payment-integration#card-provider-flows). * **Web-only currencies.** Not every fiat ticker is depositable via API; confirm `can_deposit` in the [Asset Status](/api-reference/market-data/asset-status-list) response before generating an invoice, and route unsupported tickers through the WhiteBIT web interface. To complete the on-ramp, reach the currency for the crypto withdrawal through Convert where a conversion is needed: request a quote via `POST /api/v4/convert/estimate`, then execute it with `POST /api/v4/convert/confirm` before the quote expires. Honor the per-quote expiry returned in the response rather than assuming a fixed window. The convert service routes balances internally; no manual transfers between Main and Trade balances are required. The conversion pairs available to the account — including whether a fiat balance converts directly — are confirmed with the account manager. The crypto withdrawal step is documented in [Crypto Withdrawals](/guides/payment-integration#create-a-withdrawal); for EEA accounts the crypto withdrawal carries a Travel Rule payload — see [Travel Rule](/concepts/travel-rule). ## Off-ramp flow: crypto in, fiat out ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Partner as Partner backend participant WhiteBIT as WhiteBIT API participant Hook as Partner webhook endpoint Partner->>WhiteBIT: POST /api/v4/main-account/address Note over WhiteBIT: Deposit confirms on-chain.
Travel Rule hold may apply (EEA and Turkey) WhiteBIT-->>Hook: deposit.processed Partner->>WhiteBIT: POST /api/v4/convert/estimate → /convert/confirm Partner->>WhiteBIT: POST /api/v4/main-account/withdraw (fiat ticker + beneficiary object) WhiteBIT-->>Hook: withdraw.successful Partner->>WhiteBIT: POST /api/v4/main-account/history (reconciliation) ``` Receive the crypto leg on a [deposit address](/api-reference/account-wallet/get-cryptocurrency-deposit-address) of the main account; dedicated per-transaction addresses via [`/create-new-address`](/api-reference/account-wallet/create-new-address-for-deposit) require per-account permission from [support@whitebit.com](mailto:support@whitebit.com). Inbound deposits for EEA and Turkey accounts are held until Travel Rule verification completes — see [Travel Rule](/concepts/travel-rule). For the fiat leg, choose the fee semantics: `POST /api/v4/main-account/withdraw` treats `amount` as including the fee, while `POST /api/v4/main-account/withdraw-pay` charges the fee on top so the recipient receives the specified amount. Fiat withdrawals require a `beneficiary` object; the required sub-fields vary by ticker and provider, so verify the current contract on the [Create Withdraw Request](/api-reference/account-wallet/create-withdraw-request) reference before integration. A `customerIp` field is additionally required for USD or EUR with the VISAMASTER provider. The EUR SEPA IBAN example below uses the `SEPA_BCB_GROUP` provider, one of the SEPA/bank-rail providers (`SEPA`, `SEPA_CLEAR_JUNCTION`, `SEPA_BCB_GROUP`, `FINCI`, `ZEN`, `BANKING_CIRCLE`) that requires a top-level `bankBic` field carrying the beneficiary bank's BIC/SWIFT code; the active provider for the account is confirmed via the [Asset Status](/api-reference/market-data/asset-status-list) endpoint or the account manager. An EUR IBAN transfer (SEPA) request body: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "ticker": "EUR", "amount": "500", "address": "DE89370400440532013000", "bankBic": "DEUTDEFF", "beneficiary": { "firstName": "Firstname", "lastName": "Lastname" }, "provider": "SEPA_BCB_GROUP", "uniqueId": "24529046", "request": "/api/v4/main-account/withdraw", "nonce": 1594297865000 } ``` * **Partial withdrawals.** `partialEnable: true` raises the maximum limit for fiat withdrawals; the application must then handle the `Partially successful` status (18) and reconcile `requestAmount` against `processedAmount` in the history record. * **KYC.** Fiat withdrawals require KYC verification. In exceptional, documented cases the institutional team can arrange a per-account override — see [Fiat withdrawal](/guides/payment-integration#fiat-withdrawal). Withdrawals are irreversible once processed. Validate the destination details and amounts before submitting, and test the flow with minimum amounts first — no public testnet or sandbox is available. ## Reconciliation and monitoring Webhooks are the primary channel: verify the domain, then configure the webhook URL — see [Webhooks](/platform/webhook) for the setup flow. Verify the HMAC-SHA512 signature on every delivery using the `X-TXC-APIKEY`, `X-TXC-PAYLOAD`, and `X-TXC-SIGNATURE` headers, and track the strictly increasing `nonce` in each payload. Delivery is retried a small number of times spaced roughly an hour apart over a window of about one day; treat the cadence as best-effort. There is no webhook replay mechanism, so pair webhooks with polling: query `POST /api/v4/main-account/history` (`transactionMethod: 1` for deposits, `2` for withdrawals) on a regular cycle and deduplicate against received events. The [reconciliation pattern](/guides/payment-integration#webhook-reconciliation) in the Payment Integration guide walks through the full loop. The identifier appears under different names across the API surface: | Field | Where it appears | Meaning | | - | - | - | | `uniqueId` | `fiat-deposit-url` and withdrawal requests | Client-side transaction identifier, up to 255 characters | | `unique_id` | History filter and records | The deposit/withdraw identifier in history responses | | `transactionId` | `refund-deposit` request, refund webhooks | Deposit transaction UUID, sourced from the `deposit.canceled` webhook | | `id` | `refund-deposit` response | The same deposit transaction UUID, echoed back — not a refund identifier | | `depositId` | `refund-history` filter and records | The same deposit transaction UUID | | `refundId` | `refund-history` records | The refund's own UUID, returned only by refund history | | `transaction_id` | History records | System-wide transaction UUID, never reused | Mark transactions complete only at terminal statuses: 3/7 for success, 4/9 for canceled deposits, 4 for canceled withdrawals. Platform availability is published at [status.whitebit.com](https://status.whitebit.com); per-asset deposit and withdrawal availability is reported by the [Asset Status](/api-reference/market-data/asset-status-list) endpoint. ## Failure and exception paths Build handling for each of these before go-live: | Scenario | Documented behavior | Partner action | | - | - | - | | SEPA deposit arrives without the `uniqueId` payment reference | The transfer cannot be matched to the deposit request automatically | Validate the reference field in the payment UX; unmatched settlements go through manual reconciliation with institutional support | | Deposit canceled (status 4 or 9) | The `deposit.canceled` webhook fires; canceled crypto deposits may be refundable | Trigger [`refund-deposit`](/api-reference/account-wallet/refund-deposit) with the transaction UUID; outcomes arrive as `refund.successful` or `refund.failed` | | Deposit unconfirmed by the user (status 5) | The transaction waits for manual confirmation on the platform | Notify the account operator; track the status via history polling | | Deposit frozen for AML review (status 21) | The record surfaces in the deposit history with the frozen status | Escalate to [institutional@whitebit.com](mailto:institutional@whitebit.com) if the freeze persists | | Deposit held for Travel Rule (status 27/28) | No webhook fires for Travel Rule transitions; the hold surfaces via history polling | Submit originator data via the [deposit verification endpoint](/api-reference/travel-rule/submit-deposit-verification) where the Travel Rule API is enabled; otherwise complete verification on the platform | | Partial fiat withdrawal (status 18, with `partialEnable`) | The withdrawal completes partially | Reconcile `requestAmount` against `processedAmount` and surface the remainder to operations | | Fiat withdrawal without KYC | The request fails validation with an account-verification error | Complete KYC, or arrange the exception-only override with the institutional team | | VISAMASTER invoice link opened without a `Referer` header | The end user lands on the WhiteBIT homepage instead of the payment provider | Test the redirect in the real delivery surface — messengers and email clients strip the header | ## What's next Activation, SEPA matching, fee semantics, reconciliation, and compliance questions. Endpoint-level lifecycle reference: statuses, fees, fiat operations, refunds. Pre-production readiness verification for keys, webhooks, and compliance. # On/Off-Ramp Source: https://docs.whitebit.com/guides/on-off-ramp-overview Move corporate funds between fiat and crypto on WhiteBIT: what the on/off-ramp integration provides, who it serves, the two-phase access model, the enablement gates, and how to get onboarded. The WhiteBIT on/off-ramp integration moves corporate funds between fiat and digital assets, in both directions — fiat in to crypto out, and crypto back to EUR — with all fiat operations at the partner's main account. For the flows, code, and reconciliation, see the [Integration guide](/guides/on-off-ramp-integration). The [On/Off-Ramp FAQ](/guides/on-off-ramp-faq) answers the common questions on activation, SEPA matching, fee semantics, reconciliation, and compliance. Adjacent scenarios route to separate guides: * The integration collects payments from end users or processes merchant flows — see [Payment Integration](/guides/payment-integration). * End customers hold dedicated accounts under a partner master account — see the [Embedded Trading integration guide](/guides/sub-account-integration). * For the full partner-type map, see [Partner Solutions](/guides/partner-solutions). ## What On/Off-Ramp provides * **Fiat deposits via API** — a hosted payment URL for SEPA bank transfer or card checkout, per the providers enabled for the account. * **Fiat withdrawals via API** — EUR payouts over IBAN (SEPA), plus card rails where enabled, each carrying a beneficiary record. * **Quoted-rate conversion** — a locked quote executed before the balance moves, so the rate is known up front. * **The crypto leg** — deposit addresses, withdrawals, and the refund flow. * **Reconciliation** — signed webhooks plus history polling with client-side identifiers. The [Integration guide](/guides/on-off-ramp-integration) documents each endpoint, the request bodies, and both directions. ## Who On/Off-Ramp is for * **Corporate crypto investors** — convert company treasury funds between EUR and digital assets on the main account. * **Businesses settling revenue over EUR rails** — move payouts or revenue between fiat and crypto without operating end-user accounts. * **Crypto-native companies with fiat obligations** — off-ramp digital assets to EUR to pay suppliers, payroll, or tax from the company bank account. * **Fiat-first companies funding on-chain operations** — on-ramp EUR to USDC or other digital assets for on-chain payouts, vendor settlement, or protocol operations on the main account. ## How it works Every flow authenticates with an [HMAC-signed API key](/api-reference/authentication) on the partner's main account. Crypto operations are available after standard account setup; fiat operations require completed [Institutional Onboarding](/institutional/onboarding) with approved fiat access — a separate, non-automatic phase after KYB. The [Integration guide](/guides/on-off-ramp-integration) covers both directions end to end: the fiat leg, the conversion step, and the crypto leg. ## Program terms Fee and limit figures are set per individual agreement, so no numbers appear in these pages. During onboarding, the account manager confirms: * The fee schedule for fiat deposits and withdrawals applicable to the account. * Deposit and withdrawal limits, for both fiat and crypto. * The enabled currency and provider matrix. At runtime, [Asset Status](/api-reference/market-data/asset-status-list) reports the per-currency `can_deposit` / `can_withdraw` flags and the request `provider` values; the [Fee](/api-reference/market-data/fee) endpoint reports the fees and limits per fiat asset. * Settlement windows and cutoff behavior for the fiat rails in use, including weekends and holidays. * The conversion pairs available to the account. ## Compliance essentials Compliance shapes which assets and flows are available to the account. The [Integration guide](/guides/on-off-ramp-integration) shows how each constraint affects requests; [Regulatory Compliance](/institutional/compliance) holds the full reference. * **MiCA (EEA):** EEA accounts cannot deposit, withdraw, or create WhiteBIT Codes in USDT since December 30, 2024. Use USDC or EURI for the crypto leg. See [Regulatory Compliance](/institutional/compliance). * **Travel Rule (EEA and Turkey):** inbound crypto deposits are held until Travel Rule verification completes; crypto withdrawals carry a Travel Rule payload. See [Travel Rule](/concepts/travel-rule). * **Fiat KYC:** fiat withdrawals require KYC verification. In exceptional, documented cases the institutional team can arrange a per-account override. ## How to get started Fiat access is the second phase of [Institutional Onboarding](/institutional/onboarding) and is not automatic after KYB approval. Phase 1 (corporate account, KYB, API keys) enables crypto operations; Phase 2 adds EUR/SEPA capabilities after review by a fiat processing partner, with source-of-funds documentation. WhiteBIT manages the fiat-partner onboarding on the applicant's behalf. **How to apply:** email **[institutional@whitebit.com](mailto:institutional@whitebit.com)** with a description of the service. Include the registered legal entity (name, registration number, jurisdiction), licenses or registrations held, whether the scope is crypto-only or fiat as well, and the countries where the service operates. The full application question list is on the [Partner Solutions](/guides/partner-solutions#how-to-apply) page. Fiat deposits and withdrawals operate at the partner's **main account** (institutional fiat access). Per-end-user fiat rails are not a standard shipped capability; confirm any such requirement with WhiteBIT before designing around it. Five capabilities in the ramp integration carry a dedicated enablement gate: | Capability | Gate | Contact | | - | - | - | | Fiat operations (Phase 2) | Institutional onboarding, fiat-partner review | [institutional@whitebit.com](mailto:institutional@whitebit.com) | | `fiat-deposit-url` endpoint | Per-account activation | WhiteBIT support, with the API key | | `successLink` / `failureLink` redirects | Feature activation, domain validated | WhiteBIT support | | Dedicated deposit addresses (`/create-new-address`) | Per-account permission | [support@whitebit.com](mailto:support@whitebit.com) | | Travel Rule API | Per-account enablement | Account manager or [institutional@whitebit.com](mailto:institutional@whitebit.com) | ## Support and contacts * **Onboarding status, limits, and institutional matters:** [institutional@whitebit.com](mailto:institutional@whitebit.com), or the assigned account manager once onboarded. * **Fiat endpoint enablement and access questions:** WhiteBIT support, with the API key included in the request. * **Dedicated deposit addresses:** [support@whitebit.com](mailto:support@whitebit.com). * **OTC block trading** for large conversions is part of the institutional catalog — see the [Institutional Overview](/institutional/overview). * **Self-service:** [help.whitebit.com](https://help.whitebit.com) for platform questions; this portal for API documentation. ## What's next The on-ramp and off-ramp flows, code, reconciliation, and failure paths. Activation, SEPA matching, fee semantics, reconciliation, and compliance questions. The two-phase KYB and fiat access process with the document checklist. # Order Parameter Rules Source: https://docs.whitebit.com/guides/order-parameter-rules Defines unsupported parameter combinations for order requests and explains related validation errors. ## Overview The guide describes parameter combinations the API does not support and explains how to resolve related errors. *** ## Retail Price Improvement (RPI) and IOC RPI orders use post-only behavior by design. An RPI order does not support the IOC flag. ### Issue A request sets both `rpi=true` and `ioc=true`. ### Result The API rejects the request and returns error code `40`. ### Fix Remove `ioc` when using `rpi`, or disable `rpi` when IOC behavior is required. *** ## IOC and post-only Immediate-or-cancel requests taker execution with the unfilled remainder canceled; post-only guarantees maker execution. The two flags request opposite behavior and cannot be combined. ### Issue A request sets both `ioc=true` and `postOnly=true`. ### Result The API rejects the request and returns error code `37`. The error payload is `{"ioc": ["Either IOC or PostOnly flag in true state is allowed."]}`. ### Fix Set at most one of `ioc` or `postOnly` per order. *** ## RPI and post-only RPI orders apply post-only behavior automatically. An explicit `postOnly=true` on an RPI order is rejected. ### Issue A request sets both `rpi=true` and `postOnly=true`. ### Result The API rejects the request with a validation error. ### Fix Send `rpi=true` without the `postOnly` flag. Post-only behavior is already guaranteed for RPI orders. *** ## RPI flag without account permission Sending `rpi=true` from a private-API source requires the [RPI](/glossary#retail-price-improvement-rpi) flag to be enabled on the account. ### Issue A request sets `rpi=true` from a private-API source, and the account does not have the RPI flag enabled. ### Result The API rejects the request and returns error code `43`. ### Fix Contact the account manager to enable the RPI flag. After enablement, retry the request. *** ## Retail flag without account permission Sending `retail=true` from a private-API source requires the [Retail flag](/glossary#retail-flag) to be enabled on the account. ### Issue A request to [`POST /api/v4/order/new`](/api-reference/trading/create-limit-order) or [`POST /api/v4/order/bulk`](/api-reference/trading/bulk-limit-order) sets `retail=true` from a private-API source, and the account does not have the Retail flag enabled. ### Result The API rejects the request and returns error code `42`. The error payload is `{"retail": ["api.validation.retail.not_allowed"]}`. ### Fix Contact the account manager to enable the Retail flag. After enablement, retry the request. *** ## BBO role and explicit price The `bboRole` parameter (available on [`POST /api/v4/order/new`](/api-reference/trading/create-limit-order), [`POST /api/v4/order/bulk`](/api-reference/trading/bulk-limit-order) items, and [`POST /api/v4/order/stop_limit`](/api-reference/trading/create-stop-limit-order)) tells the system to select the best bid/offer price instead of an explicit limit price: `1` = Queue method, `2` = Counterparty method. * `price` is required only when `bboRole` is not set. When `bboRole` is set, the BBO method determines the execution price. * `postOnly` is allowed only when `bboRole` is not set. * `ioc` can be combined with `bboRole` only under the Counterparty method (`2`). ### Issue A request omits `price` without setting `bboRole`, or combines `bboRole` with `postOnly`, or combines `bboRole` under the Queue method (`1`) with `ioc`. ### Result The API rejects the request with a validation error. When `price` is missing and `bboRole` is not set, the error payload names the `price` field (`"Price field is required."`). ### Fix Provide an explicit `price`, or set `bboRole` and drop the parameters that conflict with the selected method. # Partner FAQ Source: https://docs.whitebit.com/guides/partner-faq Cross-cutting questions common to every WhiteBIT partner program: onboarding and KYB, authentication and OAuth, test environments, fees, and rate limits. Questions common to every WhiteBIT partner program. For program-specific questions, see the FAQ on each program funnel. ## Onboarding and eligibility ### Partner onboarding and KYB Partner programs are approval-gated: every application is individually reviewed, and institutional onboarding completes KYB of the company plus KYC of the responsible person before provisioning. See [Institutional Onboarding](/institutional/onboarding). ### Where to apply Program applications go to `institutional@whitebit.com` with the registered legal entity, licenses held, the intended account structure, who performs end-customer verification, and the countries served. The full intake list is on [Partner Solutions](/guides/partner-solutions#how-to-apply). ### Choosing an integration path Partner labels overlap, so routing is by structure: who holds the end user's account and who performs verification. See [Partner Solutions](/guides/partner-solutions) and the [integration models](/concepts/integration-models) concept. ## Authentication ### Primary authentication method The primary method is an HMAC-SHA512-signed API key, sent with the `X-TXC-APIKEY`, `X-TXC-PAYLOAD`, and `X-TXC-SIGNATURE` headers. See [First API Call](/guides/first-api-call). ### Acting on a customer's own account Partners act on a customer's own account through the OAuth-based [Fast API Key](/guides/fast-api-key-integration) flow, which issues a user-scoped key from the WhiteBIT consent screen. ### OAuth status Fast API Key is live. The classic OAuth 2.0 Authorization Code Grant flow for direct account-data access is deprecated and scheduled for removal on November 1, 2026. See [OAuth 2.0](/platform/oauth/overview). ## Test environments ### Sandbox availability WhiteBIT does not offer a public testnet or sandbox. Test on the live API with minimum order sizes and low-minimum assets; Demo Tokens are available for risk-free spot practice. See the [Go-Live Checklist](/best-practices/go-live-checklist). ## Fees and terms ### Program fees and revenue share Fee schedules and revenue-share terms are set per program and agreed individually during onboarding; the applicable figures are on each program overview and the canonical program pages. See [Partner Solutions](/guides/partner-solutions#program-terms-and-security). ## Rate limits ### How rate limits are applied Rate limits are set per scope and per endpoint rather than as a single global value, and are counted per IP address. See [Rate Limits](/api-reference/rate-limits). ## Regions and base URL ### API base URL The global REST base URL is `https://whitebit.com`. Regional environment options are confirmed during onboarding. See [First API Call](/guides/first-api-call). ## What's next Route to the right program funnel. Make a public call, then add HMAC signing for authenticated endpoints. # Partner Solutions Source: https://docs.whitebit.com/guides/partner-solutions Route each partner type — account operators, market makers, payments, wallets, app builders, and institutions — to the right WhiteBIT integration path. WhiteBIT partners integrate through program funnels — one per partner type. Pick a partner type from the cards, or use the three structural questions to route an overlapping label. Each path leads to a program overview, an integration guide, and a program FAQ. Partner programs are approval-gated — see [How to apply](#how-to-apply). ## Choose an integration path Per-customer sub-accounts under a partner master — account isolation, per-customer API keys, and fee share on referred trading. Maker rebates, colocation infrastructure, and bulk-order capabilities through the Market-Making Program. Deposits, payouts, and merchant flows — plus corporate on/off-ramp between fiat and crypto. Place WhiteBIT behind the partner product as the wallet, custody, and settlement building block. A full white-label exchange delivered as a dedicated, custom-branded instance. Offer Crypto Lending yield to end users, each in a segregated sub-account. Copy trading, trading bots, and portfolio apps built over users' own accounts via a partner-held API key. OTC, portfolio margin, custody, and venue listings for funds, desks, banks, and exchanges. Partner labels overlap (a single business can span two different architectures), so the fastest routing comes from three structural questions: 1. **Account holding** — do end users hold personal WhiteBIT accounts, or does the partner operate accounts on the end users' behalf? Own accounts with a partner-held API key are **Model B** → [App Builders](/guides/app-builders-overview). Partner-operated [sub-accounts](/products/sub-accounts/overview) are **Model A** → [Embedded Trading](/guides/embedded-trading-overview). Compare the two models on the [integration models](/concepts/integration-models) concept; building a full backend instead of a single account model → compare [Wallet-as-a-Service](/guides/waas-overview) and [Crypto-as-a-Service](/guides/caas-overview). 2. **Direction** — is the partner building on the WhiteBIT API, or proposing WhiteBIT integrate into an external platform or network? The latter is a partnership conversation — contact `institutional@whitebit.com` directly (see [Funds & Institutions](/institutional/overview)). 3. **Scope** — trading, payments, or both? Payment and payout integrations route to [Payments & Fiat](/guides/payments-overview) regardless of the answers above. Common use cases mapped to a program: | Use case | Program | | - | - | | Copy trading, trading bots, portfolio apps (users keep own accounts) | [App Builders](/guides/app-builders-overview) | | Hosted customer accounts under a partner master | [Embedded Trading](/guides/embedded-trading-overview) | | Wallets, neobanks (add wallet or payout capability) | [Wallet-as-a-Service](/guides/waas-overview) | | Branded white-label exchange under the partner's own brand | [Crypto-as-a-Service](/guides/caas-overview) | | Offer yield/earn to end users (Crypto Lending) | [Yield-as-a-Service](/guides/yaas-overview) | | Payment gateways, payouts, merchant flows | [Payments & Fiat](/guides/payments-overview) | | Corporate on/off-ramp (own-account fiat ↔ crypto) | [Payments & Fiat](/guides/payments-overview) | | Market making | [Market Makers](/guides/market-maker-overview) | | Price aggregators and market-data consumers (public data, no API key) | [Market Data](/products/market-data/overview) | | Order/execution management systems (OEMS) and connectivity networks listing WhiteBIT as a venue | [Funds & Institutions](/institutional/overview) | | Inviting WhiteBIT into an external platform or network | `institutional@whitebit.com` | ## REST vs. WebSocket decision matrix | Use case | Recommended | Reason | | - | - | - | | Live prices | WebSocket | Streaming push, no polling | | Orderbook depth | WebSocket | Real-time depth updates | | Place / modify / cancel orders | REST or WebSocket | Request–response over REST; single-connection placement over WebSocket | | Monitor balances | WebSocket | Real-time balance updates | | Fetch historical trades | REST API | One-time queries, paginated | | Check open orders | REST or WebSocket | REST for on-demand; WebSocket for real-time | Order placement runs over REST for request–response confirmation and atomic bulk placement; the [WebSocket order methods](/websocket/order-management/overview) add an alternative on the same authorized connection, on the global platform only. Combining REST for order management with WebSocket for market data remains the most common integration pattern. See the [WebSocket API](/websocket/overview) for the available channels and the [API Reference](/api-reference/overview) for endpoint details. ## How to apply Partner-program applications go to `institutional@whitebit.com` and are individually reviewed before provisioning. Including the following in the first message routes the application to the right team without extra clarification rounds: **About the company (all applicants):** 1. Registered legal entity — full legal name, registration number, and jurisdiction (not a brand or product name). 2. Licenses or registrations held, with the regulator and register reference. Unlicensed platforms qualify for models where WhiteBIT verifies end users directly; KYC reliance is separately gated — see the [Wallet-as-a-Service](/guides/waas-overview) page for the eligibility conditions. 3. Application capacity — the applicant's own behalf or on behalf of a client — and the intended contracting counterparty. **About the integration (all applicants):** 4. Direction — building on the WhiteBIT API, or proposing WhiteBIT integrate into an external platform or network (the latter is a partnership conversation rather than an application). 5. Intended account structure: (a) own main account only; (b) end users' own WhiteBIT accounts with a partner-held API key; (c) per-customer sub-accounts under the partner's master (main) account; (d) a pooled (omnibus) structure — a pooled account for end-user funds is not offered, but declaring the intent lets WhiteBIT propose the closest supported model (see [why not a pooled account](/concepts/integration-models#why-not-a-pooled-account)). 6. Scope — crypto only, or fiat as well, and at which level (partner account or end users). **About end users (partners serving end users):** 7. The party performing end-user KYC — the partner or WhiteBIT — and, for partner-side KYC, the supervisory basis. 8. The user population reached — direct clients, or customers of the partner's merchants or clients — and the business vertical. 9. The countries where the service is offered or marketed, and the geo-gating approach (how the service restricts availability by user country or region). 10. For sub-account requests: settlement topology — per-customer deposit addresses, or deposits and withdrawals concentrated at the master account with internal allocation. ## Program terms and security Program terms — revenue share and eligibility — differ by program; the specific band and how the share is reported are on each program overview. Security certifications apply platform-wide. Revenue-share terms depend on the program. Embedded Trading partners earn a share of the trading fees that referred customers generate across all products, with payouts initiated by the partner, most commonly once per month — see [WhiteBIT Embedded Trading](https://institutional.whitebit.com/broker-program) for current rates. Other partner programs confirm commercial terms during onboarding. ## What's next The most-integrated program — the starting point for operating customer accounts. Cross-cutting answers on KYB, sandbox access, fees, and rate limits. Make a public call, then add HMAC signing for authenticated endpoints. # Payment Integration Source: https://docs.whitebit.com/guides/payment-integration Crypto deposits, withdrawals, withdrawals with currency conversion, fiat operations (SEPA and card providers), WhiteBIT Codes, and Express Withdraw payments — status state machines, fee calculation, and webhook reconciliation. Move funds into and out of WhiteBIT programmatically: generate deposit addresses, submit crypto and fiat withdrawals, convert between currencies before withdrawing, settle between accounts with WhiteBIT Codes, and charge a WhiteBIT user's balance with Express Withdraw. Each flow documents the transaction lifecycle, status state machine, fee calculation, and webhook events, where each applies. **EEA users:** USDT deposits and withdrawals have been unavailable since December 30, 2024 (MiCA compliance). Use USDC or EURI as alternatives. See [Regulatory Compliance](/institutional/compliance) for details. ## Prerequisites Before integrating any flow on this page: * **API key** — create an API key with the required permissions in the WhiteBIT dashboard. Every endpoint on this page requires [HMAC-signed requests](/api-reference/authentication) (`X-TXC-APIKEY`, `X-TXC-PAYLOAD`, `X-TXC-SIGNATURE` headers). Store the secret per [Security Best Practices](/best-practices/security). * **Webhook URL** — configure the webhook endpoint to receive transaction notifications. See [Webhooks](/platform/webhook) for the setup flow. * **Fiat access** — fiat operations additionally require completed [institutional onboarding](/institutional/onboarding) with approved fiat access. ## Use cases Four scenarios cover the most common partner integrations. Each closes with a link to the section documenting the endpoints. ### UC1 — Payment provider with per-end-user deposit address A payment-provider partner assigns each end customer a unique deposit address and credits the customer's account when funds arrive. Reconciliation is webhook-driven by `uniqueId` (each deposit address corresponds to one customer in the partner's database). ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram autonumber participant P as Partner backend participant U as End user participant W as WhiteBIT API participant B as Blockchain P->>W: POST /api/v4/main-account/create-new-address W-->>P: 201 — unique address (+ memo if applicable) P->>U: Show deposit address + QR U->>B: Send funds to address B-->>W: Deposit detected W->>P: webhook: deposit.accepted (status 15) W->>P: webhook: deposit.updated (confirmation count) W->>P: webhook: deposit.processed (status 3 — terminal) P->>P: Match by address / uniqueId → credit customer ``` See [Deposit address generation](#deposit-address-generation) for endpoint detail. ### UC2 — EEA crypto withdrawal with Travel Rule A partner serving EEA end users submits withdrawals with the required `travelRule` object. The withdrawal goes through compliance review before on-chain broadcast. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram autonumber participant P as Partner backend participant U as End user (EEA, withdrawal destination) participant W as WhiteBIT API participant C as Compliance participant V as Destination VASP Note over P,W: Travel Rule applies to all crypto withdrawals from EEA accounts. U->>P: Provide destination address + beneficiary details P->>W: POST /api/v4/main-account/withdraw with Travel Rule data Note right of P: Travel Rule data: wallet type,
beneficiary, VASP identification W-->>P: HTTP 201 — withdrawal created W->>P: webhook: withdraw.unconfirmed W->>C: Review beneficiary data alt Approved C-->>W: Approved W->>P: webhook: withdraw.pending (status in 1, 2, 6, 10–17) W->>V: On-chain broadcast to destination VASP wallet W->>P: webhook: withdraw.successful (status 3 — terminal) P->>P: Reconcile by unique identifier → mark customer withdrawal complete else Rejected C-->>W: Rejected W->>P: webhook: withdraw.canceled (status 4) P->>P: Notify end user — Travel Rule data rejected end ``` See [Create a withdrawal](#create-a-withdrawal) for endpoint detail. ### UC3 — Crypto payout with conversion When the partner holds one currency in Main balance but needs to send another, request a conversion quote, confirm it, and submit the withdrawal. The convert service handles balance routing internally; no manual Main↔Trade transfers are required. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram autonumber participant P as Partner backend participant W as WhiteBIT API participant B as Blockchain P->>W: POST /api/v4/main-account/balance W-->>P: Available balance P->>W: POST /api/v4/convert/estimate W-->>P: Quote identifier + rate + expiry P->>W: POST /api/v4/convert/confirm W-->>P: Converted amount P->>W: POST /api/v4/main-account/withdraw (converted currency, destination address) W-->>P: HTTP 201 W->>B: On-chain broadcast W->>P: webhook: withdraw.successful (terminal) ``` See [Conversion in the withdrawal flow](#conversion-in-the-withdrawal-flow) for endpoint detail. ### UC4 — Charge a WhiteBIT user's balance (Express Withdraw) A merchant or partner service collects a crypto payment from a WhiteBIT user's balance instantly and off-chain: the partner creates a single-use payment token, presents the returned URL, and the user confirms in one tap. Settlement is an internal zero-fee transfer into the partner's Main balance. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram autonumber participant P as Partner backend participant U as End user (payer) participant W as WhiteBIT P->>W: POST /api/v4/main-account/express-withdraw/token W-->>P: 201 — payment URL + expiry (token valid 90 seconds) P->>U: Present URL (redirect, deep link, or QR) U->>W: Open URL — WhiteBIT shows ticker + amount U->>W: Confirm payment W->>W: Internal transfer: user balance → partner Main balance (0 fee, off-chain) W-->>P: Funds credited, token marked used ``` See [Express Withdraw payments](#express-withdraw-payments) for endpoint detail. ## Crypto deposits Generate deposit addresses, track the deposit lifecycle, handle refunds, and clear Travel Rule holds. ## Deposit address generation Generate a deposit address by calling `POST /api/v4/main-account/address`. See the [API Reference](/api-reference/account-wallet/get-cryptocurrency-deposit-address) for the full endpoint specification. **Required parameters:** | Parameter | Type | Description | | - | - | - | | `ticker` | string | Currency ticker (e.g., `BTC`, `ETH`). The currency must have `can_deposit: true` in the [Asset Status](/api-reference/market-data/asset-status-list) response. | **Optional parameters:** `network` — cryptocurrency network (e.g., `ERC20`, `TRC20`). Required for multi-network currencies like USDT; omit for single-network currencies. Query the [Asset Status](/api-reference/market-data/asset-status-list) endpoint for available networks per currency. The endpoint returns the same address for the same ticker and network combination on repeated calls — addresses are permanent and reusable, not ephemeral. **Key response fields:** `account.address`, `account.memo` (for currencies requiring a memo or destination tag), `required.fixedFee`, `required.flexFee`, `required.minAmount`, `required.maxAmount`. **Rate limit:** subject to platform-level rate limits — see [Rate Limits](/api-reference/rate-limits) for current enforced values. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Generate a BTC deposit address curl -X POST "https://whitebit.com/api/v4/main-account/address" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "BTC", "request": "/api/v4/main-account/address", "nonce": 1594297865000 }' # Generate an ERC20 USDT deposit address curl -X POST "https://whitebit.com/api/v4/main-account/address" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "USDT", "network": "ERC20", "request": "/api/v4/main-account/address", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import hashlib import hmac import json import time import base64 import requests API_KEY = "YOUR_API_KEY" API_SECRET = "YOUR_SECRET" BASE_URL = "https://whitebit.com" def send_request(endpoint, payload): payload["request"] = endpoint payload["nonce"] = int(time.time() * 1000) body = json.dumps(payload) encoded = base64.b64encode(body.encode()).decode() signature = hmac.new( API_SECRET.encode(), encoded.encode(), hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": encoded, "X-TXC-SIGNATURE": signature, } return requests.post(f"{BASE_URL}{endpoint}", headers=headers, data=body) # Generate a BTC deposit address response = send_request("/api/v4/main-account/address", {"ticker": "BTC"}) print(response.json()) # Generate an ERC20 USDT deposit address response = send_request( "/api/v4/main-account/address", {"ticker": "USDT", "network": "ERC20"} ) print(response.json()) ``` For Go and PHP examples, see [SDKs](/sdks). ## Unique address per user The `POST /api/v4/main-account/address` endpoint above returns the same address for the same ticker and network combination on every call. For payment provider integrations that assign a unique deposit address per end user, use `POST /api/v4/main-account/create-new-address` instead — this endpoint generates a fresh address on every call. See the [API Reference](/api-reference/account-wallet/create-new-address-for-deposit) for the full specification. The `/create-new-address` endpoint is not available by default. Contact [support@whitebit.com](mailto:support@whitebit.com) to request access. For sub-accounts, crypto deposits are disabled by default. To enable deposits, contact the assigned Account Manager or [institutional@whitebit.com](mailto:institutional@whitebit.com). **Required parameters:** | Parameter | Type | Description | | - | - | - | | `ticker` | string | Currency ticker (e.g., `BTC`, `ETH`) | **Optional parameters:** `network` (required for multi-network currencies; for USDT the default network is `ERC20`), `type` (address type for currencies that support several formats — BTC and LTC accept `p2sh-segwit` and `bech32`; the default is `bech32`). **Rate limit:** subject to platform-level rate limits — see [Rate Limits](/api-reference/rate-limits) for current enforced values. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Generate a unique BTC deposit address curl -X POST "https://whitebit.com/api/v4/main-account/create-new-address" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "BTC", "request": "/api/v4/main-account/create-new-address", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Generate a unique BTC deposit address response = send_request("/api/v4/main-account/create-new-address", { "ticker": "BTC", }) address = response.json() print("New address:", address["account"]["address"]) ``` **Choosing between the two endpoints:** The choice depends on the partner's reconciliation model. Partners managing one consolidated wallet per asset (treasury, market-maker, single-merchant) use `/address`; repeat calls return the same address. Partners assigning one address per end customer (payment provider, per-user wallet) use `/create-new-address`; each call returns a fresh address, so an incoming deposit identifies the end user by address alone. | Endpoint | Behavior | Best for | | - | - | - | | `POST /api/v4/main-account/address` | Returns the same address for the same ticker + network | Single-wallet setups, treasury management | | `POST /api/v4/main-account/create-new-address` | Generates a new address on every call | Payment providers assigning one address per end user | ## Deposit lifecycle After funds arrive at a generated deposit address, the deposit passes through a defined sequence of states before crediting to the Main balance. 1. Address generated (`POST /api/v4/main-account/address`) 2. Funds sent by the external party — mempool detection begins 3. Confirmation tracking begins — `deposit.accepted` webhook fires while `confirmations.actual` is below `confirmations.required` 4. Each confirmation-count change fires the `deposit.updated` webhook with the new `confirmations.actual` — this event tracks progress; it does not signal completion 5. Deposit credited to Main balance — `deposit.processed` webhook fires — **terminal success state** 6. OR: Deposit canceled — `deposit.canceled` webhook fires — **terminal failure state** 7. OR (EEA/Turkey): Travel Rule hold — deposit frozen (status 27 or 28). If the Travel Rule API is enabled, submit originator data via API to unfreeze; otherwise manual action at whitebit.com is required. See [Travel Rule](#travel-rule-eea-and-turkey) below. ## Deposit status state machine The deposit/withdraw history endpoint returns numeric status codes. The following table maps each code to the meaning and the corresponding webhook event. Numeric status codes are namespaced by `transactionMethod`. The same code may mean different things for deposits (`transactionMethod: 1`) and withdrawals (`transactionMethod: 2`). Always interpret the code in the context of the `transactionMethod` that returned it. | Status | State | Webhook | Terminal? | Partner action | Description | | - | - | - | - | - | - | | 15 | Pending | `deposit.accepted` | No | Wait for next webhook | Deposit detected, awaiting confirmations | | 15 | Updated | `deposit.updated` | No | Wait for next webhook | Confirmation count changed | | 3, 7 | Successful | `deposit.processed` | Yes | Credit end user, close watcher | Funds credited to Main balance | | 4, 9 | Canceled | `deposit.canceled` | Yes | Surface refund flow — see [Refund flow](#refund-flow) | Deposit canceled (refund may be available) | | 5 | Unconfirmed by user | — | No | Notify end user — manual action required at whitebit.com | Awaiting user action | | 21 | AML frozen | — | No | Wait — under compliance review. Escalate to institutional team if >24h | Deposit frozen by AML controls | | 22 | Uncredited | — | No | Wait — credit pending. Escalate to support if >24h | Detected but not credited | | 27 | Travel Rule frozen | — | No | Notify end user — Travel Rule data required at whitebit.com | Awaiting Travel Rule data (EEA / Turkey) | | 28 | Travel Rule processing | — | No | Wait — Travel Rule data under review | Travel Rule data submitted | Use `POST /api/v4/main-account/history` with `transactionMethod: 1` and `status` filter to poll for deposits in specific states. See the [endpoint page](/api-reference/account-wallet/get-deposit-withdraw-history) for the current enforced rate limit. ## Network confirmations Each cryptocurrency network requires a different number of block confirmations before the platform credits a deposit. Webhook payloads include `confirmations.actual` and `confirmations.required` fields — the `confirmations.required` value determines when the deposit completes. Query the [Asset Status](/api-reference/market-data/asset-status-list) endpoint (`GET /api/v4/public/assets`) for per-currency confirmation requirements. Confirmation requirements vary by currency and network. Do not hardcode specific numbers — always retrieve the current values from the Asset Status endpoint. ## Partial / over-payment scenarios Crypto deposits credit the actual on-chain amount received; the system does not flag deposits as "underpaid" or "overpaid". If a partner expects an exact amount (e.g., for invoice matching), reconciliation logic must compare the deposit amount in the `deposit.processed` webhook against the expected amount and surface mismatches as application-level alerts. ## Refund flow When a deposit is canceled (status 4 or 9), a refund may be available. **Endpoint:** `POST /api/v4/main-account/refund-deposit` — see the [API Reference](/api-reference/account-wallet/refund-deposit) for the full specification. **Prerequisites:** * The deposit must have status `canceled`. * Obtain `transactionId` from the `deposit.canceled` webhook (`uniqueId` field) or from the deposit/withdraw history in the WhiteBIT interface. **Parameters:** | Parameter | Type | Required | Description | | - | - | - | - | | `transactionId` | string | Yes | Transaction UUID of the canceled deposit. | | `address` | string | Yes | Destination wallet address for the refund. | | `memo` | string | No | Destination [memo](/glossary#memodestination-tag) for the refund address. Without it, the refund goes to the address with no memo. | The refund `address` must satisfy three constraints: * The address must support the same network and asset as the original deposit. * The address must not be a WhiteBIT-generated deposit address (an address created by `/api/v4/main-account/address` or `/api/v4/main-account/create-new-address`) — the endpoint refunds to external addresses only. * The address does not need to match the original sender address. **Webhook events for refund outcomes:** * `refund.successful` — refund completed (includes `refundAmount`, `refundNetworkFee`, `refundHash`) * `refund.failed` — refund failed (the destination address does not support the required network or asset, or address validation fails; use a different address or contact support) **Track refund status:** [`POST /api/v4/main-account/refund-history`](/api-reference/account-wallet/get-refund-history) returns every refund on the account with its current status. A refund with status `canceled` is final. A refund with status `in_process` is not final yet, including after a `refund.failed` webhook caused by an internal failure. Filter by `depositId` to check one deposit. **Rate limit:** subject to platform-level rate limits — see [Rate Limits](/api-reference/rate-limits) for current enforced values. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST "https://whitebit.com/api/v4/main-account/refund-deposit" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "transactionId": "5e112b38-9e12-4345-a1b2-c3d4e5f67890", "address": "bc1qRefundAddress1234567890abcdef", "request": "/api/v4/main-account/refund-deposit", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} response = send_request("/api/v4/main-account/refund-deposit", { "transactionId": "5e112b38-9e12-4345-a1b2-c3d4e5f67890", "address": "bc1qRefundAddress1234567890abcdef", }) print(response.json()) ``` ## Required endpoints for deposits | Endpoint | Purpose | API Reference | | - | - | - | | `POST /api/v4/main-account/create-new-address` | Generate a unique deposit address per user | [Create New Address](/api-reference/account-wallet/create-new-address-for-deposit) | | Webhooks (`deposit.accepted`, `deposit.updated`, `deposit.processed`) | Deposit status notifications | [Webhooks](/platform/webhook) | | `POST /api/v4/main-account/refund-deposit` | Refund a canceled deposit | [Refund Deposit](/api-reference/account-wallet/refund-deposit) | | `POST /api/v4/main-account/refund-history` | Track refund status | [Get Refund History](/api-reference/account-wallet/get-refund-history) | | `POST /api/v4/main-account/history` | Query deposit and withdrawal history | [History](/api-reference/account-wallet/get-deposit-withdraw-history) | | `POST /api/v4/main-account/balance` | Check Main balance | [Main Balance](/api-reference/account-wallet/main-balance) | | `POST /api/v4/main-account/withdrawable-balance` | Check how much is withdrawable while deposits await confirmation | [Withdrawable Balance](/api-reference/account-wallet/withdrawable-balance) | | `POST /api/v4/main-account/fee` | Available currencies, networks, and deposit limits | [Get Fees](/api-reference/account-wallet/get-fees) | For integrations that use a single persistent deposit address instead of unique addresses per user, substitute `POST /api/v4/main-account/address` ([API Reference](/api-reference/account-wallet/get-cryptocurrency-deposit-address)) for the `/create-new-address` endpoint. ## Travel Rule (EEA and Turkey) Since May 18, 2025, WhiteBIT places inbound crypto deposits for EEA and Turkey accounts on hold until Travel Rule verification completes. * **Status 27** (`DEPOSIT_TRAVEL_RULE_FROZEN`): deposit frozen, awaiting Travel Rule data from the account holder * **Status 28** (`DEPOSIT_TRAVEL_RULE_FROZEN_PROCESSING`): Travel Rule data submitted, under review by WhiteBIT **API-based verification:** When the Travel Rule API is enabled for the account, partners can submit originator data via `POST /api/v4/travel-rule/deposit/verification` to unfreeze deposits programmatically. See [Travel Rule](/concepts/travel-rule) for the full verification flow and request format. **Manual verification fallback:** If the Travel Rule API is not enabled for the account, frozen deposits require manual action at whitebit.com. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) to request Travel Rule API access. See [Regulatory Compliance](/institutional/compliance) for the full Travel Rule reference. See the [Travel Rule help center article](https://help.whitebit.com/hc/en-gb/articles/24093241373341-Travel-Rule-Requirements-Updates-to-Crypto-Withdrawals-Interface-and-API) for the complete requirements. ## Crypto withdrawals Submit crypto withdrawals, attach the Travel Rule payload for EEA accounts, and follow the withdrawal state machine and fee model. ## Create a withdrawal Submit a crypto withdrawal by calling `POST /api/v4/main-account/withdraw`. See the [API Reference](/api-reference/account-wallet/create-withdraw-request) for the full endpoint specification. Two withdrawal endpoints are available: | Endpoint | Fee Handling | | - | - | | `POST /api/v4/main-account/withdraw` | Amount **includes** the fee — the receiver gets `amount - fee` | | `POST /api/v4/main-account/withdraw-pay` | Amount **excludes** the fee — the receiver gets the exact amount specified; the platform charges the fee on top | Crypto withdrawals cannot be reversed once broadcast on-chain. Verify the destination address and network before submitting the request — funds sent to a wrong address or an incompatible network are lost. **Internal-transfer routing:** When the destination `address` belongs to another WhiteBIT user, the platform may route the transfer as an internal off-chain transfer rather than an on-chain broadcast, in which case no blockchain fee applies and the recipient sees the funds immediately. This routing is not guaranteed for every destination — confirm the behavior with WhiteBIT for the specific flow before designing around fee-free instant settlement, or funds may settle on-chain with the standard fee. For deterministic fee-free settlement between known WhiteBIT accounts, use [WhiteBIT Codes](#whitebit-codes-overview) rather than relying on withdrawal auto-routing. **Required parameters:** | Parameter | Type | Description | | - | - | - | | `ticker` | string | Currency ticker (e.g., `BTC`, `ETH`) | | `amount` | string | Withdrawal amount | | `address` | string | Destination wallet address | | `uniqueId` | string | Unique transaction identifier — any unique string up to 255 characters per request. The endpoint does not validate the value as a UUID. | **Optional parameters:** `network` (required for multi-network currencies), `memo` (for currencies requiring a memo or destination tag). **Rate limit:** subject to platform-level rate limits — see [Rate Limits](/api-reference/rate-limits) for current enforced values. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST "https://whitebit.com/api/v4/main-account/withdraw" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "BTC", "amount": "0.001", "address": "bc1qExample1234567890abcdef", "uniqueId": "order-12345-btc-001", "request": "/api/v4/main-account/withdraw", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} response = send_request("/api/v4/main-account/withdraw", { "ticker": "BTC", "amount": "0.001", "address": "bc1qExample1234567890abcdef", "uniqueId": "order-12345-btc-001", }) print(response.json()) ``` ## Travel Rule for EEA withdrawals Crypto withdrawals from EEA accounts require a `travelRule` object in the request body. The object identifies the destination wallet and, for hosted wallets, the destination VASP (Virtual Asset Service Provider — the exchange or custodian hosting the receiving wallet). ### Structured format (recommended) | Field | Type | Description | | - | - | - | | `walletType` | string | `"hosted"` (VASP-hosted) or `"unhosted"` (self-custody) | | `beneficiary` | object | Beneficiary details (`type`, `firstName`/`lastName` or `fullName`, `residenceCountry`, `address`) | | `vaspData` | object | VASP identification (`vaspId` or `vaspName`) — required when `walletType` is `"hosted"` | See [Travel Rule](/concepts/travel-rule) for the full schema reference and request examples. ### Legacy format (deprecated) The platform still accepts the legacy flat format, but legacy submissions **do not pass Travel Rule verification**. Migrate to the structured format above for compliance. | Field | Type | Description | | - | - | - | | `type` | string | `"individual"` or `"entity"` — the receiver type | | `vasp` | string | Destination platform (VASP) name (e.g., `"Binance"`) | | `name` | string | If individual: first name. If entity: entity name. | | `address` | string | If individual: last name. If entity: entity address. | See [Travel Rule — Legacy format](/concepts/travel-rule#legacy-format-withdrawals-only) for migration guidance. ## Withdrawal confirmation model After a withdrawal request is submitted, the system validates the request and begins processing. The `POST /api/v4/main-account/withdraw` endpoint returns HTTP 201 when validation succeeds. **The platform confirms and processes API-initiated withdrawals immediately** — the signed request is the authentication. There is no interactive 2FA step between the POST response and the processing start. **Exceptions to immediate processing:** * **Sub-account withdrawals** wait for main-account approval before processing. * **Withdrawals to AML-blocked destination addresses** freeze pending compliance review. * **Temporary withdrawal freeze (3 days)** applies after a password reset or a 2FA setting change on the account. Status transitions follow the state machine below: unconfirmed → pending → successful or canceled. Webhook events track the full lifecycle. A revised confirmation model for IP-whitelisted API keys is planned but not yet deployed. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) for availability. ## Withdrawal status state machine The withdrawal lifecycle progresses through the following states. | Status | State | Webhook | Terminal? | Partner action | Description | | - | - | - | - | - | - | | — | Unconfirmed | `withdraw.unconfirmed` | No | Wait for next webhook | Withdrawal created | | 1, 2, 6, 10–17 | Pending | `withdraw.pending` | No | Wait for next webhook | Withdrawal in progress (all codes in range indicate active pending) | | 3, 7 | Successful | `withdraw.successful` | Yes | Mark complete, close watcher | Withdrawal completed, funds sent | | 4 | Canceled | `withdraw.canceled` | Yes | Surface to operations | Withdrawal canceled | | 5 | Unconfirmed by user | — | No | Notify end user — manual action required | Awaiting user action | | 18 | Partially successful | `withdraw.partial_successful` | No | Reconcile against `requestAmount` / `processedAmount`; surface remainder to operations | Part of the withdrawal succeeded (fiat with `partialEnable: true`) | | 21 | AML frozen | — | No | Wait — under compliance review. Escalate to institutional team if >24h | Withdrawal frozen by AML controls | ## Fee calculation Withdrawal fees combine a fixed component and a flexible (percentage-based) component. **Fee model** (sourced from the deposit address endpoint response and the [Asset Status](/api-reference/market-data/asset-status-list) endpoint): * `fixedFee` — flat fee charged regardless of amount * `flexFee` — percentage-based fee with floor and ceiling: * `percent` — percentage rate * `minFee` — minimum fee (floor) * `maxFee` — maximum fee (ceiling) **Fee calculation formula:** ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} percentFee = amount * (percent / 100) flexComponent = clamp(percentFee, minFee, maxFee) totalFee = fixedFee + flexComponent ``` If `maxFee` is `"0"`, no ceiling applies. **Worked example — BTC withdrawal of 0.5 BTC:** ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} fixedFee = 0.0004 BTC flexFee: percent = 0, minFee = 0, maxFee = 0 percentFee = 0.5 * 0 = 0 flexComponent = clamp(0, 0, 0) = 0 totalFee = 0.0004 + 0 = 0.0004 BTC Using /withdraw: Sender sends 0.5 BTC, receiver gets 0.5 - 0.0004 = 0.4996 BTC Using /withdraw-pay: Sender pays 0.5004 BTC, receiver gets 0.5 BTC ``` Fee parameters vary by currency and network. Query the Asset Status endpoint (`GET /api/v4/public/assets`) for current fee values. ## Required endpoints for withdrawals | Endpoint | Purpose | API Reference | | - | - | - | | `POST /api/v4/main-account/balance` | Check Main balance before withdrawal | [Main Balance](/api-reference/account-wallet/main-balance) | | `POST /api/v4/travel-rule/vasps` | Get available VASPs for Travel Rule (EEA withdrawals) | [Get VASPs](/api-reference/travel-rule/get-vasps) | | `POST /api/v4/main-account/withdraw` or `/withdraw-pay` | Create a withdrawal request | [Create Withdraw](/api-reference/account-wallet/create-withdraw-request) | | Webhooks (`withdraw.unconfirmed`, `withdraw.pending`, `withdraw.successful`, `withdraw.canceled`) | Withdrawal status notifications | [Webhooks](/platform/webhook) | | `POST /api/v4/main-account/history` | Query deposit and withdrawal history | [History](/api-reference/account-wallet/get-deposit-withdraw-history) | | `POST /api/v4/main-account/fee` | Available currencies, networks, and withdrawal limits | [Get Fees](/api-reference/account-wallet/get-fees) | For withdrawals that include currency conversion before sending, see [Withdrawal with conversion](#withdrawal-with-conversion) for the extended endpoint list. ## Fiat operations Generate fiat deposit invoices and submit fiat withdrawals once institutional fiat access is approved. ## Prerequisites for fiat operations Fiat deposit and withdrawal operations require completion of institutional onboarding with approved fiat access. **This flow applies to the institutional partner's master account.** For sub-account fiat scope and constraints under Embedded Trading, see the [Embedded Trading integration guide](/guides/sub-account-integration). Fiat operations require completion of institutional onboarding including business verification (KYB) and fiat provider approval. See [Institutional Onboarding](/institutional/onboarding) for the full two-phase process. Fiat endpoints are not available until WhiteBIT explicitly approves fiat access. The onboarding process has two phases: Phase 1 (crypto access via KYB) and Phase 2 (fiat access via fiat processing partner review). Fiat access is **not** automatic after KYB approval — a separate review process with the fiat processing partner is required. ## Fiat deposit The fiat deposit flow is invoice-based: generate a payment URL, hand it to the end user, and reconcile the settlement. Call `POST /api/v4/main-account/fiat-deposit-url` with the fiat ticker, amount, provider, and a partner-side `uniqueId`. The response contains a `url`. See the [API Reference](/api-reference/account-wallet/get-fiat-deposit-url) for the full specification. The end user opens the returned URL and completes the payment with the provider or bank. The bank-side transfer must carry the `uniqueId` in the payment-reference field — see [SEPA payment reference](#sepa-payment-reference) below. Confirm the credited deposit through the deposit history (`POST /api/v4/main-account/history`) or the Main balance (`POST /api/v4/main-account/balance`), matching by `uniqueId`. The fiat deposit endpoint requires per-account activation. Contact WhiteBIT support and provide the API key to request access. **Required parameters:** | Parameter | Type | Description | | - | - | - | | `ticker` | string | Fiat currency ticker (e.g., `EUR`) | | `amount` | string | Deposit amount | | `provider` | string | Payment provider — check Asset Status endpoint for fiat currencies with `can_deposit: true` | | `uniqueId` | string | Unique transaction identifier | **Optional parameters:** | Parameter | Type | Description | | - | - | - | | `successLink` | string | Redirect URL after successful deposit. HTTPS only. Redirect links require feature activation — contact support before use; unactivated or non-HTTPS links fail validation. | | `failureLink` | string | Redirect URL after failed deposit. Same HTTPS and activation requirement as `successLink`. | | `returnLink` | string | Redirect URL the end user lands on after the deposit flow (success or failure). Optional fallback target. | | `address` | string | For `provider: "VISAMASTER"` — the end user's card number (PAN). Required when funding by card. | | `customer` | object | Customer identity block. Required for `provider: "VISAMASTER"` (USD/EUR) and `provider: "MERCURYO"`. Sub-fields: `firstName`, `lastName`, `email`, `birthDate` (YYYY-MM-DD), `address.{line1, line2, city, zipCode, countryCode}`. | | `expiresAfter` | integer | Invoice expiration in seconds. Maximum 86400 (24 hours). Accepted only for `provider: "VISAMASTER"` and `provider: "CHECKOUT"`. | Not every fiat ticker is depositable via API. Check `can_deposit` in the [Asset Status](/api-reference/market-data/asset-status-list) response before generating an invoice; tickers without API deposit support run through the WhiteBIT web interface. The endpoint returns a URL that the end user opens to complete the fiat deposit. Take the `provider` value for the currency from the [Asset Status](/api-reference/market-data/asset-status-list) response. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Generate a fiat deposit invoice (provider value from Asset Status) curl -X POST "https://whitebit.com/api/v4/main-account/fiat-deposit-url" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "EUR", "provider": "PROVIDER", "amount": "100", "uniqueId": "fiat-deposit-001", "request": "/api/v4/main-account/fiat-deposit-url", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Generate a fiat deposit invoice (provider value from Asset Status). # The send_request() helper is defined in the Crypto deposits section. response = send_request("/api/v4/main-account/fiat-deposit-url", { "ticker": "EUR", "provider": "PROVIDER", "amount": "100", "uniqueId": "fiat-deposit-001", }) invoice_url = response.json()["url"] print("Send the end user to:", invoice_url) ``` ### SEPA payment reference The `uniqueId` submitted in the `/fiat-deposit-url` request must appear in the SEPA payment-reference field of the bank-side transfer initiated by the end user. WhiteBIT uses this string to match the incoming SEPA settlement to the original deposit request. If the end user omits or alters it, the deposit may settle unmatched and require manual reconciliation through institutional support. ### Card-provider flows **VISAMASTER `Referer` header:** When using the VISAMASTER provider, configure the browser to send the `Referer` header when opening the invoice link. If the header is missing (e.g., when opening the link from a Telegram message or an email client that strips referrers), WhiteBIT redirects the end user to the homepage instead of the payment provider. Test the redirect path in the actual deployment surface (mobile app, email link, in-app web view) before go-live. ### Deposit request errors Common synchronous rejections from `/fiat-deposit-url` and the recovery for each: | Error | Cause | Recovery | | - | - | - | | `Your domain scheme incorrect. Use https only` | `successLink` / `failureLink` uses HTTP | Use HTTPS redirect URLs | | `Currency is not depositable via API` | The ticker is not enabled for API fiat deposits | Check `can_deposit` in the Asset Status response; use the web interface for blocked tickers | | `User not verified` | Account verification incomplete | Complete institutional onboarding before requesting invoices | | `Amount is too big for deposit` / `Daily limit reached` | Amount exceeds the per-transaction or daily limit | Query `POST /api/v4/main-account/fee` for current limits and retry within the returned limits | ## Fiat withdrawal Create a fiat withdrawal using the same `POST /api/v4/main-account/withdraw` endpoint used for crypto, specifying a fiat ticker. The same withdrawal endpoints apply (`/withdraw` and `/withdraw-pay`). Use fiat-specific tickers such as `EUR`, `USD`, `USD_VISAMASTER`, `EUR_VISAMASTER`. The `beneficiary` object is required for fiat withdrawals with tickers `USD_VISAMASTER`, `EUR_VISAMASTER`, `USD`, and `EUR`. Set `partialEnable` to `true` for increased maximum limits — the application must then handle status 18 ("Partially successful"). ### Beneficiary object fields Sub-field requirements vary by ticker and provider. Verify the current contract on the [Create Withdraw](/api-reference/account-wallet/create-withdraw-request) reference before integration. | Sub-field | Required for | Notes | | - | - | - | | `firstName` | USD\_VISAMASTER, USD, EUR | — | | `lastName` | USD\_VISAMASTER, USD, EUR | — | | `email` | USD\_VISAMASTER, EUR\_VISAMASTER | — | | `code` | Provider-dependent | — | | `phone` | VISAMASTER + USD/EUR | — | | `birthDate` | USD\_VISAMASTER, EUR\_VISAMASTER, MERCURYO | Format: `YYYY-MM-DD` | | `cardToken`, `cardTokenSave`, `fingerprintSession` | Card-tokenization flows | — | | `card.{save, name, firstName, lastName, number, month, year}` | Card-funded flows | — | | `address.{line1, line2, city, zip, country}` | Address-required flows | — | | `bank.{routingNumber, name, address, country}` | Bank-direct flows | — | Fiat withdrawals require KYC verification. Accounts without KYC verification cannot process fiat withdrawals. In exceptional cases, the WhiteBIT institutional team may grant a per-account override that permits fiat withdrawal without standard KYC. This is exception-only — not a default capability. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) for integrations with a documented case requiring the override. See [Institutional Onboarding](/institutional/onboarding) for the full fiat onboarding process. ## Required endpoints for fiat operations | Endpoint | Purpose | API Reference | | - | - | - | | `POST /api/v4/main-account/fiat-deposit-url` | Generate a fiat deposit invoice | [Fiat Deposit URL](/api-reference/account-wallet/get-fiat-deposit-url) | | `POST /api/v4/main-account/withdraw` or `/withdraw-pay` | Create a fiat withdrawal | [Create Withdraw](/api-reference/account-wallet/create-withdraw-request) | | `POST /api/v4/main-account/balance` | Check Main balance | [Main Balance](/api-reference/account-wallet/main-balance) | | `POST /api/v4/main-account/withdrawable-balance` | Check how much is withdrawable while deposits await confirmation | [Withdrawable Balance](/api-reference/account-wallet/withdrawable-balance) | | `POST /api/v4/main-account/history` | Query deposit and withdrawal history | [History](/api-reference/account-wallet/get-deposit-withdraw-history) | | `POST /api/v4/main-account/fee` | Available currencies, providers, and limits | [Get Fees](/api-reference/account-wallet/get-fees) | ## WhiteBIT Codes Move balance fee-free between WhiteBIT accounts by creating and applying codes. ## WhiteBIT Codes overview WhiteBIT Codes enable fee-free value transfer between WhiteBIT accounts. WhiteBIT Codes are alphanumeric strings representing a fixed amount of a specific currency. One account creates a code, shares the code string via any channel, and another account applies the code to receive the funds. * **Fee-free** — no fees for creating or applying codes * Use cases: internal transfers between accounts, promotional distributions, settlement between sub-accounts or partner accounts * Optional passphrase protection (up to 25 characters) ## Lifecycle and behavior **State machine:** A WhiteBIT Code moves through two states: `created` (an unredeemed code exists; the platform reserves the creator's funds) and `applied` (terminal — the code has been redeemed; funds credited to the redeemer). There is no void or cancel operation; the creator cannot reclaim an unredeemed code. **Apply failures:** Codes may fail to apply for several reasons (expired, invalid format, non-existent, wrong passphrase). The apply response distinguishes an already-applied code and a code applied by its own creator; the platform collapses the remaining failure modes into a generic rejection. If a redeemer's apply fails on a recently-created code, request a fresh code from the creator. **Correlation:** The `code` string is the only correlation key shared between creator and redeemer. The creator-side `description` field is creator-only and not exposed to the redeemer. Partners running redemption flows must map the code to an internal user ID on the partner side. The code string is a bearer token — possession grants redemption, and the creator cannot reclaim an unredeemed code. A leaked code is spendable by whoever holds it. **Security model:** Share codes through trusted channels and consider the optional passphrase for an additional protection layer. Passphrases accept Latin letters, digits, and ASCII symbols (no whitespace, no Unicode) up to 25 characters. Treat the code string as sensitive on the partner side: do not log it in plaintext, do not include it in error reports, do not commit it to version control. ## Create and apply a code The code lifecycle has two steps: create and apply. **Create:** `POST /api/v4/main-account/codes` — see the [API Reference](/api-reference/account-wallet/create-code) **Required parameters:** | Parameter | Type | Description | | - | - | - | | `ticker` | string | Currency ticker (e.g., `BTC`, `ETH`) | | `amount` | string | Amount to transfer (max precision: 18 decimal places; maximum value 1e17). | **Optional parameters:** | Parameter | Type | Description | | - | - | - | | `passphrase` | string | Passphrase for protection (up to 25 characters, Latin letters, digits, and ASCII symbols). | | `description` | string | Description visible only to the creator (up to 280 characters). | | `async` | boolean | Processing-mode flag accepted by the endpoint. Confirm the exact semantic with the institutional team before relying on it in production. | **Key response fields:** `code` — the generated WhiteBIT Code string to share with the redeemer; `message` — success message; `external_id` — external identifier. **Rate limit:** subject to platform-level rate limits — see [Rate Limits](/api-reference/rate-limits) for current enforced values. **Apply:** `POST /api/v4/main-account/codes/apply` — see the [API Reference](/api-reference/account-wallet/apply-code) **Required parameters:** | Parameter | Type | Description | | - | - | - | | `code` | string | The WhiteBIT Code string | **Optional parameters:** | Parameter | Type | Description | | - | - | - | | `passphrase` | string | Required if the code was created with a passphrase | | `async` | boolean | Processing-mode flag accepted by the endpoint. Confirm the exact semantic with the institutional team before relying on it in production. | **Rate limit:** subject to platform-level rate limits — see [Rate Limits](/api-reference/rate-limits) for current enforced values. **Webhook event:** `code.apply` fires when an account applies a code. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Create a WhiteBIT Code curl -X POST "https://whitebit.com/api/v4/main-account/codes" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "USDT", "amount": "100", "passphrase": "securePass123", "description": "Partner settlement Q1", "request": "/api/v4/main-account/codes", "nonce": 1594297865000 }' # Apply a WhiteBIT Code curl -X POST "https://whitebit.com/api/v4/main-account/codes/apply" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "code": "WBe11f4fce-2a53-4edc-b195-66b693bd77e3USDT", "passphrase": "securePass123", "request": "/api/v4/main-account/codes/apply", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Create a WhiteBIT Code create_response = send_request("/api/v4/main-account/codes", { "ticker": "USDT", "amount": "100", "passphrase": "securePass123", "description": "Partner settlement Q1", }) code = create_response.json().get("code") print(f"Created code: {code}") # Apply the WhiteBIT Code apply_response = send_request("/api/v4/main-account/codes/apply", { "code": code, "passphrase": "securePass123", }) print(apply_response.json()) ``` ## Express Withdraw Charge a WhiteBIT user's balance in one confirmation with a single-use payment token. ## Express Withdraw payments Express Withdraw lets an approved partner charge a specific amount from a WhiteBIT user's balance in one confirmation. The partner integrates a single endpoint — `POST /api/v4/main-account/express-withdraw/token` ([API Reference](/api-reference/account-wallet/create-express-withdraw-token)) — and WhiteBIT hosts everything the paying user sees. Settlement is an internal balance move: instant, off-chain, and fee-free on both sides. Express Withdraw is available only for B2B partner services and requires a separate approval process. Request access at [https://institutional.whitebit.com/](https://institutional.whitebit.com/). Without the permission, the endpoint returns `403 Forbidden`. ## Token lifecycle A payment token moves through four states: ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} stateDiagram-v2 [*] --> Created: POST /api/v4/main-account/express-withdraw/token Created --> Created: Re-request with same externalId + ticker + amount returns the same token Created --> Presented: Partner presents url (redirect, deep link, or QR) Presented --> Confirmed: User confirms on the WhiteBIT-hosted page Presented --> Expired: No confirmation within 90 seconds Confirmed --> [*]: WhiteBIT debits the payer, credits the partner Main balance, marks the token used Expired --> [*]: Re-creating with the same externalId issues a fresh token ``` 1. **Created** — the partner calls the create-token endpoint with `ticker`, `amount`, and a partner-side `externalId` (order or invoice identifier). The response carries the payment `url` and `expireAt` (UTC); every token is valid for 90 seconds after creation. 2. **Presented** — the partner hands the `url` to the user as a redirect, mobile deep link, or QR code. Treat the value as opaque: WhiteBIT returns the hosted web confirmation page by default, or a deep link when one is configured for the partner at onboarding; the token travels in the `token` query parameter either way. 3. **Confirmed** (terminal) — the user, authenticated on WhiteBIT, reviews the exact `ticker` and `amount` and confirms. WhiteBIT re-validates balance, limits, and permissions, debits the user, credits the partner's Main balance in the same operation, and marks the token used. 4. **Expired** (terminal) — a token left unconfirmed for 90 seconds becomes unusable. Re-create the payment with the same `externalId`; WhiteBIT issues a fresh token. Create the token as close as possible to the moment of presenting it — the 90-second window covers the user's review and confirmation, not the partner's checkout flow. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Create an Express Withdraw payment token (single-use, valid 90 seconds). # The send_request() helper is defined in the Crypto deposits section. response = send_request("/api/v4/main-account/express-withdraw/token", { "ticker": "USDT", "amount": "25.50", "externalId": "order-100294", }) payment = response.json() print("Send the user to:", payment["url"]) print("Token expires at (UTC):", payment["expireAt"]) ``` ## Idempotency and replay protection The `externalId` is unique per partner account and drives both guarantees: * Re-requesting a token for the same `externalId` with an identical `ticker` and `amount` while the token is still valid returns the **same** token — safe to retry after a timeout without double-charging. * Changing `ticker` or `amount` for a pending `externalId` fails with error code `18` — parameters of a pending payment cannot change; use a new `externalId`. * Re-submitting an `externalId` that the user already paid fails with error code `19` — the order is settled, and the rejection prevents a duplicate charge. See the [endpoint page](/api-reference/account-wallet/create-express-withdraw-token) for the full error-code table. ## Limits and eligibility * **Per-payment cap:** 10,000 USDT-equivalent, rejected with error code `191` above the cap. WhiteBIT enforces the cap at token creation and re-enforces it at confirmation. * **Currency:** crypto only; the ticker must be withdrawal-enabled on the platform. The endpoint rejects fiat tickers. * **No self-payments:** the paying user and the token creator must be different WhiteBIT accounts. * **Payer eligibility:** at confirmation the user must have withdrawals enabled, pass the standard withdrawal restriction checks, and hold a sufficient balance. * **Rate limits:** standard private-API limits apply — see [Rate Limits](/api-reference/rate-limits); the endpoint has no endpoint-specific limit. ## Withdrawal with conversion Convert the source currency before withdrawing, using the Convert service. ## Conversion in the withdrawal flow When the currency held in Main balance differs from the currency the end user needs to withdraw, request a conversion quote, confirm it, and then submit the withdrawal. The [Convert](/platform/convert) service handles balance routing internally — manual transfers between Main and Trade balances are not required. ## Step-by-step flow Verify the source currency is available in Main balance. **Endpoint:** `POST /api/v4/main-account/balance` — [API Reference](/api-reference/account-wallet/main-balance) Request a quote for converting the source currency to the withdrawal currency. The response includes an `id` (quote identifier), the quoted `rate`, and `expireAt` (Unix timestamp). **Endpoint:** `POST /api/v4/convert/estimate` — [API Reference](/api-reference/convert/convert-estimate) Confirm the quote using `quoteId` from the estimate response. The conversion executes atomically. **Endpoint:** `POST /api/v4/convert/confirm` — [API Reference](/api-reference/convert/convert-confirm) Submit a withdrawal to the end user's external address using the converted currency. **Endpoint:** `POST /api/v4/main-account/withdraw` or `POST /api/v4/main-account/withdraw-pay` — [API Reference](/api-reference/account-wallet/create-withdraw-request) The `withdraw.successful` webhook fires when the withdrawal completes. See [Webhooks](/platform/webhook) for setup and signature verification. Query the history endpoint to confirm the withdrawal status. See [Withdrawal status state machine](#withdrawal-status-state-machine) for the full status state machine. **Endpoint:** `POST /api/v4/main-account/history` — [API Reference](/api-reference/account-wallet/get-deposit-withdraw-history) The convert service sets quote expiry per quote and returns the value in `expireAt` (Unix timestamp). Confirm the quote before that time elapses, or request a new estimate. See [Convert](/platform/convert) for full parameter details, direction options, and history queries. ## Conversion errors Common synchronous rejections from `/convert/confirm` and the recovery for each: | Error code | Cause | Recovery | | - | - | - | | `20` (`api.converter.quoteExpired`) | The quote expired before confirmation | Request a new estimate and confirm within the quote window | | `37` | Insufficient balance at confirm time — the platform re-checks the balance on confirm, and the balance can change within the quote window even when the estimate succeeded | Top up the Main balance or request a new estimate for a smaller amount | | `0` with the `quoteId` field key `frontendServerSide.converter.quoteInvalid` | The quote was already used or never existed — the response does not distinguish the two | Request a new estimate | Error `message` values may arrive as translation keys (e.g., `api.converter.quoteExpired`) rather than finalized English strings. Treat the `code` and the field name under `errors` as the stable contract. ## Code example Convert USDT to BTC and withdraw BTC to an external address. The estimate returns a short-lived quote — confirm it before it expires, or request a new one: ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Partner as Partner backend participant WB as WhiteBIT API Partner->>WB: POST /api/v4/main-account/balance WB-->>Partner: Main balance for the source currency Partner->>WB: POST /api/v4/convert/estimate WB-->>Partner: conversion quote with rate and expiry alt confirmed before quote expiry Partner->>WB: POST /api/v4/convert/confirm WB-->>Partner: final converted amounts else quote expired Partner->>WB: POST /api/v4/convert/estimate (new quote) end Partner->>WB: POST /api/v4/main-account/withdraw WB-->>Partner: withdrawal accepted WB->>Partner: withdraw.successful webhook ``` The critical-path call is the estimate — every later step reuses identifiers from its response. The Crypto deposits section defines the `send_request()` helper used below. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Request a conversion estimate (USDT → BTC). The response carries the # quote "id" for /convert/confirm, the "rate", and "expireAt". estimate = send_request("/api/v4/convert/estimate", { "from": "USDT", "to": "BTC", "direction": "from", "amount": "100", }) data = estimate.json() print("Quote:", data["id"], "Rate:", data["rate"], "Expires at:", data["expireAt"]) ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Request a conversion estimate (USDT → BTC). The response carries the # quote "id" for /convert/confirm, the "rate", and "expireAt". curl -X POST "https://whitebit.com/api/v4/convert/estimate" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "from": "USDT", "to": "BTC", "direction": "from", "amount": "100", "request": "/api/v4/convert/estimate", "nonce": 1594297865000 }' ``` For Go and PHP examples, see [SDKs](/sdks). ## Required endpoints for withdrawal with conversion | Endpoint | Purpose | API Reference | | - | - | - | | `POST /api/v4/main-account/balance` | Check Main balance | [Main Balance](/api-reference/account-wallet/main-balance) | | `POST /api/v4/main-account/withdrawable-balance` | Check how much is withdrawable while deposits await confirmation | [Withdrawable Balance](/api-reference/account-wallet/withdrawable-balance) | | `POST /api/v4/convert/estimate` | Request a conversion quote | [Convert Estimate](/api-reference/convert/convert-estimate) | | `POST /api/v4/convert/confirm` | Confirm and execute a conversion | [Convert Confirm](/api-reference/convert/convert-confirm) | | `POST /api/v4/main-account/withdraw` | Create a withdrawal request | [Create Withdraw](/api-reference/account-wallet/create-withdraw-request) | | Webhooks (`withdraw.successful`) | Withdrawal status notifications | [Webhooks](/platform/webhook) | | `POST /api/v4/main-account/history` | Query deposit and withdrawal history | [History](/api-reference/account-wallet/get-deposit-withdraw-history) | | `POST /api/v4/main-account/fee` | Currencies, networks, and withdrawal limits | [Get Fees](/api-reference/account-wallet/get-fees) | ## Webhook reconciliation Reliable fund tracking requires both webhook-based and polling-based reconciliation. **Primary method — webhooks for real-time notifications:** * Configure the webhook URL (see [Webhooks](/platform/webhook)) * Verify the HMAC-SHA512 signature on every incoming webhook. Each delivery includes three headers — `X-TXC-APIKEY` (the WhiteBIT webhook API key), `X-TXC-PAYLOAD` (base64-encoded JSON body), and `X-TXC-SIGNATURE` (HMAC-SHA512 of the payload with the webhook key's secret). See [Security Best Practices](/best-practices/security) for the verification algorithm. * Track the `nonce` field — each webhook nonce is strictly greater than the previous. The nonce travels inside the JSON payload, not in a separate header. **Retry policy:** The platform retries failed deliveries over a 24-hour window — see [Webhooks](/platform/webhook) for the retry schedule. **Fallback method — poll `POST /api/v4/main-account/history`:** * Use `transactionMethod: 1` for deposits, `transactionMethod: 2` for withdrawals * Filter by `status` array for specific states * Recommended polling interval: every 5 minutes for active monitoring * See [Rate Limits](/api-reference/rate-limits) for current enforced values For balance endpoints, WebSocket account streams, and polling-interval guidance beyond deposits and withdrawals, see [Account Monitoring](/guides/account-monitoring). **Deduplication:** Use the `uniqueId` from webhook payloads and history responses to deduplicate across webhook and polling paths. The meaning of `uniqueId` differs by direction: for withdrawals, the value echoes the identifier supplied in the withdrawal request; for deposits, the platform assigns the value (the transaction identifier that the refund endpoint consumes as `transactionId`). Both are unique per transaction and safe as idempotency keys. WhiteBIT does not offer a webhook replay mechanism. Implement polling as a fallback for outages longer than the 24-hour retry window. Store all processed `uniqueId` values to prevent double-processing. **Reconciliation pattern:** 1. Receive webhook — verify signature — extract `uniqueId` and `status` 2. Store the event with `uniqueId` as the idempotency key 3. On polling cycle: query the history endpoint — compare `uniqueId` values against stored events 4. Process any events found via polling that the webhook path did not deliver 5. Mark transactions as complete only when the transaction reaches a terminal status (3/7 for success, 4/9 for canceled deposits, 4 for canceled withdrawals) ## What's next Webhook setup, event types, signature verification, and retry behavior. Estimate and confirm flow, plus conversion history queries. API key management, IP whitelisting, and secret storage. Journey-level guide for corporate fiat ↔ crypto clients: onboarding gates, EUR/SEPA flows, and failure paths. # Payments & Fiat FAQ Source: https://docs.whitebit.com/guides/payments-faq Common questions about WhiteBIT payments and fiat: access and enablement, crypto and fiat flows, SEPA, Travel Rule, and reconciliation. Common questions about the WhiteBIT Payments & Fiat program. ## Access and enablement ### Access to fiat operations Fiat deposits and withdrawals require completed [institutional onboarding](/institutional/onboarding) with approved fiat access — a separate second phase that is not automatic after KYB. See the [On/Off-Ramp overview](/guides/on-off-ramp-overview#how-to-get-started). ### Per-account activations Four capabilities are enabled per account rather than by default — the fiat deposit invoice endpoint, dedicated per-user deposit addresses, Express Withdraw, and Travel Rule API access. Request these capabilities through the account manager or `institutional@whitebit.com`. See the [enablement gates](/guides/on-off-ramp-overview#how-to-get-started). ## Crypto flows ### Persistent versus per-user deposit addresses A persistent address suits single-wallet and treasury setups; a fresh address per end customer suits payment providers that reconcile by address. See [Choosing between the two endpoints](/guides/payment-integration#unique-address-per-user). ### Charging a WhiteBIT user off-chain Express Withdraw charges a specific amount from a WhiteBIT user's balance in one confirmation, settling as an instant off-chain transfer into the partner's Main balance. See [Express Withdraw payments](/guides/payment-integration#express-withdraw-payments). ## Fiat and SEPA ### SEPA payment reference The `uniqueId` submitted with the fiat deposit request must appear in the SEPA payment-reference field so the incoming settlement matches the original request. See [SEPA payment reference](/guides/payment-integration#sepa-payment-reference). ### SEPA deposit provider and bank details The deposit-side SEPA provider for EUR fiat deposits and whether a `bankBic` sub-field is required are confirmed per account and are not documented in the public reference, so verify both with WhiteBIT during onboarding. See the [On/Off-Ramp guide](/guides/on-off-ramp-integration) for the fiat deposit flow. ## Compliance ### Travel Rule for EEA and Turkey Inbound crypto deposits for EEA and Turkey accounts are held until Travel Rule verification completes, and crypto withdrawals from EEA accounts carry a Travel Rule payload. See [Travel Rule](/concepts/travel-rule). ## Reconciliation ### Matching deposits and withdrawals Reconciliation is webhook-driven with history polling as a fallback, deduplicated on the `uniqueId` carried in both paths. See [Webhook reconciliation](/guides/payment-integration#webhook-reconciliation). ## What's next What the Payments & Fiat program provides and who it is for. Deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. Cross-cutting answers shared across programs — KYB, sandbox, fees, and rate limits. # Payments & Fiat Source: https://docs.whitebit.com/guides/payments-overview Move funds into and out of WhiteBIT programmatically — crypto deposits and payouts, fiat EUR/SEPA and card rails, merchant charges, and corporate on/off-ramp between fiat and crypto. The Payments & Fiat program covers programmatic movement of funds into and out of WhiteBIT: crypto deposits and payouts, fiat rails over EUR/SEPA and card providers, instant off-chain merchant charges, and corporate on/off-ramp between fiat and crypto. It suits payment providers crediting end customers, merchants collecting payments, and businesses settling revenue over EUR rails. ## What Payments & Fiat provides * **Crypto deposits** — a persistent or per-end-user deposit address, with incoming funds reconciled by webhook ([Payment Integration](/guides/payment-integration#deposit-address-generation)). * **Crypto and fiat payouts** — withdrawals with optional on-the-fly currency conversion ([Payment Integration](/guides/payment-integration#create-a-withdrawal)). * **Fiat rails** — EUR/SEPA bank transfers and card-provider checkout, added through institutional onboarding ([On/Off-Ramp guide](/guides/on-off-ramp-integration)). * **Merchant charges** — one-tap, off-chain settlement from a WhiteBIT user's balance with [Express Withdraw](/guides/payment-integration#express-withdraw-payments), and fee-free transfers with [WhiteBIT Codes](/platform/whitebit-codes). * **Reconciliation** — signed [webhooks](/platform/webhook) plus history polling keyed on client-side identifiers. ## Who Payments & Fiat is for * **Payment providers** — assign a deposit address per end customer and credit accounts on confirmation. * **Merchants and platforms** — collect crypto payments from WhiteBIT users instantly and off-chain. * **Corporate on/off-ramp clients** — move company funds between fiat and crypto over EUR rails. ## How it works Every flow authenticates with an HMAC-signed API key and reconciles against signed webhooks and history polling. Most crypto flows are available after standard account setup; some — Express Withdraw and dedicated per-user deposit addresses — require a separate per-account enablement, and fiat flows require completed [institutional onboarding](/institutional/onboarding) with approved fiat access (a separate second phase). The [Payment Integration guide](/guides/payment-integration) documents each flow — deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw — and the [On/Off-Ramp guide](/guides/on-off-ramp-integration) covers the corporate fiat ↔ crypto journey end to end. ## Program terms Fee schedules and limits for fiat deposits and withdrawals are set per individual agreement and confirmed by the account manager during onboarding; the enabled currency and provider matrix is reported at runtime and reviewed at onboarding (see [program terms](/guides/on-off-ramp-overview#program-terms)). Compliance obligations apply to cross-border transfers: For transfers in scope of the Travel Rule, originator and beneficiary information is required. See [Travel Rule](/concepts/travel-rule) for the field requirements and the transfer flow. The deposit-side SEPA provider for EUR fiat deposits is confirmed per account at onboarding and is not documented in the public reference; the [On/Off-Ramp guide](/guides/on-off-ramp-integration) documents the deposit and withdrawal flows and the per-account values confirmed at onboarding. ## How to get started Build crypto flows against the [Payment Integration guide](/guides/payment-integration). For fiat rails, email `institutional@whitebit.com` with the registered legal entity, the licenses held, whether the scope is crypto-only or fiat as well, and the countries served, then complete [institutional onboarding](/institutional/onboarding). Clear the [Go-Live Checklist](/best-practices/go-live-checklist) before real volume. ## What's next Deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw. Access and enablement, SEPA, Travel Rule, and reconciliation. The corporate fiat ↔ crypto journey over EUR/SEPA rails. # Embedded Trading Integration Guide Source: https://docs.whitebit.com/guides/sub-account-integration Integration guide for WhiteBIT Embedded Trading: eligibility and approval, per-customer sub-account setup, per-customer API keys, and revenue reconciliation. WhiteBIT Embedded Trading serves partners that operate a dedicated [sub-account](/glossary#sub-account) for each end customer under a partner master account. The program provides per-customer account isolation, per-customer API keys, fee-free internal transfers between the master account and sub-accounts, and a revenue share of up to **40%** of the trading fees generated by referred customers. Embedded Trading is one of several integration paths. Other partner types route to separate guides: * End customers keep personal WhiteBIT accounts and the partner holds a user-scoped API key (trading bots, [copy trading](/guides/copy-trading), portfolio apps) — see [Fast API Key via OAuth](/guides/fast-api-key-integration). * The choice between backend models (managed sub-accounts, attribution, KYC reliance) is still open — see [Wallet-as-a-Service](/guides/waas-overview). * The integration centers on deposits, withdrawals, payouts, or merchant flows — see [Payment Integration](/guides/payment-integration). Corporate fiat ↔ crypto conversion on the partner's own account is covered by the [On/Off-Ramp Guide](/guides/on-off-ramp-integration). * For the full partner-type map, see [Partner Solutions](/guides/partner-solutions). ## Prerequisites Before building the sub-account integration: * **Approved Embedded Trading enrollment** — the program is approval-gated (see [Eligibility and approval](#eligibility-and-approval)); apply via `institutional@whitebit.com`. * **Master-account KYB** — completed through [Institutional Onboarding](/institutional/onboarding). * **API access** — [HMAC-signed requests](/api-reference/authentication) on the master account; store the secret per [Security Best Practices](/best-practices/security). * **Model fit** — this is Model A (partner-operated sub-accounts); confirm against the [integration models](/concepts/integration-models) concept. ## Eligibility and approval Embedded Trading enrollment is approval-gated. Every application is individually reviewed before sub-account provisioning is enabled. **How to apply:** email `institutional@whitebit.com` with a description of the service. Include the registered legal entity (name, registration number, jurisdiction), licenses or registrations held (with the regulator and register reference), the intended account structure, who performs end-customer KYC, crypto-only or fiat scope, and the countries where the service is offered or marketed. The full application question list is on the [Partner Solutions](/guides/partner-solutions#how-to-apply) page. Master-account KYB via [Institutional Onboarding](/institutional/onboarding) is part of enrollment. The end-customer KYC verification flow is WhiteBIT-branded and cannot be white-labeled. **KYC reliance eligibility:** KYC reliance — WhiteBIT relying on the partner's own customer verification — may be available, but is not enabled by default. It is never automatic, and operates as a delegation: responsibility for customer verification is never transferred. Eligibility is assessed case by case. Reliance is available only to partners that are supervised AML-obligated entities (for example EMI, PI, VASP, or MiCA-CASP license holders) in an adequate jurisdiction, applying broadly equivalent customer due diligence, under a written agreement and an individual WhiteBIT Compliance assessment. A confirmed entry on the relevant public register establishes the licensing basis; a confirmed EU/MiCA entity is additionally required when EU users are in scope. Licensing regimes and entity structures vary, and the examples above may not capture every case. Describe your licence(s), jurisdiction, and customer due-diligence approach in full in your application so the WhiteBIT Compliance team can review your specific situation and make a determination. Partners without a qualifying license integrate on the standard track: WhiteBIT verifies each end customer directly through the WhiteBIT-branded KYC flow described below. ## Program terms The revenue share is up to **40%** of the trading fees generated by referred customers. Whether the share covers spot trading fees only or extends to other products is part of the commercial terms; the reconciliation walkthrough below computes on spot executed-history. The applicable rate and any additional commercial terms are agreed individually during enrollment; the canonical program terms are published on the [Embedded Trading program page](https://institutional.whitebit.com/broker-program). Joint marketing activities — social media co-posts, blog posts, targeted email newsletters, AMA sessions, and trading competitions — are scheduled with WhiteBIT during onboarding. Referral-based earning without operating customer accounts is covered by the separate WhiteBIT Affiliate Program, which has its own terms. ## Account architecture Each end customer trades from a dedicated sub-account under the partner's master account: * **Independent balances**, scoped at creation via `permissions.spotEnabled` and `permissions.collateralEnabled`. Trades on one sub-account do not affect another. * **Up to 50 API keys per sub-account**, independent from the main account and from other sub-accounts, each with an IP whitelist and permission scope. * **Sub-account count per master** — the number of sub-accounts a master account can create is not a fixed published limit; confirm the ceiling that applies to the account with WhiteBIT during enrollment. - **Withdrawal control at the master account** — sub-account withdrawals surface on the master account for confirmation via the [unconfirmed-withdrawals list](/api-reference/sub-accounts/list-unconfirmed-sub-account-withdrawals) and [confirm](/api-reference/sub-accounts/confirm-sub-account-withdrawal) endpoints. The sub-account withdrawal endpoints are not available by default — request access via `institutional@whitebit.com`; a `404` response indicates the endpoints are not yet enabled for the account. - **Crypto deposits are disabled by default.** Once deposits are enabled for the account (request via the assigned account manager or `institutional@whitebit.com`), the capability applies to the account and its sub-accounts; a sub-account then generates deposit addresses through the standard [deposit address endpoint](/api-reference/account-wallet/get-cryptocurrency-deposit-address) using its own API key with deposit permission. **Endpoint map:** | Operation | Endpoint | Reference | | - | - | - | | Create | `POST /api/v4/sub-account/create` | [Create Sub-Account](/api-reference/sub-accounts/create-sub-account) | | Edit | `POST /api/v4/sub-account/edit` | [Edit Sub-Account](/api-reference/sub-accounts/edit-sub-account) | | Delete | `POST /api/v4/sub-account/delete` | [Delete Sub-Account](/api-reference/sub-accounts/delete-sub-account) | | List | `POST /api/v4/sub-account/list` | [List of Sub-Accounts](/api-reference/sub-accounts/list-of-sub-accounts) | | Block / Unblock | `POST /api/v4/sub-account/block` · `/unblock` | [Block](/api-reference/sub-accounts/block-sub-account) · [Unblock](/api-reference/sub-accounts/unblock-sub-account) | | Transfer | `POST /api/v4/sub-account/transfer` | [Sub-Account Transfer](/api-reference/sub-accounts/sub-account-transfer) | | Balances | `POST /api/v4/sub-account/balances` | [Sub-Account Balances](/api-reference/sub-accounts/sub-account-balances) | | KYC URL | `POST /api/v4/sub-account/kyc-url` | [Get Sub-Account KYC URL](/api-reference/sub-accounts/kyc-url) | | API keys | `POST /api/v4/sub-account/api-key/create` (+ edit, delete, list, reset, IP-address management) | [Create Sub-Account API Key](/api-reference/sub-accounts/create-sub-account-api-key) | The sub-account endpoints in the table above share a rate limit of 1000 requests per 10 seconds; `POST /api/v4/trade-account/executed-history` allows 12000 requests per 10 seconds — see [Rate limits](/api-reference/rate-limits). Transfers between the master account and any sub-account are fee-free in both directions — master-to-sub for funding a customer account, sub-to-master for revenue collection. See the [Sub-Accounts Overview](/products/sub-accounts/overview) for the full product reference. ## Customer onboarding flow The KYC branch is selected at creation via the `shareKyc` parameter: with `shareKyc: true` the sub-account shares the master account's verification and no separate customer KYC applies; with `shareKyc: false` (or omitted) the `email` field is required and the end customer completes verification individually. Steps 2–3 apply to the dedicated-KYC branch (`shareKyc: false` or omitted). With `shareKyc: true`, the sub-account shares the master account's verification — skip directly to Step 4 (Fund the account and enable trading) once the sub-account is created. Call `POST /api/v4/sub-account/create` with `alias` and the `permissions` object (`spotEnabled`, `collateralEnabled`), plus `email` when `shareKyc` is `false` or omitted — [API Reference](/api-reference/sub-accounts/create-sub-account). A KYC URL can be generated only for a sub-account that is activated (has an associated user), active, and does not use shared KYC. Poll `POST /api/v4/sub-account/list` and read the `status` and `userId` fields for the new sub-account — [API Reference](/api-reference/sub-accounts/list-of-sub-accounts). Calling `kyc-url` before activation returns `400 "Account is not confirmed"`. Call `POST /api/v4/sub-account/kyc-url` with the sub-account `id` — [API Reference](/api-reference/sub-accounts/kyc-url). The end customer opens the temporary link and completes the WhiteBIT-branded identity verification, which also confirms the sub-account email address. Track the sub-account state via the list endpoint. Transfer initial funds fee-free via `POST /api/v4/sub-account/transfer`, and create a dedicated API key via `POST /api/v4/sub-account/api-key/create` for customers needing direct API access. Once crypto deposits are enabled for the account, the sub-account generates its own deposit address via the [deposit address endpoint](/api-reference/account-wallet/get-cryptocurrency-deposit-address) using its own API key with deposit permission. Sub-account withdrawals require master-account confirmation — see [Account architecture](#account-architecture) above for the unconfirmed-withdrawals list and confirm endpoints. Critical-path call — create a sub-account with dedicated KYC: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST "https://whitebit.com/api/v4/sub-account/create" \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "alias": "customer-001", "email": "customer@example.com", "shareKyc": false, "permissions": {"spotEnabled": true, "collateralEnabled": false}, "request": "/api/v4/sub-account/create", "nonce": 1594297865000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64, hashlib, hmac, json, time, requests API_KEY, API_SECRET = "YOUR_API_KEY", "YOUR_SECRET" endpoint = "/api/v4/sub-account/create" body = json.dumps({ "alias": "customer-001", "email": "customer@example.com", "shareKyc": False, "permissions": {"spotEnabled": True, "collateralEnabled": False}, "request": endpoint, "nonce": int(time.time() * 1000), }) payload = base64.b64encode(body.encode()).decode() signature = hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha512).hexdigest() response = requests.post( "https://whitebit.com" + endpoint, headers={"Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload, "X-TXC-SIGNATURE": signature}, data=body, ) print(response.json()) # id, alias, userId, email, status ``` For Go and PHP examples, see [SDKs](/sdks). The signing process is documented in [Private HTTP API authentication](/api-reference/authentication). ## Per-customer API keys Each sub-account supports up to **50 API keys**, managed via the [sub-account API key endpoints](/api-reference/sub-accounts/create-sub-account-api-key) (create, edit, delete, list, reset) with dedicated [IP-address management](/api-reference/sub-accounts/create-sub-account-api-key-ip-address). * Assign the minimum permission set per key (`Info + Trading` for trading-only customers; deposit and withdrawal permissions only where funds movement is required) — see [Security Best Practices](/best-practices/security) for the permission model and key-handling rules. * Configure the IP whitelist per key to match the customer's infrastructure. Create separate API keys for each customer sub-account. Never share the master account's API keys with customers. For structured order tracking across customer sub-accounts, use `clientOrderId` naming conventions — see [Client Order ID: account-operator implementation](/guides/client-order-id#example-account-operator-implementation). ## Revenue monitoring Embedded Trading does not expose a dedicated fee-share endpoint. Earnings are reported through the WhiteBIT [Analytical Dashboard](https://help.whitebit.com/hc/en-gb/articles/19885341884573-How-to-Use-WhiteBIT-Analytical-Dashboard), which tracks referral statistics and trading volumes. Payout mechanics and settlement schedule are agreed during enrollment. **Programmatic reconciliation:** 1. List sub-accounts via `POST /api/v4/sub-account/list`. 2. For each sub-account, query trade history via `POST /api/v4/trade-account/executed-history` using the sub-account's own API key — [API Reference](/api-reference/trading/query-executed-order-history). 3. For each executed deal, multiply the fee charged by the agreed fee-share percentage. 4. Sum across all sub-accounts to produce earnings for the reporting window. Reconcile the locally computed totals against the dashboard for each settlement period, and track per-customer volume separately for per-customer reconciliation. ## Fiat operations Fiat deposits and withdrawals (EUR/SEPA) operate at the partner's master-account level and require institutional fiat access — the second phase of [Institutional Onboarding](/institutional/onboarding), completed through a fiat processing partner review. Sub-accounts support crypto operations; sub-account balances are funded and collected through fee-free internal transfers with the master account. See [Payment Integration](/guides/payment-integration) for fiat endpoint details. ## Testing WhiteBIT has no public testnet or sandbox. Validate the full flow — sub-account creation, KYC, per-customer keys, funding, and a first trade — on the live API using a test sub-account and minimum order sizes. Activate Demo Tokens (`DBTC`/`DUSDT`) for risk-free spot practice on the `DBTC_DUSDT` pair, and check per-asset minimums via the [Asset Status](/api-reference/market-data/asset-status-list) endpoint before placing orders. Sub-account creation, KYC, fee-free transfers, and revenue reconciliation can all be exercised on this test cohort before real customers are onboarded. Work through the [Go-Live Checklist](/best-practices/go-live-checklist) first. ## Integration checklist * [ ] **Application** — application sent to `institutional@whitebit.com` with the [intake details](/guides/partner-solutions#how-to-apply) and approved. * [ ] **Master account KYB** — KYB verification completed for the partner entity. * [ ] **Master API key** — master account API key created with appropriate permissions. * [ ] **Sub-account creation** — test sub-account created with the intended `permissions` scope and KYC branch. * [ ] **Activation and KYC** — sub-account activation observed via `sub-account/list`; KYC URL generated and completed (dedicated-KYC branch). * [ ] **Deposit enablement** (if per-customer deposits apply) — crypto-deposit enablement requested via the account manager or `institutional@whitebit.com`. * [ ] **Fund transfer** — fee-free transfer between master and sub-account verified in both directions. * [ ] **Per-customer API key** — API key created for a sub-account with IP whitelist configured. * [ ] **Balance monitoring** — `sub-account/balances` query working across all sub-accounts. * [ ] **Revenue reconciliation** — per-sub-account trade-history collection and fee-share computation in place. * [ ] **Fiat access** (if applicable) — institutional onboarding Phase 2 completed for SEPA access on the master account. * [ ] **Security review** — IP whitelists, key permissions, and secret storage reviewed per [Security Best Practices](/best-practices/security). * [ ] **Go-live review** — all items on the [Go-Live Checklist](/best-practices/go-live-checklist) verified. ## What's next Sub-account isolation model, transfer mechanics, and per-key permission scopes. Step-by-step KYB and fiat onboarding process. Pre-production readiness verification. # AI tools Source: https://docs.whitebit.com/guides/use-with-ai WhiteBIT AI tools — a trading MCP server, a CLI, and documentation integrations for Claude Code, Cursor, Claude Desktop, Codex, and OpenClaw. WhiteBIT provides two categories of AI tools: **trading tools** for executing trades and querying account data, and **documentation tools** for searching the API reference inside a development environment. Connect Claude Code, Cursor, Claude Desktop, Codex, or OpenClaw to 115 WhiteBIT trading tools. Place orders, check balances, manage positions, and query market data using natural language. Trade and manage the account directly from the terminal. 110+ commands with JSON output, multi-profile support, dry-run mode, and shell completion. Built for scripting and CI/CD pipelines. Configure Cursor, VS Code, or Claude Desktop to search the full WhiteBIT API documentation via MCP. The AI client gains direct access to all endpoint reference pages. Copy any documentation page for AI consumption, open pages in ChatGPT, Claude, Perplexity, or Grok, and access MCP connection options — from the dropdown on every documentation page. ## Trading tools The [MCP server](/guides/mcp-server) and [CLI](/guides/cli) connect directly to the WhiteBIT exchange API. Both tools require a WhiteBIT account and API key for authenticated operations. Public market data tools (prices, order book, market info) require no authentication. | Tool | Best for | Authentication | | - | - | - | | MCP server | Natural language trading in an AI client | API key for private tools; no credentials for market data | | CLI | Terminal-based trading, scripting, automation | API key or environment variables | ### What the trading tools support **Market data (no API key required)** * Current prices, tickers, and 24-hour statistics * Order book depth and recent trades * Funding rate history and platform status **Spot trading** * Place, cancel, and modify limit, market, and stop orders * Bulk order operations * Open order listing and order history **Collateral trading** * Open and close leveraged positions * Manage leverage and position mode * Conditional orders: OCO, stop-limit, trigger-market **Wallet and account** * Deposit addresses for crypto and fiat * Withdrawal requests * Transfer between main, spot, and collateral accounts * WhiteBIT codes (create, apply, list) **Lending and earn** * Fixed and flexible staking plans * Interest payment history **Sub-accounts** * Sub-account listing and balance queries * Transfers to and from sub-accounts **Mining pool** and **currency conversion** are also available via the MCP server. ## Documentation tools The [docs search MCP](/guides/ai-ide-setup) and [docs page AI menu](/guides/ai-context-menu) help developers access API reference content inside AI tools without switching context. The documentation search MCP (`https://docs.whitebit.com/mcp`) and the trading MCP (`http://localhost:8080/mcp`) are separate integrations. The documentation MCP searches API reference pages. The trading MCP executes API calls against the WhiteBIT exchange. ## Supported AI clients | AI client | Trading MCP | Documentation MCP | Contextual menu | | - | :-: | :-: | :-: | | Claude Code | ✓ | — | — | | Cursor | ✓ | ✓ | ✓ | | Claude Desktop | ✓ | ✓ | — | | Codex | ✓ | — | — | | OpenClaw | ✓ | — | — | | VS Code | — | ✓ | ✓ | | ChatGPT, Claude, Perplexity, Grok | — | — | ✓ | ## Related resources * [MCP server](/guides/mcp-server) — Setup guide and client configuration for the WhiteBIT trading MCP * [CLI](/guides/cli) — Installation, authentication, command reference, and examples * [AI tools FAQ](/guides/ai-faq) — Common questions about API key safety, supported clients, and account practices * [Authentication](/api-reference/authentication) — How to generate and manage WhiteBIT API keys # Wallet-as-a-Service FAQ Source: https://docs.whitebit.com/guides/waas-faq Common questions about WhiteBIT Wallet-as-a-Service: scope and delivery, integration models, onboarding and access, integration, and compliance. Answers to common questions about WhiteBIT Wallet-as-a-Service (WaaS). ## Scope and delivery ### Delivery model WaaS puts WhiteBIT behind the partner's own product as the exchange, custody, and settlement backend — a wallet and payments building block, not a full white-label exchange. See the [WaaS overview](/guides/waas-overview). ### WaaS and Crypto-as-a-Service WaaS is the wallet and deposit-address building block; Crypto-as-a-Service is the full white-label exchange offering, and it uses the WaaS building block for end-customer wallets. See [Crypto-as-a-Service](/guides/caas-overview). ## Integration models ### Choosing a model Three models are available — managed sub-accounts, attribution, and sub-accounts with KYC reliance — split by who holds the end-user account and who performs KYC. See [Choose an integration model](/guides/waas-overview#choose-an-integration-model). ### KYC reliance eligibility KYC reliance is gated: it requires a supervised, AML-obligated entity and an individual WhiteBIT Compliance assessment. See the [eligibility conditions](/guides/waas-integration#kyc-reliance-eligibility). ### Pooled account A single pooled (omnibus) account for all end users is not offered, because pooled custody conflicts with client-fund segregation and Travel Rule requirements. See [why not a pooled account](/concepts/integration-models#why-not-a-pooled-account). ## Onboarding and access ### Onboarding phases Institutional onboarding has two phases: Phase 1 grants crypto operations access after KYB; optional Phase 2 adds EUR/SEPA fiat access. See [Institutional Onboarding](/institutional/onboarding). ### Per-user deposit address enablement Per-user deposit addresses (`create-new-address`) are disabled by default. Request enablement through the account manager or `institutional@whitebit.com`. See the [Developer guide](/guides/waas-integration#prerequisites). ### Crypto deposit enablement Crypto deposits are disabled by default on institutional accounts and cannot be enabled through the API. See [crypto deposit enablement](/guides/caas-faq#crypto-deposit-enablement). ## Integration ### Reconciliation approach Webhooks are the primary reconciliation channel; polling transaction history is a required fallback, since webhook delivery is retried but not replayed. Deduplicate by `uniqueId`. See [Payment and payout flows](/guides/waas-integration#payment-and-payout-flows). ### Fiat operations scope Fiat deposit and withdrawal operate at the partner's master-account level, not per end user. Per-end-user fiat rails are not a standard shipped capability. See the [Developer guide](/guides/waas-integration). ### Test environment availability WhiteBIT does not offer a public testnet or sandbox. Test on the live API with minimum amounts and check per-asset minimums via [Asset Status](/api-reference/market-data/asset-status-list); the WhiteBIT Codes flow in [WaaS Recipes](/guides/waas-recipes) is a low-risk way to try a real signed call. ## Compliance ### MiCA and Travel Rule for EEA end users For EEA users, MiCA restricts some stablecoin operations, and the Travel Rule governs EEA and Turkey transfers; both affect the assets and flows available to those end users. See [Regulatory Compliance](/institutional/compliance) and [Travel Rule](/concepts/travel-rule). ## Support ### Support contacts The assigned account manager is the primary contact. Programs and onboarding go to `institutional@whitebit.com`. Platform questions are answered at [help.whitebit.com](https://help.whitebit.com), and API documentation is on docs.whitebit.com. ## What's next What WaaS provides, the integration models, and how to apply. The technical integration: models, payment flows, compliance, and testing. Runnable examples with a starter repo. Cross-cutting answers shared across programs — KYB, sandbox, fees, and rate limits. # Wallet-as-a-Service integration Source: https://docs.whitebit.com/guides/waas-integration Technical integration for Wallet-as-a-Service partners: the models, payment and payout flows, compliance requirements, and testing. **For developers.** This page covers the technical integration. For what WaaS is, the models at a business level, and how to apply, see the [WaaS overview](/guides/waas-overview). The integration models are described in the [Integration models](/concepts/integration-models) concept. This guide covers where to start for each and the flows the models share. ## Prerequisites * **Approved WaaS partner enrollment** — see the [WaaS overview](/guides/waas-overview) for what WaaS provides and how to apply. * **A chosen backend model** — managed sub-accounts, attribution, or KYC reliance; compare on the [integration models](/concepts/integration-models) concept. * **API access** — [HMAC-signed requests](/api-reference/authentication); per-user deposit addresses (`create-new-address`) enabled for the account. ## Where to start per model * **Managed sub-accounts.** WhiteBIT creates a dedicated sub-account per end user under the partner's master account and performs KYC on each one. Build with [Sub-Accounts](/products/sub-accounts/overview) for account creation and management, and the [Embedded Trading integration guide](/guides/sub-account-integration) for the full walkthrough — eligibility, per-customer API keys, and fee-share reconciliation. * **Attribution (own account + OAuth).** Each end user keeps a personal WhiteBIT account and grants the partner a scoped API key through the consent screen. Build against [Fast API Key via OAuth](/guides/fast-api-key-integration) for the authorization flow, key issuance, and permission scopes. * **Sub-accounts with KYC reliance.** The same sub-account architecture as the managed model, but the partner performs end-user KYC instead of WhiteBIT, under a Compliance-approved agreement. Build with the same [Embedded Trading integration guide](/guides/sub-account-integration); complete [Institutional Onboarding](/institutional/onboarding) first to establish the reliance agreement. See [KYC reliance eligibility](#kyc-reliance-eligibility) below for the conditions. Commercial terms for the program: Revenue-share terms depend on the program. Embedded Trading partners earn a share of the trading fees that referred customers generate across all products, with payouts initiated by the partner, most commonly once per month — see [WhiteBIT Embedded Trading](https://institutional.whitebit.com/broker-program) for current rates. Other partner programs confirm commercial terms during onboarding. ## KYC reliance eligibility KYC reliance — WhiteBIT relying on the partner's own customer verification — may be available, but is not enabled by default. It is never automatic, and operates as a delegation: responsibility for customer verification is never transferred. Eligibility is assessed case by case. Reliance is available only to partners that are supervised AML-obligated entities (for example EMI, PI, VASP, or MiCA-CASP license holders) in an adequate jurisdiction, applying broadly equivalent customer due diligence, under a written agreement and an individual WhiteBIT Compliance assessment. A confirmed entry on the relevant public register establishes the licensing basis; a confirmed EU/MiCA entity is additionally required when EU users are in scope. Licensing regimes and entity structures vary, and the examples above may not capture every case. Describe your licence(s), jurisdiction, and customer due-diligence approach in full in your application so the WhiteBIT Compliance team can review your specific situation and make a determination. ## Payment and payout flows Fund-movement flows, with parameters and code examples, are in the [Payment Integration guide](/guides/payment-integration). The per-user deposit and payout cycle: ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram autonumber participant P as Partner backend participant U as End user participant W as WhiteBIT participant B as Blockchain P->>W: POST /api/v4/main-account/create-new-address W-->>P: Unique per-user deposit address P->>U: Share deposit address U->>B: Send funds on-chain B-->>W: Deposit confirmed W->>P: Deposit webhooks: deposit.accepted then deposit.processed P->>P: Reconcile by uniqueId, credit the end user P->>W: POST /api/v4/main-account/withdraw (EEA: with travelRule object) W->>B: On-chain payout to the user's address ``` Reconcile by webhook, and poll transaction history as a **required** fallback: webhook delivery is retried but has no replay, so an event can be missed and must be recovered by polling. Deduplicate by `uniqueId`. See [Webhooks](/platform/webhook) for signatures and delivery semantics. API [rate limits](/api-reference/rate-limits) apply per endpoint; sub-account limits are set per agreement. Fiat deposit and withdrawal operate at the **master-account** level (institutional fiat access). Per-end-user fiat rails are not a standard shipped capability; confirm any such requirement with WhiteBIT first. **Compliance requirements that affect the requests:** * EEA withdrawals require a `travelRule` object; in the sub-account models the partner submits it for each sub-account withdrawal it initiates. Inbound EEA/Turkey deposits are held until verification completes. See [Travel Rule](/concepts/travel-rule). * For EEA users, use USDC or EURI, not USDT. See [Regulatory Compliance](/institutional/compliance). ## More flows Additional use cases (conversion payouts, refunds, exact-amount payouts, multichain payouts) are catalogued in [Recipes](/guides/waas-recipes), with the full parameter reference in the [Payment Integration guide](/guides/payment-integration). **Travel Rule (programmatic):** submit originator data via `travel-rule/deposit/verification` and fetch the VASP list via `travel-rule/vasps` (EEA and Turkey). See [Travel Rule](/concepts/travel-rule). ## Testing WhiteBIT does not offer a public testnet or sandbox. Test on the live API with minimum amounts, and check per-asset minimums via the [Asset Status](/api-reference/market-data/asset-status-list) endpoint first. The WhiteBIT Codes flow is a low-risk way to try a real signed call on a small amount (see [Recipes](/guides/waas-recipes)). ## What's next Runnable examples and the starter repo. Endpoint-level reference for every payment and payout flow. Scope, integration models, onboarding, and compliance questions. # Wallet-as-a-Service Source: https://docs.whitebit.com/guides/waas-overview Put WhiteBIT behind a partner's product as the exchange, custody, and settlement backend. What WaaS provides, the integration models, and how to get started. Wallet-as-a-Service (WaaS) lets a partner put WhiteBIT behind its own product as the exchange, custody, and settlement backend. This overview covers fit and model selection. For the technical integration, see the [Developer guide](/guides/waas-integration). Adding wallets and payouts to an existing product fits WaaS. Launching a full branded exchange instead fits [Crypto-as-a-Service](/guides/caas-overview), which composes the WaaS wallet building block for its end-customer wallets. The [WaaS Recipes](/guides/waas-recipes) show runnable examples of deposit addresses, reconciliation, payouts, and settlement. ## What WaaS provides * A unique crypto deposit address per end user, with incoming funds reconciled by webhook. * Crypto and fiat payouts, including withdrawal with on-the-fly currency conversion. * Fee-free settlement between accounts with WhiteBIT Codes, or one-tap charges with Express Withdraw. * Fireblocks connectivity and built-in AML controls on deposit and withdrawal flows. ## Choose an integration model Each end user gets a sub-account under the partner's master account. **WhiteBIT verifies (KYC) each user** and is the user's counterparty. Each end user opens a **separate** WhiteBIT account; the partner connects via an OAuth-issued key. **WhiteBIT does the KYC.** Attribution / fee-share is arranged separately. Managed sub-accounts, but **WhiteBIT relies on the partner's KYC** of the end user. Requires a compliance assessment and agreement — see the eligibility conditions. A single pooled (omnibus) account for all users is not offered: pooled custody conflicts with MiCA client-fund segregation and Travel Rule requirements. Each model above keeps segregated sub-accounts, with a master account acting only as a settlement hub. Two questions place a partner: **(1)** does the end user hold a separate WhiteBIT account, or does the partner manage accounts on the end user's behalf? **(2)** who runs KYC, WhiteBIT or the partner? The practical difference between the two sub-account models is who verifies the end users: with managed sub-accounts WhiteBIT does; with KYC reliance the partner does. The final choice and any compliance gate are confirmed with WhiteBIT. KYC reliance — WhiteBIT relying on the partner's own customer verification — may be available, but is not enabled by default. It is never automatic, and operates as a delegation: responsibility for customer verification is never transferred. Eligibility is assessed case by case. Reliance is available only to partners that are supervised AML-obligated entities (for example EMI, PI, VASP, or MiCA-CASP license holders) in an adequate jurisdiction, applying broadly equivalent customer due diligence, under a written agreement and an individual WhiteBIT Compliance assessment. A confirmed entry on the relevant public register establishes the licensing basis; a confirmed EU/MiCA entity is additionally required when EU users are in scope. Licensing regimes and entity structures vary, and the examples above may not capture every case. Describe your licence(s), jurisdiction, and customer due-diligence approach in full in your application so the WhiteBIT Compliance team can review your specific situation and make a determination. ## Program terms Pricing is agreed per contract during onboarding — negotiated per partner rather than a published rate card, and distinct from Embedded Trading's revenue-share model. WaaS uses bundled pricing with no per-stage charges. Eligibility for the gated KYC-reliance variant is assessed case by case per the conditions above. ## Compliance at a glance * **Travel Rule (EEA and Turkey):** transfers must carry sender/recipient data. Inbound deposits for EEA/Turkey accounts are held until verification completes; withdrawals carry a travel-rule payload. See [Travel Rule](/concepts/travel-rule). * **MiCA (EEA):** some stablecoin operations are restricted for EEA users, which affects the assets available to those users. See [Regulatory Compliance](/institutional/compliance). ## How to apply 1. Complete KYB as part of [Institutional Onboarding](/institutional/onboarding). Fiat access is a separate second phase, not automatic after KYB. 2. Create API keys and configure webhooks in the WhiteBIT dashboard. 3. Request the enablement the model needs (sub-account and crypto-deposit enablement, per-user deposit addresses) via the account manager or [institutional@whitebit.com](mailto:institutional@whitebit.com). 4. Work through the [Go-Live Checklist](/best-practices/go-live-checklist) before real volume. To get started or discuss a model, contact [institutional@whitebit.com](mailto:institutional@whitebit.com) or the account manager. ## What's next The technical integration: models, payment flows, compliance, and testing. Runnable examples with a starter repo. Scope, integration models, onboarding, and compliance questions. # Wallet-as-a-Service Recipes Source: https://docs.whitebit.com/guides/waas-recipes Anchor use cases for Wallet-as-a-Service partners: per-user deposit addresses, reconciliation, payouts, and WhiteBIT Codes. Each recipe links to the guide and API reference that document its endpoints. Anchor use cases for **Wallet-as-a-Service** partners, on the managed sub-accounts model. Each recipe links to the guide and API reference that document its endpoints. This is a curated selection of common use cases, not the full API surface; for every endpoint and parameter, see the [Developer guide](/guides/waas-integration) and the [Payment Integration guide](/guides/payment-integration). These are `private` (signed) endpoints, so each call needs an API key. Enablement prerequisites vary by flow: * **Sub-account and payout flows** require institutional onboarding (KYB). * **Per-user deposit addresses** (`main-account/create-new-address`) are disabled by default — request access via `support@whitebit.com`. * **Sub-account crypto deposits** are disabled by default — request enablement through the assigned account manager or `institutional@whitebit.com`. * **WhiteBIT Codes** work on a regular account without KYB (see the live demo below). A runnable Python starter that packages these flows is planned. Create a sub-account per end user and assign a deposit address to reconcile funds against.
**Endpoints:** `sub-account/create`, `main-account/create-new-address`
Credit users from deposit webhooks, with history polling as the required fallback. Deduplicate by `uniqueId`.
**Endpoints:** `main-account/history` + webhooks
Send a crypto payout to a user's address, with on-the-fly conversion where needed.
**Endpoints:** `main-account/withdraw`
Move balance fee-free between accounts by creating and applying a WhiteBIT Code.
**Endpoints:** `main-account/codes`, `main-account/codes/apply`
Hold one currency, pay out another: quote, confirm, then withdraw the converted asset.
**Endpoints:** `convert/estimate`, `convert/confirm`, `main-account/withdraw`
Return funds from a canceled deposit (status 4/9) to an address.
**Endpoints:** `main-account/refund-deposit`
The receiver gets the exact amount; the fee is charged on top of the account balance.
**Endpoints:** `main-account/withdraw-pay`
Pay out an asset on any supported network via the `network` parameter.
**Endpoints:** `main-account/withdraw`
## Run the recipes Each use case above maps to signed REST calls documented in the [Payment Integration guide](/guides/payment-integration), which carries copy-pasteable cURL and Python examples per endpoint. Before running any flow, create an API key with the required permissions and confirm the enablement prerequisites above apply to the account. A fuller Python starter that packages every recipe into one clone-and-run project is planned; the WhiteBIT Codes flow below is runnable today. ## Demo Run it (needs a key with Codes permission and USDT on the main account): ``` git clone https://github.com/tihran-voitov_wbt/waas-starter.git cd waas-starter python3 -m venv .venv && source .venv/bin/activate pip install -r requirements-demo.txt cp .env.example .env # add WB_API_KEY / WB_API_SECRET python app.py # http://localhost:5004 ``` Live WhiteBIT Codes on a real balance: create a code for 1 USDT with `POST /api/v4/main-account/codes` and apply it with `POST /api/v4/main-account/codes/apply`, then watch the main-account balance move. Real API calls, no mock. **To reproduce:** use an API key with WhiteBIT Codes permission on an account that holds the USDT on its main balance, then call the create and apply endpoints — see [WhiteBIT Codes](/platform/whitebit-codes) and the [create](/api-reference/account-wallet/create-code) and [apply](/api-reference/account-wallet/apply-code) references. ## What's next Integration models, payment flows, and compliance. What WaaS is and how to get started. # WebSocket Quickstart Source: https://docs.whitebit.com/guides/websocket-quickstart Connect to the WhiteBIT WebSocket API — subscribe to real-time prices, orderbook updates, and private balance changes. Connect to the WhiteBIT WebSocket API for real-time streaming data. The guide targets developers building trading bots, live price feeds, or account monitoring dashboards. The same authorized connection also places orders — see [Placing orders over the same connection](#placing-orders-over-the-same-connection) (global platform only). ## Prerequisites * A terminal with a WebSocket client (Python `websocket-client` library, or `wscat` for interactive testing) * For private channels: a WhiteBIT API key with **Trading** permission and familiarity with [Authentication](/api-reference/authentication) * No special setup for public channels — same zero-authentication principle as the [Market Data API](/products/market-data/overview) WhiteBIT has no public testnet or sandbox. Private channel subscriptions expose live account data. Store API credentials securely — never commit secrets to version control or expose credentials in shared environments. For risk-free balance-change testing, use Demo Tokens (DBTC/DUSDT) — activate from the [WhiteBIT Codes page](https://whitebit.com/codes). ## Connection parameters | Detail | Value | | - | - | | Endpoint | `wss://wss.whitebit.com/ws` | | Protocol | JSON-RPC 2.0 over WebSocket | | Inactivity timeout | 60 seconds — send `ping` every 50 seconds or less | | Rate limit | 12,000 requests per 10 seconds per connection; order placements draw on a separate 10,000 per 10 seconds budget | Establish a WebSocket connection. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import websocket import json ws = websocket.create_connection("wss://wss.whitebit.com/ws") print("Connected to WebSocket API") ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} wscat -c wss://wss.whitebit.com/ws ``` A successful connection produces no immediate response. The server is ready to receive subscription messages. For Go and PHP examples, see [SDKs](/sdks). Subscribe to real-time price updates for BTC\_USDT. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Subscribe to BTC_USDT last price subscribe_msg = { "id": 1, "method": "lastprice_subscribe", "params": ["BTC_USDT"] } ws.send(json.dumps(subscribe_msg)) # Receive subscribe confirmation result = json.loads(ws.recv()) print(f"Subscribe result: {result}") # Receive price updates update = json.loads(ws.recv()) print(f"Price update: {update}") ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > {"id": 1, "method": "lastprice_subscribe", "params": ["BTC_USDT"]} ``` **Subscribe confirmation:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} {"id": 1, "result": {"status": "success"}, "error": null} ``` **Update message:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": null, "method": "lastprice_update", "params": ["BTC_USDT", "65432.10"] } ``` The `params` array contains: market name (index 0) and last traded price (index 1). The server pushes updates at 1-second intervals while the subscription is active. Subscribe to orderbook depth updates for BTC\_USDT with 5 price levels. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Subscribe to BTC_USDT depth, 5 levels, no aggregation depth_msg = { "id": 2, "method": "depth_subscribe", "params": ["BTC_USDT", 5, "0", True] } ws.send(json.dumps(depth_msg)) # Receive subscribe confirmation result = json.loads(ws.recv()) print(f"Depth subscribe: {result}") # Receive depth snapshot/update depth = json.loads(ws.recv()) print(f"Depth update: {depth}") ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > {"id": 2, "method": "depth_subscribe", "params": ["BTC_USDT", 5, "0", true]} ``` **Parameters:** market name, depth limit (a fixed set of values from 1 to 100), price aggregation interval (`"0"` = no aggregation), and the multiple-subscription flag. Full parameter semantics, including flag and unsubscribe behavior: [Depth channel](/websocket/market-streams/depth). **Update message:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": null, "method": "depth_update", "params": [ true, { "asks": [["65450.00", "0.500"], ["65460.00", "1.200"]], "bids": [["65430.00", "0.800"], ["65420.00", "1.500"]], "timestamp": 1700000000.123, "event_time": 1700000000.125, "update_id": 12345 }, "BTC_USDT" ] } ``` The first element in `params` is a boolean: `true` = full snapshot, `false` = incremental update. To maintain a local orderbook, apply incremental updates to the initial snapshot. Steps 1–3 cover public channels (no authentication required). Steps 4–5 require an API key — see [Authentication](/api-reference/authentication) for key creation and HMAC-SHA512 signing details. Private channels (balance updates, order updates) require authentication. First obtain a WebSocket token via the REST API, then send an `authorize` message. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64 import hashlib import hmac import time import requests API_KEY = "YOUR_API_KEY" API_SECRET = "YOUR_API_SECRET" BASE_URL = "https://whitebit.com" # Part A — Get WebSocket token via REST API path = "/api/v4/profile/websocket_token" data = {"request": path, "nonce": int(time.time() * 1000)} data_json = json.dumps(data) payload_b64 = base64.b64encode(data_json.encode()).decode() signature = hmac.new( API_SECRET.encode(), payload_b64.encode(), hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload_b64, "X-TXC-SIGNATURE": signature, } token_response = requests.post(BASE_URL + path, headers=headers, data=data_json) ws_token = token_response.json().get("websocket_token") print(f"WebSocket token obtained") # Part B — Send authorize message over WebSocket auth_msg = { "id": 3, "method": "authorize", "params": [ws_token, "public"] } ws.send(json.dumps(auth_msg)) auth_result = json.loads(ws.recv()) print(f"Auth result: {auth_result}") ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # First obtain a token via REST (see Python example), # then send in wscat: > {"id": 3, "method": "authorize", "params": ["YOUR_WS_TOKEN", "public"]} ``` **Token endpoint:** `POST /api/v4/profile/websocket_token` (authenticated REST call). **Authorization response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} {"id": 3, "result": {"status": "success"}, "error": null} ``` After authentication, subscribe to real-time spot balance changes. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Subscribe to USDT and BTC balance updates balance_msg = { "id": 4, "method": "balanceSpot_subscribe", "params": ["USDT", "BTC"] } ws.send(json.dumps(balance_msg)) # Receive subscribe confirmation result = json.loads(ws.recv()) print(f"Balance subscribe: {result}") # Updates arrive within 1 second of any balance change update = json.loads(ws.recv()) print(f"Balance update: {update}") ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > {"id": 4, "method": "balanceSpot_subscribe", "params": ["USDT", "BTC"]} ``` **Update message — sent within 1 second of any balance change (trade or transfer):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": null, "method": "balanceSpot_update", "params": [ { "USDT": { "available": "985.50", "freeze": "14.50" } } ] } ``` Key fields: `available` (funds ready for trading), `freeze` (funds locked in open orders). The server closes the connection after 60 seconds of inactivity. Send a ping message to verify the connection is alive. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} ping_msg = {"id": 0, "method": "ping", "params": []} ws.send(json.dumps(ping_msg)) pong = json.loads(ws.recv()) print(f"Ping result: {pong}") ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > {"id": 0, "method": "ping", "params": []} ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} {"id": 0, "result": "pong", "error": null} ``` In production, send a ping every 50 seconds or less to prevent disconnection. ## Error responses Failed requests return a JSON-RPC error object in the `error` field: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 3, "result": null, "error": { "code": 1, "message": "invalid argument" } } ``` Check the `error` field on every response before treating a request as confirmed. Typical failures: an expired or invalid token in `authorize` — obtain a fresh one via `POST /api/v4/profile/websocket_token` — and a market name that does not exist in a subscribe call. Error codes and connection limits: [WebSocket Rate Limits & Error Codes](/websocket/rate-limits). The six steps above cover a single connection. Production integrations need automatic reconnection and state recovery, covered next. ## Reconnection and state recovery WebSocket connections can drop due to network issues or server maintenance. Production integrations require automatic reconnection, re-authentication, and state recovery logic. ### Reconnection with exponential backoff The recovery flow after a dropped connection: reconnect with growing delays, re-authenticate with a fresh token, resubscribe every channel, then resync local state. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Client participant REST as REST API participant WS as WebSocket API Note over Client,WS: active connection with subscriptions WS--xClient: connection drops loop until connected — delay doubles from 1s to 30s max, plus jitter Client->>Client: wait for the backoff delay Client->>WS: reconnect end Client->>REST: POST /api/v4/profile/websocket_token REST-->>Client: fresh WebSocket token Client->>WS: authorize WS-->>Client: authorization confirmed Client->>WS: resubscribe (depth_subscribe, lastprice_subscribe, balanceSpot_subscribe, ordersPending_subscribe) WS-->>Client: confirmations, then snapshots and updates resume Client->>Client: resync state per channel type ``` The critical path is the reconnect loop — wait with backoff and jitter, reconnect, resubscribe, and reset the delay only after a successful connection: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import asyncio, json, random, websockets SUBSCRIPTIONS = [ {"method": "depth_subscribe", "params": ["BTC_USDT", 20, "0", True]}, {"method": "balanceSpot_subscribe", "params": ["USDT", "BTC"]}, ] async def listen_with_reconnect(): delay = 1 while True: try: async with websockets.connect("wss://wss.whitebit.com/ws") as ws: delay = 1 # reset backoff after a successful connection # Private channels: authorize first with a fresh token # ("Authenticate for private channels" above) for msg_id, sub in enumerate(SUBSCRIPTIONS, start=1): await ws.send(json.dumps({"id": msg_id, **sub})) # Ping every 50 seconds in a background task # ("Send a keepalive ping" above) while True: update = json.loads(await ws.recv()) # Resync per channel type ("State recovery after reconnect" below) except (OSError, websockets.exceptions.ConnectionClosed): wait = min(delay + random.uniform(0, delay * 0.5), 30) delay = min(delay * 2, 30) # exponential backoff, 1s → 30s max await asyncio.sleep(wait) ``` Key points: * **Keepalive ping** — send `ping` every 50 seconds from a background task, staying inside the 60-second inactivity timeout even when no updates flow * **Exponential backoff** — delays double on each failure (1s → 2s → 4s → ... → 30s max) with random jitter to prevent thundering herd * **Fresh token** — obtain a new WebSocket token on every reconnect; tokens may expire during long disconnections * **Full resubscription** — re-subscribe to all channels after reconnecting; the server does not remember previous subscriptions For an implementation with fill monitoring, grid strategy logic, and error recovery, see [Building a Trading Bot — Auto-resubscription](/guides/building-a-trading-bot#auto-resubscription-after-reconnect). ### State recovery after reconnect Different channels use different update models. The recovery strategy depends on the channel type: | Update model | Channels | Recovery strategy | | - | - | - | | Snapshot on subscribe | [Depth](/websocket/market-streams/depth) | First message after subscribe is a full snapshot — local state auto-recovers. Apply incremental updates from subsequent messages. Detect gaps via the `past_update_id` chain on incremental deltas; keepalive snapshots (`params[0]` is `true`) are full resets, not gaps. | | Periodic full snapshot | [Positions](/websocket/account-streams/positions), [Borrows](/websocket/account-streams/borrows), [Market](/websocket/market-streams/market), [Market Today](/websocket/market-streams/market-today) | Full state arrives within 1–1.5s of subscribing — no gap to fill. | | Incremental delta | [Balance Spot](/websocket/account-streams/balance-spot), [Balance Margin](/websocket/account-streams/balance-margin) | **Query first, then subscribe.** Send a one-time query (`balanceSpot_request` / `balanceMargin_request`) to get full state, then subscribe for incremental changes. | | Event stream | [Orders Pending](/websocket/account-streams/orders-pending), [Orders Executed](/websocket/account-streams/orders-executed), [Deals](/websocket/account-streams/deals), [Trades](/websocket/market-streams/trades) | **Query first, then subscribe.** The server does not buffer events during a disconnection. Use the one-time query operation or the REST equivalent to backfill, then subscribe. Trades resubscription replays a snapshot of up to the 100 latest trades — deduplicate by trade `id`. | | Event-only (no snapshot) | [Margin Positions Events](/websocket/account-streams/margin-positions-events), [Borrows Events](/websocket/account-streams/borrows-events) | Pair with the snapshot channel ([Positions](/websocket/account-streams/positions) / [Borrows](/websocket/account-streams/borrows)) for complete state awareness. | | Simple replacement | [Last Price](/websocket/market-streams/lastprice), [Book Ticker](/websocket/market-streams/book-ticker), [Kline](/websocket/market-streams/kline) | Each message replaces previous value — no gap handling needed. | For incremental-delta and event-stream channels, use a **query-then-subscribe** pattern: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} async def recover_and_subscribe(ws): """Query current state, then subscribe for live updates.""" # Step 1 — query full state await ws.send(json.dumps({ "id": 10, "method": "balanceSpot_request", "params": [] })) snapshot = json.loads(await ws.recv()) # Initialize local state from snapshot["result"] # Step 2 — subscribe for incremental updates await ws.send(json.dumps({ "id": 11, "method": "balanceSpot_subscribe", "params": ["USDT", "BTC"] })) ``` ## Placing orders over the same connection The connection this guide opens and authorizes also carries order flow. The [WebSocket Order Management](/websocket/order-management/overview) methods place, modify, and cancel spot, margin, and futures orders as JSON-RPC calls — the same envelope as a subscribe frame, with two differences: `params` carries a single object rather than positional values, and the error codes are numbered independently of REST. A placement uses the same frame shape as a subscribe request: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 101, "method": "order_limit_place", "params": [ { "market": "BTC_USDT", "side": "buy", "amount": "0.01", "price": "60000", "client_order_id": "quote-1" } ] } ``` The server answers with one frame echoing `id`; correlate it against the interleaved subscription pushes by `id`. See [Order Management](/websocket/order-management/overview) for the full method set, parameters, and error reference. ## What's next REST API counterpart — polling-based market data for simpler integrations. Combine WebSocket data with order placement for automated trading. Place, modify, and cancel orders over the same connection (global platform only). Combine a REST snapshot and a WebSocket stream into a live price board — no API key. Full channel catalog — market and account streams with schema references. # Yield-as-a-Service FAQ Source: https://docs.whitebit.com/guides/yaas-faq Common questions about WhiteBIT Yield-as-a-Service: scope, the integration model, onboarding and access, operations, and how B2B yield differs from the self-service flow. Answers to common questions about WhiteBIT Yield-as-a-Service (YaaS). ## Scope and delivery ### What Yield-as-a-Service delivers YaaS lets a partner offer WhiteBIT Crypto Lending yield to end users through the API, under the partner's own brand. See the [overview](/guides/yaas-overview). ### Difference from the self-service quickstart The [Crypto Lending quickstart](/products/lending/quickstart) shows the self-service flow for a single account; YaaS adds the B2B layer — a sub-account per end user, funding, and per-user reconciliation. See the [Integration guide](/guides/yaas-integration). ## Integration model ### How end-user funds are segregated Each end user earns in a dedicated sub-account with independent balances and history; the master account is the funding hub. See [How it works](/guides/yaas-overview#how-it-works). ### Whether end users need separate WhiteBIT accounts End users do not open separate accounts — each is provisioned as a sub-account under the partner's master account (Model A). See [Sub-Accounts](/products/sub-accounts/overview). ### Pooled account A single pooled (omnibus) account for end-user funds is not offered, because pooled custody conflicts with client-fund segregation and Travel Rule requirements. See [why not a pooled account](/concepts/integration-models#why-not-a-pooled-account). ## Onboarding and access ### How lending access is granted Crypto Lending is available on the master account with B2B access; on sub-accounts it is not enabled by default and must be enabled per sub-account on request. See [How to get started](/guides/yaas-overview#how-to-get-started). ### API key type for a sub-account Running lending on a sub-account requires a **type:2** key (info, trading, deposits, withdraws). See [Prerequisites](/guides/yaas-integration#prerequisites). ## Operations ### Tracking each end user's earnings Each sub-account's investments and payment history are that end user's earnings; there is no aggregated cross-sub report, so reconciliation is per sub-account. See [Reconcile earnings per user](/guides/yaas-integration#4-reconcile-earnings-per-user). ### Fixed versus flexible plans Fixed plans lock funds for a term with interest paid at maturity; flexible plans allow withdrawal anytime with interest credited daily. See [Crypto Lending](/products/lending/overview). ### Test environment availability WhiteBIT does not offer a public testnet or sandbox. Test on the live API with minimum amounts. See the [Integration guide](/guides/yaas-integration#testing). ## Compliance ### Regulatory review Eligibility to offer yield to end users is assessed during KYB and handled as part of onboarding rather than in the API. See [Regulatory Compliance](/institutional/compliance). ## Support ### Support contacts The assigned account manager is the primary contact; programs and onboarding go to `institutional@whitebit.com`. See [Institutional Onboarding](/institutional/onboarding). ## What's next What Yield-as-a-Service provides, the model, and how to apply. Provision sub-accounts, invest, and reconcile earnings. # Yield-as-a-Service integration Source: https://docs.whitebit.com/guides/yaas-integration Technical integration for Yield-as-a-Service: provision a sub-account per end user, fund it, run the Crypto Lending lifecycle in each sub-account, and reconcile earnings per user. **For developers.** This page covers the technical integration. For what YaaS is, the model, and how to apply, see the [Yield-as-a-Service overview](/guides/yaas-overview). Yield-as-a-Service uses **Model A** — one [sub-account](/products/sub-accounts/overview) per end user, with the [Crypto Lending](/products/lending/overview) lifecycle run inside each sub-account using that sub-account's own API key. This guide covers the B2B layer — provisioning, funding, and per-user reconciliation. The lending lifecycle itself is documented in the [Crypto Lending quickstart](/products/lending/quickstart); the only difference here is the signing key. ## Prerequisites * **Crypto Lending enabled where it runs.** Lending is available on the master account with B2B access; on sub-accounts it is **not enabled by default** — request enablement for each end-user sub-account via the account manager or `institutional@whitebit.com` (see the [overview](/guides/yaas-overview#how-to-get-started)). Until it is enabled, the lending endpoints are not available on that sub-account. * **A sub-account per end user**, each with its own **type:2** API key (info, trading, deposits, withdraws) — type:2 is required to run lending on a sub-account. * **Funds in the master Main balance** to allocate to each sub-account. * **HMAC-signed requests** — see [Authentication](/api-reference/authentication). ## Integration building blocks ### 1. Provision a sub-account per end user Create one sub-account per end user and issue that sub-account a type:2 API key. Build with [Sub-Accounts](/products/sub-accounts/overview) for account creation and key management, and the [Embedded Trading integration guide](/guides/sub-account-integration) for the full walkthrough (per-customer keys, KYC-URL branding). | Endpoint | Purpose | | - | - | | `POST /api/v4/sub-account/create` | Create a sub-account (`alias`, `permissions`) | | `POST /api/v4/sub-account/api-key/create` | Issue the sub-account a key (`type: 2`, `subAccountId`, `title`) | ### 2. Fund the sub-account Move funds from the master Main balance to the end user's sub-account with a fee-free transfer. | Endpoint | Purpose | | - | - | | `POST /api/v4/sub-account/transfer` | `id` (sub-account), `direction: main_to_sub`, `ticker`, `amount` | ### 3. Offer yield inside the sub-account Run the Crypto Lending lifecycle — fetch plans, invest, track, withdraw — signed with the **sub-account's own key**, so investments and interest stay in that sub-account's balance. The request and response fields are documented in the [Crypto Lending quickstart](/products/lending/quickstart); the only B2B difference is the signing key. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Invest on an end user's behalf — signed with THAT sub-account's type:2 key curl -X POST https://whitebit.com/api/v4/main-account/smart-flex/investments/invest \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: SUBACCOUNT_API_KEY" \ -H "X-TXC-PAYLOAD: PAYLOAD" \ -H "X-TXC-SIGNATURE: SIGNATURE" \ -d '{ "plan": "PLAN_ID", "amount": "100.00", "withReinvest": true, "request": "/api/v4/main-account/smart-flex/investments/invest", "nonce": 1709340000000 }' ``` The `main-account/` path segment addresses the **signing account's own Main balance** — for a sub-account key, that is the sub-account's balance, not the master's. This is why a sub-account key runs the lending lifecycle against that end user's funds. | Endpoint | Purpose | | - | - | | `POST /api/v4/main-account/smart-flex/plans` | Available flexible plans | | `POST /api/v4/main-account/smart-flex/investments/invest` | Invest on the end user's behalf | | `POST /api/v4/main-account/smart-flex/investments/withdraw` | Withdraw to the sub-account Main balance | | `POST /api/v4/main-account/smart/plans` | Available fixed plans | ### 4. Reconcile earnings per user Each sub-account's investments and payment history are that end user's earnings. There is no aggregated cross-sub report, so attribution is per sub-account — read each sub-account with its own key. | Endpoint | Purpose | | - | - | | `POST /api/v4/main-account/smart-flex/investments` | The end user's active flexible investments | | `POST /api/v4/main-account/smart-flex/investments/payment-history` | Interest credited to the end user | Per-user lifecycle: ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram autonumber participant P as Partner backend participant M as Master account participant S as End-user sub-account participant L as Crypto Lending P->>S: Create sub-account + type:2 key P->>M: POST /sub-account/transfer (main_to_sub) M-->>S: Balance allocated P->>L: Invest, signed with the sub-account key L-->>S: Interest credited to the sub-account balance P->>L: Withdraw to the sub-account Main balance P->>P: Reconcile per sub-account (payment-history) ``` ## Testing WhiteBIT does not offer a public testnet or sandbox. Test on the live API with minimum amounts, and check available plans and per-plan minimums via the plans endpoints first. ## Reference * [Sub-Accounts](/products/sub-accounts/overview) — create and manage per-user accounts and keys. * [Crypto Lending](/products/lending/overview) — Fixed and Flex plan mechanics, supported assets, and the full endpoint reference. * [Crypto Lending quickstart](/products/lending/quickstart) — the invest, track, and withdraw lifecycle. ## What's next How B2B yield differs from the self-service flow. Plan mechanics, supported assets, and the endpoint reference. Create and manage the per-user accounts this program provisions. # Yield-as-a-Service Source: https://docs.whitebit.com/guides/yaas-overview Offer WhiteBIT Crypto Lending yield to end users through the API. What Yield-as-a-Service provides, the integration model, and how to get started. Yield-as-a-Service (YaaS) lets a partner offer WhiteBIT [Crypto Lending](/products/lending/overview) yield to end users under the partner's own brand. This overview covers fit and the integration model. For the technical build, see the [Integration guide](/guides/yaas-integration). The [Crypto Lending](/products/lending/overview) product pages describe the earn capability itself — plan types, supported assets, and the endpoint reference. This program covers how a partner delivers that capability to many end users. ## What Yield-as-a-Service provides * Fixed-term and flexible yield plans, offered to end users through the API ([Crypto Lending](/products/lending/overview)). * Per-user segregation: each end user earns in a dedicated [sub-account](/products/sub-accounts/overview), with independent balances and history. * Full lifecycle control — present plans, invest on an end user's behalf, track earnings, and withdraw — all programmatic. * Auto-reinvestment for compounding on flexible plans. ## Who Yield-as-a-Service is for * **Fintechs, wallets, and neobanks** — add an earn feature for end users without building a yield engine, custody, or risk management. * **Exchanges and brokers** — offer yield on idle customer balances alongside trading. ## How it works YaaS uses **Model A**: the partner operates one [sub-account](/products/sub-accounts/overview) per end user under a master account, and runs the lending lifecycle inside each sub-account using that sub-account's own API key. Funds, investments, and interest stay segregated per user; the master account acts as the funding hub. Endpoint mechanics are on the [Integration guide](/guides/yaas-integration). ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} flowchart LR U[End user] --> P[Partner backend] P -->|one sub-account per user| S[WhiteBIT sub-account] S -->|invest · earn · withdraw| L[Crypto Lending] ``` A single pooled (omnibus) account for end-user funds is not offered: pooled custody conflicts with MiCA client-fund segregation and Travel Rule requirements. Each end user's yield sits in a segregated sub-account. See [why not a pooled account](/concepts/integration-models#why-not-a-pooled-account). ## Program terms Crypto Lending access is approval-gated and assessed during KYB. It is available on the master account, and **enabled per sub-account on request** — sub-accounts do not have lending enabled by default. Commercial terms are agreed per contract during onboarding. KYC reliance — WhiteBIT relying on the partner's own customer verification — may be available, but is not enabled by default. It is never automatic, and operates as a delegation: responsibility for customer verification is never transferred. Eligibility is assessed case by case. Reliance is available only to partners that are supervised AML-obligated entities (for example EMI, PI, VASP, or MiCA-CASP license holders) in an adequate jurisdiction, applying broadly equivalent customer due diligence, under a written agreement and an individual WhiteBIT Compliance assessment. A confirmed entry on the relevant public register establishes the licensing basis; a confirmed EU/MiCA entity is additionally required when EU users are in scope. Licensing regimes and entity structures vary, and the examples above may not capture every case. Describe your licence(s), jurisdiction, and customer due-diligence approach in full in your application so the WhiteBIT Compliance team can review your specific situation and make a determination. ## How to get started 1. Complete KYB as part of [Institutional Onboarding](/institutional/onboarding). 2. Request Crypto Lending enablement via the account manager or `institutional@whitebit.com` — for the master account, and for each sub-account that will offer yield. 3. Build the integration — see the [Integration guide](/guides/yaas-integration). ## What's next Provision sub-accounts, invest on an end user's behalf, and reconcile earnings. How B2B yield differs from the self-service flow. The earn capability this program builds on. # WhiteBIT API Platform Source: https://docs.whitebit.com/index Build trading integrations, payment flows, and institutional infrastructure on one of Europe's largest cryptocurrency exchanges.

WhiteBIT API Platform

Build trading integrations, payment flows, and institutional infrastructure on one of Europe's largest cryptocurrency exchanges.

900+ Markets REST + WebSocket 24/7 Support
## About WhiteBIT WhiteBIT is a European cryptocurrency exchange founded in 2018 and part of the W Group ecosystem. One of the largest crypto exchanges in Europe by traffic, WhiteBIT serves 8,000,000+ registered users with \$3.5T in cumulative trading volume. **Security certifications:** * ISO/IEC 27001 information security management * ISO/IEC 27701:2019 privacy information management * CCSS Level 3 cryptocurrency security standard (certified by Hacken, December 2024) * PCI DSS Level 1 payment card industry compliance (October 2024) * CER.live security score: 100/100 — first exchange to achieve a perfect score * Proof of reserves audited by Hacken (November 2024) — [audit report](https://hacken.io/audits/whitebit/) * Processes data in accordance with GDPR * **96% cold wallet storage** — the majority of platform digital assets are held in cold storage
## Getting Started WhiteBIT does not offer a public testnet or sandbox environment. Test integrations on the live API using minimum order sizes. Pairs like USDT\_UAH and assets with low minimums are suitable for testing. Check minimum order sizes via `GET /api/v4/public/markets`. ### Prerequisites * WhiteBIT account — [Register at whitebit.com](https://whitebit.com/auth/register) * Identity verification completed * API key generated (required for private endpoints only) — [API key settings](https://whitebit.com/settings/api) Public endpoints (market data, server time, asset statuses) require no authentication and no account. Generate an API key only when accessing private endpoints. ### Choose an integration method For understanding market structure and trading pair notation, see [Markets & Trading Pairs](/concepts/markets). Make a public call, then add HMAC signing for authenticated endpoints. Stream real-time market data and account updates over persistent connections.
Partner Programs

Find the integration path for each partner type.

Per-customer sub-accounts under a partner master, or apps built over users' own accounts via a partner-held API key. Maker rebates, colocation infrastructure, and bulk-order capabilities through the Market-Making Program. Deposits, payouts, merchant flows, and corporate on/off-ramp between fiat and crypto. OTC, portfolio margin, custody, and venue listings for funds, desks, banks, and exchanges.
Popular Quickstarts

Jump directly to a common integration task.

Public endpoints — no authentication required. Limit order on a spot pair in 5 minutes. Subscribe to live ticker and orderbook channels. Create accounts, transfer funds, issue per-account API keys.
Explore Products

All products available for programmatic integration.

Public endpoints for prices, orderbooks, and trades. No authentication required. 800+ spot pairs with 6 order types including bulk orders. Leveraged spot trading up to 10x on collateral balance. Perpetual contracts with up to 100x leverage on 270+ pairs. Fixed and flexible lending plans via the U EARN platform. Create thousands of separate trading accounts under one umbrella. Programmatic access to WhitePool mining statistics and payouts. Instant asset conversion at quoted rates. Generate and apply redeemable codes for internal transfers.
## Integration Methods * **REST API** — 100+ authenticated endpoints and 14 public endpoints. [API Reference](/api-reference/overview) * **WebSocket API** — Real-time market data and account updates over persistent connections. [WebSocket Reference](/websocket/overview) * **SDKs** — Go, Python, PHP client libraries. [SDKs page](/sdks) * **OAuth 2.0** — Partner-only, for third-party applications acting on behalf of WhiteBIT users. [OAuth overview](/platform/oauth/overview) * **AI Tools** — MCP server and CLI for AI-assisted integration. [AI Hub](/guides/use-with-ai) ## Platform-only features The following features are available through the WhiteBIT platform interface and are not accessible via API: Auto-Invest, Nova Card, Staking, P2P, and the built-in Copy Trading feature (partner-built copy trading over user-granted API keys is a separate integration — see [Fast API Key via OAuth](/guides/fast-api-key-integration)). Visit [whitebit.com](https://whitebit.com) for details. ## Platform availability * **Status page:** [status.whitebit.com](https://status.whitebit.com) — real-time operational status for the platform, API, and blog. The status page shows a rolling 45-day window of incidents and maintenance; for a longer history, contact support. * **Per-asset status:** [whitebit.com/system-page](https://whitebit.com/system-page) — deposit, withdrawal, and transfer availability per asset * **Maintenance:** Planned maintenance — and asset suspensions for network upgrades or hard forks, when known in advance — is announced ahead of time on the status page and, where possible, via the WhiteBIT Telegram notifications channel. Unplanned incidents are tracked on the status page in real time.
Ready to Get Started?

Start building with the WhiteBIT API.

# Regulatory Compliance Source: https://docs.whitebit.com/institutional/compliance MiCA USDT restrictions, Travel Rule requirements, data processing, certifications, and restricted jurisdictions affecting API integrations. Regulatory requirements affect API behavior depending on account jurisdiction. Two active regimes require integration changes for European Economic Area ([EEA](/glossary#european-economic-area-eea)) accounts: MiCA restrictions on USDT operations and Travel Rule data requirements on crypto withdrawals. | Regulation | Affected accounts | API impact | | - | - | - | | [MiCA — USDT restrictions](#mica-usdt-restrictions-for-eea-users) | EEA | USDT deposits, withdrawals, and WhiteBIT Codes rejected since December 30, 2024 | | [Travel Rule](#travel-rule-eea-crypto-withdrawals) | EEA (and Turkey) | `travelRule` object required on crypto withdrawals since May 19, 2025; deposit status codes 27 and 28 | | [Data processing (GDPR)](#data-processing-and-privacy) | All | No API impact — data processing terms and DPA availability | ## MiCA: USDT restrictions for EEA users Since **December 30, 2024**, EEA accounts cannot deposit, withdraw, or create WhiteBIT Codes in USDT. The restriction implements Markets in Crypto-Assets Regulation (MiCA) requirements — Tether (USDT issuer) has not obtained EU e-money authorization. ### Impact on API integrations * The server rejects USDT deposit requests from EEA accounts * The server rejects USDT withdrawal requests from EEA accounts * The server blocks WhiteBIT Codes denominated in USDT for EEA accounts * No endpoint schema changes — the same endpoints apply, but the server returns an error for USDT operations from EEA-jurisdiction accounts * Non-EEA accounts are not currently affected ### Recommended alternatives | Stablecoin | Peg | MiCA status | | - | - | - | | **USDC** | US dollar | EU e-money license obtained (issuer: Circle) | | **EURI** | Euro | MiCA-compliant | ### MiCA integration guidance Do not hardcode USDT as the default stablecoin for EEA users. Use the [Asset Status endpoint](/api-reference/market-data/asset-status-list) (`GET /api/v4/public/assets`) to check available currencies dynamically. Build currency selection logic that respects jurisdiction-specific restrictions. **Source:** [Changes to USDT Services for EEA Users (Help Center)](https://help.whitebit.com/hc/en-gb/articles/23937597184413-Important-Update-Changes-to-USDT-Services-for-EEA-Users) ### MiCA transaction thresholds The following platform-level thresholds apply to EEA users under MiCA. Any integration should account for the possibility that end users may encounter additional verification steps at these levels: | Threshold | Platform behavior | | - | - | | > 1,000 EUR | Anonymous transactions prohibited — know-your-customer (KYC) verification required | | ≥ 10,000 EUR per transaction | Additional verification checks may apply | | > 50,000 EUR annually | Enhanced due diligence required | Only fiat-backed stablecoins (e.g., USDC, EURI) are permitted under MiCA. Algorithmic stablecoins are not allowed for EEA accounts. ## Travel Rule: EEA crypto withdrawals Since **May 19, 2025**, crypto withdrawals from EEA accounts (and Turkey) require a `travelRule` object in the withdrawal request body. The requirement implements the Financial Action Task Force (FATF) Travel Rule for Virtual Asset Service Providers (VASPs). The Travel Rule API endpoints are not available to all accounts. To request access, contact the assigned Account Manager or email [institutional@whitebit.com](mailto:institutional@whitebit.com). See the [Travel Rule overview](/api-reference/travel-rule/overview) for details. ### Timeline | Date | Event | | - | - | | May 18, 2025 | New deposit status codes (27, 28) activated | | May 19, 2025 | Travel Rule enforcement activated for withdrawals | ### Withdrawal request: travelRule object The `travelRule` object is required on [`POST /api/v4/main-account/withdraw`](/api-reference/account-wallet/create-withdraw-request) for crypto withdrawals from EEA accounts (and Turkey). The object uses a structured format: | Parameter | Description | | - | - | | `walletType` | Destination wallet type: `hosted` (VASP-hosted — exchange or custodian) or `unhosted` (self-custody wallet) | | `beneficiary` | Receiver details: `type` (`individual` or `entity`), `firstName` and `lastName` (individual) or `fullName` (entity), `residenceCountry`, and an `address` object | | `vaspData` | Required when `walletType` is `hosted`: `vaspId` from the [Get VASPs](/api-reference/travel-rule/get-vasps) endpoint, or `vaspName` when the destination VASP is not in the list | For the complete field-level reference, see the [withdraw endpoint](/api-reference/account-wallet/create-withdraw-request) and the [Travel Rule concept page](/concepts/travel-rule). The API still accepts a legacy flat format (`type`, `vasp`, `name`, `address`), but withdrawals submitted in the legacy format **do not pass Travel Rule verification**. Use the structured format for all integrations and migrate existing ones — see the [legacy field mapping](/concepts/travel-rule#legacy-format-withdrawals-only) for the migration. ### Code example: withdrawal with Travel Rule The flow: collect the beneficiary and destination-wallet details from the end user first, then submit the withdrawal with the `travelRule` object attached. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant User as End user participant Partner as Partner backend participant WB as WhiteBIT API User->>Partner: withdrawal request Partner->>User: collect beneficiary and destination wallet details Partner->>WB: POST /api/v4/main-account/withdraw (travelRule object) alt travelRule object included WB-->>Partner: withdrawal accepted else travelRule object missing WB-->>Partner: request rejected end ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # EEA crypto withdrawal with Travel Rule (individual, hosted wallet) curl -X POST https://whitebit.com/api/v4/main-account/withdraw \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "ticker": "ETH", "amount": "0.5", "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18", "uniqueId": "withdrawal-001", "travelRule": { "walletType": "hosted", "beneficiary": { "type": "individual", "firstName": "John", "lastName": "Doe", "residenceCountry": "DEU" }, "vaspData": { "vaspId": "vasp-001" } }, "request": "/api/v4/main-account/withdraw", "nonce": 1709340000000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # EEA crypto withdrawal with Travel Rule (individual, hosted wallet). # Request body for POST /api/v4/main-account/withdraw: body = { "ticker": "ETH", "amount": "0.5", "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18", "uniqueId": "withdrawal-001", "travelRule": { "walletType": "hosted", "beneficiary": { "type": "individual", "firstName": "John", "lastName": "Doe", "residenceCountry": "DEU", }, "vaspData": {"vaspId": "vasp-001"}, }, } # To send: add "request" and "nonce" to the body, serialize with compact # separators (the server rejects spaced JSON), sign with HMAC-SHA512, and # send with the X-TXC-APIKEY / X-TXC-PAYLOAD / X-TXC-SIGNATURE headers — # implementation in the First API Call guide linked below. ``` [First API Call](/guides/first-api-call) documents the signing details (payload construction, nonce, and headers). For Go and PHP examples, see [SDKs](/sdks). **Entity example:** For entity withdrawals, set `beneficiary.type` to `"entity"` and provide the legal name in `fullName`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} "travelRule": { "walletType": "hosted", "beneficiary": { "type": "entity", "fullName": "Acme Trading Ltd", "residenceCountry": "DEU" }, "vaspData": { "vaspName": "Famous Vasp Inc" } } ``` ### Deposit status codes Two deposit status codes indicate Travel Rule verification in progress. Travel Rule deposit holds apply to EEA and Turkey accounts. | Status code | Name | Description | | - | - | - | | 27 | `DEPOSIT_TRAVEL_RULE_FROZEN` | Deposit frozen — awaiting Travel Rule verification | | 28 | `DEPOSIT_TRAVEL_RULE_FROZEN_PROCESSING` | Travel Rule verification in progress | Deposits with status 27 or 28 are not credited to the account balance until Travel Rule verification completes. Build deposit monitoring logic to handle status codes 27 and 28 gracefully — do not treat frozen deposits as failed deposits. To resolve a frozen deposit: when the Travel Rule API is enabled for the account, submit the required data via [Submit deposit verification](/api-reference/travel-rule/submit-deposit-verification); otherwise the depositor provides the data manually through the WhiteBIT interface. ### Travel Rule integration guidance Partners must collect beneficiary information (wallet type, beneficiary details, VASP identification) from end users **before** submitting withdrawal requests. The server rejects withdrawal requests from EEA (and Turkey) accounts that omit the `travelRule` object. **Source:** [Travel Rule Requirements (Help Center)](https://help.whitebit.com/hc/en-gb/articles/24093241373341-Travel-Rule-Requirements-Updates-to-Crypto-Withdrawals-Interface-and-API) ## Data processing and privacy * **Data residency:** WhiteBIT processes data in the European Union. A Data Processing Agreement (DPA) is available on request. * **GDPR:** WhiteBIT processes data in accordance with the General Data Protection Regulation (GDPR). * **Sub-processors:** For the current list of sub-processors, contact [compliance@whitebit.com](mailto:compliance@whitebit.com). * **Data retention:** For data retention policies, contact [compliance@whitebit.com](mailto:compliance@whitebit.com). ## Certifications and audits | Certification | Details | | - | - | | ISO 27001 | Information security management. | | PCI DSS Level 1 | Payment card data security. | | CCSS Level 3 | Cryptocurrency Security Standard. Audited by Hacken. | For certificate numbers, issuing bodies, and validity dates, contact [institutional@whitebit.com](mailto:institutional@whitebit.com). Independent verification is available on request. ## VASP registrations WhiteBIT holds VASP registrations in multiple jurisdictions. For a complete list of registration jurisdictions, supervising authorities, and registration numbers, contact [compliance@whitebit.com](mailto:compliance@whitebit.com). ## Restricted jurisdictions For a current list of restricted and prohibited jurisdictions, contact [compliance@whitebit.com](mailto:compliance@whitebit.com). ## Regulatory scope Regulatory requirements are evolving. Travel Rule enforcement and MiCA restrictions currently apply to EEA accounts (and Turkey for Travel Rule). WhiteBIT may extend enforcement to additional jurisdictions. Monitor the [WhiteBIT Help Center](https://help.whitebit.com/hc/en-gb) and the [Changelog](/changelog) for updates. ## Contact * **[compliance@whitebit.com](mailto:compliance@whitebit.com)** — DPA requests, sub-processor lists, data retention policies, VASP registration details, and restricted-jurisdiction confirmations * **[institutional@whitebit.com](mailto:institutional@whitebit.com)** — certificate verification, Travel Rule API access, and institutional onboarding Include the account jurisdiction, the partner type, and the specific request in the first message to avoid an extra clarification round-trip. ## What's Next Product catalog and partner-type routing. Step-by-step institutional onboarding process. # Institutional Onboarding Source: https://docs.whitebit.com/institutional/onboarding Two-phase onboarding process for institutional partners: crypto operations access and fiat operations (EUR/SEPA) setup. Institutional onboarding involves two distinct phases: crypto operations access (required for all partners) and fiat operations access (optional, for EUR/SEPA). Each phase has a separate compliance review cycle. ## Overview The onboarding process involves KYC, KYB, compliance review cycles, and (for fiat) additional documentation through a fiat processing partner. Listing the requirements upfront helps partners prepare documentation before starting, reducing back-and-forth delays. **Timeline:** Timeline varies depending on corporate structure, document availability, and compliance feedback cycles. Allow 2-4 weeks for Phase 1 and an additional 2-4 weeks for Phase 2. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) for current processing estimates. ## Phase 1: Crypto Operations Access Phase 1 grants access to crypto trading, [sub-accounts](/products/sub-accounts/overview), [lending](/products/lending/overview), and all API endpoints. Register at [whitebit.com/auth/register](https://whitebit.com/auth/register). Use the corporate email address that will serve as the primary account contact. Navigate to account verification settings. Complete individual identity verification for the person with signing authority. Navigate to [whitebit.com/verification-business](https://whitebit.com/verification-business). Click "Get link" to generate the KYB verification form. Complete and submit the form with corporate documentation. The WhiteBIT compliance team reviews the submission. Expect clarification requests and additional documentation requirements. Respond to compliance feedback promptly -- the review cycle involves back-and-forth until all requirements are met. Upon approval, full crypto operations become available. Generate API keys at [whitebit.com/settings/api](https://whitebit.com/settings/api). Begin API integration using the [First API Call](/guides/first-api-call) guide. **Enabling crypto deposits.** Crypto deposits are disabled by default. Once enabled for the account, the capability applies to the account and its [sub-accounts](/products/sub-accounts/overview); enablement is not available via API. To request it, contact the assigned Account Manager or email [institutional@whitebit.com](mailto:institutional@whitebit.com). ## Phase 2: Fiat Operations Access (EUR/SEPA) Phase 2 adds EUR deposit and withdrawal capabilities via SEPA. Phase 2 requires additional onboarding through WhiteBIT and a fiat processing partner. WhiteBIT manages the fiat processing partner onboarding on behalf of the partner. Partners do not contact the fiat processing partner directly. ### Required Documents The fiat processing partner typically requests the following. All documents must be in English (translated if necessary), apostilled, and less than 3 months old. **Corporate documents:** * Memorandum and Articles of Association * Extract from Register of Legal Entities **Beneficial owner source of funds/wealth:** * Annual tax declaration * Salary payslips (most recent 6 months) * Bank statements (most recent 6 months) * Relevant agreements and invoices **Company source of funds:** * Annual tax declaration * Financial statement or audit report * Bank statements (most recent 6 months) * Relevant agreements and invoices Document requirements may vary based on jurisdiction and corporate structure. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) for current requirements before preparing documents. ### Process After WhiteBIT submits the documentation to the fiat processing partner, the fiat processing partner's compliance team reviews the submission. Expect an iterative review cycle similar to Phase 1. Upon final approval, EUR/SEPA operations become available on the account. ## Contact For institutional onboarding inquiries, partnership discussions, or to check the status of an in-progress application, contact **[institutional@whitebit.com](mailto:institutional@whitebit.com)**. ## What's next Explore the full catalog of institutional products and services. MiCA, Travel Rule, and regional regulatory requirements affecting API behavior. Fiat EUR/SEPA rails via API after Phase 2 — deposits, withdrawals, conversion, and reconciliation. # Funds & Institutions Source: https://docs.whitebit.com/institutional/overview WhiteBIT's product catalog for funds and institutions -- desks, hedge funds, asset managers, prop firms, and trading venues: trading, liquidity, custody, and settlement infrastructure. WhiteBIT provides institutional and B2B partners -- market makers, hedge funds, trading platforms, fintechs, and token projects -- with trading, liquidity, custody, and settlement infrastructure. API key authentication (HMAC-SHA512) is the primary integration method. Fast API Key -- an OAuth-issued API key for acting on a customer's own account -- is live; see [Fast API Key via OAuth](/guides/fast-api-key-integration). For other partner types -- account operators, market makers, payments, wallets, or app builders -- start at [Partner Solutions](/guides/partner-solutions), the router to the right integration path. This page is the catalog for **funds and institutions** -- desks, hedge funds, asset managers, prop firms, and trading venues. ## Product Catalog Products marked with *API* have public API endpoints documented in the docs portal. All others require institutional agreements -- contact [institutional@whitebit.com](mailto:institutional@whitebit.com). ### Products with API Documentation **[Sub-Accounts](/products/sub-accounts/overview)** *API* -- Create and manage thousands of separate trading accounts. Independent API keys and IP whitelists per sub-account. Fee-free instant transfers. 19 API endpoints. **[Colocation](/platform/colocation)** *API* -- Low-latency infrastructure across EEA/EMEA and APAC regions. 35 endpoints available via colocation. Contact account manager for connection details including region, availability zone placement, and base URLs. **[Crypto Lending](/products/lending/overview)** *API* -- Fixed and Flex lending plans. \~90 supported assets. 13 API endpoints. Fixed and Flex plans require B2B partner permissions. **[Mining Pool](/products/mining/overview)** *API* -- Bitcoin mining pool (WhitePool). Account creation, hashrate monitoring, payout configuration. 11 API endpoints. ### Products Requiring Institutional Agreement **[Market-Making Program](https://institutional.whitebit.com/market-making-program)** -- Maker fee rebates up to -0.012%. Volume threshold: \$100M+/30 days for spot. Dedicated colocation access. See the [Market Maker Guide](/guides/market-maker-integration) for full integration documentation. **Credit Line** -- Borrow against existing positions to fund new trades without liquidating holdings. Terms, interest rates, and KPI requirements are individually negotiated. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) for availability. **[OTC Trading](https://institutional.whitebit.com/otc)** -- Chat Trading for large block transactions with no volume limits. Automated RFQ in development. No slippage on large orders. Contact [otc@whitebit.com](mailto:otc@whitebit.com) or visit [whitebit.com/m/otc](https://whitebit.com/m/otc). **[Crypto-as-a-Service (CaaS)](https://institutional.whitebit.com/crypto-as-a-service)** -- White-label exchange platform. 80+ blockchain networks, 330+ assets. Go-to-market in approximately 4 weeks. Integration model: dedicated instance with custom branding. Example: WhiteBIT x Crassula partnership enabling digital banks to add crypto functionality. See the [CaaS overview](/guides/caas-overview) for the integration guide. **[Liquidity Providing](https://institutional.whitebit.com/liquidity-provision)** -- Access to WhiteBIT's order books for external platforms. Peak daily volume: \$2.5B. **[Portfolio Margin](https://institutional.whitebit.com/portfolio-margin-access)** -- Cross-collateral margining. Minimum: 200,000 USDT. Up to 10x leverage. USDT and USDC collateral only. Collateral asset weights: [collateral-weight](https://whitebit.com/trading-data/collateral-weight). **[Custody](https://institutional.whitebit.com/crypto-custody)** -- 96% cold wallet storage. Fireblocks integration. ISO 27001, CCSS Level 3, and PCI DSS Level 1 certified, with the CCSS Level 3 assessment conducted by Hacken. **[Wallet-as-a-Service (WaaS)](https://institutional.whitebit.com/crypto-wallets-for-business)** -- Generate deposit addresses across 340+ crypto assets and 80+ networks via API. Supports bulk payments, automatic per-recipient address generation, multichain transfers (receive on one network, send on another), and built-in AML compliance checks. Fireblocks integration for custody security. Bundled pricing with no per-stage charges. See the [WaaS integration guide](/guides/waas-overview). **[Payments for Businesses](https://institutional.whitebit.com/payments-for-businesses)** -- SEPA EUR payments. Mass payouts. Merchant payment processing via Whitepay. **[Embedded Trading](https://institutional.whitebit.com/broker-program)** -- Earn up to 40% of trading fees from referred users. Two integration architectures — partner-operated sub-accounts or customers' own accounts via Fast API Key. Cross-marketing support. See the [Embedded Trading overview](/guides/embedded-trading-overview) for both models and full integration documentation. **[Token Listing](https://institutional.whitebit.com/token-listing)** -- 330+ projects listed across Spot and Futures markets. Marketing support, trading tournaments, and Launchpad participation included post-listing. **Listing requirements:** 1. Product with real-world utility and practical user value 2. Detailed whitepaper covering concept, goals, and operational mechanics 3. Registered company with an experienced team 4. Open-source code repository with a verified smart contract audit 5. Demonstrated ability to provide and maintain market liquidity **Process:** Submit application → team assessment → terms discussion → contract signing → exchange announcement → marketing launch. Timeline: weeks to months depending on submission completeness. Fees are individually negotiated. Apply: [whitebit.com/token-listing](https://whitebit.com/token-listing) | Contact: [listing@whitebit.com](mailto:listing@whitebit.com) ## Additional Programs * **VIP Program** -- tiered fee discounts for high-volume traders. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) for tier qualification. * **Launchpad** -- token launch platform for new projects. Available alongside Token Listing. See [institutional.whitebit.com](https://institutional.whitebit.com). * **Whitepay** -- merchant crypto payment processing. See [Payments for Businesses](https://institutional.whitebit.com/payments-for-businesses). ## Security & Compliance * **Certifications:** ISO 27001, CCSS Level 3, and PCI DSS Level 1, with the CCSS Level 3 assessment conducted by Hacken. Details available on request. * **GDPR compliant** -- data processed in the European Union. Data Processing Agreement (DPA) available on request. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com). * **VASP registrations** -- registered in multiple jurisdictions. For a complete list of VASP registration jurisdictions and supervisory authorities, contact [compliance@whitebit.com](mailto:compliance@whitebit.com). * **Regulatory compliance** -- MiCA and Travel Rule compliance documented on the [Compliance](/institutional/compliance) page. ## Get Started Contact **[institutional@whitebit.com](mailto:institutional@whitebit.com)** for partnership inquiries, program applications, and institutional onboarding. See the [Onboarding Guide](/institutional/onboarding) for the step-by-step process. ## What's Next Step-by-step institutional onboarding process. MiCA, Travel Rule, and regional compliance requirements. Integration sequence by business type. Cross-cutting answers on KYB, sandbox access, fees, and rate limits. # Colocation Services Source: https://docs.whitebit.com/platform/colocation WhiteBIT offers professional-grade [colocation](https://docs.whitebit.com/glossary/#colocation) services for [high-frequency trading (HFT)](https://docs.whitebit.com/glossary/#high-frequency-trading-hft) and algorithmic trading operations. Place trading servers close to the exchange’s [matching engine](https://docs.whitebit.com/glossary/#matching-engine) to achieve minimal [latency](https://docs.whitebit.com/glossary/#latency) and enhanced trading performance. # Performance Highlights Execute trades with ultra-low latency Connect directly to WhiteBIT's matching engine Choose between Europe and Asia data centers Full technical assistance and monitoring ## Implementation Guide 1. [Contact the institutional sales team](#contact-options) 2. Complete KYB verification 3. Sign service agreement 4. Provide technical requirements 5. Schedule implementation #### Network Setup * Network: 10Gbit connectivity minimum * Compute: 4+ vCPU cores minimum * Instance type: dedicated EC2 instances (recommended — low-performance VPS results in higher latency) * Security: IP address pool required for allowlisting #### Region Selection * Trading operations supported across EEA/EMEA and APAC regions * Contact the account manager for connection details including region, availability zone placement, and base URLs The technical team will assist with: * Network configuration including aws cloud latency optimized proxy * Performance testing * Trading system integration ## Available Connectivity Colocation supports both REST API and WebSocket connections. The REST API provides access to a subset of endpoints optimized for low-latency trading. WebSocket connections enable real-time market data and order updates. For the full list of 35 available colocation endpoints, quoting strategies, and infrastructure best practices, see the [Market Maker Integration Guide](/guides/market-maker-integration). Colocation provides a **subset** of the full WhiteBIT API. Only specific trading, collateral, and utility endpoints are available via the colocation infrastructure. See the [Market Maker Integration Guide](/guides/market-maker-integration#available-colocation-endpoints) for the complete endpoint list. ## Contact Options For detailed pricing and technical specifications: * Email: [institutional@whitebit.com](mailto:institutional@whitebit.com) * Web Form: [institutional.whitebit.com/colocation](https://institutional.whitebit.com/colocation#anchor-form) Service availability and specifications may vary by region. Contact the team for location-specific details. ## What's Next Full colocation walkthrough: endpoints, quoting strategy, and infrastructure best practices. Configure STP modes for two-sided quoting on colocation infrastructure. # Convert Source: https://docs.whitebit.com/platform/convert Instantly convert between currencies at a quoted rate without placing orders on the orderbook. Convert provides instant currency conversion at a quoted rate. Unlike [spot trading](/products/spot/overview), Convert requires no orderbook interaction — request a quote and confirm it before it expires, or do both in a single call, and the conversion executes immediately. ## When to use Convert | Feature | Convert | Spot Trading | | - | - | - | | Execution | Instant at quoted rate | Depends on orderbook liquidity | | Orderbook | No orderbook interaction | Orders placed on the orderbook | | Order types | Single quote-and-confirm flow | 6 order types (limit, market, stop-limit, stop-market, OCO, bulk) | | Best for | Quick conversions, price estimation | Advanced trading strategies, precise price control | Convert also serves as a price estimation tool. Call the estimate endpoint before placing a market order to preview the approximate execution price. ## Conversion flow The quoted-rate flow has two steps: estimate and confirm. Send a `POST` request to [`/api/v4/convert/estimate`](/api-reference/convert/convert-estimate) with the following parameters: `from` (source ticker), `to` (destination ticker), `direction` (`"from"` or `"to"`), and `amount`. The response includes `id` (quote identifier), `give`, `receive`, `rate`, and `expireAt`. Send a `POST` request to [`/api/v4/convert/confirm`](/api-reference/convert/convert-confirm) with `quoteId` set to the `id` returned by the estimate. The response returns `finalGive` and `finalReceive`. Each estimate response includes an `expireAt` timestamp — confirm before that moment. Honour the value returned per quote rather than hard-coding a fixed window. If the quote expires before confirmation, request a new estimate. [Convert Auto Confirm](/api-reference/convert/convert-auto-confirm) collapses both steps into one request: the quote is requested and accepted in one call, so no expiry window applies and no `quoteId` round-trip is needed. The endpoint accepts an optional idempotency key that makes a retry safe. ## API endpoints Convert uses 4 authenticated endpoints. All require HMAC-SHA512 signing. | Endpoint | Purpose | Rate limit | | - | - | - | | [`POST /api/v4/convert/estimate`](/api-reference/convert/convert-estimate) | Request a conversion quote | 10,000 req / 10 sec | | [`POST /api/v4/convert/confirm`](/api-reference/convert/convert-confirm) | Confirm and execute a quote | 10,000 req / 10 sec | | [`POST /api/v4/convert/auto-confirm`](/api-reference/convert/convert-auto-confirm) | Request and accept a quote in a single call | 10,000 req / 10 sec | | [`POST /api/v4/convert/history`](/api-reference/convert/convert-history) | Retrieve conversion history (max 6 months) | 10,000 req / 10 sec | ## Estimate parameters | Parameter | Type | Required | Description | | - | - | - | - | | `from` | string | Yes | Source currency ticker (e.g., `BTC`) | | `to` | string | Yes | Destination currency ticker (e.g., `USDT`) | | `direction` | string | Yes | `"from"` = amount is in source currency; `"to"` = amount is in destination currency | | `amount` | string | Yes | Amount to convert or receive | ## Code example Estimate a BTC-to-USDT conversion and confirm the quote. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Step 1: Request a conversion estimate curl -X POST https://whitebit.com/api/v4/convert/estimate \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -H "Content-Type: application/json" \ -d '{ "from": "BTC", "to": "USDT", "direction": "from", "amount": "1", "request": "/api/v4/convert/estimate", "nonce": 1 }' ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": "123", "from": "BTC", "to": "USDT", "give": "1", "receive": "34299.76831549", "rate": "34299.76831549", "expireAt": 1699016476 } ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Step 2: Confirm the quote using the id from the estimate response curl -X POST https://whitebit.com/api/v4/convert/confirm \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -H "Content-Type: application/json" \ -d '{ "quoteId": "123", "request": "/api/v4/convert/confirm", "nonce": 2 }' ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "finalGive": "1", "finalReceive": "34299.76831549" } ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Step 1: Request a conversion estimate. # Request body for POST /api/v4/convert/estimate: estimate_body = { "from": "BTC", "to": "USDT", "direction": "from", "amount": "1", } # The response returns id, give, receive, rate, and expireAt. # Step 2: Confirm before expireAt, quoting the estimate id. # Request body for POST /api/v4/convert/confirm: confirm_body = { "quoteId": "123", # id from the estimate response } # To send: add "request" and "nonce" to the body, serialize with compact # separators (the server rejects spaced JSON), sign with HMAC-SHA512, and # send with the X-TXC-APIKEY / X-TXC-PAYLOAD / X-TXC-SIGNATURE headers — # implementation in the First API Call guide linked below. ``` [First API Call](/guides/first-api-call) documents the signing details (payload construction, nonce, and headers). For Go and PHP examples, see [SDKs](/sdks). ## History filters The [history endpoint](/api-reference/convert/convert-history) supports filtering by `fromTicker`, `toTicker`, `quoteId`, and time range (`from`/`to` timestamps). The default limit is 100 records. The maximum history depth is 6 months from the current month. ## Convert in payment flows Convert is commonly used as part of the withdrawal flow when the currency held in Main balance differs from the currency an end user needs to withdraw. The pattern is: request an estimate, confirm the quote, then submit the withdrawal in the destination currency — balance routing is handled internally by the convert service. For the full step-by-step withdrawal-with-conversion flow including code examples, see [Payment Integration](/guides/payment-integration). ## What's next Deposit and withdrawal flows including conversion. Place orders on the orderbook with 6 order types. Transfer funds between accounts using fee-free digital vouchers. # OAuth 2.0 on WhiteBIT Source: https://docs.whitebit.com/platform/oauth/overview OAuth 2.0 integration with WhiteBIT enables secure, token-based authorization for third-party applications. **Deprecated.** The OAuth 2.0 Authorization Code Grant flow for direct account-data access is deprecated and will be removed on **November 1, 2026**. New partner integrations should use the [Fast API Key flow](/guides/fast-api-key-integration), which issues a WhiteBIT API key on the user's behalf and calls the standard [V4 API](/api-reference/authentication). ## Key Benefits * **Enhanced Security**: Users grant access without sharing WhiteBIT credentials with third-party applications * **Granular Permissions**: Fine-grained scope controls allow users to limit what third-party applications can access * **Streamlined Trading Experience**: Enables seamless integration with portfolio trackers, trading bots, and analysis tools * **Developer-Friendly**: Standardized implementation familiar to developers across the ecosystem ## How WhiteBIT OAuth Works Users approve access for a third-party application through WhiteBIT’s authorization page The application exchanges the authorization code for an access token The application uses the access token to make API calls to WhiteBIT on the user’s behalf When the access token expires, the application can use a refresh token to obtain a new one ## Use Cases #### Partner API key issuance Partner platforms issue WhiteBIT API keys on behalf of end users through the OAuth API key flow. The flow replaces manual key creation with a consent-driven bootstrap: the user authorizes the partner once, and the WhiteBIT platform issues a partner-scoped API key with a secret that the partner retrieves through a dedicated endpoint. See the [Fast API Key integration guide](/guides/fast-api-key-integration). #### Trading Bots & Algorithmic Trading Enable automated trading strategies without storing WhiteBIT credentials in third-party systems. Trading bots can place, modify, and cancel orders while only having the specific permissions required. ### Portfolio Trackers & Analytics Allow portfolio management applications to read balance and trade history information without write access to trading functions, providing users with consolidated views of assets across multiple platforms. ### Mobile Applications Provide a seamless authentication experience in mobile apps without requiring users to enter and store WhiteBIT credentials in the app. ### Enterprise Integrations Enable business systems to securely connect to WhiteBIT for institutional trading, reporting, and compliance purposes with proper audit controls. ## Available Scopes WhiteBIT OAuth 2.0 implementation supports a wide range of permission scopes available for request during client setup, including: * Account information access * Balance and transaction history * Order management (read, create, delete) * Market data access * Trading history * OAuth API key management (`apikeys.create`, `apikeys.read`, `apikeys.delete`) * And more specialized permissions For a complete list of available scopes and detailed implementation instructions, please visit the [Usage](/platform/oauth/usage/overview#scopes) page. ## Getting Started **WhiteBIT OAuth 2.0 integration is exclusively offered to close ecosystem partners.** To integrate WhiteBIT OAuth 2.0 with an application, contact support at [support@whitebit.com](mailto:support@whitebit.com) — the channel applies to the deprecated classic flow; new integrations enroll in the [Fast API Key flow](/guides/fast-api-key-integration) via `institutional@whitebit.com`. The support team guides through the OAuth integration process, including: 1. Application registration and approval 2. Scope request and configuration 3. Implementation support for the OAuth 2.0 authorization flow 4. Technical documentation for token exchange and API authentication Once the integration request is approved, detailed instructions are provided for implementing the OAuth 2.0 flow. ## Next Steps: Implementation Details The [Usage](/platform/oauth/usage/overview) page provides comprehensive documentation on: * Endpoint specifications for authorization and token exchange * Request and response formats with example code * Complete list of available scopes and associated permissions * Step-by-step implementation guides for common scenarios * Troubleshooting tips and best practices The usage documentation guides through the entire implementation process from initial setup to making the first authenticated API calls. For partner integrations that need to issue API keys on behalf of users, the [Fast API Key integration guide](/guides/fast-api-key-integration) covers the end-to-end consent and key-management flow. The [OAuth endpoint overview](/api-reference/oauth/usage/overview) lists every OAuth endpoint in the API Reference. ## Support For questions or assistance with OAuth 2.0 integration, contact support at [support@whitebit.com](mailto:support@whitebit.com). # Usage Overview Source: https://docs.whitebit.com/platform/oauth/usage/overview OAuth 2.0 authentication endpoints for obtaining and refreshing access tokens. **Deprecated.** The OAuth 2.0 Authorization Code Grant flow for direct account-data access is deprecated and will be removed on **November 1, 2026**. New partner integrations should use the [Fast API Key flow](/guides/fast-api-key-integration), which issues a WhiteBIT API key on the user's behalf and calls the standard [V4 API](/api-reference/authentication). ## Introduction WhiteBIT OAuth 2.0 implementation uses the standard **Authorization Code Grant** flow. This flow is suitable for server-side applications where the client secret can be securely stored. The OAuth 2.0 endpoints documented on this page cover the Authorization Code Grant flow for read access to account data. For partner-issued API keys, a separate OAuth API key flow uses Authorization Code with PKCE (S256) and issues a short-lived access token together with a refresh token. See the [Fast API Key integration guide](/guides/fast-api-key-integration) for the full integration. ## Authorization Code Grant flow The flow involves three parties: the end user in a browser, the client application backend, and WhiteBIT. The client application redirects the user to WhiteBIT for authentication and consent, receives a one-time authorization code on the registered callback URL, exchanges the code for tokens server-side, and refreshes the access token on expiry. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant User as End user (browser) participant App as Client application participant WB as WhiteBIT User->>App: open sign-in with WhiteBIT App->>User: redirect to GET /auth/login (client ID, state) User->>WB: authenticate and grant consent WB->>User: redirect to callback URL (authorization code, state) User->>App: callback request App->>App: validate state against the stored session value App->>WB: POST /oauth2/token (authorization code) WB-->>App: access token + refresh token App->>WB: API requests with the access token App->>WB: POST /oauth2/refresh_token (refresh token) WB-->>App: new access token + refresh token ``` Generate a cryptographically secure random `state` value before redirecting to [`GET /auth/login`](/api-reference/oauth/usage/authorize), store the value in the session, and validate the callback against the stored value before exchanging the code — treat mismatched or missing state as a possible CSRF attempt and abort the flow. Access tokens are short-lived; refresh the access token server-side instead of re-running the consent flow. ## Token exchange Exchange the authorization code received on the callback URL for an access token by calling [`POST /oauth2/token`](/api-reference/oauth/usage/get-access-token) with a form-encoded body: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/oauth2/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "code=AUTHORIZATION_CODE" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "access_token": "MZM1MDBMMJYTNWM4MI0ZNTIYLTKXNDATNZY1MZHKM2Y2MJY3", "expires_in": 300, "refresh_token": "ODK5ZTVKZDUTYTI5ZC01NWJHLTGZZDMTYWFKYTNMNJHHMGZM", "scope": "codes.apply,show.userinfo", "token_type": "Bearer" } } ``` Store both tokens server-side. The `expires_in` value is the access-token lifetime in seconds. See the [Get Access Token reference](/api-reference/oauth/usage/get-access-token) for the full request and error contract, including the IP allowlist requirement. ## Token refresh When the access token expires, obtain a new one with [`POST /oauth2/refresh_token`](/api-reference/oauth/usage/refresh-token) — without user interaction: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/oauth2/refresh_token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "token=REFRESH_TOKEN" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "access_token": "NTBLZJKYNZETNJFIZC0ZNGM1LWJMYTMTODBJYZRKNWE2NMRM", "expires_in": 300, "refresh_token": "ODZMNMRHM2ETMZQZZI01OTQYLWEWMZATNWQ0NDYZNJBMOWUW", "scope": "codes.apply,show.userinfo", "token_type": "Bearer" } } ``` Each refresh returns a new refresh token — replace the stored pair on every refresh. The refresh token is also short-lived and rate-limited; see the [Refresh Token reference](/api-reference/oauth/usage/refresh-token) for the token lifetimes and rate limit. ## Scopes Available Scopes (requested during client setup): * `general`: General API access * `show.userinfo`: Access to basic user information * `users.read`: Read user data * `users.email.read`: Read user email information * `users.kyc.read`: Information about whether a user has passed KYC verification * `orders.read`: Read trading orders * `orders.create`: Create trading orders * `orders.delete`: Delete trading orders * `balances.read`: Read account balances * `markets.read`: Read market information * `deals.read`: Read trading deals * `orders_history.read`: Read order history * `users.transactions.read`: Read user transactions * `users.converts.read`: Read currency conversion history * `users.balances.read`: Read user account balances * `users.orders.read`: Read user orders * `users.deals.read`: Read user deals * `apikeys.create`: Issue an OAuth-bound API key during the consent flow * `apikeys.read`: Read OAuth-issued API key state and retrieve its secret once * `apikeys.delete`: Delete an OAuth-issued API key owned by the OAuth2 client # API Overview Source: https://docs.whitebit.com/platform/overview The WhiteBIT API covers REST and WebSocket endpoints, base URLs, versioning, and integration setup. ## Introduction WhiteBIT API provides comprehensive access to the trading platform through both `public` and `private` endpoints. Using any WhiteBIT API endpoint confirms agreement to the [Terms of Use](https://whitebit.com/terms/api). ## REST API The REST API provides access to market data, trading, account management, and more. See the [API Reference](/api-reference/overview) for full details. * **Market Data**: Public endpoints for market info, orderbook, trades, and statistics — use `GET` with [query string](https://en.wikipedia.org/wiki/Query_string) parameters * **Trading & Account**: Private endpoints for spot trading, collateral trading, account management, and sub-accounts — use `POST` with appropriate Body data and Headers * **Authentication**: Required for all private endpoints — [Authentication Guide](/api-reference/authentication) * **IP Restrictions**: Up to 5 trusted IPs can be configured for security ## WebSocket API WebSocket connections provide real-time data streaming and interaction. See the [WebSocket Overview](/websocket/overview) for connection details. * [Market Streams](/websocket/market-streams/overview) — Market data, klines, order book, trades, and statistics * [Account Streams](/websocket/account-streams/overview) — Account data, balances, orders, and deals ## Other Integration Options * [**Webhooks**](/platform/webhook) - Receive events and notifications on a server * [**OAuth**](/platform/oauth/overview) - Implement secure third-party authorization * [**Colocation**](/platform/colocation) - Low-latency trading infrastructure services * [**Self-Trade Prevention**](/platform/self-trade-prevention) - Mechanisms to prevent wash trading ## Resources * [**SDKs**](/sdks) - Official software development kits * [**Glossary**](/glossary) - Terminology and definitions * [**FAQ**](/faq) - Frequently asked questions * [**Status Page**](https://status.whitebit.com/) - Real-time service status and incident monitoring * [**AI Tools**](/guides/use-with-ai) - AI chat tools and IDE integrations for exploring the API documentation # Self Trade Prevention (STP) Source: https://docs.whitebit.com/platform/self-trade-prevention Self Trade Prevention (STP) is a mechanism to prevent traders from executing trades against the same trader's orders. The feature helps maintain market integrity and avoid unintentional self-trading scenarios. ## Overview When placing [orders](/glossary#orders), specify how the system should handle potential self-trades using the `stp` parameter. This parameter determines the behavior when an order would match against another order from the same account. Deprecation notice: the long-form mode values `cancel_both`, `cancel_new`, and `cancel_old` are deprecated. The long-form values remain accepted and behave identically to the abbreviated equivalents (`cb`, `cn`, `co`) until a migration deadline is announced, after which the API rejects the long-form values. Responses already return only the abbreviated values. Migrate integrations to the abbreviated forms now. ## STP Modes The following STP modes are available: | Mode | Description | | - | - | | `no` | Default mode. Self-trades are allowed | | `cb` | Cancel both: the new order and the existing order will be canceled | | `cn` | Cancel new: the new order will be canceled, and the existing order will remain | | `co` | Cancel old: the existing order will be canceled, and the new order will be placed | ## Usage Specify the STP mode when placing any type of order: * [Limit orders](/glossary#limit-order) * [Market orders](/glossary#market-order) * [Stop-limit orders](/glossary#stop-limit-order) * [Stop-market orders](/glossary#stop-market-order) * [OCO orders](/glossary#oco-orders) (One Cancels Other) * [Collateral orders](/glossary#collateral) ### Example ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "market": "BTC_USDT", "side": "buy", "amount": "0.001", "price": "40000", "stp": "cb" } ``` ## Supported Endpoints STP is supported on the following API endpoints: * [POST `/api/v4/order/new`](/api-reference/trading/create-limit-order) (Limit orders) * [POST `/api/v4/order/market`](/api-reference/trading/create-market-order) (Market orders) * [POST `/api/v4/order/stock_market`](/api-reference/trading/create-buy-stock-market-order) (Stock market orders) * [POST `/api/v4/order/stop_limit`](/api-reference/trading/create-stop-limit-order) (Stop-limit orders) * [POST `/api/v4/order/stop_market`](/api-reference/trading/create-stop-market-order) (Stop-market orders) * [POST `/api/v4/order/bulk`](/api-reference/trading/bulk-limit-order) (Bulk limit orders — per order item) * [POST `/api/v4/order/modify`](/api-reference/trading/modify-order) (Modify order) * [POST `/api/v4/order/collateral/limit`](/api-reference/trading/collateral-limit-order) (Collateral limit orders) * [POST `/api/v4/order/collateral/market`](/api-reference/trading/collateral-market-order) (Collateral market orders) * [POST `/api/v4/order/collateral/stop-limit`](/api-reference/trading/collateral-stop-limit-order) (Collateral stop-limit orders) * [POST `/api/v4/order/collateral/trigger-market`](/api-reference/trading/collateral-trigger-market-order) (Collateral trigger market orders) * [POST `/api/v4/order/collateral/oco`](/api-reference/trading/create-collateral-oco-order) (Collateral OCO orders) ## Best Practices 1. **Default Behavior**: If no STP mode is specified, the system defaults to `no`, allowing self-trades. 2. **Risk Management**: For automated trading systems or when running multiple strategies, use `cb` or `cn` to prevent unintentional self-trades. 3. **Market Making**: When running [market making](/glossary#maker) strategies, consider using `cn` to maintain existing orders' queue position. ## Response Handling When an order is affected by STP rules, the order response includes the `stp` field indicating the applied mode. The `stp` field always returns the abbreviated value (`no`, `cb`, `cn`, `co`), even when the request used a deprecated long-form value. The order status will reflect the outcome based on the STP mode: * Orders canceled due to STP will have a "CANCELED" status * Successfully placed orders will proceed with normal status progression # Webhook HTTP API Source: https://docs.whitebit.com/platform/webhook Configure webhook callbacks to receive real-time notifications for deposits and withdrawals on WhiteBIT. ## Why Webhooks? Webhooks deliver real-time HTTP notifications when events occur on a WhiteBIT account — deposits arriving, withdrawals completing, codes being applied, and refunds processing. Without webhooks, the only alternative is polling the deposit/withdrawal history endpoints repeatedly. **Webhooks vs polling:** | | Webhooks | Polling | | - | - | - | | Latency | Real-time (seconds) | Depends on polling interval | | Server load | Event-driven — no wasted requests | Constant requests, mostly empty | | Reliability | \~3 delivery attempts spaced roughly hourly over a \~1-day window | As reliable as the polling loop | | Recommended for | Production payment flows | Fallback for outages exceeding the delivery window | There is no webhook replay mechanism. If every delivery attempt fails, the event is dropped. Implement polling of the [deposit / withdrawal history](/api-reference/account-wallet/get-deposit-withdraw-history) endpoint as a fallback so events can be reconciled after extended consumer downtime. **Common use cases:** * **Payment processing** — Detect incoming deposits and credit end users automatically * **Withdrawal monitoring** — Track withdrawal lifecycle from creation to completion or cancellation * **Code redemption** — Receive notification when a WhiteBIT Code is applied * **Refund handling** — Detect successful or failed refunds for reconciliation ## How to use A webhook is a separate entity with its own generated key and secret. It is not a property of a trading API key, and a trading API key never carries a webhook URL. An account has at most one webhook. The platform enforces this limit, so a second webhook cannot be created on the same account. A sub-account counts as a separate account, so the main account and each sub-account can have one webhook. Event types are selected on the webhook itself, so a single URL receives every event type subscribed on it. 1. Log in to whitebit.com. 2. Open the API keys tab. 3. Select the web-hook configuration tab. 4. Paste the correct URI for the web server to process web-hook calls. 5. Press Generate a new key button and toggle the activation switcher to "Activated". The secret key is shown only once. Save it in a secure key store. ## Requirements ### For web hook keys generation Before using webhooks, verify ownership of the domain set as the webhook destination. Use one of three methods: 1. Add a TXT DNS record to the domain with the webhook public key. 2. Add the plain text file `whiteBIT-verification.txt` to the root domain folder and provide public web access. Place the public webhook key in the file. 3. Implement the `/whiteBIT-verification` endpoint to respond with 200 OK and return a JSON array containing the public webhook key. Example: `[""]` Passing one of these checks enables the webhook. ### For processing web-hook requests All web hook requests are performing using POST method and with application/json content type. Consumer server should respond with 200 HTTP status code. If the consumer cannot handle the webhook, the platform retries delivery a small number of times spaced roughly an hour apart, over a window of about one day. Treat the exact cadence as best-effort, not a contract, and pair webhook consumption with periodic history polling for reconciliation. #### Body data All web-hook requests are performing with ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "string", "params": { "nonce": 0 }, "id": "uniqueID" } ``` **method** - string. The name of method which was evaluated. Web hooks API supports such web-hook methods: * **code.apply**. Performs when code owned by a customer was applied. **id** - string. Uuid to identify every request. **params** - the request payload. Contains data about the actions triggering the webhook call. The field also contains a [nonce](/glossary#nonce). **'nonce'** - a number always **greater** than the previous request’s nonce number #### Request headers Also, all request contains additional data in headers: 1. `'Content-type': 'application/json'` 2. `'X-TXC-APIKEY': api_key` - the WhiteBIT webhook API key 3. `'X-TXC-PAYLOAD': payload'` - where payload is base64-encoded body data 4. `'X-TXC-SIGNATURE': signature` - where signature is `hex(HMAC_SHA512(payload), key=api_secret))`. `api_secret` is the secret of the generated webhook key. On the consumer side, process the security headers to verify the request originated from WhiteBIT. ## WebHook Methods ### WhiteBIT code apply Performed when [code](/glossary#whitebit-codes) was applied. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "code.apply", "params": { "code": "", "nonce": 1 }, "id": "45a1d85d-2fdf-483e-8dfa-6d253148c730" } ``` ### WhiteBIT deposit to main balance Performed when deposit was accepted. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "deposit.accepted", "params": { "address": "wallet address", // deposit address "amount": "0.000600000000000000", // amount of deposit "createdAt": 1593437922, // timestamp of deposit "currency": "Tether US", // deposit currency "description": "", // deposit description "fee": "0.000000000000000000", // deposit fee "memo": "", // deposit memo "method": 1, // called method 1 - deposit, 2 - withdraw "network": "ERC20", // if currency is multi network "status": 15, // transactions status "ticker": "USDT_ETH", // deposit currency ticker "transactionHash": "transaction hash", // deposit transaction hash "uniqueId": null, // unique Id of deposit "confirmations": { // if transaction has confirmations info it will display here "actual": 1, // current block confirmations "required": 2 // required block confirmation for successful deposit } }, "id": "uuid" } ``` Performed when deposit was update. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "deposit.updated", "params": { "address": "wallet address", // deposit address "amount": "0.000600000000000000", // amount of deposit "createdAt": 1593437922, // timestamp of deposit "currency": "Tether US", // deposit currency "description": "update", // deposit description "fee": "0.000000000000000000", // deposit fee "memo": "", // deposit memo "network": "ERC20", // if currency is multi network "status": 15, // transactions status "ticker": "USDT_ETH", // deposit currency ticker "transactionHash": "transaction hash", // deposit transaction hash "uniqueId": null, // unique Id of deposit "confirmations": { // if transaction has confirmations info it will display here "actual": 1, // current block confirmations "required": 2 // required block confirmation for successful deposit } }, "id": "uuid" } ``` Performed when the deposit was processed and is available on the balance. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "deposit.processed", "params": { "address": "wallet address", // deposit address "amount": "0.000600000000000000", // amount of deposit "createdAt": 1593437922, // timestamp of deposit "currency": "Tether US", // deposit currency "description": "", // deposit description "fee": "0.000000000000000000", // deposit fee "memo": "", // deposit memo "method": 1, // called method 1 - deposit, 2 - withdraw "network": "ERC20", // if currency is multi network "status": 15, // transactions status "ticker": "USDT_ETH", // deposit currency ticker "transactionHash": "transaction hash", // deposit transaction hash "uniqueId": null, // unique Id of deposit "confirmations": { // if transaction has confirmations info it will display here "actual": 1, // current block confirmations "required": 2 // required block confirmation for successful deposit } }, "id": "uuid" } ``` Performed when deposit was canceled. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "deposit.canceled", "params": { "address": "wallet address", // deposit address "amount": "100.00", // amount of deposit "createdAt": 1593437922, // timestamp of deposit "currency": "Tether US", // deposit currency "description": "", // deposit description "fee": "0.000000000000000000", // deposit fee "memo": "", // deposit memo "method": 1, // called method 1 - deposit, 2 - withdraw "network": "ERC20", // if currency is multi network, "null" if no multi network "status": 15, // transactions status "ticker": "USDT_ETH", // deposit currency ticker "transactionHash": "transaction hash", // deposit transaction hash "uniqueId": null, // unique Id of deposit "confirmations": { // if transaction has confirmations info it will display here "actual": 1, // current block confirmations "required": 32 // required block confirmation for successful deposit } }, "id": "uuid" } ``` #### Travel Rule deposit statuses (EEA) For EEA users, an inbound deposit may be frozen pending Travel Rule verification, and the deposit carries a Travel Rule status code (see the table below). There is currently no webhook for these transitions, so track status changes via the [deposit/withdraw history](/api-reference/account-wallet/get-deposit-withdraw-history). When the Travel Rule API is enabled for the account, submit the deposit originator data via [Submit deposit originator data](/api-reference/travel-rule/submit-deposit-verification) (`POST /api/v4/travel-rule/deposit/verification`); otherwise the deposit is verified manually at whitebit.com. Funds are credited only after successful verification. For details on Travel Rule requirements and the travelRule object for withdrawals, see [Regulatory Compliance](/institutional/compliance). Deposit status codes: | Code | Status | Description | | - | - | - | | 15 | Pending | Deposit detected, awaiting confirmations | | 27 | Travel Rule Frozen | Deposit frozen; the user must complete Travel Rule verification (EEA) | | 28 | Travel Rule Frozen Processing | Travel Rule data submitted, verification in progress (EEA) | ### WhiteBIT withdraw from main balance Performed when withdraw was created. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "withdraw.unconfirmed", "params": { "address": "wallet address", // withdraw address "amount": "100.00", // amount of withdraw "createdAt": 1593437922, // timestamp of withdraw "currency": "Tether US", // withdraw currency "ticker": "USDT", // withdraw currency ticker "description": null, // withdraw description "fee": "0.000000000000000000", // withdraw fee "memo": "", // withdraw memo "method": 2, // called method 1 - deposit, 2 - withdraw "network": "TRC20", // if currency is multi network, "null" if no multi network "status": 15, // transactions status "transactionHash": "transaction hash", // withdraw transaction hash "uniqueId": null // unique Id of withdraw }, "id": "uuid" } ``` Performed when withdraw is pending. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "withdraw.pending", "params": { "address": "wallet address", // withdraw address "amount": "100.00", // amount of withdraw "createdAt": 1593437922, // timestamp of withdraw "currency": "Tether US", // withdraw currency "ticker": "USDT", // withdraw currency ticker "description": null, // withdraw description "fee": "0.000000000000000000", // withdraw fee "memo": "", // withdraw memo "method": 2, // called method 1 - deposit, 2 - withdraw "network": "TRC20", // if currency is multi network, "null" if no multi network "status": 15, // transactions status "transactionHash": "transaction hash", // withdraw transaction hash "uniqueId": null // unique Id of withdraw }, "id": "uuid" } ``` Performed when withdraw was canceled. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "withdraw.canceled", "params": { "address": "wallet address", // withdraw address "amount": "100.00", // amount of withdraw "createdAt": 1593437922, // timestamp of withdraw "currency": "Tether US", // withdraw currency "ticker": "USDT", // withdraw currency ticker "description": null, // withdraw description "fee": "0.000000000000000000", // withdraw fee "memo": "", // withdraw memo "method": 2, // called method 1 - deposit, 2 - withdraw "network": "TRC20", // if currency is multi network, "null" if no multi network "status": 15, // transactions status "transactionHash": "transaction hash", // withdraw transaction hash "uniqueId": null // unique Id of withdraw }, "id": "uuid" } ``` Performed when withdraw was completed. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "withdraw.successful", "params": { "address": "wallet address", // withdraw address "amount": "100.00", // amount of withdraw "createdAt": 1593437922, // timestamp of withdraw "currency": "Tether US", // withdraw currency "ticker": "USDT", // withdraw currency ticker "description": null, // withdraw description "fee": "0.000000000000000000", // withdraw fee "memo": "", // withdraw memo "method": 2, // called method 1 - deposit, 2 - withdraw "network": "TRC20", // if currency is multi network, "null" if no multi network "status": 15, // transactions status "transactionHash": "transaction hash", // withdraw transaction hash "uniqueId": null // unique Id of withdraw }, "id": "uuid" } ``` ### WhiteBIT refund successful Triggered after the system successfully completes a refund. `memo` is the destination memo sent in the [refund request](/api-reference/account-wallet/refund-deposit). Unlike deposit and withdraw webhooks, which send `""`, refund webhooks send `null` when no memo was provided. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "refund.successful", "params": { "transactionId": "5e112b38-...", "status": "completed", "refundAddress": "GDTSOI56...", "depositAmount": "100", "currency": "Tether USDT", "ticker": "USDT", "network": "ERC-20", "createdAt": 1733924412, "processedAt": 1733925012, "refundNetworkFee": "1", "refundAmount": "99", "refundHash": "0x767ebd2...", "memo": null, // refund destination memo, null if not provided "nonce": 0 }, "id": "uuid" } ``` ### WhiteBIT refund failed Triggered after the system fails to complete a refund. The system rejects the refund if the destination address does not support the required network or asset, or if validation fails. Use a different address or contact support. Request example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "method": "refund.failed", "params": { "transactionId": "5e112b38-...", "status": "failed", "refundAddress": "GDTSOI56...", "depositAmount": "100", "currency": "Tether USDT", "ticker": "USDT", "network": "ERC-20", "createdAt": 1733924412, "processedAt": 1733925012, "memo": null, // refund destination memo, null if not provided "nonce": 0 }, "id": "uuid" } ``` `refund.failed` is also sent when a refund attempt fails for an internal reason. In that case, [Get refund history](/api-reference/account-wallet/get-refund-history) still shows the refund as `in_process` and the refund is not final. A refund with status `canceled` in the refund history is final. ## What's Next End-to-end guide for deposit and withdrawal processing with webhook reconciliation. HMAC-SHA512 signature verification, API key management, and production hardening. # WhiteBIT Codes Source: https://docs.whitebit.com/platform/whitebit-codes Create and apply fee-free digital vouchers to transfer crypto between WhiteBIT accounts. WhiteBIT Codes are fee-free digital vouchers for transferring cryptocurrency between WhiteBIT accounts. A code encapsulates a specific amount of a currency — the creator generates the code, shares the code string, and the recipient applies the code to receive the funds. ## Use cases Codes provide a simple transfer mechanism without requiring the recipient's deposit address. * **Internal transfers** — Move funds between accounts without withdrawal fees * **Partner payouts** — Distribute funds to multiple recipients by generating codes programmatically * **Promotions and rewards** — Create codes as promotional vouchers; optionally protect with a passphrase ## Code lifecycle The code lifecycle has two phases: creation and application. Send a `POST` request to [`/api/v4/main-account/codes`](/api-reference/account-wallet/create-code) with `ticker` (e.g., `ETH`), `amount` (string, up to 18 decimal places), optional `passphrase` (max 25 characters, latin letters + numbers + symbols, no whitespace), and optional `description` (max 280 characters, visible only to the creator). The amount is debited from the [Main balance](/concepts/balances). The response returns a `code` string (format: `WB{uuid}{TICKER}`, e.g., `WBe11f4fce-2a53-4edc-b195-66b693bd77e3ETH`) and an `external_id`. Transmit the code string to the intended recipient. If a passphrase was set, share the passphrase separately. The recipient calls [`POST /api/v4/main-account/codes/apply`](/api-reference/account-wallet/apply-code) with the `code` string and `passphrase` (if set). Funds are credited to the recipient's [Main balance](/concepts/balances). A `code.apply` [webhook event](/platform/webhook) fires on the creator's account. ## API endpoints WhiteBIT Codes uses 4 authenticated endpoints. All operate on the [Main balance](/concepts/balances). | Endpoint | Purpose | Rate limit | | - | - | - | | [`POST /api/v4/main-account/codes`](/api-reference/account-wallet/create-code) | Create a new code | 1,000 req / 10 sec | | [`POST /api/v4/main-account/codes/apply`](/api-reference/account-wallet/apply-code) | Apply (redeem) a code | 60 req / 1 sec | | [`POST /api/v4/main-account/codes/my`](/api-reference/account-wallet/get-my-codes) | List codes created by the account | 1,000 req / 10 sec | | [`POST /api/v4/main-account/codes/history`](/api-reference/account-wallet/get-codes-history) | Full code history (created + applied) | 1,000 req / 10 sec | ## Create parameters | Parameter | Type | Required | Description | | - | - | - | - | | `ticker` | string | Yes | Currency ticker (e.g., `ETH`, `BTC`) | | `amount` | string | Yes | Amount to encapsulate. Up to 18 decimal places. Must be greater than 0, capped at 1e17, and not exceed the Main balance. | | `passphrase` | string | No | Optional protection. Latin letters, numbers, symbols only. Max 25 characters. No whitespace. | | `description` | string | No | Internal note visible only to the creator. Max 280 characters. | ## Code example Create a code for 0.002 ETH with a passphrase, then apply the code on a different account. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Step 1: Create a WhiteBIT code curl -X POST https://whitebit.com/api/v4/main-account/codes \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -H "Content-Type: application/json" \ -d '{ "ticker": "ETH", "amount": "0.002", "passphrase": "mySecretPass1", "request": "/api/v4/main-account/codes", "nonce": 1 }' ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "code": "WBe11f4fce-2a53-4edc-b195-66b693bd77e3ETH", "message": "Code was successfully created", "external_id": "be08a482-5faf-11ed-9b6a-0242ac120002" } ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Step 2: Apply the code on the recipient's account curl -X POST https://whitebit.com/api/v4/main-account/codes/apply \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -H "Content-Type: application/json" \ -d '{ "code": "WBe11f4fce-2a53-4edc-b195-66b693bd77e3ETH", "passphrase": "mySecretPass1", "request": "/api/v4/main-account/codes/apply", "nonce": 2 }' ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "message": "Code was successfully applied", "ticker": "ETH", "amount": "0.002", "external_id": "be08a482-5faf-11ed-9b6a-0242ac120002" } ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Step 1: Create a WhiteBIT code. # Request body for POST /api/v4/main-account/codes: create_body = { "ticker": "ETH", "amount": "0.002", "passphrase": "mySecretPass1", } # The response returns the code string and an external_id. # Step 2: Apply the code on the recipient's account. # Request body for POST /api/v4/main-account/codes/apply: apply_body = { "code": "WBe11f4fce-2a53-4edc-b195-66b693bd77e3ETH", # from the create response "passphrase": "mySecretPass1", } # To send: add "request" and "nonce" to the body, serialize with compact # separators (the server rejects spaced JSON), sign with HMAC-SHA512, and # send with the X-TXC-APIKEY / X-TXC-PAYLOAD / X-TXC-SIGNATURE headers — # implementation in the First API Call guide linked below. ``` [First API Call](/guides/first-api-call) documents the signing details (payload construction, nonce, and headers). For Go and PHP examples, see [SDKs](/sdks). ## Error codes Create endpoint error codes: | Code | Description | | - | - | | 0 | Fiat currencies available on the front-end only | | 1 | Currency is not withdrawable | | 3 | Amount is too small | | 5 | Not enough balance | | 6 | Amount is less than or equal to fee | For apply errors, the most common is "Incorrect code or passphrase" — verify the code string and passphrase are correct. ## Regional restrictions EEA users: USDT codes are blocked since December 30, 2024 (MiCA compliance). Tether has not obtained EU authorization. Use USDC or EURI as alternatives. See [Regulatory Compliance](/institutional/compliance) for details. ## What's next Receive real-time notifications when codes are applied. Instantly convert between currencies at a quoted rate. # Compare Trading Products Source: https://docs.whitebit.com/products/compare-trading Choose between Spot, Margin, and Futures trading on the WhiteBIT API — use case guide, capability comparison, and API routing reference. Not sure which trading product to integrate? Use the comparison below to match the target use case to the right product, then go directly to that product's overview. ## Which product is right for this use case? * **No leverage needed** — Use [Spot Trading](/products/spot/overview). Direct asset ownership, no liquidation risk, 800+ spot pairs. * **Leverage on spot pairs, simpler risk model** — Use [Margin Trading](/products/margin/overview). Up to 10x leverage on spot pairs (e.g., `BTC_USDT`). No funding rates, no Hedge Mode. * **Perpetual contracts, higher leverage, funding rate mechanics** — Use [Futures Trading](/products/futures/overview). Up to 100x leverage on perpetual pairs (e.g., `BTC_PERP`), Hedge Mode for simultaneous long/short positions, periodic funding rate settlement. ## Comparison | | Spot | Margin | Futures | | - | - | - | - | | Instrument type | Spot pairs (`BTC_USDT`) | Spot pairs (`BTC_USDT`) | Perpetual pairs (`BTC_PERP`) | | Leverage | None | Up to 10x | Up to 100x | | [Liquidation risk](/concepts/liquidation) | No | Yes | Yes | | [Maintenance Margin Rate](/concepts/liquidation) | — | 3% for 1x–10x | 3% for 1x–10x | | Hedge Mode | No | No | Yes — long + short on the same pair simultaneously | | Funding rates | No | No | Yes — periodic settlement between longs and shorts | | Available pairs | 800+ | Spot pairs with collateral enabled | 270+ perpetual pairs | | Balance required | [Trade balance](/concepts/balances) | [Collateral balance](/concepts/balances) | [Collateral balance](/concepts/balances) | | API endpoints | Spot Trading (`/api/v4/order/new`, etc.) | Collateral (`/api/v4/order/collateral/`) | Same collateral endpoints — pair name routes the order | | Kill-switch | Yes | No | No | | Bulk orders | Yes (up to 20 per call) | Yes (up to 20 per call) | Yes (up to 20 per call) | ## API routing: Margin vs Futures Margin Trading and Futures Trading share the same API endpoints. The **pair name** is the only differentiator: * Spot pair (e.g., `BTC_USDT`) → **Margin Trading** * Perpetual pair (e.g., `BTC_PERP`) → **Futures Trading** All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. There is no separate "margin" or "futures" parameter in the request body — the market pair name alone determines which product is used. Both Margin and Futures draw from the same **Collateral balance**. Leverage is also configured account-wide via a single endpoint — it applies to both products simultaneously. ## What's Next 800+ spot pairs, 6 order types, kill-switch, bulk orders. No leverage. Up to 10x leverage on spot pairs using the Collateral account. Perpetual contracts up to 100x, Hedge Mode, and funding rates. # Futures Trading Source: https://docs.whitebit.com/products/futures/overview Perpetual contracts on 270+ pairs with up to 100x leverage, Hedge Mode, and funding rate mechanics on WhiteBIT. Perpetual contracts on 270+ [pairs](/concepts/markets) with up to 100x leverage and Hedge Mode for simultaneous long/short positions. The Futures Trading API shares the collateral trading endpoints with Margin Trading — the perpetual pair name (e.g., `BTC_PERP`) determines routing to the futures market. ## Capabilities * **Up to 100x leverage** — Adjustable per account via the [leverage endpoint](/api-reference/trading/change-collateral-account-leverage). Allowed values: 1, 2, 3, 5, 10, 20, 50, 100. * **Cash-settled** — profit and loss is the difference between entry and exit price; no physical delivery of the underlying asset * **Hedge Mode** — Hold simultaneous long and short positions on the same pair ([check mode](/api-reference/trading/collateral-account-hedge-mode), [update mode](/api-reference/trading/update-collateral-account-hedge-mode)) * **270+ perpetual pairs** — BTC\_PERP, ETH\_PERP, and more * **Funding rates** — Periodic settlement between long and short holders ([funding history](/api-reference/trading/funding-history)) * **USDTB bonus collateral** — Platform-granted bonus collateral token usable for futures margin (not depositable, not withdrawable) * **6 order types** — Limit, Market, Stop-Limit, Trigger-Market, OCO, Bulk-Limit ([details](/concepts/order-types)) **API naming convention:** WhiteBIT's API uses "collateral" endpoints for both Margin and Futures trading. The market pair determines the product: spot pairs (e.g., `BTC_USDT`) for Margin, perpetual pairs (e.g., `BTC_PERP`) for Futures. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. See [Compare Trading Products](/products/compare-trading) for a full side-by-side comparison. WhiteBIT's demo account supports **spot trading only** — it does not support Futures or Margin trading. Test all leveraged trading flows on the live API with minimum order sizes. See [First API Call](/guides/first-api-call) for safe testing guidance. ## Who Uses This * **Hedge funds** — Delta-neutral strategies, funding rate harvesting, directional leveraged trades on perpetual contracts * **HFT / Prop trading firms** — High-frequency futures strategies with [colocation](/platform/colocation) (3–5 ms latency) * **Quantitative developers** — Programmatic position management, cross-margin optimization, automated hedging ## Common Integration Patterns **Directional perpetual trading** — Open leveraged long or short positions on perpetual contracts. Set leverage via the [leverage endpoint](/api-reference/trading/change-collateral-account-leverage), place orders through the [collateral order endpoints](/api-reference/trading/collateral-overview), and monitor positions with the [open positions endpoint](/api-reference/trading/open-positions). The API returns a `liquidationPrice` field in position responses for risk monitoring. **Delta-neutral strategies** — Use [Hedge Mode](/api-reference/trading/update-collateral-account-hedge-mode) to hold simultaneous long and short positions on the same perpetual pair. Profit from funding rate differentials while maintaining market-neutral exposure. Fetch current funding rates via the [public futures endpoint](/api-reference/market-data/available-futures-markets-list) and historical rates via the [funding history endpoint](/api-reference/trading/funding-history). ## Risk Mechanics ### Margin Modes Futures positions operate in one of two margin modes: * **Cross Margin** — All available collateral in the account backs every open position. Higher capital efficiency, but a single losing position can affect the entire account balance. * **Isolated Margin** — Each position has a fixed margin allocation. Losses are capped at the isolated margin amount. Other positions and the remaining collateral balance remain unaffected. Check the current margin configuration via the [collateral account summary endpoint](/api-reference/trading/collateral-account-summary). Leverage can be adjusted using the [leverage endpoint](/api-reference/trading/change-collateral-account-leverage). ### Liquidation Positions face liquidation when the maintenance margin requirement is breached. Liquidation is evaluated against the **mark price**, not the last traded price, and the Maintenance Margin Rate is 3% for leverage 1x–10x. Partial liquidation closes part of the position first; [Auto-Deleveraging](/concepts/auto-deleveraging) is the final stage when order-book liquidity cannot absorb the liquidation order. Full mechanics — mark price derivation, leverage brackets, the liquidation sequence, and the `liquidationPrice` / `liquidationState` / `marginFraction` fields for risk monitoring: [Liquidation and margin requirements](/concepts/liquidation). * **Mark price** (not last traded price) is used for liquidation calculations. Temporary price wicks do not trigger liquidation. Subscribe to [Premium index](/websocket/market-streams/premium-index) over WebSocket for a live push of mark price, index price, and funding rate, or fetch a one-time snapshot from the [futures markets endpoint](/api-reference/market-data/available-futures-markets-list). * **Partial liquidation** is the primary mechanism: only a portion (e.g., 20–30%) of the position is closed first to restore margin. If partial liquidation is insufficient, full liquidation follows. * **Liquidation sequence:** margin positions first (smallest to largest initial margin value) → crypto borrowings → futures positions last * **Maintenance Margin Rate (MMR):** 3% for leverage 1x–10x. Per-market leverage limits and collateral brackets: [collateral brackets page](https://whitebit.com/trading-data/collateral-brackets) * The API returns a `liquidationPrice` field in position responses — monitor the liquidation price alongside collateral balance * When a position is liquidated, the collateral allocated to the position is lost * **Auto-Deleveraging (ADL):** Final-stage mechanism activated only when standard market liquidity cannot fully cover a liquidated position. ADL closes profitable counterparty positions on the opposite side, ranked by an internal Rating; integrators monitor exposure via the ADL Grade indicator (0–4). See [Auto-Deleveraging](/concepts/auto-deleveraging) for the full mechanism, formulas, and risk-management guidance. > **Coming soon:** Detailed mark price methodology and liquidation price formulas will be published here. For institutional inquiries, contact [institutional@whitebit.com](mailto:institutional@whitebit.com). ### Funding Rates Perpetual contracts use a funding rate mechanism to keep the contract price aligned with the spot index price: * **Settlement interval per market** — The `funding_interval_minutes` field on the [futures markets endpoint](/api-reference/market-data/available-futures-markets-list) returns the cadence for each pair. At each settlement, long holders pay short holders or vice versa depending on the funding rate. * **Positive rate** = longs pay shorts (contract price above index). **Negative rate** = shorts pay longs. * Fetch the current predicted funding rate for any pair via `GET /api/v4/public/futures`, or subscribe to [Premium index](/websocket/market-streams/premium-index) for a live push * Fetch historical funding rates via `GET /api/v4/public/funding-history/{market}` * Fetch account-specific funding payments via `POST /api/v4/collateral-account/funding-history` ### USDTB USDTB is a platform-granted bonus collateral token: * Usable as margin for futures positions * Cannot be deposited or withdrawn — granted through platform promotions or programs * Appears in the collateral account balance alongside USDT and other collateral assets ## Technical Overview | Detail | Value | | - | - | | Endpoints | 21 shared with Margin (all `POST`, all authenticated) | | Authentication | HMAC-SHA512 ([guide](/api-reference/authentication)) | | Rate limits | Vary per endpoint ([details](/api-reference/rate-limits)) | | Pair format | Perpetual pairs: `BTC_PERP`, `ETH_PERP`, etc. | Endpoint categories (shared with Margin Trading): * **Account & Balance** — Balance, balance summary, account summary, leverage, hedge mode (6 endpoints) * **Order Management** — Limit, bulk-limit, market, stop-limit, trigger-market, OCO, cancel (7 endpoints) * **Order Queries** — Conditional orders, OCO orders (2 endpoints) * **Position Management** — Open positions, ADL quantile (returns perpetual markets only), close position, position history, closed-position PNL, funding history (6 endpoints) There is no collateral-specific modify endpoint. The shared [modify order](/api-reference/trading/modify-order) endpoint covers collateral markets. The pair name determines whether an order is Margin or Futures. Perpetual pairs (e.g., `BTC_PERP`) route to Futures. Spot pairs (e.g., `BTC_USDT`) route to Margin. For full endpoint documentation, see the [Collateral Trading API Reference](/api-reference/trading/collateral-overview). For Go and PHP examples, see [SDKs](/sdks). ## What's Next Open a first futures position in 5 minutes. Compare with leveraged spot pairs — up to 10x leverage. Full endpoint documentation for all 21 collateral trading endpoints. # Crypto Lending Source: https://docs.whitebit.com/products/lending/overview Earn yield on crypto assets through fixed-term and flexible lending plans with 13 API endpoints for full lifecycle management. Earn yield on crypto assets through fixed-term and flexible lending plans -- 13 API endpoints for full lifecycle management. ## Capabilities The Crypto Lending API supports two plan types with distinct yield mechanics. * **Fixed plans** -- lock assets for 10-360 day terms. Interest paid at maturity. Interest ratio conversion when target currency differs from source currency. * **Flexible plans** -- deposit and withdraw anytime. Interest calculated hourly, credited daily. Auto-reinvestment option compounds returns. * **\~90 supported assets** -- invest in a wide range of crypto assets (check available plans dynamically via the plans endpoint) * **Auto-invest** -- configure automatic recurring investments into Flex plans * **Full lifecycle API** -- create, monitor, withdraw, and close investments programmatically ## Who uses this * **Treasury operations** -- exchanges and trading firms putting idle [Main balance](/concepts/balances) assets to work in Flex plans between active trading periods. * **Yield integrators** -- fintechs and platforms offering yield to end users. ## Common Integration Patterns **Idle asset management** -- Monitor [Main balance](/concepts/balances) for idle assets. Invest surplus into Flex plans (withdraw anytime, no lock-up). Set up auto-invest for recurring allocation. Withdraw back to Main balance before trading. **Yield-as-a-service** -- Delivering yield to many end users is a partner program with its own model and lifecycle -- see [Yield-as-a-Service](/guides/yaas-overview). ## Plan Types | Feature | Fixed Plans | Flex Plans | | - | - | - | | Lock-up | 10, 20, 30, 90, 180, or 360 days | None (withdraw anytime) | | Interest | Paid at maturity | Calculated hourly, credited daily | | Early withdrawal | Allowed — but **interest is forfeited** | Allowed — **accrued interest is retained** | | Auto-reinvest | N/A | Available | | Auto-invest | N/A | Available | | API access | B2B partners only | B2B partners only | **Lending API access:** Both Fixed (`/api/v4/main-account/smart/`) and Flex (`/api/v4/main-account/smart-flex/`) lending endpoints require B2B partner permissions. Complete the [institutional services form](https://whitebit.com/institutional-services/b2b) to request access. Until access is granted, these endpoints return `403` with `"You don't have permission to use this endpoint. Please contact support for more details"`. ## Technical Overview * **13 endpoints** total (5 fixed + 8 flex), all `POST`, all authenticated * **Authentication:** HMAC-SHA512 ([guide](/api-reference/authentication)) * **Rate limits:** 1000 requests per 10 seconds per endpoint ([details](/api-reference/rate-limits)) For full endpoint documentation, see the [Crypto Lending API Reference](/api-reference/account-wallet/overview). ## Platform Context The WhiteBIT platform brands lending products as **U EARN**. The platform also offers Staking and Auto-Invest for recurring purchases -- available via the [platform UI](https://whitebit.com), not the API. ## What's Next Create a first Flex investment in under 5 minutes. Offer this yield to end users as a partner program. Full endpoint documentation for all 13 lending endpoints. # Crypto Lending Quickstart Source: https://docs.whitebit.com/products/lending/quickstart Walk through the four Flex endpoints — fetch plans, invest, check status, withdraw — in under 5 minutes. The four endpoints below cover the full Flex lifecycle — fetch plans, invest, check status, withdraw — operating against Main balance. Access requires B2B partner permissions plus a key with the Trade permission. ## Prerequisites * A WhiteBIT account with completed KYC ([register](https://whitebit.com/auth/register)) * An API key with **Trade** permission ([create key](https://whitebit.com/settings/api)) * B2B partner access to the lending endpoints ([institutional services form](https://whitebit.com/institutional-services/b2b)) * Funds in [Main balance](/concepts/balances) (the lending API operates on Main balance, not Trade balance) * HMAC-SHA512 signing configured ([authentication guide](/api-reference/authentication)) * `curl` and `jq` installed (for command-line examples) Both Flex and Fixed plan endpoints require B2B partner permissions. Request access via the [institutional services form](https://whitebit.com/institutional-services/b2b). See the [overview](/products/lending/overview) for details. Retrieve the list of available Flex plans to find a plan ID for investment. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/main-account/smart-flex/plans \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{"request": "/api/v4/main-account/smart-flex/plans", "nonce": 1709340000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests, json, hmac, hashlib, base64, time API_KEY = "YOUR_API_KEY" API_SECRET = "YOUR_SECRET" BASE_URL = "https://whitebit.com" def make_request(endpoint, body): nonce = int(time.time() * 1000) body["request"] = endpoint body["nonce"] = nonce data_json = json.dumps(body) payload = base64.b64encode(data_json.encode()) signature = hmac.new( API_SECRET.encode(), payload, hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload.decode(), "X-TXC-SIGNATURE": signature, } return requests.post(f"{BASE_URL}{endpoint}", headers=headers, data=data_json) # Fetch available Flex plans response = make_request("/api/v4/main-account/smart-flex/plans", {}) plans = response.json() print(json.dumps(plans, indent=2)) ``` For Go and PHP examples, see [SDKs](/sdks). **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "id": "8f2e9d3c-1a4b-4c2d-9e5f-6a7b8c9d0e1f", "ticker": "USDT", "minInvestment": "10.0", "maxInvestment": "100000.0", "maxRate": "0.15" }, "..." ] ``` Save the `id` value from a plan to use in the next step. Invest into the selected Flex plan using the plan ID from Step 1. Sign the request as in Step 1 (`make_request` builds the payload and signature); for language clients, see [SDKs](/sdks). **Endpoint:** `POST /api/v4/main-account/smart-flex/investments/invest` | Field | Type | Required | Description | | - | - | - | - | | `plan` | string (UUID) | Yes | Plan ID from Step 1 | | `amount` | string | Yes | Amount to invest | | `withReinvest` | boolean | No | Enables auto-reinvestment | **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "transaction_id": "tx_9f3e0d4c-2b5c-4d3e-8f6g-7a8b9c0d1e2f" } } ``` Verify the investment was created and check its status. Sign the request as in Step 1. **Endpoint:** `POST /api/v4/main-account/smart-flex/investments` (no additional fields) **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": [ { "id": "inv_7e2d9c3b-1a4b-4c2d-9e5f-6a7b8c9d0e1f", "planId": "8f2e9d3c-1a4b-4c2d-9e5f-6a7b8c9d0e1f", "currency": "USDT", "invested": "100.00", "withAutoReinvest": true, "status": 1, "..." } ], "..." } ``` Withdraw funds from the Flex investment back to Main balance. Sign the request as in Step 1. **Endpoint:** `POST /api/v4/main-account/smart-flex/investments/withdraw` | Field | Type | Required | Description | | - | - | - | - | | `plan` | string (UUID) | Yes | The plan to withdraw from | | `amount` | string | Yes | Amount to withdraw; partial withdrawals supported (use the full invested amount to withdraw everything) | **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "transaction_id": "tx_9f3e0d4c-2b5c-4d3e-8f6g-7a8b9c0d1e2f" } } ``` After completing Step 4, the withdrawn amount returns to the [Main balance](/concepts/balances). Verify by checking the [Main balance endpoint](/api-reference/account-wallet/overview). ## What's Next Fixed vs Flex plan mechanics, B2B partner permissions for lending endpoints, \~90 supported assets, and auto-invest behavior. Full endpoint documentation for all 13 lending endpoints. For Go and PHP examples, see [SDKs](/sdks). # Margin & Futures Quickstart Source: https://docs.whitebit.com/products/margin-futures/quickstart Open a first leveraged position on WhiteBIT — Margin Trading (up to 10x) or Futures Trading (up to 100x) — in under 5 minutes. Open a first leveraged position on WhiteBIT. Margin Trading and Futures Trading share identical API endpoints — only the pair name differs. Select a tab below to follow the steps for the preferred product. **API naming convention:** WhiteBIT's API uses "collateral" endpoints for both Margin and Futures trading. The market pair determines the product: spot pairs (e.g., `BTC_USDT`) for Margin, perpetual pairs (e.g., `BTC_PERP`) for Futures. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. ## Prerequisites * A WhiteBIT account ([register](https://whitebit.com/auth/register)) * An API key with **Trading** permission ([create one](https://whitebit.com/settings/api)) * Funds in the **Collateral** balance (transfer from Main balance if needed — see [Balances & Transfers](/concepts/balances)) * Familiarity with HMAC-SHA512 signing — see [Authentication](/api-reference/authentication) WhiteBIT has no public testnet or sandbox. All leveraged orders execute against the live orderbook. Use minimum order amounts, low leverage (2x–5x), and prices far from market to safely test. Leveraged positions carry liquidation risk — see [Margin Trading](/products/margin/overview) or [Futures Trading](/products/futures/overview) for risk details. ## Authentication Helper The signing helper signs every Python example in this page. See [Authentication](/api-reference/authentication) for the full HMAC-SHA512 derivation. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64 import hashlib import hmac import json import time import requests API_KEY = "YOUR_API_KEY" # Replace with actual API key API_SECRET = "YOUR_API_SECRET" # Replace with actual API secret BASE_URL = "https://whitebit.com" def send_request(path, data=None): if data is None: data = {} data["request"] = path data["nonce"] = int(time.time() * 1000) data_json = json.dumps(data) payload_b64 = base64.b64encode(data_json.encode()).decode() signature = hmac.new( API_SECRET.encode(), payload_b64.encode(), hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload_b64, "X-TXC-SIGNATURE": signature, } return requests.post(BASE_URL + path, headers=headers, data=data_json).json() ``` For Go and PHP examples, see [SDKs](/sdks). ## Steps Margin Trading uses spot pairs (e.g., `BTC_USDT`) with up to 10x leverage. Verify available collateral funds. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/collateral-account/balance \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"request":"/api/v4/collateral-account/balance","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} balance = send_request("/api/v4/collateral-account/balance") print(balance) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "USDT": 1000.50, "BTC": 0.0 } ``` The response maps each collateral asset to an available balance amount. Set the account leverage to 5x. Leverage applies account-wide across all collateral positions. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/collateral-account/leverage \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"leverage":5,"request":"/api/v4/collateral-account/leverage","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} result = send_request("/api/v4/collateral-account/leverage", { "leverage": 5 }) print(result) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "leverage": 5 } ``` Allowed leverage values: 1, 2, 3, 5, 10. Margin Trading supports up to 10x. Create a limit buy order on BTC\_USDT. Set the price well below the current market price — the order remains open without filling, allowing safe testing. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/collateral/limit \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","side":"buy","amount":"0.001","price":"30000","request":"/api/v4/order/collateral/limit","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} order = send_request("/api/v4/order/collateral/limit", { "market": "BTC_USDT", "side": "buy", "amount": "0.001", "price": "30000" # Price far below market — order will not fill }) print(order) orderId = order.get("orderId") print(f"Order ID: {orderId}") ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "orderId": 12345678, "market": "BTC_USDT", "side": "buy", "type": "limit", "amount": "0.001", "price": "30000", "...": "..." } ``` When a collateral limit order fills, a position is created. Open positions include a `liquidationPrice` field — monitor the liquidation price for risk management. See the [open positions endpoint](/api-reference/trading/open-positions) for details. Query open positions. If the limit order from the previous step has not filled, the response is empty. Once an order fills, positions appear with key risk fields. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/collateral-account/positions/open \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","request":"/api/v4/collateral-account/positions/open","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} positions = send_request("/api/v4/collateral-account/positions/open", { "market": "BTC_USDT" }) print(positions) for pos in positions: print(f" Position {pos['positionId']}: {pos['positionSide']} " f"liquidation at {pos['liquidationPrice']}") ``` **Expected response (when a position exists):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "positionId": 87654321, "market": "BTC_USDT", "amount": "0.001", "basePrice": "65000.00", "pnl": "0", "margin": "13.00", "liquidationPrice": "52100.00", "positionSide": "LONG", "...": "..." } ] ``` Key fields: `basePrice` (entry price), `liquidationPrice` (price at which the position is force-closed), `positionSide` (LONG, SHORT, or BOTH), `margin` (funds allocated to the position). Cancel the limit order to release the reserved collateral. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/cancel \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_USDT","orderId":12345678,"request":"/api/v4/order/cancel","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} cancel = send_request("/api/v4/order/cancel", { "market": "BTC_USDT", "orderId": orderId }) print(cancel) ``` To close an open position (after a filled order), use the [close position endpoint](/api-reference/trading/close-position) with `positionId` and `market`: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Close an open position (when one exists) close = send_request("/api/v4/collateral-account/position/close", { "positionId": 87654321, "market": "BTC_USDT" }) ``` Futures Trading uses perpetual pairs (e.g., `BTC_PERP`) with up to 100x leverage and optional Hedge Mode. Verify available collateral funds. The same Collateral balance serves both Margin and Futures. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/collateral-account/balance \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"request":"/api/v4/collateral-account/balance","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} balance = send_request("/api/v4/collateral-account/balance") print(balance) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "USDT": 1000.50, "BTC": 0.0 } ``` Set account leverage to 5x. Leverage applies account-wide. Futures supports up to 100x, but use a conservative value for testing. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/collateral-account/leverage \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"leverage":5,"request":"/api/v4/collateral-account/leverage","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} result = send_request("/api/v4/collateral-account/leverage", { "leverage": 5 }) print(result) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "leverage": 5 } ``` Allowed leverage values: 1, 2, 3, 5, 10, 20, 50, 100. Hedge Mode allows simultaneous long and short positions on the same pair. Skip to disable (default: one-directional positions only). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/collateral-account/hedge-mode/update \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"hedgeMode":true,"request":"/api/v4/collateral-account/hedge-mode/update","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} hedge = send_request("/api/v4/collateral-account/hedge-mode/update", { "hedgeMode": True }) print(hedge) ``` Check the current mode at any time: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} mode = send_request("/api/v4/collateral-account/hedge-mode") print(mode) # {"hedgeMode": true} ``` Create a limit buy order on BTC\_PERP. Set the price well below the current market price — the order remains open without filling, allowing safe testing. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/collateral/limit \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_PERP","side":"buy","amount":"0.001","price":"30000","request":"/api/v4/order/collateral/limit","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} order = send_request("/api/v4/order/collateral/limit", { "market": "BTC_PERP", "side": "buy", "amount": "0.001", "price": "30000" # Price far below market — order will not fill }) print(order) orderId = order.get("orderId") print(f"Order ID: {orderId}") ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "orderId": 12345678, "market": "BTC_PERP", "side": "buy", "type": "limit", "amount": "0.001", "price": "30000", "...": "..." } ``` The only difference from the Margin tab: `BTC_PERP` (perpetual pair) instead of `BTC_USDT` (spot pair). The API endpoint and request structure are identical. Query open positions. If the limit order from the previous step has not filled, the response is empty. Once an order fills, positions appear with key risk fields including `liquidationPrice`. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/collateral-account/positions/open \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_PERP","request":"/api/v4/collateral-account/positions/open","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} positions = send_request("/api/v4/collateral-account/positions/open", { "market": "BTC_PERP" }) print(positions) for pos in positions: print(f" Position {pos['positionId']}: {pos['positionSide']} " f"liquidation at {pos['liquidationPrice']}") ``` **Expected response (when a position exists):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "positionId": 87654321, "market": "BTC_PERP", "amount": "0.001", "basePrice": "65000.00", "pnl": "0", "margin": "13.00", "liquidationPrice": "52100.00", "positionSide": "LONG", "...": "..." } ] ``` Key fields: `basePrice` (entry price), `liquidationPrice` (price triggering forced closure — uses mark price, not last traded price; see [Liquidation](/concepts/liquidation)), `positionSide` (LONG, SHORT, or BOTH in Hedge Mode), `margin` (funds allocated to the position). Cancel the limit order to release the reserved collateral. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/cancel \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: BASE64_PAYLOAD" \ -H "X-TXC-SIGNATURE: HMAC_SIGNATURE" \ -d '{"market":"BTC_PERP","orderId":12345678,"request":"/api/v4/order/cancel","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} cancel = send_request("/api/v4/order/cancel", { "market": "BTC_PERP", "orderId": orderId }) print(cancel) ``` To close an open position (after a filled order), use the [close position endpoint](/api-reference/trading/close-position) with `positionId` and `market`: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Close an open position (when one exists) close = send_request("/api/v4/collateral-account/position/close", { "positionId": 87654321, "market": "BTC_PERP" }) ``` The limit order is canceled and the reserved collateral returns to the available Collateral balance. Margin and Futures share endpoint paths verbatim — only the pair name (`BTC_USDT` vs `BTC_PERP`) routes the order. **Collateral balance isolation** — Leveraged trading requires funds in the Collateral balance specifically. Depositing to the Main balance is not sufficient — an explicit transfer to Collateral is required before any collateral order can be placed. The Collateral balance is shared between Margin and Futures; there is no separate pool per product. **How leverage amplifies risk** — At 5x leverage, 1 USDT of collateral controls 5 USDT of market exposure. A 20% adverse price move against a 5x position wipes the allocated margin entirely, triggering partial liquidation. WhiteBIT's partial liquidation mechanism closes 20–30% of the position first to restore margin; full liquidation follows only if that is insufficient. The `liquidationPrice` field in position responses shows exactly where this occurs — monitor it alongside the collateral balance in production. ## What's Next Isolated Margin mode, 6 order types (Limit, Market, Stop-Limit, Trigger-Market, OCO, Bulk-Limit), partial-liquidation flow at 20–30%, and the borrowed-funds fee model. Perpetual contracts, Hedge Mode, funding rates, and risk mechanics. Full endpoint documentation for all 21 collateral trading endpoints. # Margin Trading Source: https://docs.whitebit.com/products/margin/overview Leveraged trading on spot pairs with up to 10x leverage using a collateral account on WhiteBIT. Leveraged trading on [spot pairs](/concepts/markets) with up to 10x leverage using a collateral account. Margin Trading provides access to the same liquid spot markets (e.g., BTC\_USDT, ETH\_USDT) with amplified exposure through borrowed funds. ## Capabilities * **Up to 10x leverage** — Adjustable per account via the [leverage endpoint](/api-reference/trading/change-collateral-account-leverage) * **Isolated Margin mode** — Limit risk to the margin allocated to a specific position, preventing cross-position liquidation cascades * **6 order types** — Limit, Market, Stop-Limit, Trigger-Market, OCO, Bulk-Limit ([details](/concepts/order-types)) * **Bulk orders** — Place up to 20 collateral limit orders in a single call ([endpoint](/api-reference/trading/collateral-bulk-limit-order)) * **Position management** — Open, monitor, and close positions programmatically ([open positions](/api-reference/trading/open-positions), [close](/api-reference/trading/close-position)) **API naming convention:** WhiteBIT's API uses "collateral" endpoints for both Margin and Futures trading. The market pair determines the product: spot pairs (e.g., `BTC_USDT`) for Margin, perpetual pairs (e.g., `BTC_PERP`) for Futures. All endpoints under `/api/v4/order/collateral/` and `/api/v4/collateral-account/` serve both products. See [Compare Trading Products](/products/compare-trading) for a full side-by-side comparison. ## Who Uses This * **Hedge funds** — Hedging spot holdings or amplifying directional exposure with controlled risk * **Prop trading firms** — Leveraged strategies on liquid spot pairs with isolated margin for risk containment * **Experienced algo traders** — Programmatic margin management through the collateral account API ## Common Integration Patterns **Hedging** — Open opposing margin positions to offset risk on existing spot holdings. For example, short BTC\_USDT on margin while holding BTC in a spot wallet. Use the [collateral account balance](/api-reference/trading/collateral-account-balance) endpoint to monitor margin utilization. **Leveraged directional trading** — Amplify exposure with controlled risk via isolated margin. Set leverage via the [leverage endpoint](/api-reference/trading/change-collateral-account-leverage), place orders, and monitor positions through the [open positions endpoint](/api-reference/trading/open-positions). The API returns a `liquidationPrice` field in position responses for risk monitoring. ## Risk Context **Borrowed funds fee:** A commission is charged for using borrowed funds — only applied when an order is at least partially executed. Unexecuted orders incur no borrowing fee. See the [trading fees page](https://whitebit.com/trading-data/trading-fees) for the current rate. No public endpoint returns the rate itself; accrued cost per open borrow arrives as `unrealized_funding` on the [Borrows](/websocket/account-streams/borrows) stream. Liquidation can occur when the maintenance margin threshold is breached. The Maintenance Margin Rate is 3% for leverage 1x–10x, and partial liquidation closes part of the position before full liquidation. Full mechanics — the maintenance margin schedule, leverage brackets, the liquidation sequence, and the `liquidationPrice` / `liquidationState` / `marginFraction` fields for risk monitoring: [Liquidation and margin requirements](/concepts/liquidation). **WBT holder benefit:** Holding WBT (WhiteBIT Token) can reduce the maker commission by up to 100% on margin orders. See the [VIP program](https://whitebit.com/vip-program) for current tier details. **Portfolio Margin** is available for institutional clients with a minimum 200,000 USDT collateral balance. Portfolio Margin provides up to 10x leverage with portfolio-level risk assessment. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) or see the [Institutional Overview](/institutional/overview) for details. ## Technical Overview | Detail | Value | | - | - | | Endpoints | 21 shared with Futures (all `POST`, all authenticated) | | Authentication | HMAC-SHA512 ([guide](/api-reference/authentication)) | | Rate limits | Vary per endpoint ([details](/api-reference/rate-limits)) | | Pair format | Spot pairs: `BTC_USDT`, `ETH_USDT`, etc. | Endpoint categories (shared with Futures Trading): * **Account & Balance** — Balance, balance summary, account summary, leverage, hedge mode (6 endpoints) * **Order Management** — Limit, bulk-limit, market, stop-limit, trigger-market, OCO, cancel (7 endpoints) * **Order Queries** — Conditional orders, OCO orders (2 endpoints) * **Position Management** — Open positions, ADL quantile (returns perpetual markets only), close position, position history, closed-position PNL, funding history (6 endpoints) There is no collateral-specific modify endpoint. The shared [modify order](/api-reference/trading/modify-order) endpoint covers collateral markets. The pair name determines whether an order is Margin or Futures. Spot pairs (e.g., `BTC_USDT`) route to Margin. Perpetual pairs (e.g., `BTC_PERP`) route to Futures. For full endpoint documentation, see the [Collateral Trading API Reference](/api-reference/trading/collateral-overview). For Go and PHP examples, see [SDKs](/sdks). ## What's Next Open a first leveraged position in 5 minutes. Compare with perpetual contracts — up to 100x leverage and Hedge Mode. Full endpoint documentation for all 21 collateral trading endpoints. # Market Data Source: https://docs.whitebit.com/products/market-data/overview Real-time and historical market data across 900+ trading pairs — no authentication required. Real-time and historical market data across 900+ trading pairs — no authentication required. The Market Data API provides prices, orderbooks, recent trades, asset statuses, and funding rates through 14 public GET endpoints. ## Capabilities * **Server status** — Check platform availability before integrating (`GET /api/v4/public/ping`, `GET /api/v4/public/time`) * **Market catalog** — Fetch all available spot and futures markets with minimum amounts, tick sizes, and statuses ([Markets & Trading Pairs](/concepts/markets)) * **Real-time pricing** — 24-hour ticker data for all pairs or individual markets * **Orderbook depth** — Full or limited-depth orderbook snapshots for any market * **Recent trades** — Latest executed trades per market * **Asset statuses** — Deposit/withdrawal availability per currency, network, and chain * **Funding rates** — Current and historical funding rates for perpetual futures markets ## Who Uses This * **Developers evaluating the API** — Zero setup, no API key, no authentication. Start making calls immediately. * **Trading bots and algorithms** — Market state checks, price feeds, orderbook analysis before placing orders * **Analytics platforms** — Historical trade data, market statistics, asset network information * **Price aggregators** — Ticker data across 900+ pairs for display and comparison ## Common Integration Patterns **Price feeds** — Poll the ticker endpoint for periodic price updates or subscribe to the `lastprice` [WebSocket channel](/guides/websocket-quickstart) for real-time streaming. The ticker endpoint returns 24-hour volume, last price, and percentage change. **Orderbook analysis** — Fetch depth snapshots via REST for point-in-time analysis or subscribe to the `depth` WebSocket channel for real-time updates. The depth endpoint accepts a `limit` parameter (1–100) to control response size. **Pre-trade checks** — Before placing orders, fetch market details to verify minimum order amounts, tick sizes, market status (active/disabled), and asset deposit/withdrawal availability. ## Technical Overview | Detail | Value | | - | - | | Endpoints | 14 (all `GET`, all public) | | Authentication | None required | | Rate limit | 20,000 requests per 10 seconds (default); some endpoints differ — see [Rate Limits](/api-reference/rate-limits) | | Base URL | `https://whitebit.com` | | WebSocket URL | `wss://wss.whitebit.com/ws` | Key endpoints: * `GET /api/v4/public/markets` — All tradable market pairs: spot (including margin-enabled), perpetual futures, and TradFi futures * `GET /api/v4/public/futures` — Futures market pairs * `GET /api/v4/public/ticker` — 24-hour ticker for all pairs * `GET /api/v4/public/orderbook/{market}` — Orderbook depth * `GET /api/v4/public/trades/{market}` — Recent trades * `GET /api/v4/public/assets` — Asset deposit/withdrawal statuses * `GET /api/v4/public/funding-history/{market}` — Funding rate history for perpetual pairs For full endpoint documentation, see the [Market Data API Reference](/api-reference/market-data/overview). For Go and PHP examples, see [SDKs](/sdks). ## What's Next Fetch live prices and orderbooks in under 2 minutes — no authentication required. Full endpoint documentation for all 14 public endpoints. Stream real-time price updates and orderbook changes. # Market Data Quickstart Source: https://docs.whitebit.com/products/market-data/quickstart Fetch live prices, orderbooks, and recent trades from the WhiteBIT API — no authentication required. Fetch live market data from the WhiteBIT API in under 2 minutes. All Market Data endpoints are public — no account, no API key, no signing. ## Prerequisites * A terminal or HTTP client (curl, Postman, or any programming language with HTTP support) * No WhiteBIT account needed * No API key needed Confirm the API is reachable and operational. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl https://whitebit.com/api/v4/public/ping ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get("https://whitebit.com/api/v4/public/ping") print(response.json()) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} ["pong"] ``` Retrieve the full list of trading pairs with minimum amounts and trading rules. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl https://whitebit.com/api/v4/public/markets ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get("https://whitebit.com/api/v4/public/markets") markets = response.json() print(f"Total markets: {len(markets)}") print(markets[0]) ``` **Expected response (trimmed):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "name": "BTC_USDT", "stock": "BTC", "money": "USDT", "stockPrec": "6", "moneyPrec": "2", "makerFee": "0.1", "takerFee": "0.1", "minAmount": "0.00001", "minTotal": "1", "tradesEnabled": true, "type": "spot" }, "..." ] ``` The response contains 900+ markets. Key fields: `name` (pair), `stock` (base currency), `money` (quote currency), `minAmount` (minimum order quantity), `minTotal` (minimum order value). For Go and PHP examples, see [SDKs](/sdks). Fetch 24-hour pricing and volume data. The ticker endpoint returns all pairs — filter for the desired market. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl https://whitebit.com/api/v4/public/ticker ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get("https://whitebit.com/api/v4/public/ticker") ticker = response.json() btc_usdt = ticker.get("BTC_USDT", {}) print(btc_usdt) ``` **Expected response (BTC\_USDT entry):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "BTC_USDT": { "base_id": 1, "quote_id": 825, "last_price": "65432.10", "base_volume": "1234.567", "quote_volume": "80765432.10", "isFrozen": false, "change": "2.5" } } ``` Key fields: `last_price` (most recent trade price), `base_volume` (24h volume in base currency), `quote_volume` (24h volume in quote currency), `change` (24h percentage change). Retrieve the current orderbook depth. The `limit` parameter controls the number of price levels returned (1–100). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl "https://whitebit.com/api/v4/public/orderbook/BTC_USDT?limit=5" ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get( "https://whitebit.com/api/v4/public/orderbook/BTC_USDT", params={"limit": 5} ) orderbook = response.json() print(f"Best ask: {orderbook['asks'][0]}") print(f"Best bid: {orderbook['bids'][0]}") ``` **Expected response (trimmed):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "ticker_id": "BTC_USDT", "timestamp": 1700000000, "asks": [ ["65450.00", "0.500"], ["65460.00", "1.200"] ], "bids": [ ["65430.00", "0.800"], ["65420.00", "1.500"] ] } ``` Each entry is a `[price, quantity]` pair. `asks` = sell orders (ascending by price), `bids` = buy orders (descending by price). Retrieve the most recently executed trades for BTC\_USDT. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl https://whitebit.com/api/v4/public/trades/BTC_USDT ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests response = requests.get("https://whitebit.com/api/v4/public/trades/BTC_USDT") trades = response.json() print(f"Latest trade: {trades[0]}") ``` **Expected response (trimmed):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "tradeID": 123456789, "price": "65435.50", "quote_volume": "0.015", "base_volume": "981.53", "trade_timestamp": 1700000000, "type": "buy" }, "..." ] ``` Key fields: `tradeID` (unique identifier), `price` (execution price), `type` ("buy" or "sell"), `trade_timestamp` (Unix time in seconds). These five public endpoints cover one-shot lookups. For continuous updates, switch to the [WebSocket Quickstart](/guides/websocket-quickstart) — a single connection replaces every poll above. **No authentication — by design** — Market Data endpoints are intentionally public. No API key, no HMAC signing, no account. WhiteBIT exposes pricing, orderbook, and trade data publicly to support price aggregators, data vendors, and integration testing without requiring account creation. Public endpoints have separate rate limits but no per-key restrictions. **Polling vs streaming** — The five steps above use REST (request → response). This is appropriate for one-time lookups but expensive for real-time monitoring: polling the ticker endpoint every second across hundreds of pairs exhausts rate limits quickly and adds latency. For continuous price or orderbook updates, use [WebSocket](/guides/websocket-quickstart) instead — a single persistent connection streams each update as it occurs, with no polling overhead. ## What's next Place a first trade — requires an API key with Trading permission. Stream real-time price updates instead of polling. Combine a REST snapshot and a WebSocket stream into a live price board — no API key. Set up API keys and HMAC signing for authenticated endpoints. # Mining Pool Source: https://docs.whitebit.com/products/mining/overview Manage Bitcoin mining operations via API -- from account creation to hashrate monitoring, worker management, and payout configuration. Manage Bitcoin mining operations via API -- from account creation to hashrate monitoring, worker management, and payout configuration. 11 API endpoints provide full operational visibility and control. Mining Pool is not a cloud mining platform. Actual mining requires connecting ASIC hardware (or a hosted mining service) to the stratum URL provided by the API. The endpoints below manage mining accounts and monitor performance -- physical hardware must be connected separately. ## Capabilities The Mining Pool API covers the full mining operations lifecycle. * **Mining account creation** -- create and manage multiple mining accounts via `POST /api/v4/mining/accounts/create`. Each account name must be unique (alphanumeric + underscores). * **Hashrate monitoring** -- track hashrate performance per account and per individual worker. Historical hashrate data available via `POST /api/v4/mining/hashrate` with configurable intervals (5m, 1h, 24h). * **Rewards tracking** -- view mining rewards received per account via `POST /api/v4/mining/rewards`. * **Worker management** -- list online workers by name, monitor individual worker hashrate performance. * **Payout configuration** -- set payout destination to [Main balance](/concepts/balances) or an external BTC address via `POST /api/v4/mining/payout-destination/edit`. * **Watcher links** -- create shareable monitoring links with configurable permissions and expiration via `POST /api/v4/mining/watcher-links/create`. Useful for hosting providers sharing stats with clients. ## Who Uses This * **Mining operations** -- large-scale miners managing multiple accounts and workers. API integration for automated hashrate monitoring and payout management. * **Hosting providers** -- mining hosting services managing client accounts. Watcher links allow sharing monitoring access without exposing API keys. * **Individual miners** -- miners connecting ASIC hardware to the WhitePool stratum endpoint. API provides programmatic access to rewards and performance data. ## Common Integration Patterns **Mining operations dashboard** -- Create mining accounts per physical location or hardware batch. Monitor aggregate and per-worker hashrate via API. Set up automated alerts when hashrate drops below thresholds. Configure payout destinations ([Main balance](/concepts/balances) for trading, external BTC address for cold storage). Share read-only access with stakeholders via watcher links. **Hosting provider integration** -- Create separate mining accounts per client (one mining account per customer). Generate watcher links with appropriate permissions for client visibility. Track rewards per account for billing and revenue sharing. Monitor worker status programmatically for uptime SLAs. ## Platform Context The WhiteBIT platform brands the mining pool as **WhitePool**. Stratum connection details (pool URL, ports) are available via the `POST /api/v4/mining/miners/info` endpoint after creating a mining account. Miners connect ASIC hardware to the provided stratum URL (`stratum+tcp://pool.whitebit.com:3333` or `:3334`). ## Technical Overview * **11 endpoints** (all `POST`, all authenticated) * **Endpoint groups:** accounts (2), rewards (1), hashrate (1), payout (2), miners/workers (3), watcher links (2) * **Authentication:** HMAC-SHA512 ([guide](/api-reference/authentication)) * **Rate limits:** 1000 requests per 10 seconds per endpoint ([details](/api-reference/rate-limits)) * **Mining protocol:** Stratum (connection details returned by `POST /api/v4/mining/miners/info`) For full endpoint documentation, see the [Mining Pool API Reference](/api-reference/account-wallet/overview). ## What's Next Create a mining account and configure payouts in under 5 minutes. Full endpoint documentation for all 11 mining endpoints. # Mining Pool Quickstart Source: https://docs.whitebit.com/products/mining/quickstart Create a mining account, view stratum connection details, check hashrate, and configure payout destination -- step by step. Mining account creation is API-only — no UI flow exists. The four steps below cover account creation, stratum lookup, hashrate monitoring, and payout configuration, all under one API key with the appropriate Mining scope. ## Prerequisites * A WhiteBIT account with completed KYC ([register](https://whitebit.com/auth/register)) * An API key with appropriate permissions ([create key](https://whitebit.com/settings/api)) * HMAC-SHA512 signing configured ([authentication guide](/api-reference/authentication)) * `curl` and `jq` installed (for command-line examples) Mining account creation is fully API-driven and requires no prior UI setup. However, actual mining requires connecting ASIC hardware (or a hosted mining service) to the stratum URL provided in Step 2. Without connected hardware, hashrate will be zero and no rewards will accrue. Create a new mining account with a unique name. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/mining/accounts/create \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "name": "my_miner_01", "request": "/api/v4/mining/accounts/create", "nonce": 1709340000000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests, json, hmac, hashlib, base64, time API_KEY = "YOUR_API_KEY" API_SECRET = "YOUR_SECRET" BASE_URL = "https://whitebit.com" def make_request(endpoint, body): nonce = int(time.time() * 1000) body["request"] = endpoint body["nonce"] = nonce data_json = json.dumps(body) payload = base64.b64encode(data_json.encode()) signature = hmac.new( API_SECRET.encode(), payload, hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload.decode(), "X-TXC-SIGNATURE": signature, } return requests.post(f"{BASE_URL}{endpoint}", headers=headers, data=data_json) # Create a mining account response = make_request("/api/v4/mining/accounts/create", { "name": "my_miner_01", }) print(json.dumps(response.json(), indent=2)) ``` For Go and PHP examples, see [SDKs](/sdks). **Required field:** `name` (unique, alphanumeric + underscores, max 255 characters). **Optional:** `referralCode`. **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "name": "my_miner_01", "createdAt": 1709340000 } } ``` Retrieve stratum URLs, fee information, and worker counts for the mining account. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/mining/miners/info \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "account": "my_miner_01", "request": "/api/v4/mining/miners/info", "nonce": 1709340000001 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Get stratum connection details response = make_request("/api/v4/mining/miners/info", { "account": "my_miner_01", }) print(json.dumps(response.json(), indent=2)) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "fee": "2.5", "workers": { "online": 0, "offline": 0, "low": 0 }, "stratum": [ {"url": "stratum+tcp://pool.whitebit.com:3333", "workersCount": 0}, {"url": "stratum+tcp://pool.whitebit.com:3334", "workersCount": 0} ] } } ``` Use the returned stratum URL and port to configure mining hardware. Set the `user` field in the miner configuration to the mining account name (`my_miner_01`). Monitor hashrate performance for the mining account. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/mining/hashrate \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "account": "my_miner_01", "interval": "1h", "request": "/api/v4/mining/hashrate", "nonce": 1709340000002 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Check hashrate response = make_request("/api/v4/mining/hashrate", { "account": "my_miner_01", "interval": "1h", }) print(json.dumps(response.json(), indent=2)) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": { "account": "my_miner_01", "hashrate": [ {"timestamp": 1709340000, "hashrate": "0", "rejectRate": 0} ] } } ``` Hashrate will be zero until mining hardware connects and submits shares. Available intervals: `5m`, `1h`, `24h`. Set the payout destination to Main balance (for trading or lending) or an external BTC address (for cold storage). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Option A: Payout to Main balance curl -X POST https://whitebit.com/api/v4/mining/payout-destination/edit \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "accountName": "my_miner_01", "destination": "main_balance", "request": "/api/v4/mining/payout-destination/edit", "nonce": 1709340000003 }' # Option B: Payout to external BTC address curl -X POST https://whitebit.com/api/v4/mining/payout-destination/edit \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "accountName": "my_miner_01", "destination": "external_address", "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", "request": "/api/v4/mining/payout-destination/edit", "nonce": 1709340000004 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Option A: Payout to Main balance response = make_request("/api/v4/mining/payout-destination/edit", { "accountName": "my_miner_01", "destination": "main_balance", }) print(response.json()) # Option B: Payout to external BTC address response = make_request("/api/v4/mining/payout-destination/edit", { "accountName": "my_miner_01", "destination": "external_address", "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", }) print(response.json()) ``` **Required fields:** `accountName`, `destination` (`main_balance` or `external_address`). When `destination` is `external_address`, the `address` field (BTC address) is also required. **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "payoutDestination": "main_balance", "externalAddress": null } ``` After connecting mining hardware to the stratum URL from Step 2, hashrate data appears within minutes. Rewards begin accruing once shares are submitted. Track rewards via `POST /api/v4/mining/rewards`. ## What's Next Stratum ports 3333 and 3334, hashrate intervals (5m, 1h, 24h), watcher links for shared monitoring, and the WhitePool platform branding. Full endpoint documentation for all 11 mining endpoints. For Go and PHP examples, see [SDKs](/sdks). # Spot Trading Source: https://docs.whitebit.com/products/spot/overview Programmatic access to 800+ trading pairs across 410+ crypto assets on WhiteBIT. WhiteBIT supports 800+ trading pairs across 410+ crypto assets. The Spot Trading API provides programmatic access to WhiteBIT [spot markets](/concepts/markets) with 6 order types, bulk-limit orders (up to 20 orders per call), and a kill-switch that cancels all active orders after a configurable timeout. ## Capabilities * **6 order types** — Market, Limit, Stop-Limit, Stop-Market, Stock-Market, Bulk-Limit ([details](/concepts/order-types)) * **Bulk orders** — Place up to 20 limit orders in a single API call ([endpoint](/api-reference/trading/bulk-limit-order)) * **Kill-switch** — Emergency mechanism to cancel all active orders after a configurable timeout ([sync timer](/api-reference/trading/sync-kill-switch-timer), [status](/api-reference/trading/status-kill-switch-timer)) * **Order modification** — Modify existing orders in-place without canceling and recreating ([endpoint](/api-reference/trading/modify-order)) * **Client Order ID** — Attach custom identifiers for order tracking and reconciliation * **Self-Trade Prevention** — Prevent accidental self-crossing when quoting both sides ([details](/platform/self-trade-prevention)) ## Who Uses This * **Trading firms** — Automated execution across hundreds of pairs with bulk-limit orders, the kill-switch, and in-place order modification * **Fintechs** — Embedded spot trading in consumer or business applications via the REST API * **Embedded Trading** — WhiteBIT liquidity offered to end users via [Embedded Trading](/guides/embedded-trading-overview) (up to 40% of the trading fee generated by referred users) * **Market makers** — Liquidity provision through the [Market-Making Program](/guides/market-maker-overview) (maker rebates up to -0.012% for qualifying volume above \$100M/30 days) ## Common Integration Patterns **Trading automation** — Combine the REST API for order placement with [WebSocket](/guides/websocket-quickstart) for real-time price data; orders can also be placed (global platform only) over the [WebSocket order methods](/websocket/order-management/overview). Set the [kill-switch](/api-reference/trading/sync-kill-switch-timer) timer so all active orders cancel automatically if the bot stops sending heartbeats. Existing integrations include Bitsgap and TradingView. **Market making** — Use [bulk limit orders](/api-reference/trading/bulk-limit-order) (up to 20 per call) alongside the real-time orderbook [depth WebSocket channel](/guides/websocket-quickstart). The [Market-Making Program](/guides/market-maker-overview) offers maker fee rebates up to -0.012% for qualifying volume (\$100M+/30 days). Pair with [colocation](/platform/colocation) for low-latency execution (3–5 ms) and [sub-accounts](/products/sub-accounts/overview) to run market-making and directional strategies on independent balances with separate API keys. Enable [Self-Trade Prevention](/platform/self-trade-prevention) to avoid accidental self-crossing. **Multi-exchange arbitrage** — Subscribe to the `lastprice` WebSocket channel for real-time price monitoring across pairs. Use [colocation](/platform/colocation) (3–5 ms latency) for execution speed. Market orders provide immediate fills at best available price. ## Fee Structure | | Maker | Taker | | - | - | - | | Base rate | 0.1% | 0.1% | | VIP (best tier) | -0.001% | 0.03% | | Market-Making Program (best tier) | -0.012% | 0.020% | Full fee schedule with all VIP tier breakpoints: [trading fees page](https://whitebit.com/trading-data/trading-fees) and [VIP program](https://whitebit.com/vip-program). Query current fees via the [market fee endpoint](/api-reference/trading/query-market-fee), or the effective fee for one market via the [single-market fee endpoint](/api-reference/trading/query-market-fee-single). ## Technical Overview | Detail | Value | | - | - | | Endpoints | 20 (all `POST`, all authenticated) | | Authentication | HMAC-SHA512 ([guide](/api-reference/authentication)) | | Rate limits | Vary per endpoint ([details](/api-reference/rate-limits)) | | Base URL | `https://whitebit.com` | | WebSocket URL | `wss://wss.whitebit.com/ws` | Endpoint categories: * **Account** — Trade balance query (1 endpoint) * **Order management** — Create, modify, cancel orders; bulk operations (10 endpoints) * **Order queries** — Active orders, executed history, execution deals, order history, delisting orders (5 endpoints) * **Market fees** — Default maker/taker rates, custom per-market overrides, and the effective fee for a single market (2 endpoints) * **Kill-switch** — Sync timer, status (2 endpoints) For full endpoint documentation, see the [Spot Trading API Reference](/api-reference/trading/spot-overview). For Go and PHP examples, see [SDKs](/sdks). ## What's Next Place a first trade in 5 minutes. All 20 spot trading endpoints with parameters, signing, error codes, and rate limits. Build a Python trading bot with signed REST orders, WebSocket fills, kill-switch heartbeat, and a grid-bot example. # Spot Trading Quickstart Source: https://docs.whitebit.com/products/spot/quickstart Place a first spot trade on WhiteBIT — check balance, create a limit order, and cancel the order — in under 5 minutes. Place a limit order on BTC\_USDT against the live orderbook with HMAC-SHA512 signing. The four-step block below uses a price far below market, so the order opens but does not fill — safe for testing without risking a fill. ## Prerequisites * A WhiteBIT account ([register](https://whitebit.com/auth/register)) * An API key with **Trading** permission ([create one](https://whitebit.com/settings/api)) * Funds in the **Trade** balance (transfer from Main balance if needed — see [Balances & Transfers](/concepts/balances)) * Familiarity with HMAC-SHA512 signing — see [Authentication](/api-reference/authentication) WhiteBIT has no public testnet or sandbox. All orders execute against the live orderbook. For risk-free practice, use Demo Tokens (DBTC/DUSDT) — activate from the [WhiteBIT Codes page](https://whitebit.com/codes). For real-asset testing, use minimum order sizes and cancel test orders after verification. Verify available funds before placing an order. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # See /api-reference/authentication for signing details. curl -X POST https://whitebit.com/api/v4/trade-account/balance \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{"ticker":"USDT","request":"/api/v4/trade-account/balance","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64 import hashlib import hmac import json import time import requests API_KEY = "YOUR_API_KEY" # Replace with actual API key API_SECRET = "YOUR_SECRET" # Replace with actual API secret BASE_URL = "https://whitebit.com" def send_request(path, data=None): if data is None: data = {} data["request"] = path data["nonce"] = int(time.time() * 1000) data_json = json.dumps(data) payload_b64 = base64.b64encode(data_json.encode()).decode() signature = hmac.new( API_SECRET.encode(), payload_b64.encode(), hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload_b64, "X-TXC-SIGNATURE": signature, } return requests.post(BASE_URL + path, headers=headers, data=data_json).json() # Check USDT balance balance = send_request("/api/v4/trade-account/balance", {"ticker": "USDT"}) print(balance) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "USDT": { "available": "1000.00", "freeze": "0" } } ``` `available` = funds ready for trading. `freeze` = funds locked in active orders. The cURL examples show request structure with placeholder headers. For a runnable signing implementation, use the Python tab. For Go and PHP examples, see [SDKs](/sdks). Create a limit buy order on BTC\_USDT. Set the price well below the current market price to avoid immediate execution — the order remains open for safe testing. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Set price well below current market to prevent execution. curl -X POST https://whitebit.com/api/v4/order/new \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{"market":"BTC_USDT","side":"buy","amount":"0.0001","price":"30000","request":"/api/v4/order/new","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} order = send_request("/api/v4/order/new", { "market": "BTC_USDT", "side": "buy", "amount": "0.0001", "price": "30000" # Well below market — adjust if needed }) print(order) orderId = order.get("orderId") print(f"Order ID: {orderId}") ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "orderId": 12345678, "clientOrderId": "", "market": "BTC_USDT", "side": "buy", "type": "limit", "timestamp": 1700000000.000, "amount": "0.0001", "price": "30000", "...": "..." } ``` Request fields: `market` (trading pair), `side` ("buy" or "sell"), `amount` (quantity in the base asset), `price` (limit price in the quote asset). Optional: `clientOrderId` (custom identifier), `stp` (self-trade prevention mode). Verify the newly placed order appears in the active orders list. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/orders \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{"market":"BTC_USDT","request":"/api/v4/orders","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} active_orders = send_request("/api/v4/orders", {"market": "BTC_USDT"}) print(f"Active orders: {len(active_orders)}") for o in active_orders: print(f" Order {o['orderId']}: {o['side']} {o['amount']} @ {o['price']}") ``` **Expected response (trimmed):** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "orderId": 12345678, "market": "BTC_USDT", "side": "buy", "amount": "0.0001", "price": "30000", "...": "..." } ] ``` Cancel the limit order using the `orderId` returned in Step 2. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/order/cancel \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{"market":"BTC_USDT","orderId":12345678,"request":"/api/v4/order/cancel","nonce":1700000000000}' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} cancel = send_request("/api/v4/order/cancel", { "market": "BTC_USDT", "orderId": orderId }) print(cancel) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "orderId": 12345678, "market": "BTC_USDT", "side": "buy", "amount": "0.0001", "price": "30000", "...": "..." } ``` The response confirms the canceled order details. The previously frozen funds return to the available Trade balance. To verify canceled orders later, query the [order history](/api-reference/trading/query-executed-order-history) endpoint. The Trade balance now reflects the returned funds. **Trade balance vs Main balance** — WhiteBIT separates funds into Main balance (deposits, withdrawals) and Trade balance (order placement). An explicit transfer moves funds between balances; the API never draws from Main balance automatically. When a limit order is accepted, the required funds move from `available` to `freeze` in the Trade balance — after cancellation, `freeze` returns to zero and `available` is restored. Details: [Balances & Transfers](/concepts/balances). ## What's next Open a first leveraged position with up to 100x leverage. Explore all 6 order types including Stop-Limit and Bulk-Limit. REST and WebSocket together — order placement, kill-switch heartbeat, fill monitoring, reconnect logic, and a grid-bot worked example. # Sub-Accounts Source: https://docs.whitebit.com/products/sub-accounts/overview Create and manage thousands of separate trading accounts under one umbrella -- each with independent balances, API keys, and IP whitelists. Create and manage thousands of separate trading accounts under one umbrella -- each with independent balances, API keys, and IP whitelists. 20 API endpoints cover the full lifecycle from account creation to withdrawal approval. ## Capabilities The Sub-Accounts API provides full programmatic control over multi-account architectures. * **Account CRUD** -- create, edit, delete, and list sub-accounts. Each sub-account gets a unique identifier and independent settings. * **Fee-free instant transfers** -- move assets between the main account and any sub-account without fees or delays via `POST /api/v4/sub-account/transfer` * **Per-sub-account API keys** -- generate dedicated API keys for each sub-account with independent IP whitelists (up to 50 IPs per key). The 50-key limit applies per sub-account, independent from the main account and from other sub-accounts. Supports create, edit, delete, reset, and IP management. * **KYC URL generation** -- generate temporary KYC verification links for sub-account users via `POST /api/v4/sub-account/kyc-url`. Requirements: sub-account must be activated, active, and not using shared KYC. * **Withdrawal approval flow** -- list pending sub-account withdrawals via `POST /api/v4/sub-account/withdraw/unconfirmed-list`, then approve each one via `POST /api/v4/sub-account/withdraw/confirm`. Not available by default -- request access via [institutional@whitebit.com](mailto:institutional@whitebit.com). * **Direct crypto deposits** -- once enabled for the account, sub-accounts receive crypto directly at dedicated deposit addresses, generated via the standard [deposit-address endpoint](/api-reference/account-wallet/get-cryptocurrency-deposit-address) using the sub-account's own API key. Disabled by default (see note below). ## Who Uses This * **Fund managers and asset managers** -- separate client funds into isolated sub-accounts. Independent API keys per strategy or client. Fee-free transfers for rebalancing. ([Institutional sub-accounts](https://institutional.whitebit.com/sub-accounts)) * **Account operators and trading platforms** -- onboard end users as sub-accounts under [Embedded Trading](https://institutional.whitebit.com/broker-program). Earn up to 40% of trading fees generated by referred users. Manage API keys centrally. * **Prop trading firms** -- isolate trading strategies with separate risk profiles. Per-account balance monitoring. Independent position tracking. ## Common Integration Patterns **Fund / Asset Manager** -- Create a sub-account per client or investment strategy. Generate independent API keys for each, allowing automated trading without exposing the main account. Transfer funds fee-free between the main account and sub-accounts for rebalancing. Monitor balances across all sub-accounts via `POST /api/v4/sub-account/balances`. Track transfer history via `POST /api/v4/sub-account/transfer/history`. *(Source: [institutional.whitebit.com/sub-accounts](https://institutional.whitebit.com/sub-accounts))* **Account operator / Agency** -- Apply to [Embedded Trading](https://institutional.whitebit.com/broker-program) (contact [institutional@whitebit.com](mailto:institutional@whitebit.com)). Create sub-accounts for each end user. Generate KYC URLs for customer verification. Earn up to 40% of the trading fee generated by referred users; the applicable rate is agreed during enrollment. Manage all sub-account API keys from the main account. **EUR/SEPA operations for account operators:** Fiat deposit and withdrawal functionality requires separate institutional onboarding through WhiteBIT and a fiat processing partner. See the [Onboarding Guide](/institutional/onboarding) for the full process. **Crypto deposits are disabled by default.** Once enabled for the account, the capability applies to the account and its sub-accounts; enablement is not available via API. To request it, contact the assigned Account Manager or email [institutional@whitebit.com](mailto:institutional@whitebit.com). **Prop Trading Firm** -- Create isolated sub-accounts per trading strategy or desk. Assign different risk budgets by controlling the balance in each sub-account. Use per-sub-account API keys to run independent trading bots — traders, risk managers, operations, and finance teams can each have separately permissioned access. Block or unblock sub-accounts via API to enforce risk controls. *(Source: [institutional.whitebit.com/sub-accounts](https://institutional.whitebit.com/sub-accounts))* ## Technical Overview * **20 endpoints** (all `POST`, all authenticated) * **Endpoint groups:** account management (4), transfers (2), blocking (2), balances (1), withdrawals (2), API key management (5), IP whitelist management (3), KYC (1) * **Authentication:** HMAC-SHA512 ([guide](/api-reference/authentication)) * **Rate limits:** 1000 requests per 10 seconds per endpoint ([details](/api-reference/rate-limits)) * **Availability:** the withdrawal endpoints are not available by default; request access via [institutional@whitebit.com](mailto:institutional@whitebit.com) For full endpoint documentation, see the [Sub-Accounts API Reference](/api-reference/sub-accounts/overview). ## What's Next Create a sub-account and transfer funds in under 5 minutes. Full endpoint documentation for all 20 sub-account endpoints. End-to-end integration guide for Embedded Trading. # Sub-Accounts Quickstart Source: https://docs.whitebit.com/products/sub-accounts/quickstart Create a sub-account, transfer funds, generate an API key, and check balances -- step by step. Each sub-account holds its own balance and API keys. Funds and signing scopes are isolated from the main account; transfers between the two accounts are explicit and fee-free. The four steps below set up that isolation, from creation through balance verification. ## Prerequisites * A WhiteBIT account with completed KYC ([register](https://whitebit.com/auth/register)) * An API key with **Trade** permission and sub-account management capability ([create key](https://whitebit.com/settings/api)) * Funds in [Main balance](/concepts/balances) (sub-account transfers draw from Main balance) * HMAC-SHA512 signing configured ([authentication guide](/api-reference/authentication)) * `curl` and `jq` installed (for command-line examples) Create a new sub-account with an alias and permissions. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/sub-account/create \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "alias": "strategy-alpha", "email": "strategy-alpha@example.com", "permissions": {"spotEnabled": true, "collateralEnabled": false}, "request": "/api/v4/sub-account/create", "nonce": 1709340000000 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests, json, hmac, hashlib, base64, time API_KEY = "YOUR_API_KEY" API_SECRET = "YOUR_SECRET" BASE_URL = "https://whitebit.com" def make_request(endpoint, body): nonce = int(time.time() * 1000) body["request"] = endpoint body["nonce"] = nonce data_json = json.dumps(body) payload = base64.b64encode(data_json.encode()) signature = hmac.new( API_SECRET.encode(), payload, hashlib.sha512 ).hexdigest() headers = { "Content-Type": "application/json", "X-TXC-APIKEY": API_KEY, "X-TXC-PAYLOAD": payload.decode(), "X-TXC-SIGNATURE": signature, } return requests.post(f"{BASE_URL}{endpoint}", headers=headers, data=data_json) # Create a sub-account response = make_request("/api/v4/sub-account/create", { "alias": "strategy-alpha", "email": "strategy-alpha@example.com", "permissions": {"spotEnabled": True, "collateralEnabled": False}, }) sub_account = response.json() print(json.dumps(sub_account, indent=2)) ``` For TypeScript and Python SDK examples, see [SDKs](/sdks). **Required fields:** `alias` (display name), `permissions` (object with `spotEnabled` and `collateralEnabled`). When `shareKyc` is `false` or omitted, `email` is also required. **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": "8e667b4a-0b71-4988-8af5-9474dbfaeb51", "alias": "strategy-alpha", "userId": "u-12345", "email": "s***@example.com", "status": "active", "color": "#FF5733", "kyc": { "shareKyc": false, "kycStatus": "verified" }, "permissions": { "spotEnabled": true, "collateralEnabled": false } } ``` Save the `id` value for subsequent steps. Move assets from the main account to the newly created sub-account. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/sub-account/transfer \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "id": "", "direction": "main_to_sub", "ticker": "USDT", "amount": "100", "request": "/api/v4/sub-account/transfer", "nonce": 1709340000001 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Transfer funds to sub-account response = make_request("/api/v4/sub-account/transfer", { "id": "", "direction": "main_to_sub", "ticker": "USDT", "amount": "100", }) print(response.json()) ``` **Required fields:** `id` (sub-account UUID), `direction` (`main_to_sub` or `sub_to_main`), `ticker`, `amount`. Transfers are instant and fee-free. **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "transaction_id": "tx_..." } ``` Generate a dedicated API key for the sub-account to enable independent trading. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/sub-account/api-key/create \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "subAccountId": "", "type": 1, "title": "Trading Bot Key", "request": "/api/v4/sub-account/api-key/create", "nonce": 1709340000002 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Create API key for sub-account response = make_request("/api/v4/sub-account/api-key/create", { "subAccountId": "", "type": 1, "title": "Trading Bot Key", }) print(response.json()) ``` **Required fields:** `subAccountId` (UUID), `type` (1 = info and trading, 2 = info, trading, deposits, withdrawals). **Optional:** `title` (custom name for the key). Save the `secretKey` immediately -- the API does not return the secret key again after creation. To receive crypto deposits directly, the sub-account needs a `type: 2` key (deposits and withdrawals) **and** the account must have deposits enabled. Crypto deposits are disabled by default — to enable crypto deposits for the account and its sub-accounts, contact the assigned Account Manager or email [institutional@whitebit.com](mailto:institutional@whitebit.com). Once enabled, generate the address via the standard [deposit-address endpoint](/api-reference/account-wallet/get-cryptocurrency-deposit-address) signed with the sub-account's own key. Verify that the transferred funds appear in the sub-account balance. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/sub-account/balances \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "id": "", "request": "/api/v4/sub-account/balances", "nonce": 1709340000003 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Check sub-account balances response = make_request("/api/v4/sub-account/balances", { "id": "", }) print(json.dumps(response.json(), indent=2)) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "USDT": [ { "main": "100", "spot": "0", "collateral": "0" } ] } ``` The response keys ticker symbols to an array of balance objects. `main`, `spot`, and `collateral` show available funds in each balance type for the sub-account. The sub-account now has an isolated balance and a dedicated API key. To restrict the key to known IPs, call `POST /api/v4/sub-account/api-key/ip-address/create` with the whitelist. ## Sub-account withdrawal approval When the sub-account withdrawal feature is enabled, a withdrawal created with a sub-account key does not settle immediately. The transaction enters `unconfirmed_by_main_account` status and waits for main account approval, giving the main account a control point over every sub-account withdrawal. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant Sub as Sub-account (own key) participant WB as WhiteBIT participant Main as Main account (own key) Main->>WB: POST /sub-account/api-key/edit (enable withdraw URL) WB-->>Main: 200 — withdraw enabled on the key Sub->>WB: POST /main-account/withdraw WB-->>Sub: status unconfirmed_by_main_account Main->>WB: POST /sub-account/withdraw/unconfirmed-list WB-->>Main: pending withdrawals (transaction id) Main->>WB: POST /sub-account/withdraw/confirm (transaction id) WB-->>Main: 200 — released for processing Note over WB: Unconfirmed withdrawals expire if not confirmed ``` The sub-account withdrawal endpoints are not available by default. To request access, contact [institutional@whitebit.com](mailto:institutional@whitebit.com). Without main account confirmation, an unconfirmed withdrawal expires after a retention period. A newly created `type: 2` key lists the `withdraw` and `deposit` groups in `accessEndpoints`, but each URL defaults to `enable: false`. Until the withdraw URL is enabled, `POST /api/v4/main-account/withdraw` returns `401` with `{"code":4,"message":"This API Key is not authorized to perform this action."}`. Enable it from the main account with [Edit Sub-Account API Key](/api-reference/sub-accounts/edit-sub-account-api-key) (`POST /api/v4/sub-account/api-key/edit`): ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/sub-account/api-key/edit \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "apiKeyId": "SUB_ACCOUNT_API_KEY_ID", "title": "Trading Bot Key", "urls": [ { "url": "/api/v4/main-account/withdraw", "enable": true } ], "request": "/api/v4/sub-account/api-key/edit", "nonce": 1709340000006 }' ``` `title` is required; reuse the key's current title to avoid renaming it. The `urls` array is merged into the key's existing settings, so enabling the withdraw URLs leaves other endpoints untouched. Verify with [List Sub-Account API Keys](/api-reference/sub-accounts/list-sub-account-api-keys): the withdraw URLs under `accessEndpoints` now show `enable: true`. The sub-account creates the withdrawal with the sub-account's own `type: 2` API key (deposits and withdrawals) on the standard [Create withdraw request](/api-reference/account-wallet/create-withdraw-request) endpoint (`POST /api/v4/main-account/withdraw`). No main-account-side initiation endpoint exists — the request is signed with the sub-account key. The resulting transaction enters `unconfirmed_by_main_account` status. Using a main-account key, list the sub-account withdrawals awaiting approval. Capture the `id` of each transaction to confirm. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/sub-account/withdraw/unconfirmed-list \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "limit": 100, "offset": 0, "request": "/api/v4/sub-account/withdraw/unconfirmed-list", "nonce": 1709340000004 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # List unconfirmed sub-account withdrawals response = make_request("/api/v4/sub-account/withdraw/unconfirmed-list", { "limit": 100, "offset": 0, }) print(json.dumps(response.json(), indent=2)) ``` Each item includes the transaction `id`, `subAccountId`, `currency`, `amount`, and `createdAt`. Approve a listed withdrawal by external `id`. A successful call returns an empty object and releases the withdrawal for processing. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://whitebit.com/api/v4/sub-account/withdraw/confirm \ -H "Content-Type: application/json" \ -H "X-TXC-APIKEY: YOUR_API_KEY" \ -H "X-TXC-PAYLOAD: YOUR_PAYLOAD" \ -H "X-TXC-SIGNATURE: YOUR_SIGNATURE" \ -d '{ "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "request": "/api/v4/sub-account/withdraw/confirm", "nonce": 1709340000005 }' ``` ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} # Confirm a sub-account withdrawal response = make_request("/api/v4/sub-account/withdraw/confirm", { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", }) print(response.status_code, response.json()) ``` Confirmation is the only main-account action on an unconfirmed withdrawal — no reject endpoint exists, and an unconfirmed withdrawal that is never confirmed expires automatically. ## What's Next Integration patterns for fund managers, account operators, and prop trading firms. Fee share up to 40%, sub-account-per-customer onboarding, KYC URL generation, and per-customer API keys with dedicated IP whitelists. For TypeScript and Python SDK examples, see [SDKs](/sdks). # SDKs Source: https://docs.whitebit.com/sdks Official WhiteBIT SDK repositories for Go, Python, and PHP. WhiteBIT publishes official SDK repositories for Go, Python, and PHP. Each repository has its own README with install, authentication, and usage details. ## Official SDKs Official WhiteBIT SDK for Go developers. Official WhiteBIT SDK for Python developers. Official WhiteBIT SDK for PHP developers. Authentication models differ across SDKs (some accept Bearer tokens issued via partner flows, some sign HMAC-SHA512 requests with an API key + secret). Consult each repository's README for the supported authentication mode and installation steps before integrating. For raw HMAC-SHA512 signing without an SDK dependency, see [First API Call](/guides/first-api-call). Store API keys in environment variables (such as `WB_API_KEY` and `WB_API_SECRET`). Never hardcode credentials in source files. ## What's Next Step-by-step quickstart using curl and Python — no SDK required. HMAC-SHA512 signing, API key setup, and IP binding. # ADL quantile Source: https://docs.whitebit.com/websocket/account-streams/adl-quantile Subscribe to ADL (Auto-Deleveraging) quantile updates for open futures positions via WhiteBIT WebSocket. Subscribe to the ADL quantile — the 0–4 deleveraging-priority rank for the account's open futures positions — delivered as a push stream instead of a client-side poll of the [ADL quantile endpoint](/api-reference/trading/adl-quantile). A higher quantile means a position closes sooner if a liquidation on that market exhausts order-book liquidity. See [ADL Grade](/concepts/auto-deleveraging#adl-grade) for the ranking mechanism and formula behind the value. This channel does **NOT** support query operations — only subscribe/update/unsubscribe. For a one-time snapshot, call [`POST /api/v4/collateral-account/adl-quantile`](/api-reference/trading/adl-quantile). Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Subscribe to ADL quantile The server pushes an update immediately on subscribe, then re-pushes the current quantile for all active subscriptions every **30 seconds**, whether or not a position changed. A client sees a position's updated quantile no later than 30 seconds after the change, without needing to resubscribe. ## Update frequency The server pushes an update immediately after a successful subscribe, then independently re-pushes the current quantile for all active subscriptions every **30 seconds** — a periodic poll, not an event triggered by a position or mark price change. ## Error codes ## ADL quantile update object * [ADL quantile (REST)](/api-reference/trading/adl-quantile) — one-time HTTP snapshot of the same data. * [Auto-Deleveraging concept](/concepts/auto-deleveraging#adl-grade) — rating formula and grade thresholds behind the quantile values. * [Open positions](/api-reference/trading/open-positions) — list all currently open collateral trading positions. # Authorize Source: https://docs.whitebit.com/websocket/account-streams/authorize Authorize a WebSocket connection to subscribe to private account data streams on WhiteBIT. Authorize the WebSocket connection for private channel access. Send a WebSocket token obtained from the REST API. This channel handles WebSocket connection authorization. Authorize once per connection — all private channels become accessible after a single successful authorization. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Authorization flow **Step 1 — Get a WebSocket token** Call the REST endpoint to obtain a short-lived token: ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} POST /api/v4/profile/websocket_token ``` See [WebSocket Authentication](/websocket/authentication) for the full flow including request signing. **Step 2 — Send authorization request** **Step 3 — Receive confirmation** The connection is authorized. Subscribe to any private channel on the same connection. Authorization is per connection, not per subscription. Authorize once, then subscribe to as many private channels as needed on the same WebSocket connection. ## Update frequency Client-initiated. Send an `authorize` request after each new WebSocket connection. ## Error codes # Balance Margin Source: https://docs.whitebit.com/websocket/account-streams/balance-margin Subscribe to real-time margin balance updates for a WhiteBIT account via WebSocket. Query or subscribe to collateral (margin) balance updates. The response includes total balance, borrowed amount, and available amounts with and without borrowing. Updates are pushed every 1.5 seconds when the margin balance changes. Use the query operation for a one-time snapshot; use subscribe for continuous updates. Balance available for margin trade equals `balance × leverage` and depends on orderbook liquidity and open positions. When a position opens, the balance does not change, but the amount available for trading decreases. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query margin balance (one-time) Fetch current margin balances for specific assets without subscribing. `params`: `[asset, asset, ...]`. Pass asset tickers to query specific balances. Pass an empty array to query all assets. **Request** **Response** ## Subscribe to margin balance Updates include only assets whose margin balance changed. To hydrate full state on startup or after reconnection, send a `balanceMargin_request` query before subscribing. See [Reconnection and state recovery](/guides/websocket-quickstart#state-recovery-after-reconnect) for the full pattern. ## Update frequency The server pushes updates every **1.5 seconds** when the margin balance changes. ## Error codes ## Balance object * [Collateral Account Balance](/api-reference/trading/collateral-account-balance) — margin balance snapshot via REST. * [Balance Spot](/websocket/account-streams/balance-spot) — spot (trade) balance updates via WebSocket. # Balance Spot Source: https://docs.whitebit.com/websocket/account-streams/balance-spot Subscribe to real-time spot balance updates for a WhiteBIT account via WebSocket. Get and subscribe to [spot balance](/glossary#balance-spotbalance-trade) updates. The server sends incremental updates — only assets whose balance changed are included in each message. To retrieve the current state at any time without maintaining a subscription, use the one-time query operation. The server pushes updates every 1 second when a balance changes. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query spot balance (one-time) Fetch current spot balances for specific assets without subscribing. `params`: `[asset, asset, ...]`. Pass asset tickers to query specific balances. Pass an empty array to query all assets. **Request** **Response** ## Subscribe to spot balance Updates include only assets whose balance changed. To hydrate full state on startup or after reconnection, send a `balanceSpot_request` query before subscribing. See [Reconnection and state recovery](/guides/websocket-quickstart#state-recovery-after-reconnect) for the full pattern. ## Update frequency The server pushes updates every **1 second** when the balance changes. ## Error codes ## Balance object * [Trading balance](/api-reference/trading/trading-balance) — spot balance snapshot via REST. # Borrows Source: https://docs.whitebit.com/websocket/account-streams/borrows Query current margin borrows for a WhiteBIT account via WebSocket. Subscribe to collateral borrow status updates for all open margin positions, including borrow amounts, unrealized funding, and liquidation prices. The server pushes full snapshots of all open borrows every 1.5 seconds when borrow data changes. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Subscribe to borrows Each update is a full snapshot of all open borrows — local state auto-recovers within 1.5 seconds of subscribing. No gap-filling is needed after reconnection. ## Update frequency The server pushes updates every **1.5 seconds** when borrow data changes. ## Error codes ## Borrow object * [Borrows Events](/websocket/account-streams/borrows-events) — real-time margin call and liquidation events for collateral borrows. # Borrows Events Source: https://docs.whitebit.com/websocket/account-streams/borrows-events Subscribe to real-time margin borrow events for a WhiteBIT account via WebSocket. Subscribe to margin call and liquidation event notifications for collateral borrows. Events fire when a borrow enters margin call or liquidation state. This is an event-driven channel — updates are pushed once per state change, with no periodic polling or snapshot on subscribe. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Subscribe to borrow events This channel delivers events only on state changes — no snapshot is sent on subscribe, and events missed during a disconnection are not replayed. For complete borrow state awareness, pair this channel with [Borrows](/websocket/account-streams/borrows), which sends full snapshots every 1.5 seconds. ## Update frequency Updates are pushed in **real time** on borrow state changes (new borrow, repayment, liquidation). ## Error codes ## Borrow event object * [Borrows](/websocket/account-streams/borrows) — current borrow state with periodic full snapshots. # Deals Source: https://docs.whitebit.com/websocket/account-streams/deals Subscribe to real-time trade deal notifications for a WhiteBIT account via WebSocket. Query or subscribe to real-time trade execution (deal) notifications. Each deal represents a matched trade with price, amount, fee, and counterparty details. **Update interval:** real-time. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query deals (one-time) Fetch historical deal records for a market without subscribing. **Request** **Response** ## Subscribe to deals Trade events during a disconnection are not replayed. After reconnecting, use `deals_request` to query recent deals, or call the REST [Executed Order History](/api-reference/trading/query-executed-order-history) endpoint to backfill fills missed during the disconnection. See [Reconnection and state recovery](/guides/websocket-quickstart#state-recovery-after-reconnect). ## Update frequency Updates are pushed in **real time** on each trade execution for the account. ## Error codes ## Deal object * [Orders Pending](/websocket/account-streams/orders-pending) — open order lifecycle events via WebSocket. * [Orders Executed](/websocket/account-streams/orders-executed) — completed order records via WebSocket. * [Executed Order History](/api-reference/trading/query-executed-order-history) — trade history via REST for backfilling missed deals. ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Margin Positions Events Source: https://docs.whitebit.com/websocket/account-streams/margin-positions-events Subscribe to real-time margin position change events for a WhiteBIT account via WebSocket. Subscribe to margin call and liquidation event notifications for collateral positions. Events fire when a position enters margin call or liquidation state. The channel uses an event-driven update model — no snapshot is sent on subscribe; updates are delivered only when a position state change occurs. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Subscribe to position events This channel delivers events only on state changes — no snapshot is sent on subscribe, and events missed during a disconnection are not replayed. For complete position state awareness, pair this channel with [Positions](/websocket/account-streams/positions), which sends full snapshots every second. ## Update frequency Updates are pushed in **real time** on margin position state changes (open, close, liquidation). ## Position event object ## Error codes * [Positions](/websocket/account-streams/positions) — current position state with P\&L and liquidation price, updated every second. # Orders Executed Source: https://docs.whitebit.com/websocket/account-streams/orders-executed Subscribe to real-time notifications when account orders are executed on WhiteBIT via WebSocket. Query or subscribe to executed order history with optional filtering by order type (limit, market, or both). Each record includes execution details, fees, and status. **Update interval:** real-time. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query executed orders (one-time) Fetch historical executed orders for a market without subscribing. **Request** **Response** The private stream returns executed orders, including orders using Retail Price Improvement (RPI) mode. ## Subscribe to executed orders Execution events during a disconnection are not replayed. After reconnecting, use `ordersExecuted_request` to query recent executed orders, or call the REST [Executed Order History](/api-reference/trading/query-executed-order-history) endpoint to backfill missed records. See [Reconnection and state recovery](/guides/websocket-quickstart#state-recovery-after-reconnect). ## Update frequency Updates are pushed in **real time** when an order is fully executed or canceled. ## Error codes ## Executed order object * [Orders Pending](/websocket/account-streams/orders-pending) — stream of open (unexecuted) orders. * [Deals](/websocket/account-streams/deals) — individual trade fills for each executed order. ## Used in these guides * [Copy Trading](/guides/copy-trading) — mirror a lead trader's orders into followers' own accounts via OAuth-issued keys. # Orders Pending Source: https://docs.whitebit.com/websocket/account-streams/orders-pending Subscribe to real-time updates on pending account orders on WhiteBIT via WebSocket. Query or subscribe to active (unexecuted) orders across specified markets. The server pushes `ordersPending_update` events in real time on every order state change. Subscribe to multiple markets simultaneously by passing market names in the `params` array. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query pending orders (one-time) Fetch current pending orders for a market without subscribing to updates. **Request** **Response** ## Subscribe to order updates Events during a disconnection are not replayed. After reconnecting, query current open orders with `ordersPending_request` or the REST [Query Unexecuted Orders](/api-reference/trading/query-unexecuted-orders) endpoint before re-subscribing. See [Reconnection and state recovery](/guides/websocket-quickstart#state-recovery-after-reconnect). ## Update frequency Updates are pushed in **real time** on every order state change (new, modified, partially filled). ## Error codes ## Order modification behavior When `POST /api/v4/order/modify` is called, the matching engine cancels the original order and creates a replacement, producing **two sequential events**: 1. `event_id=3` (Finish) — original order cancelled. The `id` in the payload matches the old `order_id`. 2. `event_id=1` (New) — replacement order created with a **new `order_id`**. Clients tracking orders by `order_id` must update the stored value after each modify call. Use `client_order_id` for stable correlation across modifications.
The private stream returns active orders, including orders using Retail Price Improvement (RPI) mode. Because public `depth` excludes RPI orders, this stream is the source for an account's own RPI orders — see [including RPI orders in a local order book](/websocket/market-streams/depth#including-rpi-orders-in-a-local-order-book) for how to overlay those orders onto the public order book.
## Stop order activation When a stop order ([types](/websocket/account-streams/overview#order-types) `3`, `4`, `9`, `10`) triggers, the server emits an `event_id=1` (New) event for the now-active order **without** a preceding `event_id=3` (Finish) for the stop record. The `order_id` is preserved across activation — the same id appears on both the original stop and the activated order. The `type` and `status` fields do not change on activation: the type integer stays (`3` → `3`, and so on), and `status` remains `OPEN` (or transitions to `PARTIALLY_FILLED` only once the activated order begins filling). The arrival of a second `event_id=1` for an `order_id` already present in local state is the only activation signal. Clients tracking orders by `order_id` must **upsert** on `order_id` rather than append, otherwise the resting stop and the activated order will appear as two entries for the same logical order. This applies to all stop types: spot stop-limit (`3`), spot stop-market (`4`), margin stop-limit (`9`), and margin stop-market (`10`). Types `3` and `4` are spot-only; margin and futures markets use types `9` and `10`. ## Order object Fields present in both the query response (`records[]`) and the pushed `ordersPending_update` payload. * [Orders Executed](/websocket/account-streams/orders-executed) — stream of filled and cancelled orders. * [Query Unexecuted Orders](/api-reference/trading/query-unexecuted-orders) — open order snapshot via REST for state recovery after reconnection. # Account Streams Source: https://docs.whitebit.com/websocket/account-streams/overview Private WebSocket account streams provide real-time access to balances, orders, deals, and positions on WhiteBIT. Browse the available private WebSocket channels below. For connection details and message format, see the [WebSocket Overview](/websocket/overview). For rate limits, see [WebSocket Rate Limits](/websocket/rate-limits). ## Order types Several Account Stream channels return a `type` field identifying the order type. Use this table to interpret the value. | ID | Description | | - | - | | 1 | Limit | | 2 | Market | | 202 | Market [stock](/glossary#stock) | | 3 | Stop limit | | 4 | Stop market | | 203 | Stop market [stock](/glossary#stock) | | 7 | Margin limit | | 8 | Margin market | | 9 | Margin stop limit | | 10 | Margin stop market | | 14 | Margin normalization | **Type 14 (Margin normalization)** is a system-generated order, not one the account places. The platform creates it to settle a negative balance or on borrow closure (for example, a fee deduction or a funding accrual that pushes a balance below zero). Despite the name, it is not limited to margin markets and can also occur on spot. A normalization order always executes as the taker, and it is not subject to [self-trade prevention](/platform/self-trade-prevention), so it can match against the account's own resting order. When it does, both sides of the trade belong to the account. A taker fee is charged at the account's taker rate. On execution, an update is delivered on both `ordersExecuted_update` (with `type` 14) and `deals_update`. The order type is carried on `ordersExecuted_update`; `deals_update` rows do not include an order-type field. ## Channels Authenticate the WebSocket connection to access private channels Real-time spot balance updates for the account Real-time margin balance updates for the account Stream of pending (open) orders and order updates Stream of executed orders and order updates Real-time deal execution notifications Real-time position updates for margin trading Event notifications for margin position changes Real-time borrow status updates for margin trading Event notifications for borrow changes and liquidations ADL deleveraging-priority rank for open futures positions ## Related Place, modify, and cancel orders on the same authorized connection (global platform only) # Positions Source: https://docs.whitebit.com/websocket/account-streams/positions Subscribe to real-time collateral position updates for a WhiteBIT account via WebSocket. Subscribe to collateral position updates including P\&L, liquidation price, margin, and position side. **Update interval:** 1 second. This channel does **NOT** support query operations — only subscribe/update/unsubscribe. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Subscribe to positions Each update is a full snapshot of all open positions — local state auto-recovers within 1 second of subscribing. No gap-filling is needed after reconnection. ## Update frequency The server pushes updates every **1 second** when position data changes. ## Position object ## Error codes * [Margin Positions Events](/websocket/account-streams/margin-positions-events) — real-time margin call and liquidation events for collateral positions. # WebSocket Authentication Source: https://docs.whitebit.com/websocket/authentication How to authorize a WebSocket connection for access to private Account Stream channels. Private WebSocket channels (Account Streams) require authorization before subscribing. Use a two-step flow: obtain a short-lived token via the REST API, then send an `authorize` request on the WebSocket connection. Authorization is required once per connection. After a successful `authorize` response, the connection can subscribe to any private channel without re-authorizing. *** ## Step 1: Get a WebSocket token Call `POST /api/v4/profile/websocket_token` to obtain a token. Sign the request using the standard [HMAC-SHA512 authentication](/api-reference/authentication) process — authentication is required for this endpoint. Rate limit: 10 requests per 60 seconds. **Request body:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "request": "/api/v4/profile/websocket_token", "nonce": 1594297865000 } ``` **Response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "websocket_token": "your_current_token" } ``` The `websocket_token` value is used as the credential in the next step. Tokens are short-lived — request a fresh token before each new WebSocket connection. See [Get WebSocket Token](/api-reference/account-wallet/profile-websocket-token) for the full endpoint reference. *** ## Step 2: Authorize the connection After establishing the WebSocket connection, send an `authorize` request before subscribing to any private channel. **Request:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 0, "method": "authorize", "params": [ "your_websocket_token", "public" ] } ``` | Parameter | Type | Description | | - | - | - | | `params[0]` | STRING | The WebSocket token from Step 1 | | `params[1]` | STRING | Constant value — always `"public"` | **Success response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 0, "result": { "status": "success" }, "error": null } ``` Once the connection receives `"status": "success"`, subscribe to any Account Stream channel without further authorization. *** ## Error handling If authorization fails, the `error` field contains a non-null object: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 0, "result": null, "error": { "code": 1, "message": "invalid argument" } } ``` Common causes: | Cause | Resolution | | - | - | | Expired or invalid token | Request a new token from `POST /api/v4/profile/websocket_token` | | Incorrect `params[1]` value | Always pass the string `"public"` as the second parameter | | Connection not established | Ensure the WebSocket handshake completes before sending `authorize` | *** ## Related resources * [Authorize channel](/websocket/account-streams/authorize) — AsyncAPI spec for the `authorize` method * [Account Streams](/websocket/account-streams/overview) — All private channels requiring authorization * [REST API Authentication](/api-reference/authentication) — How to sign the token request * [Get WebSocket Token](/api-reference/account-wallet/profile-websocket-token) — REST endpoint reference ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Book Ticker Source: https://docs.whitebit.com/websocket/market-streams/book-ticker Subscribe to real-time best bid and ask price updates for trading pairs via WhiteBIT WebSocket. Real-time best bid and best ask price updates for a market. The server sends an update instantly whenever the best bid or best ask changes. Each update contains the current best bid price, best bid amount, best ask price, and best ask amount for the subscribed market. Use this stream to maintain an accurate top-of-book view without polling the REST API. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Subscribe to book ticker ## Update frequency Updates are pushed **instantly** on every best bid or ask change. The channel is change-driven: the server sends nothing while the best bid and ask are unchanged, so a quiet market can go multiple seconds without an update. Do not infer connection health from message arrival — verify the connection with a [ping](/websocket/market-streams/service) instead. ## Error codes Public `bookTicker_update` events exclude Retail Price Improvement (RPI) orders. The stream includes only regular order book liquidity. RPI orders are visible in private active order endpoints and in the exchange UI order book. ## Book ticker update object ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Order Book Depth Source: https://docs.whitebit.com/websocket/market-streams/depth Subscribe to real-time order book depth updates for a trading pair via WhiteBIT WebSocket. Real-time order book data with support for both one-time snapshots and continuous subscription updates. Each update contains changed price levels (asks and bids) as `[price, amount]` tuples. The server pushes incremental deltas every 100ms; if 10 seconds pass without an emitted `depth_update` on this subscription, a full snapshot is sent as a keepalive. Use this channel to maintain a live local order book for trading logic or display. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query order book depth (one-time) Fetch a single order book snapshot without subscribing to updates. **Request** **Response** ## Subscribe to order book depth Public `depth` updates exclude Retail Price Improvement (RPI) orders. The stream includes only regular order book liquidity. ## Including RPI orders in a local order book Public `depth` excludes RPI orders by design, so RPI orders never appear in this stream. RPI resting liquidity is not published on any market-data feed — it is visible only in private active orders and in the exchange UI order book. To display an account's own RPI orders alongside the public book, overlay its private active orders onto the local depth book. Subscribe to [`ordersPending`](/websocket/account-streams/orders-pending) (private) alongside `depth_subscribe`, then merge: 1. **Overlay only orders with `rpi: true`.** Non-RPI orders already appear in the public `depth` aggregate — overlaying every order double-counts the non-RPI orders. 2. **Aggregate by price before merging.** Public `depth` levels are price-aggregated `[price, total amount]`, while the private stream is per-order. Sum the RPI orders by price level, and use each order's `left` (remaining amount), not `amount` (original size). 3. **Map the side.** Order `side` `1` (sell) → ask; `2` (buy) → bid. 4. **Upsert by `order_id`.** Add or update on `event_id` `1` (new) and `2` (update); remove on `3` (finish). `order_id` changes on modify — correlate with `client_order_id`. Stop-order activation emits a second `event_id=1` for the same `order_id`, so upsert rather than append. 5. **Filter by `market`** to match the depth subscription. This overlay reflects only the account's own RPI orders. No feed exposes other participants' RPI liquidity. ## Update frequency The server pushes updates every **100ms** when the order book changes within the subscribed depth. If 10 seconds pass without an emitted `depth_update` on this subscription, a full snapshot is sent as a keepalive. ## Error codes ## Maintaining a local order book To maintain an accurate local order book: 1. Subscribe and wait for the first message (`params[0]` is `true`) — initialize order book from snapshot 2. For each incremental update: if amount is `"0"` remove the price level; otherwise update or insert at the correct sorted position 3. Keep asks sorted ascending, bids sorted descending 4. Truncate to the configured limit after each update ## Update model **First message** (`past_update_id` absent): Full order book snapshot. Replace any existing local state. **Subsequent messages** (`past_update_id` present): Incremental deltas. Apply each price level change to the local book. ## Ordering guarantees * Updates arrive in `update_id` order. Each incremental message's `past_update_id` matches the previous message's `update_id`. * If 10 seconds pass without an emitted `depth_update` on this subscription, the server sends a full snapshot (`params[0]` is `true`, no `past_update_id`) as a keepalive. Treat this as a full reset. * `update_id` reflects changes to the full order book for this market. A keepalive snapshot may carry an `update_id` greater than the last delta's `update_id` — this is expected and reflects book activity that did not produce a `depth_update` on this subscription, not a missed message. * A gap between an incremental delta's `past_update_id` and the stored `update_id` indicates a missed message — re-subscribe to resync. ## Order book data object * [Orderbook](/api-reference/market-data/orderbook) — full order book snapshot via REST for polling use cases. * [Depth](/api-reference/market-data/depth) — lightweight depth snapshot within ±2% of last price via REST. ## Code examples ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}} type IDepth = [string, string]; interface OrderBook { asks: IDepth[]; bids: IDepth[]; } const ws = new WebSocket("wss://wss.whitebit.com/ws"); const orderBook: OrderBook = { asks: [], bids: [] }; const LIMIT = 100; ws.addEventListener("open", () => { ws.send( JSON.stringify({ id: 1, method: "depth_subscribe", params: ["ETH_BTC", LIMIT, "0", true] }), ); }); ws.addEventListener("message", (event: MessageEvent) => { const message = JSON.parse(event.data.toString()); if (message.method === "depth_update") { const updateData = message.params[0] as Partial; const isFirstMessage = !updateData.past_update_id; if (isFirstMessage) { // First message or keepalive snapshot is a full snapshot - replace order book orderBook.asks = updateData.asks ?? []; orderBook.bids = updateData.bids ?? []; } else { // Subsequent messages are incremental updates applyUpdates(orderBook.asks, updateData.asks, "ask"); applyUpdates(orderBook.bids, updateData.bids, "bid"); truncateOrderBook(orderBook.asks); truncateOrderBook(orderBook.bids); } } }); function applyUpdates(orderBookSide: IDepth[], updates: IDepth[] | undefined, side: "ask" | "bid") { if (updates === undefined) return; for (const [price, amount] of updates) { const priceIndex = orderBookSide.findIndex((level) => level[0] === price); if (amount === "0") { if (priceIndex !== -1) { orderBookSide.splice(priceIndex, 1); } } else { if (priceIndex === -1) { const insertIndex = orderBookSide.findIndex((level) => side === "ask" ? level[0] > price : level[0] < price ); if (insertIndex === -1) { orderBookSide.push([price, amount]); } else { orderBookSide.splice(insertIndex, 0, [price, amount]); } } else { orderBookSide[priceIndex][1] = amount; } } } } function truncateOrderBook(orderBookSide: IDepth[]) { if (orderBookSide.length > LIMIT) { orderBookSide.splice(LIMIT); } } ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import asyncio import json import websockets class OrderBook: def __init__(self): self.asks = [] self.bids = [] LIMIT = 100 async def depth_subscribe(): async with websockets.connect('wss://wss.whitebit.com/ws') as ws: await ws.send(json.dumps({ 'id': 1, 'method': 'depth_subscribe', 'params': ['ETH_BTC', LIMIT, '0', True] })) async for message in ws: data = json.loads(message) if data.get('method') == 'depth_update': handle_depth_update(data['params']) def handle_depth_update(params): update_data = params[0] is_first_message = update_data.get('past_update_id') is None if is_first_message: order_book.asks = update_data.get('asks', []) order_book.bids = update_data.get('bids', []) else: apply_updates(order_book.asks, update_data.get('asks', []), "ask") apply_updates(order_book.bids, update_data.get('bids', []), "bid") truncate_order_book(order_book.asks) truncate_order_book(order_book.bids) def apply_updates(order_book_side, updates, side): for price, amount in updates: price = str(price) amount = str(amount) price_index = next((i for i, level in enumerate(order_book_side) if level[0] == price), -1) if amount == '0': if price_index != -1: order_book_side.pop(price_index) else: if price_index == -1: insert_index = next((i for i, level in enumerate(order_book_side) if (side == "ask" and level[0] > price) or (side == "bid" and level[0] < price)), -1) if insert_index == -1: order_book_side.append([price, amount]) else: order_book_side.insert(insert_index, [price, amount]) else: order_book_side[price_index][1] = amount def truncate_order_book(order_book_side): if len(order_book_side) > LIMIT: del order_book_side[LIMIT:] order_book = OrderBook() asyncio.get_event_loop().run_until_complete(depth_subscribe()) ``` ```java Java theme={"theme":{"light":"github-light","dark":"github-dark"}} import java.io.ByteArrayInputStream; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.json.*; import javax.websocket.*; @ClientEndpoint public class OrderBookClient { private static final int LIMIT = 100; private static List asks = new ArrayList<>(); private static List bids = new ArrayList<>(); private static CountDownLatch latch; public static void main(String[] args) throws URISyntaxException, InterruptedException { latch = new CountDownLatch(1); WebSocketContainer container = ContainerProvider.getWebSocketContainer(); URI uri = new URI("wss://wss.whitebit.com/ws"); container.connectToServer(OrderBookClient.class, uri); latch.await(1, TimeUnit.MINUTES); } @OnOpen public void onOpen(Session session) throws Exception { JsonObject message = Json.createObjectBuilder() .add("id", 1) .add("method", "depth_subscribe") .add("params", Json.createArrayBuilder() .add("ETH_BTC") .add(LIMIT) .add("0") .add(true) ) .build(); session.getBasicRemote().sendText(message.toString()); } @OnMessage public void onMessage(String message, Session session) { JsonReader reader = Json.createReader(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8))); JsonObject jsonMessage = reader.readObject(); if ("depth_update".equals(jsonMessage.getString("method"))) { JsonArray params = jsonMessage.getJsonArray("params"); JsonObject updateData = params.getJsonObject(0); boolean isFirstMessage = !updateData.containsKey("past_update_id") || updateData.isNull("past_update_id"); if (isFirstMessage) { asks = parseOrderBookSide(updateData.getJsonArray("asks")); bids = parseOrderBookSide(updateData.getJsonArray("bids")); } else { applyUpdates(asks, updateData.getJsonArray("asks"), "ask"); applyUpdates(bids, updateData.getJsonArray("bids"), "bid"); truncateOrderBook(asks); truncateOrderBook(bids); } } } @OnClose public void onClose(Session session, CloseReason reason) { System.out.println("Connection closed: " + reason); latch.countDown(); } @OnError public void onError(Session session, Throwable throwable) { throwable.printStackTrace(); latch.countDown(); } private static List parseOrderBookSide(JsonArray jsonArray) { List orderBookSide = new ArrayList<>(); for (JsonValue value : jsonArray) { JsonArray level = value.asJsonArray(); orderBookSide.add(new IDepth(level.getString(0), level.getString(1))); } return orderBookSide; } private static void applyUpdates(List orderBookSide, JsonArray updates, String side) { for (JsonValue value : updates) { JsonArray level = value.asJsonArray(); String price = level.getString(0); String amount = level.getString(1); int priceIndex = -1; for (int i = 0; i < orderBookSide.size(); i++) { if (orderBookSide.get(i).getPrice().equals(price)) { priceIndex = i; break; } } if ("0".equals(amount)) { if (priceIndex != -1) orderBookSide.remove(priceIndex); } else { if (priceIndex == -1) { int insertIndex = -1; for (int i = 0; i < orderBookSide.size(); i++) { if ((side.equals("ask") && orderBookSide.get(i).getPrice().compareTo(price) > 0) || (side.equals("bid") && orderBookSide.get(i).getPrice().compareTo(price) < 0)) { insertIndex = i; break; } } if (insertIndex == -1) orderBookSide.add(new IDepth(price, amount)); else orderBookSide.add(insertIndex, new IDepth(price, amount)); } else { orderBookSide.get(priceIndex).setAmount(amount); } } } } private static void truncateOrderBook(List orderBookSide) { if (orderBookSide.size() > LIMIT) orderBookSide.subList(LIMIT, orderBookSide.size()).clear(); } static class IDepth { private final String price; private String amount; public IDepth(String price, String amount) { this.price = price; this.amount = amount; } public String getPrice() { return price; } public String getAmount() { return amount; } public void setAmount(String amount) { this.amount = amount; } } } ``` ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — bulk quoting, RPI, kill-switch, and market-data streams. # Kline Source: https://docs.whitebit.com/websocket/market-streams/kline Subscribe to real-time candlestick (OHLCV) chart updates for a trading pair via WhiteBIT WebSocket. Query or subscribe to candlestick (OHLCV) data for a market and interval. Each candle contains open, high, low, close, and volume values for the specified interval. The server pushes updates every 0.5 seconds while a candle is active, reflecting the latest trade activity. Use this channel to power real-time charting or detect emerging price movements. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query candlesticks (one-time) Fetch historical candlestick data for a time range. **Request** **Response** Each record is a positional array in the same format as the subscription update. ## Interval constraints The interval must meet specific alignment rules to ensure candles align with natural time boundaries. 60 must be divisible by the interval. Valid: `1`, `2`, `3`, `4`, `5`, `6`, `10`, `12`, `15`, `20`, `30` Invalid: `7`, `11`, `13`, `17` Interval must be divisible by 60, and 3600 must be divisible by the interval. Valid: `60` (1m), `120` (2m), `180` (3m), `300` (5m), `900` (15m), `1800` (30m) Invalid: `420` (7m), `660` (11m) Interval must be divisible by 3600, and 86400 must be divisible by the interval. Valid: `3600` (1h), `7200` (2h), `14400` (4h), `21600` (6h), `43200` (12h) Invalid: `18000` (5h), `25200` (7h) Valid: `86400` (1d), `172800` (2d), `259200` (3d), `604800` (1w), `2592000` (1mo) The constraints above ensure candles align with natural time boundaries (minutes, hours, days) for consistent charting. ## Subscribe to candlesticks ## Update frequency The server pushes updates every **0.5 seconds** while the candle is active. ## Error codes ## Candle object * [Kline](/api-reference/market-data/kline) — candlestick data via REST for historical queries. # Last Price Source: https://docs.whitebit.com/websocket/market-streams/lastprice Subscribe to real-time last trade price updates for trading pairs via WhiteBIT WebSocket. Query or subscribe to real-time last traded price updates for one or more markets. The channel delivers the most recent executed trade price for each subscribed market. Updates arrive every second when the price changes, making this channel suitable for live price tickers and market data dashboards. Supports both spot pairs (e.g., `BTC_USDT`) and futures markets (e.g., `BTC_PERP`). Mix spot and futures market names in a single subscribe request. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query last price (one-time) Fetch the current last price for a single market without subscribing. **Request** **Response** ## Subscribe to last price ## Update frequency The server pushes updates every **1 second** when the price changes. ## Error codes ## Last price update object # Market Statistics Source: https://docs.whitebit.com/websocket/market-streams/market Subscribe to real-time 24-hour market statistics for trading pairs via WhiteBIT WebSocket. Query or subscribe to rolling 24-hour market statistics for one or more trading pairs. Each update delivers a full statistics snapshot — open, close, high, low prices, and volume — covering the past 24 hours. The server pushes a new snapshot every second. Use this channel to power market overview displays, screeners, or price monitoring tools. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query market statistics (one-time) Fetch market statistics for any period without subscribing. **Request** **Response** ## Subscribe to market statistics Subscriptions support only a **24-hour period** (86400 seconds). Custom period subscriptions are not supported. ## Update frequency The server pushes a full statistics snapshot every **1 second**. ## Error codes ## Market statistics object # Market statistics for current day UTC Source: https://docs.whitebit.com/websocket/market-streams/market-today Subscribe to real-time current-day market statistics for trading pairs via WhiteBIT WebSocket. Query or subscribe to current UTC day market statistics for one or more trading pairs. The channel delivers open, high, low, last price, and volume data accumulated since 00:00 UTC. All statistics reset at UTC midnight. Updates arrive every second for active subscriptions, making this channel suitable for live daily market summaries and intraday performance displays. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query market today (one-time) Fetch current-day statistics for a single market without subscribing. To get data for multiple markets, either make separate requests or use the subscription method. **Request** **Response** ## Subscribe to market today ## Update frequency The server pushes a full statistics snapshot every **1 second** (UTC day reset). All statistics reset to zero at UTC midnight (00:00 UTC) each day. ## Error codes ## Market today statistics object # Market Streams Source: https://docs.whitebit.com/websocket/market-streams/overview Public WebSocket market streams provide real-time order books, trades, prices, and statistics on WhiteBIT. Browse the available public WebSocket channels below. For connection details and message format, see the [WebSocket Overview](/websocket/overview). For rate limits, see [WebSocket Rate Limits](/websocket/rate-limits). Check API service status and health Subscribe to candlestick (OHLCV) data for markets Real-time last traded price updates for markets 24-hour market statistics including volume and price changes Current day market statistics based on UTC timezone Stream of recent trades executed on the market Order book depth updates with bids and asks Best bid and ask prices in the order book Mark price, index price, and funding rate for futures markets ## Managing subscriptions Each subscribe request defines the complete set of markets for that channel on the connection. A new subscribe **replaces** the channel's previous subscription rather than adding to it — the server does not merge incremental subscribes. * **Add a market** — resubscribe with the full target list, including the markets already being received. * **Remove a market** — resubscribe with the reduced list. There is no per-market unsubscribe; sending the channel's unsubscribe method with an empty `params` array clears the whole subscription. * **Manage markets independently** — a connection holds one subscription per channel. To add or drop markets without touching the others, place those markets on separate connections. Weigh the connection limit and added latency described in [WebSocket Rate Limits](/websocket/rate-limits). On channels that send an initial snapshot on subscribe — such as [Market Trades](/websocket/market-streams/trades), which replays up to 100 of the latest trades per market — resubscribing to add or remove a market backfills the markets carried into the new list. Deduplicate by record `id` to handle the replayed snapshot. # Premium index Source: https://docs.whitebit.com/websocket/market-streams/premium-index Subscribe to mark price, index price, and funding rate updates for futures markets via WhiteBIT WebSocket. Subscribe to mark price, index price, and funding rate updates for futures markets — the same data returned by [`GET /api/v4/public/futures`](/api-reference/market-data/available-futures-markets-list), delivered as a push stream instead of a poll. **Mark price** drives margin, PnL, liquidation, and [ADL](/concepts/auto-deleveraging) calculations; **index price** and **funding rate** are informational only and are not used in any trading calculation. This channel does **NOT** support query operations — only subscribe/update/unsubscribe. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Subscribe to all futures markets Passing an empty `params` array subscribes to every futures market. All subscribed markets arrive together in a single message on each poll cycle. ## Subscribe to specific markets Passing one or more market names instead delivers a **separate message per market** on each poll cycle, with a `server_timestamp` field appended. Subscribing with named markets replaces the previous scope on this channel rather than adding to it — resubscribe with the full target list to change which markets are streamed. **Request** **Update — one message per market** ## Update frequency The server polls the matching engine and pushes a fresh snapshot every **0.5 seconds**, regardless of whether any value changed since the last cycle — this is a periodic poll, not an event triggered by a price or funding-rate change. After a `market.mark_price_update`, allow up to one poll cycle (0.5 sec) for the new value to appear on this channel. ## Error codes ## Premium index update object * [Available futures markets list](/api-reference/market-data/available-futures-markets-list) — one-time HTTP snapshot of the same `mark_price`, `index_price`, and funding-rate fields. * [Auto-Deleveraging concept](/concepts/auto-deleveraging) — how mark price feeds the liquidation and ADL rating formulas. * [Funding history](/api-reference/market-data/funding-history) — historical funding rate records for futures markets. # Service Source: https://docs.whitebit.com/websocket/market-streams/service Ping the WhiteBIT WebSocket server to check connection health and keep the connection alive. Check API availability with ping/pong and query the current server time. The Service channel supports one-time queries only — no subscription or push events. Use ping to verify connection health and retrieve the server timestamp for clock synchronization. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Update frequency Client-initiated via `server.time` request. The server enforces a **60-second** ping timeout — send a ping within 60 seconds to keep the connection alive. ## Error codes ## Ping Send a ping every 50 seconds to keep the connection alive. The server closes the connection after 60 seconds of inactivity. **Request** **Response** ## Server time **Request** **Response** `result` is the current server time as a Unix timestamp (integer seconds). # Market Trades Source: https://docs.whitebit.com/websocket/market-streams/trades Subscribe to real-time trade execution updates for a trading pair via WhiteBIT WebSocket. Subscribe to real-time trade execution updates for one or more markets. Each message delivers a batch of trade objects containing price, quantity, trade direction, and execution timestamp. The channel supports both targeted subscriptions for specific markets and a wildcard subscription for all available markets. Connect to `wss://wss.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements. ## Rate limits ## Query recent trades (one-time) Fetch recent trades for a market without subscribing. **Request** **Response** ## Subscribe to trades For each WebSocket connection, subscribe to either specific markets or all markets. **Every new subscription replaces the existing one.** To add or remove markets on an active subscription, resubscribe with the full target list — see [Managing subscriptions](/websocket/market-streams/overview#managing-subscriptions). **Initial snapshot.** On subscribe, the server first sends a snapshot — one `trades_update` carrying up to 100 of the latest trades per market, ordered newest first — then streams new trades in real time. Resubscribing replays this snapshot, so deduplicate by trade `id`. **Subscribe to all markets:** ## Update frequency Updates are pushed in **real time** on each trade execution. ## Unsubscribe Send `trades_unsubscribe` with an empty `params` array to stop receiving trade updates on the connection. There is no per-market unsubscribe — to keep a subset of markets, resubscribe with the markets to retain. See [Managing subscriptions](/websocket/market-streams/overview#managing-subscriptions). ## Error codes ## RPI orders in trade updates Trade updates can include executions originating from RPI orders: * `rpi: true` — the trade involved a Retail Price Improvement (RPI) order * `rpi: false` or absent — regular trade Public market data feeds do not expose RPI orders as visible liquidity in `depth` or `bookTicker`. RPI orders remain visible only in private active orders and in the exchange UI order book (web and mobile). ## Trade object * [Recent trades](/api-reference/market-data/recent-trades) — latest executed trades via REST for polling use cases. # Place margin BBO order Source: https://docs.whitebit.com/websocket/order-management/collateral-order-bbo-place Place a margin or futures order priced from the best bid or offer with collateral_order_bbo_place. Place a margin or futures limit order priced from the current best bid or offer. The role semantics match the spot [`order_bbo_place`](/websocket/order-management/order-bbo-place) method, and the same ordinary limit order comes back. ## Rate limits ## Place margin BBO order ### Request parameters The `bbo_role` parameter decides which side of the spread supplies the price. | Role | Price source | Effect | | - | - | - | | `1` maker | Own-side best — the best bid for a buy | Adds liquidity; `post_only` is set implicitly | | `2` taker | Opposite-side best — the best ask for a buy | Crosses the spread and matches immediately | ### Response The response is an ordinary margin limit order reporting `type` `7` — no BBO marker survives placement. The `price` field records where the order landed. See the [order object reference](/websocket/order-management/overview#order-object). No re-pegging happens. The price is resolved once, at placement, and the order then behaves like any other resting limit order as the order book moves away from it. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place margin limit order Source: https://docs.whitebit.com/websocket/order-management/collateral-order-limit-place Place a margin or futures limit order over the WhiteBIT WebSocket connection with collateral_order_limit_place. Place a margin or futures limit order that rests in the order book until it is matched or canceled. This is the counterpart of [`order_limit_place`](/websocket/order-management/order-limit-place), and like its spot twin it is the only method in the `collateral_*` family that accepts `rpi`. ## Rate limits ## Place margin limit order ### Request parameters Two parameters set this family apart from the spot methods. The `reduce_only` flag restricts the order to shrinking an existing position, and `position_side` selects the position leg in hedge mode. Both are described in [Margin & Futures orders](/websocket/order-management/overview#order-methods). Across the whole `collateral_*` family `amount` is [stock](/glossary#stock) on both sides. Leverage and margin come from the account collateral configuration and are not order parameters — see [Margin Trading](/products/margin/overview) and [Futures](/products/futures/overview). ### Response The `result` object is the standard order object plus `reduce_only` and `position_side` — see the [order object reference](/websocket/order-management/overview#order-object). A margin limit order reports `type` `7`. Hedge mode governs `position_side`. The field is optional at the request layer but functionally required once hedge mode is enabled — omitting it, or sending `BOTH`, returns error `114`, same as sending a value other than `BOTH` without hedge mode enabled. A switch in progress returns error `113`. On a non-futures margin market any value other than `BOTH` is rejected with error `1`. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place margin market order Source: https://docs.whitebit.com/websocket/order-management/collateral-order-market-place Place a margin or futures market order over the WhiteBIT WebSocket connection with collateral_order_market_place. Open, extend, reduce, or close a position at the order book price. Sending the position size on the opposite side is the usual way to flatten a position. ## Rate limits ## Place margin market order ### Request parameters No money-denominated variant exists for this family. Unlike spot, `amount` is [stock](/glossary#stock) on both sides, which is why there is no `collateral_order_market_stock_place` — this method already behaves that way. ### Response The `result` object is the standard order object plus `reduce_only` and `position_side` — see the [order object reference](/websocket/order-management/overview#order-object). A margin market order reports `type` `8` and `price` `"0"`. Set `reduce_only` when closing a position. Without it a stale size larger than the open position flips the position instead of flattening it. With the flag set, an order that would flip is rejected with error `115`, and an order with nothing to reduce is rejected with error `116` or dropped with status `AUTO_CANCELED_REDUCE_ONLY`. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place OCO group Source: https://docs.whitebit.com/websocket/order-management/collateral-order-oco-place Place a linked take-profit and stop-loss pair on a margin or futures market with collateral_order_oco_place. Place two linked orders — a limit take-profit and a stop-limit stop-loss — of which only one can execute. When either leg fills, the engine withdraws the other. Both legs point the same way, because both exit the same position. ## Rate limits ## Place OCO group ### Request parameters Three prices define the pair, and the relative position of each one matters. On a sell group, `price` — the take-profit limit — sits above the market, while `activation_price` — the stop-loss trigger — sits below it. The `stop_limit_price` value goes beyond `activation_price`, so the stop-loss leg still fills after the trigger fires. Note the naming asymmetry: the response keys the legs as `take_profit` and `stop_loss`, but there is no plain `client_order_id` parameter — only the two per-leg forms, `limit_client_order_id` and `stop_client_order_id`. ### Response One request produces three identifiers. The group id is the `id` inside `result`, next to `type: "oco"` — not the frame-level `id`, which only echoes the request. Each leg carries its own order id. Each leg is a full order object — the take-profit reports `type` `7`, the stop-loss `type` `9`. See the [order object reference](/websocket/order-management/overview#order-object). Timestamps, deal counters, and `stp` are elided in the example above for length. Cancel the pair through [`order_cancel_conditional`](/websocket/order-management/order-cancel-conditional) using the group id. Passing a leg id there, or the group id to [`order_cancel`](/websocket/order-management/order-cancel), returns error `6`. The leg ids serve for tracking fills, not for cancellation. The take-profit leg must rest as a maker order. A `price` that would cross the spread and execute immediately is rejected with error `150`, which makes an over-tight take-profit the most common cause of a failed OCO placement. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place OTO group Source: https://docs.whitebit.com/websocket/order-management/collateral-order-oto-place Place an entry order that arms its own exit on a margin or futures market with collateral_order_oto_place. Place a One-Triggers-Other group: an entry order that, once it fills, automatically arms its own exit — a take-profit, a stop-loss, or an OCO pair of both. The exit needs no second request and survives a disconnect, which makes this the safer pattern for an unattended entry. ## Rate limits ## Place OTO group ### Request parameters The parameter shape breaks the pattern used by every other order method. The entry order is a nested object under `trigger_order`, carrying the full parameter set of whichever placement method `trigger_order_type` names. The exit is described by two bare prices at the top level rather than by nested order objects. The `conditional_order_type` value decides which exit prices are required. | Exit type | Arms | Required prices | | - | - | - | | `margin_market_oco` | Take-profit and stop-loss | Both `take_profit` and `stop_loss` | | `margin_take_profit`, `margin_limit` | Take-profit only | `take_profit` only — sending `stop_loss` is rejected | | `margin_stop_loss`, `margin_stop_limit` | Stop-loss only | `stop_loss` only — sending `take_profit` is rejected | Exit prices are relative to the entry. For a buy entry the take-profit sits above and the stop-loss below; for a sell entry the reverse. Both are checked against the price bands around the entry price, and a price outside those bands returns error `250`. ### Response The `result` object carries `type` `"oto"`, the group `id`, the echoed `conditional_order_type`, the two exit prices as `take_profit_price` and `stop_loss_price`, and the `trigger_order` as a full order object. See the [order object reference](/websocket/order-management/overview#order-object). The exit legs do not exist yet. Until the entry fills, the exit legs hold no order ids and appear only as `take_profit_price` and `stop_loss_price`. Nothing can be canceled or modified per leg during that window — cancel the whole group through [`order_cancel_conditional`](/websocket/order-management/order-cancel-conditional) using the group id. Two constraints on the entry. The `rpi` flag is not allowed inside `trigger_order`, and `margin_market_oco` is not a valid `trigger_order_type` — it works only as an exit. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place margin stop-BBO order Source: https://docs.whitebit.com/websocket/order-management/collateral-order-stop-bbo-place Place a margin or futures stop order that becomes a BBO order with collateral_order_stop_bbo_place. Park a margin or futures order that turns into a BBO order when the market reaches `activation_price`. The order waits as `type` `9` with `price` `"0"`, then prices itself from the order book once the trigger fires. ## Rate limits ## Place margin stop-BBO order ### Request parameters ### Response The `result` object adds the activation fields and the position fields to the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). The order reports `type` `9` with `price` `"0"` while it waits. The maker role on a protective stop is a trade-off. It avoids the taker fee, but the resulting order may sit unfilled at the best quote while the market runs away from it — exactly the scenario a stop exists to handle. Use `bbo_role: 2`, or [`collateral_order_stop_market_place`](/websocket/order-management/collateral-order-stop-market-place), where the exit must complete; an empty order book at activation drops the order entirely. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place margin stop-limit order Source: https://docs.whitebit.com/websocket/order-management/collateral-order-stop-limit-place Place a margin or futures stop-limit order over the WhiteBIT WebSocket connection with collateral_order_stop_limit_place. Park a margin or futures limit order outside the order book. When the market reaches `activation_price`, the engine places a margin limit order at `price`. Until then the order holds `status` `OPEN` with `activated` `0`. ## Rate limits ## Place margin stop-limit order ### Request parameters The trigger direction is not a parameter. The engine derives `activation_condition` by comparing `activation_price` to the market at placement: above the market yields `gte`, below yields `lte`. ### Response The `result` object adds the activation fields and the position fields to the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). A margin stop-limit order reports `type` `9`. Cancel this order with [`order_cancel`](/websocket/order-management/order-cancel) by order id. The [`order_cancel_conditional`](/websocket/order-management/order-cancel-conditional) method applies to OCO and OTO groups only, and returns error `6` for a plain stop order. A stop-limit order also cannot be modified once it belongs to a group — see [`order_modify`](/websocket/order-management/order-modify). ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place margin stop-market order Source: https://docs.whitebit.com/websocket/order-management/collateral-order-stop-market-place Place a margin or futures stop-market order over the WhiteBIT WebSocket connection with collateral_order_stop_market_place. Fire a margin market order when the market reaches `activation_price`. This is the workhorse protective stop: because `amount` is [stock](/glossary#stock), a stop that closes a position takes the position size directly. ## Rate limits ## Place margin stop-market order ### Request parameters ### Response The `result` object adds the activation fields and the position fields to the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). A margin stop-market order reports `type` `10` with `price` `"0"`. A per-market ceiling limits how many stop-market orders one account can hold. Reaching it returns error `103` — cancel an existing stop before placing another. For a stop that tracks the position size automatically rather than a fixed amount, use [`collateral_order_tpsl_place`](/websocket/order-management/collateral-order-tpsl-place) instead. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Attach take-profit and stop-loss Source: https://docs.whitebit.com/websocket/order-management/collateral-order-tpsl-place Attach a take-profit and stop-loss pair to an open margin or futures position with collateral_order_tpsl_place. Attach a take-profit and a stop-loss to an existing position rather than to an order. The pair tracks the position: it carries no size of its own and always exits whatever is open at trigger time, so a position that grows or shrinks afterwards stays covered. ## Rate limits ## Attach take-profit and stop-loss ### Request parameters Neither `side` nor `amount` appears among the parameters. The engine derives both from the open position, which is why the legs come back with `amount` `"0"`. At least one of the two activation prices must be present — sending neither returns error `1`. Supplying only one arms a take-profit or a stop-loss on its own. On a long position the take-profit trigger sits above the market and the stop-loss below; a price on the wrong side returns error `105` or `106`. ### Response The `result` object holds the `take_profit` and `stop_loss` legs, each reporting `type` `10`. See the [order object reference](/websocket/order-management/overview#order-object). In the example both legs show `side` `1` — a sell closes a long position — and `amount` `"0"`, meaning whatever the position holds when the trigger fires. An open position is required. Without one the call fails with error `104`, so arm the pair after the entry fills rather than alongside it. For an entry that arms its own exit in a single request, use [`collateral_order_oto_place`](/websocket/order-management/collateral-order-oto-place) instead. Each call is additive. Every request creates a new pair of TP/SL orders. It does not replace or cancel the TP/SL orders already on the position, including those created through the REST API (`takeProfit` / `stopLoss` parameters) or by OTO orders. Calling the method twice leaves two pairs armed. ### Change TP/SL levels Two approaches move the levels of existing TP/SL orders: 1. Modify the existing legs with [`order_modify`](/websocket/order-management/order-modify), for example to change the activation price. 2. Cancel the existing legs with [`order_cancel`](/websocket/order-management/order-cancel), then place a new pair with `collateral_order_tpsl_place`. ### Behavior on position close When a TP/SL order triggers and closes the position, the remaining TP/SL orders for that position are cancelled automatically. The two legs are independent orders with separate ids, so cancel each one with [`order_cancel`](/websocket/order-management/order-cancel). A TPSL pair has no group id, so [`order_cancel_conditional`](/websocket/order-management/order-cancel-conditional) does not apply. TPSL legs can be modified with [`order_modify`](/websocket/order-management/order-modify). ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place BBO order Source: https://docs.whitebit.com/websocket/order-management/order-bbo-place Place a spot limit order priced from the current best bid or offer with order_bbo_place. Place a spot limit order priced from the current best bid or offer, which removes the need to read the order book before quoting. The client picks the role and the engine picks the price. ## Rate limits ## Place BBO order ### Request parameters The `bbo_role` parameter decides which side of the spread supplies the price. | Role | Price source | Effect | | - | - | - | | `1` maker | Own-side best — the best bid for a buy | Adds liquidity; `post_only` is set implicitly | | `2` taker | Opposite-side best — the best ask for a buy | Crosses the spread and matches immediately | Sending `post_only` together with `bbo_role: 2` is rejected as a wrong flag combination, because a taker order cannot be post-only. With `bbo_role: 1` the flag is redundant but accepted. ### Response The response is an ordinary limit order reporting `type` `1` — no BBO marker survives placement. The `price` field records where the order landed. See the [order object reference](/websocket/order-management/overview#order-object). No re-pegging happens. The price is resolved once, at placement, and the order then behaves like any other resting limit order as the order book moves away from it. Re-quoting requires canceling and placing again, or [`order_modify`](/websocket/order-management/order-modify). ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Cancel order Source: https://docs.whitebit.com/websocket/order-management/order-cancel Cancel a single WhiteBIT order over the WebSocket connection with order_cancel. Cancel a single order — a resting limit order, a plain conditional stop, or an individual TPSL leg — across spot, margin, and futures markets. The response returns the full order object in its final state. ## Rate limits ## Cancel order ### Request parameters The `market` parameter routes the call, so it stays required even when the order id alone would identify the order. When both identifiers are supplied, `client_order_id` takes precedence — the response still reports the engine id, which confirms which order was hit. Canceling by client order id follows the same shape: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "market": "ETH_USDT", "client_order_id": "pws_cancel_1786452693420" } ``` ### Response The `result` object is the standard order object with `status` `CANCELED` — see the [order object reference](/websocket/order-management/overview#order-object). The `mtime` field advances to the cancellation time while `ctime` stays at placement, so the pair tells how long the order lived. Verify the outcome by status, not by the absence of an error. A successful call returns `CANCELED`; an unknown or already-finished order returns error `6`. A partially filled order reports its matched quantity in `deal_stock` — cancellation withdraws only the remainder in `left`. Groups need a different call. Use [`order_cancel_conditional`](/websocket/order-management/order-cancel-conditional) for OCO and OTO groups — passing a group id here returns error `6`. Plain stop orders and TPSL legs, on the other hand, belong to this method. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Cancel all orders Source: https://docs.whitebit.com/websocket/order-management/order-cancel-all Withdraw every order on one WhiteBIT market, filtered by trading type, with order_cancel_all. Withdraw every order the authorized account holds on one market, filtered by trading type. This is the kill-switch call for a shutdown sequence or an emergency stop. ## Rate limits ## Cancel all orders ### Request parameters One market per call — no all-markets form exists, so flattening an entire book of activity means looping over the markets in use. Passing all three trading types is safe on any market, because types that do not apply are simply not matched. ### Response The result is an empty object. No list of canceled orders comes back, and nothing matched is not an error — an empty result is indistinguishable from a market that held no orders. Re-query pending orders, or watch [Orders Pending](/websocket/account-streams/orders-pending), to confirm what was actually withdrawn. Positions survive. This call covers resting and conditional orders on the market; an open position remains open, and only the orders protecting it are gone. Re-arm stops after a bulk cancel — see [`collateral_order_tpsl_place`](/websocket/order-management/collateral-order-tpsl-place) for position-tracking protection. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Cancel conditional group Source: https://docs.whitebit.com/websocket/order-management/order-cancel-conditional Cancel an OCO or OTO order group in one call with order_cancel_conditional. Cancel an OCO or OTO group in one call. Pass the group id from the placement response and every leg is withdrawn atomically, which removes the risk of a half-canceled pair leaving one exit armed. ## Rate limits ## Cancel conditional group ### Request parameters The `order_id` value is the group id — the `id` inside `result` on the [OCO](/websocket/order-management/collateral-order-oco-place) or [OTO](/websocket/order-management/collateral-order-oto-place) placement response, next to the `type` value. It is neither a leg id nor the frame-level `id`, which only echoes the request. This method has no `client_order_id` form, so the group id must be retained from placement. Canceling an OTO group uses the same request shape and returns `type` `"oto"` with the `trigger_order` reporting `CANCELED`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "market": "BTC_PERP", "order_id": 2423735895134 } ``` ### Response The response mirrors the placement response — same shape, same `type` value — with every leg reporting `status` `CANCELED`. All legs share one `mtime`, because the cancellation is a single atomic event. Groups only. A plain stop order or a TPSL leg passed here returns error `6` — cancel those with [`order_cancel`](/websocket/order-management/order-cancel). Conversely, a group id passed to `order_cancel` also returns error `6`, so the two methods are not interchangeable. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place limit order Source: https://docs.whitebit.com/websocket/order-management/order-limit-place Place a spot limit order over the WhiteBIT WebSocket connection with order_limit_place. Place a spot limit order that rests in the order book until it is matched or canceled. Among the spot placement methods, `order_limit_place` accepts the full execution-flag set, including Retail Price Improvement. The response returns the accepted order in its initial state — `OPEN` for an order that rests, `FILLED` or `PARTIALLY_FILLED` when the order matches on arrival. ## Rate limits ## Place limit order ### Request parameters The `params` array carries exactly one element: an object holding the order parameters. Unlike the subscription channels, positional parameters are not used. Prices and amounts are decimal strings, not numbers. Precision above the market setting is rejected with error `1`; consult `stepSize` and `tickSize` via `GET /api/v4/public/markets`. ### Response The `result` object is the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). A limit order reports `type` `1`. Two response conventions apply. The `side` field inverts against the request: the request sends `"buy"` or `"sell"` as a string, while the response reports `1` for sell and `2` for buy. Trailing zeros are normalized on the way out, so a price sent as `"1916.40"` returns as `"1916.4"` — compare decimal values numerically, never by string equality. Subscribe to [Orders Pending](/websocket/account-streams/orders-pending) to follow the order after placement, and to [Deals](/websocket/account-streams/deals) for its individual fills. ## Execution flags Among the spot placement methods, only `order_limit_place` accepts `rpi`. The flags constrain each other: `ioc` combines with neither `post_only` nor `rpi`, and `rpi` implies `post_only`. An illegal pair is rejected with error `1` rather than silently dropped — the full matrix is in [Order Management](/websocket/order-management/overview#execution-flag-combinations). While a market runs in post-only mode, only limit orders carrying the post-only flag are accepted; a market or stop method on the same market is rejected with error `51`. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — placing and canceling quotes over the WebSocket order methods. # Place market order Source: https://docs.whitebit.com/websocket/order-management/order-market-place Place a spot market order over the WhiteBIT WebSocket connection with order_market_place. Place a spot market order that matches immediately against the order book at the available prices. A market order never rests, so the response is already terminal — `FILLED` when the book absorbed the whole order, `PARTIALLY_FILLED` when it ran out first. ## Rate limits ## Place market order ### Request parameters The unit of `amount` depends on the side, which is the one trap in this method. A sell sizes in [stock](/glossary#stock) — the base asset. A buy sizes in [money](/glossary#money) — the quote asset to spend. For stock sizing on both sides use [`order_market_stock_place`](/websocket/order-management/order-market-stock-place). The `post_only`, `ioc`, and `rpi` flags carry no meaning for a market order and are ignored. ### Response The `result` object is the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). A spot market order reports `type` `2` and `price` `"0"`, because it carries no limit price. Read the achieved cost from `deal_money` and the matched size from `deal_stock`. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place market order in stock Source: https://docs.whitebit.com/websocket/order-management/order-market-stock-place Place a spot market order sized in the base asset on both sides with order_market_stock_place. Place a spot market order sized in the base asset on both sides. The matching behavior is identical to [`order_market_place`](/websocket/order-management/order-market-place); the difference is that `amount` is always [stock](/glossary#stock), on a buy as well as on a sell. This method suits sizing logic expressed in coins rather than in quote currency. ## Rate limits ## Place market order in stock ### Request parameters ### Response The `result` object is the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). This method reports `type` `202` and `price` `"0"`. A buy still consumes quote currency even though the order is sized in stock. The balance must cover `amount` multiplied by the best ask, plus fee, otherwise the order fills only partially. The `deal_money` field reports what the fill actually cost. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Modify order Source: https://docs.whitebit.com/websocket/order-management/order-modify Change the size, price, or trigger of a live WhiteBIT order over the WebSocket connection with order_modify. Change the size, price, or trigger of a live order without a separate cancel-and-replace round trip. The method works across spot, margin, and futures markets — no `collateral_` variant exists. ## Rate limits ## Modify order ### Request parameters The `market` parameter routes the call, so it stays required even when the order id alone would identify the order. Supply exactly one identifier — `order_id` or `client_order_id` — and at least one of `price`, `amount`, `total`, or `activation_price`. Omitted fields keep the previous values. Sending no change returns error `1`, and so does sending `amount` and `total` together, since the two express the same quantity in different units. ### Response The order id changes. Internally the engine cancels and re-places the order, so the result carries a new `id` and a fresh `ctime`, and the order loses its queue priority. Any client tracking orders by engine id must adopt the new one from this response. The `client_order_id` value carries over to the replacement, which makes it the stabler handle for anything modified repeatedly. Modifying by client order id therefore needs no bookkeeping between calls: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "market": "ETH_USDT", "client_order_id": "pws_modify_1786452694082", "amount": "0.00210" } ``` Moving a trigger works the same way — send `activation_price` on a conditional order, with or without a new `amount`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "market": "ETH_USDT", "order_id": 2423735907974, "activation_price": "1944.70", "amount": "0.00105" } ``` ### Modify a TP/SL leg A leg created by [`collateral_order_tpsl_place`](/websocket/order-management/collateral-order-tpsl-place) can be modified with this method. Send the leg's `order_id` or `client_order_id` together with a new `activation_price` to move its trigger. The take-profit and stop-loss legs are independent orders, so each one is modified with its own request. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place stop-BBO order Source: https://docs.whitebit.com/websocket/order-management/order-stop-bbo-place Place a spot stop order that becomes a BBO order on trigger, with order_stop_bbo_place. Park an order that turns into a BBO order when the market reaches `activation_price`. The price is resolved from the order book at activation time rather than at placement, which is why `price` stays `"0"` while the order waits. ## Rate limits ## Place stop-BBO order ### Request parameters The `bbo_role` semantics match [`order_bbo_place`](/websocket/order-management/order-bbo-place), with one difference: the role is applied at activation, against the order book as it stands then. Role `1` sets `post_only` on the resulting order. ### Response The `result` object adds the conditional fields to the standard order object and reports `type` `3` with `price` `"0"`. See the [order object reference](/websocket/order-management/overview#order-object). An empty order book at activation drops the order. With no quote on the required side there is nothing to peg to, so the order cannot be priced and is discarded rather than retried. Use [`order_stop_limit_place`](/websocket/order-management/order-stop-limit-place) where a guaranteed price matters more than a book-relative one. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place stop-limit order Source: https://docs.whitebit.com/websocket/order-management/order-stop-limit-place Place a spot stop-limit order that becomes a limit order on trigger, with order_stop_limit_place. Park a limit order outside the order book. When the market reaches `activation_price`, the engine places a limit order at `price`. Until then the order holds `status` `OPEN` with `activated` `0`, and consumes no balance beyond the reservation for the pending order. ## Rate limits ## Place stop-limit order ### Request parameters The two prices serve different purposes and are validated independently. `activation_price` decides when the order fires; `price` decides where the resulting limit order sits. Placing `price` past the trigger makes the resulting order marketable, which is a deliberate pattern for an exit that must fill rather than rest. The trigger direction is not a parameter. The engine derives `activation_condition` by comparing `activation_price` to the market at placement: above the market yields `gte`, below yields `lte`. ### Response The `result` object adds the conditional fields — `activation_price`, `activation_condition`, and `activated` — to the standard order object. See the [order object reference](/websocket/order-management/overview#order-object). A spot stop-limit order reports `type` `3`. Cancel a stop-limit order with [`order_cancel`](/websocket/order-management/order-cancel) by order id. The [`order_cancel_conditional`](/websocket/order-management/order-cancel-conditional) method applies to OCO and OTO groups only and returns error `6` for a plain stop order. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place stop-market order Source: https://docs.whitebit.com/websocket/order-management/order-stop-market-place Place a spot stop-market order that fires a market order on trigger, with order_stop_market_place. Fire a market order when the market reaches `activation_price`. Because the resulting order carries no limit price, `price` is reported as `"0"` both while the order waits and after it executes. This method trades price certainty for fill certainty — the opposite of [`order_stop_limit_place`](/websocket/order-management/order-stop-limit-place). ## Rate limits ## Place stop-market order ### Request parameters The unit of `amount` follows the market-order convention: [money](/glossary#money) on a buy, [stock](/glossary#stock) on a sell. For stock sizing on both sides use [`order_stop_market_stock_place`](/websocket/order-management/order-stop-market-stock-place). Unlike the stop-limit trigger, `activation_price` here is additionally validated against the market price bands. A trigger outside those bands returns error `251`. ### Response The `result` object adds the conditional fields to the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). A spot stop-market order reports `type` `4`. The example sends `amount` as `"3.00"` and the response echoes `"3"`. Trailing zeros are normalized on the way out, so compare decimal values numerically rather than by string equality. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Place stop-market order in stock Source: https://docs.whitebit.com/websocket/order-management/order-stop-market-stock-place Place a spot stop-market order sized in the base asset on both sides with order_stop_market_stock_place. Fire a market order sized in the base asset when the market reaches `activation_price`. The trigger semantics match [`order_stop_market_place`](/websocket/order-management/order-stop-market-place); only the unit of `amount` differs — here it is [stock](/glossary#stock) on a buy as well as on a sell. ## Rate limits ## Place stop-market order in stock ### Request parameters ### Response The `result` object adds the conditional fields to the standard order object — see the [order object reference](/websocket/order-management/overview#order-object). This method reports `type` `203`, the stock-denominated stop-market code. A buy spends quote currency at activation even though the order is sized in stock. The balance must cover `amount` multiplied by the best ask at trigger time, plus fee. ## Error codes Standard transport errors and the shared account, rate-limit, and region codes are listed in [Order Management](/websocket/order-management/overview#error-codes). # Order Management Source: https://docs.whitebit.com/websocket/order-management/overview Place, modify, and cancel spot, margin, and futures orders over the WhiteBIT WebSocket connection — conventions, shared enums, and the full error reference. The WebSocket transport carries order flow as well as market data and account streams. The transport exposes 21 JSON-RPC methods that place, modify, and cancel orders on spot, margin, and futures markets over the same connection used for subscriptions. This page holds the conventions shared by every order method: the request envelope, value formats, the shared enums, and the complete error reference. Each method page documents only its own request parameters and the behavior specific to that method. ## Authorization Every order method requires an authorized connection. Send `authorize` as the first frame after connecting — see [Authorize](/websocket/account-streams/authorize) for the token flow. An order method sent on an unauthorized connection is rejected with error `6`. Authorization holds for the lifetime of the connection. No re-authorization or refresh call exists. ## Request and response envelope Order methods follow the JSON-RPC structure used across the WebSocket API, with one difference from the subscription channels: `params` carries a single object rather than positional values. **Client → server** | Field | Type | Description | | - | - | - | | `id` | INTEGER | Unique request identifier. The response echoes this value. | | `method` | STRING | Order method name, for example `order_limit_place`. | | `params` | ARRAY | Array holding exactly one object with the order parameters. | **Server → client** | Field | Type | Description | | - | - | - | | `id` | INTEGER | Matches the request `id`. | | `result` | OBJECT or NULL | Order object on success; `null` on failure. | | `error` | OBJECT or NULL | Error object on failure; `null` on success. | Exactly one of `result` and `error` carries meaning. Responses arrive interleaved with subscription pushes, which carry no `id`, so correlate each answer by `id` rather than by arrival order. The same operations are available over REST — see [Create Limit Order](/api-reference/trading/create-limit-order) for the equivalent endpoint family. ## Decimal values are strings Every price, amount, and fee travels as a decimal string, which avoids floating-point rounding. The engine normalizes trailing zeros on the way out: a price sent as `"1916.40"` returns as `"1916.4"`. Compare decimal values numerically, never by string equality. Timestamps are the exception. The `ctime` and `mtime` fields are JSON numbers — Unix seconds with a microsecond fraction. ## Order methods **Spot markets** | Method | Type | Purpose | | - | - | - | | [`order_limit_place`](/websocket/order-management/order-limit-place) | `1` | Limit order resting in the order book | | [`order_market_place`](/websocket/order-management/order-market-place) | `2` | Market order, amount in money on buy | | [`order_market_stock_place`](/websocket/order-management/order-market-stock-place) | `202` | Market order, amount in stock on both sides | | [`order_stop_limit_place`](/websocket/order-management/order-stop-limit-place) | `3` | Limit order placed on trigger | | [`order_stop_market_place`](/websocket/order-management/order-stop-market-place) | `4` | Market order placed on trigger | | [`order_stop_market_stock_place`](/websocket/order-management/order-stop-market-stock-place) | `203` | Stop-market order sized in stock | | [`order_bbo_place`](/websocket/order-management/order-bbo-place) | `1` | Limit order priced from the best bid or offer | | [`order_stop_bbo_place`](/websocket/order-management/order-stop-bbo-place) | `3` | BBO order placed on trigger | **Margin and futures markets** | Method | Type | Purpose | | - | - | - | | [`collateral_order_limit_place`](/websocket/order-management/collateral-order-limit-place) | `7` | Margin limit order | | [`collateral_order_market_place`](/websocket/order-management/collateral-order-market-place) | `8` | Margin market order | | [`collateral_order_stop_limit_place`](/websocket/order-management/collateral-order-stop-limit-place) | `9` | Margin limit order placed on trigger | | [`collateral_order_stop_market_place`](/websocket/order-management/collateral-order-stop-market-place) | `10` | Margin market order placed on trigger | | [`collateral_order_bbo_place`](/websocket/order-management/collateral-order-bbo-place) | `7` | Margin order priced from the best bid or offer | | [`collateral_order_stop_bbo_place`](/websocket/order-management/collateral-order-stop-bbo-place) | `9` | Margin BBO order placed on trigger | | [`collateral_order_oco_place`](/websocket/order-management/collateral-order-oco-place) | group | Linked take-profit and stop-loss pair | | [`collateral_order_oto_place`](/websocket/order-management/collateral-order-oto-place) | group | Entry order that arms its own exit | | [`collateral_order_tpsl_place`](/websocket/order-management/collateral-order-tpsl-place) | `10` | Take-profit and stop-loss attached to a position | **All markets** | Method | Purpose | | - | - | | [`order_modify`](/websocket/order-management/order-modify) | Change size, price, or trigger of a live order | | [`order_cancel`](/websocket/order-management/order-cancel) | Cancel a single order | | [`order_cancel_conditional`](/websocket/order-management/order-cancel-conditional) | Cancel an OCO or OTO group | | [`order_cancel_all`](/websocket/order-management/order-cancel-all) | Cancel every order on one market | The `collateral_*` family targets margin and futures markets and is rejected with error `19` on a spot-only market. A spot `order_*` method on a futures market is rejected with error `1`. ## Order object Every placement, modification, and cancellation returns the same order object. Field-by-field descriptions are in [Orders Pending](/websocket/account-streams/orders-pending#order-object). Three groups of fields appear conditionally: * Conditional orders add `activation_price`, `activation_condition`, and `activated`. * Margin and futures orders add `reduce_only` and `position_side`. * Group placements return legs under `take_profit`, `stop_loss`, or `trigger_order` instead of a single flat object. The `activation_condition` field is derived by the engine rather than sent as a parameter. It reports `gte` when the activation price sits above the market at placement, and `lte` when below. The `side` field inverts between request and response. A request sends `"buy"` or `"sell"` as a string; the response reports `1` for sell and `2` for buy. ## Order type codes The numeric `type` values are listed in the [order types](/websocket/account-streams/overview#order-types) table. Three notes on reading the codes: the same code can come from more than one method, because a BBO order becomes an ordinary limit order once it is priced; a TPSL leg is internally a margin stop-market order, so `collateral_order_tpsl_place` reports `type` `10` alongside `collateral_order_stop_market_place`; and a stop order that converts into a market or BBO order carries `price` `"0"` until it activates. ## Order status | Status | Meaning | | - | - | | `OPEN` | Resting in the order book, or waiting for activation | | `PARTIALLY_FILLED` | Partly matched, remainder in `left` | | `FILLED` | Fully matched | | `CANCELED` | Canceled by the client | | `CANCELED_STP` | Removed by self-trade prevention | | `CANCELED_TAKER_BAND` | Rejected by the taker price band | | `CANCELED_RPI` | Removed by Retail Price Improvement rules | | `AUTO_CANCELED_REDUCE_ONLY` | Reduce-only order with nothing left to reduce | | `AUTO_CANCELED_LIQUIDATION` | Removed while the position was liquidated | | `DELISTING` | Removed because the market was delisted | ## Self-trade prevention The `stp` parameter decides what happens when an order would match against another order from the same account. It defaults to `no` when omitted. | Value | Alias | Behavior on self-match | | - | - | - | | `no` | — | Prevention disabled | | `co` | `cancel_old` | Cancel the resting order and let the incoming order trade | | `cn` | `cancel_new` | Cancel the incoming order | | `cb` | `cancel_both` | Cancel both sides of the self-match | See [Self-Trade Prevention](/platform/self-trade-prevention) for the platform-level behavior. ## Shared enums | Field | Values | | - | - | | `side` (request) | `"buy"`, `"sell"` | | `side` (response) | `1` sell or ask, `2` buy or bid | | `bbo_role` | `1` maker or post-only, `2` taker | | `position_side` | `"BOTH"`, `"LONG"`, `"SHORT"` | | `activation_condition` | `"gte"`, `"lte"` | | `type` (`order_cancel_all`) | `"spot"`, `"margin"`, `"futures"` | ## Execution flag combinations The execution flags constrain each other, and an illegal pair is rejected with error `1` rather than silently dropped. | Combination | Result | | - | - | | `ioc` + `post_only` | Rejected — `flags: ioc=1 and post_only=1 can't be combined` | | `ioc` + `rpi` | Rejected — `flags: ioc=1 and rpi=1 can't be combined` | | `rpi` alone | Accepted — `rpi` implies `post_only` | | `post_only` + `bbo_role: 1` | Accepted — the maker role already implies post-only | | `post_only` + `bbo_role: 2` | Rejected — `wrong flags combination` | | `rpi` inside an OTO `trigger_order` | Rejected — `flags: rpi=1 can't be set for trigger in oto` | Only `order_limit_place` and `collateral_order_limit_place` accept `rpi`. While a market runs in post-only mode, only limit orders carrying the post-only flag are accepted; every market and stop method is rejected with error `51`. When trading is disabled entirely, all methods return error `51`. ## Error codes A failure sets `result` to `null` and fills `error` with a numeric `code` and a `message`. Branch on the code and treat the message as diagnostic text that may change. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 500002, "result": null, "error": { "code": 1, "message": "invalid argument" } } ``` Two codes are overloaded on this transport. Code `6` means order not found in a cancel or modify context, and authentication required when the connection has not authorized. Code `11` means amount too small on placement, and carries the authorization server message when authorization itself fails. The numbering on this transport is independent of the REST error codes. The same number carries a different meaning on each surface — on the WebSocket transport `40` is `order is not post only`, while the REST API uses its own code for the equivalent condition. Do not carry a code learned from [REST error responses](/api-reference/authentication#common-errors) over to this transport, or the reverse. ### Validation — code 1 Every malformed request returns code `1`; the message identifies the parameter. | Message | Methods | Condition | | - | - | - | | `invalid argument` | All | Bad or missing request parameter | | `market is required`, `amount is required`, `price is required`, `activation_price is required` | Placement | A required field is absent | | `side is invalid` | Placement | `side` is neither `buy` nor `sell` | | `stp is invalid` | Placement | Not one of `no`, `co`, `cn`, `cb` or the equivalent long forms | | `market does not exist` | All | Unknown market name | | `the market is futures` | Spot `order_*` | Spot method on a futures market — use the `collateral_*` equivalent | | `the market is not margin or futures` | `collateral_*` | Collateral method on a spot-only market | | `bbo role must be an integer in range 1..2` | BBO methods | `bbo_role` outside `1`–`2`, or not an integer | | `wrong flags combination` | BBO methods | `post_only` sent together with `bbo_role: 2` | | `flags: ioc=1 and post_only=1 can't be combined` | Placement | Conflicting execution flags | | `flags: ioc=1 and rpi=1 can't be combined` | Placement | Conflicting execution flags | | `flags: rpi=1 can't be set for trigger in oto` | OTO | `rpi` inside `trigger_order` | | `position side can be used only with futures market` | `collateral_*` | `position_side` other than `BOTH` on a non-futures margin market | | `amount: precision is greater than N` | Placement | Value precision exceeds the market setting | | `amount * price must be <= X` | Placement | Order value above the maximum | | `unknown order type` | OTO | Bad `trigger_order_type` or `conditional_order_type` | | `trigger order can't be margin market OCO` | OTO | `margin_market_oco` used as the trigger type | | `take_profit and stop_loss are required` | OTO | An OCO exit is missing a price | | `only take_profit is required` | OTO | A take-profit-only exit was given a `stop_loss` | | `only stop_loss is required` | OTO | A stop-loss-only exit was given a `take_profit` | | `limit_client_order_id and stop_client_order_id cannot be equal` | OCO | The same client id on both legs | | `one of activations prices should be set` | TPSL | Neither trigger price supplied | | `order_id or client_order_id must be set for modify` | `order_modify`, `order_cancel` | Neither identifier supplied | | `at least price or amount or total or activation price should be specified` | `order_modify` | Nothing to change | | `amount and total cannot be specified simultaneously` | `order_modify` | Mutually exclusive parameters | | `order types must be an array`, `at least one order type should be specified`, `invalid or duplicate order type` | `order_cancel_all` | Bad `type` array | ### Engine rejections | Code | Message | Methods | Condition | | - | - | - | - | | `2` | `internal error` | All | Matching engine unreachable | | `3` | `service unavailable` | All | Downstream service down | | `4` | `method not found` | All | Method name typo | | `5` | `service timeout` | All | Engine did not answer in time | | `6` | `order not found`, `require authentication` | Cancel and modify; all | Unknown or already-finished order, or `authorize` was never called | | `7` | `too many requests` | All | Rate limit | | `8` | `unknown asset` | All | Asset not listed | | `9` | `unknown market` | All | Market not listed | | `10` | `balance not enough` | Placement | Insufficient spot balance | | `11` | `amount too small` | Placement | Below the market minimum amount or minimum notional | | `12` | `not enough traders` | Placement | Order book too thin to execute | | `13` | `order by taker price` | Spot placement | Post-only order would cross the spread | | `14` | `margin order by taker price` | `collateral_*` | Post-only margin order would cross | | `15`, `16` | `margin exchange stock/money not enough` | `collateral_*` | Exchange-side collateral shortfall | | `17` | `user margin balance not enough` | `collateral_*` | Insufficient collateral balance | | `19` | `market is not margin market` | `collateral_*`, `order_cancel_conditional` | Called on a spot-only market | | `40` | `order is not post only` | Limit placement without `post_only` | Market is in post-only mode | | `42` | `order slippage threshold` | Market placement | Slippage guard tripped | | `43` | `client order id already exists` | Placement | Duplicate `client_order_id` among active orders | | `51` | `trading in the market is not allowed` | All | Market suspended, or the market status blocks the method — including every market and stop method while the market runs in post-only mode | ### Conditional orders and positions | Code | Message | Methods | Condition | | - | - | - | - | | `101` | `activation price should not be equal to the last price` | Stop and conditional | Trigger equals the current last price | | `103` | `max num margin stop market orders` | Stop-market | Per-market conditional order cap reached | | `104` | `margin position not exists` | TPSL | No open position to attach to | | `105` | `wrong activation price for take profit` | TPSL, OTO | Take-profit trigger on the wrong side of the price | | `106` | `wrong activation price for stop loss` | TPSL, OTO | Stop-loss trigger on the wrong side of the price | | `108` | `wrong limit price for take profit` | OCO, OTO | Take-profit limit price inconsistent with its trigger | | `111` | `margin position is too big` | `collateral_*` | Position would exceed the size cap | | `112` | `margin pending orders value is too big` | `collateral_*` | Total pending margin order value exceeded | | `113` | `user position side change mode` | `collateral_*` | Hedge-mode switch in progress | | `114` | `order's position side does not match user's setting` | `collateral_*` | `position_side` sent (as non-`BOTH`) without hedge mode, omitted or sent as `BOTH` while hedge mode is enabled, or otherwise mismatched | | `115` | `order would result in a new position in the opposite direction` | Reduce-only | Reduce-only order would flip the position | | `116` | `margin order with reduce only is rejected` | Reduce-only | Nothing to reduce on that side | | `150` | `take profit is not post only` | OCO | The take-profit leg would execute immediately — it must be maker | | `151` | `wrong activation price for stop loss` | OCO, TPSL | Stop-loss trigger on the wrong side of the current price | | `152`, `153` | `can not place stop loss / take profit` | Group placement | A leg could not be created | | `154` | `price is outside spread` | Placement | Price outside the allowed spread | | `156` | `wrong order type` | `order_modify` | Order type cannot be modified | | `158`, `159` | `wrong activation price for limit order`, `wrong limit price for stop market order` | Conditional placement | Trigger and limit price inconsistent | | `161` | `conditional order validation` | Group placement | Group failed consistency validation | | `162`–`164` | `wrong param total / amount / price` | `order_modify` | Modified value is invalid | | `200`, `201` | `unknown conditional / trigger order type in oto` | OTO | Bad type string | | `250` | `price must be >= X / <= Y` | Placement | Price outside the market price band | | `251` | `activation price is out of bands` | Stop placement | Activation price outside the maker price bands | ### Account and rate limits | Code | Message | Condition | | - | - | - | | `601` | `account is restricted from trading` | Account-level trading restriction | | `602` | `order contains forbidden flags` | A flag blocked for the account | | `10000` | `too many requests per period` | Per-user rate limit | | `10001` | `too many new orders per period` | New-order rate limit | The transport limits are per connection: order placements count against a budget of `10000` requests per `10` seconds, and every other JSON-RPC request — cancellations, modifications, subscriptions, `ping` — counts against a separate budget of `12000` per `10` seconds. See [WebSocket Rate Limits](/websocket/rate-limits) for connection limits. ## Regional availability Order placement over WebSocket is available on the global platform only; the EU platform is not yet supported. Once available in a region, the region of the authorized connection decides which trading types — spot, margin, futures — and which individual markets are reachable. On this transport the region is carried by the authorization token; no per-request override exists. Region checks run before market and balance validation, so a region error masks any other problem with the request. When an order is rejected with one of the codes below, nothing else about it was evaluated. | Code | Message | Condition | | - | - | - | | `10006` | `region is unknown or not supported` | The region does not permit order placement | | `10007` | `futures trading is not available in your region` | Futures disabled for the region | | `10008` | `margin trading is not available in your region` | Margin disabled for the region | | `10009` | `spot trading is not available in your region` | Spot disabled for the region | | `10010` | `this market is restricted in your region` | Market on the restricted list for the region | The available order types also vary by region. In the EU region the spot order types are restricted and margin and futures are unavailable; that policy will apply here once EU support for this transport is added — see [Order types — Regional restrictions](/concepts/order-types#regional-restrictions). ## Related resources * [Authorize](/websocket/account-streams/authorize) — token flow required before any order method * [Orders Pending](/websocket/account-streams/orders-pending) — stream of order lifecycle events, and the order object reference * [Deals](/websocket/account-streams/deals) — stream of individual fills * [Order Types](/concepts/order-types) — order type concepts and regional restrictions * [WebSocket Rate Limits](/websocket/rate-limits) — connection limits, request limits, and standard error codes ## Used in these guides * [Market Maker integration](/guides/market-maker-integration) — placing and canceling quotes over the WebSocket order methods. * [Partner Solutions](/guides/partner-solutions) — the partner router's REST-versus-WebSocket transport guidance. * [Crypto-as-a-Service integration](/guides/caas-integration) — the trade surface composed into a white-label exchange. # WebSocket API Source: https://docs.whitebit.com/websocket/overview WhiteBIT WebSocket API — connection details, quickstart examples, message format, and links to all available channels. **Deprecated.** `wss://api.whitebit.com/ws` is deprecated as of September 1, 2026 and stops accepting connections on March 1, 2027. Connect to `wss://wss.whitebit.com/ws` instead. Only the host changes — see [Host migration](#host-migration). ## Connection WebSocket endpoint: **`wss://wss.whitebit.com/ws`** The API is based on [JSON-RPC](https://www.jsonrpc.org/specification) over the WebSocket protocol. The API returns time in Unix-time format. ### Host migration The Global WebSocket host moved from `api.whitebit.com` to `wss.whitebit.com` on September 1, 2026. Both hosts serve the same channels over the same `/ws` path during a 6-month transition window. | Host | Status | | - | - | | `wss://wss.whitebit.com/ws` | Current. Use for all connections. | | `wss://api.whitebit.com/ws` | Deprecated September 1, 2026. Rejects connections from March 1, 2027. | Replace the host string in the WebSocket client and redeploy. Nothing in the application protocol changes: * The `/ws` path is unchanged. * The JSON-RPC request and response format is unchanged. * Every subscription, query, and order-management method name is unchanged. * The `authorize` flow and the token format are unchanged — see [WebSocket Authentication](/websocket/authentication). * Connection and request limits are unchanged — see [WebSocket Rate Limits & Error Codes](/websocket/rate-limits). One item sits outside the application protocol: a network that allowlists destination hosts must permit `wss.whitebit.com` before the switch. The legacy host stays fully functional until March 1, 2027, so the switch does not need a coordinated cutover. An integration that resolves the host from configuration needs a configuration change only. An integration that hardcodes the host in more than one place — a reconnect helper, a failover list, a client default — must update every occurrence, because a missed entry keeps working until March 1, 2027 and fails then rather than at deploy time. *** ## Quickstart ### Prerequisites * A WebSocket client (browser, Node.js, Python, or similar) No API key is required for public channels. ### Step 1: Establish a connection Open a WebSocket connection to the endpoint. ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}} const socket = new WebSocket("wss://wss.whitebit.com/ws"); socket.onopen = () => { console.log("Connected"); }; socket.onmessage = (event) => { const data = JSON.parse(event.data); console.log("Received:", data); }; ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import asyncio import websockets import json async def connect(): async with websockets.connect("wss://wss.whitebit.com/ws") as ws: print("Connected") async for message in ws: data = json.loads(message) print("Received:", data) asyncio.run(connect()) ``` The connection opens when the WebSocket handshake completes. ### Step 2: Keep the connection alive The server closes the connection after 60 seconds of inactivity. Send a ping message every 50 seconds to keep the connection alive. Add the following to the connection established in Step 1: ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}} setInterval(() => { if (socket.readyState === WebSocket.OPEN) { socket.send(JSON.stringify({ id: 0, method: "ping", params: [], })); } }, 50000); ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import asyncio import websockets import json async def connect(): async with websockets.connect("wss://wss.whitebit.com/ws") as ws: async def keepalive(): while True: await asyncio.sleep(50) await ws.send(json.dumps({"id": 0, "method": "ping", "params": []})) asyncio.create_task(keepalive()) async for message in ws: data = json.loads(message) print("Received:", data) asyncio.run(connect()) ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 0, "result": "pong", "error": null } ``` ### Step 3: Subscribe to last price updates Subscribe to the [Last Price](/websocket/market-streams/lastprice) channel to receive real-time price updates for one or more markets. Send the subscription message using the connection from Step 1: ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}} socket.send(JSON.stringify({ id: 1, method: "lastprice_subscribe", params: ["BTC_USDT", "ETH_USDT"] })); ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import asyncio import websockets import json async def connect(): async with websockets.connect("wss://wss.whitebit.com/ws") as ws: async def keepalive(): while True: await asyncio.sleep(50) await ws.send(json.dumps({"id": 0, "method": "ping", "params": []})) asyncio.create_task(keepalive()) await ws.send(json.dumps({ "id": 1, "method": "lastprice_subscribe", "params": ["BTC_USDT", "ETH_USDT"] })) async for message in ws: data = json.loads(message) print("Received:", data) asyncio.run(connect()) ``` **Expected subscription response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 1, "result": { "status": "success" }, "error": null } ``` ### Step 4: Receive update events After a successful subscription, the server sends update events every second. Each event contains the market name and the latest price. **Example update event:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": null, "method": "lastprice_update", "params": ["BTC_USDT", "67500.50"] } ``` The `params` array contains `[market_name, last_price]`. Parse each `lastprice_update` event to display real-time prices. *** ## Message Format ### Request message | Field | Type | Description | | - | - | - | | `id` | Integer | Unique identifier to match the response to the request | | `method` | String | Name of the method to call | | `params` | Array | Parameters for the method | The connection will be closed if invalid JSON is sent. **Types of request messages:** * **Query** — one-time requests (`ping`, `candles_request`, `balanceSpot_request`, etc.) * **Subscription** — streaming updates (`candles_subscribe`, `lastprice_subscribe`, `balanceSpot_subscribe`, etc.). Repeating a subscription cancels the previous one for the same data type. ### Response message | Field | Type | Description | | - | - | - | | `id` | Integer | ID of the original request | | `result` | Object / null | `null` on failure; see channel docs for success payloads | | `error` | Object / null | `null` on success; error object on failure | **Types of response messages:** * **Query result** — direct response to a query request * **Subscription status** — success or failure of a subscription request * **Update events** — pushed by the server when subscribed data changes ### Examples **Query — ping/pong:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} // ⤴️ Request { "id": 0, "method": "ping", "params": [] } // ⤵️ Response { "id": 0, "result": "pong", "error": null } ``` **Subscription:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} // ⤴️ Request { "id": 0, "method": "candles_subscribe", "params": [] } // ⤵️ Response { "id": 0, "result": { "status": "success" }, "error": null } ``` **Update event:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": null, "method": "candles_update", "params": [] } ``` *** For connection limits, request limits, and error codes, see [WebSocket Rate Limits & Error Codes](/websocket/rate-limits). Private channels require authorization. See [WebSocket Authentication](/websocket/authentication) for the full setup flow. *** ## Channels Public channels for market data — kline, last price, trades, depth, book ticker, and more. See [Markets & Trading Pairs](/concepts/markets) for pair notation. Private channels for account data — balances, orders, deals, positions, and borrows. Requires authorization. See [Balances & Transfers](/concepts/balances) for account types. Private methods that place, modify, and cancel orders on spot, margin, and futures markets (global platform only). Requires authorization. See [Order Types](/concepts/order-types) for the available types. ## Who uses this * **Market makers** stream the real-time order book and fills — the public [Depth](/websocket/market-streams/depth) and [Book Ticker](/websocket/market-streams/book-ticker) channels plus the private [Deals](/websocket/account-streams/deals) account stream. See [Market Maker integration](/guides/market-maker-integration). * Any integration reading private account events (balances, orders, deals, positions) authorizes first — see [WebSocket Authentication](/websocket/authentication). *** ## Connection best practices Reuse a single WebSocket connection for multiple subscriptions instead of opening a new connection per channel. See [WebSocket Rate Limits & Error Codes](/websocket/rate-limits) for connection and request limits, timeout behavior, and reconnection guidance. ## Related resources * [WebSocket Authentication](/websocket/authentication) — Authorization flow for private Account Stream channels * [WebSocket Rate Limits & Error Codes](/websocket/rate-limits) — Connection limits, request limits, and error codes * [API Reference Overview](/api-reference/overview) — Base URL, quickstart, and endpoint groups * [Market Streams](/websocket/market-streams/overview) — All public channels (kline, trades, depth, book ticker) * [Account Streams](/websocket/account-streams/overview) — Private channels for balances, orders, and positions ## Used in these guides * [Partner Solutions](/guides/partner-solutions) — the partner router that maps use cases to programs. # WebSocket Rate Limits & Error Codes Source: https://docs.whitebit.com/websocket/rate-limits Connection limits, request limits, timeout behavior, and error codes for the WhiteBIT WebSocket API. Reference documentation for WebSocket connection limits, request limits, timeout behavior, and error codes. Rate limits: `1000` WebSocket connections per minute. Per connection, `10000` order placements and `12000` other JSON-RPC requests per `10` seconds. ## Connection limits | Scope | Limit | | - | - | | New connections | 1,000 per minute | | Order placements per connection | 10,000 per 10 seconds | | All other requests per connection | 12,000 per 10 seconds | Limit WebSocket connection creation to `1000` connections per minute. Order placements — the `*_place` methods on [Order Management](/websocket/order-management/overview) — count against a budget of `10000` requests per `10` seconds per connection. Every other JSON-RPC request — subscriptions, one-time queries, order cancellations and modifications, `authorize`, `ping` — counts against a separate budget of `12000` requests per `10` seconds per connection. Reuse a single WebSocket connection for multiple subscriptions. Opening a new connection per channel consumes the connection limit and increases latency. ## Subscription limits | Scope | Limit | | - | - | | Active subscriptions per connection | None | | Markets per subscription request | None | | Per-channel-type limits | None — the same `12000` requests per `10` seconds budget applies uniformly across all public and private channels | A single connection comfortably maintains subscriptions across `200` or more markets. Distributing markets across multiple connections is not required for high-market-count workloads. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 1, "method": "lastprice_subscribe", "params": ["BTC_USDT", "ETH_USDT", "SOL_USDT", "XRP_USDT"] } ``` The request above counts as one message regardless of the number of markets in `params`. Repeating a subscription replaces the previous one for the same channel. To track additional markets on an active channel, send a new subscribe request with the full target list — the server does not merge incremental subscribes. ## Rate limit handling Implement request throttling on the client side. Queue subscription requests instead of sending bursts of requests. Apply exponential backoff with jitter after receiving error code `7`. Reuse active connections instead of creating new connections. ### Rate limit error example ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": { "code": 7, "message": "too many requests" }, "result": null, "id": 2269 } ``` ## Connection timeout The server closes the WebSocket connection after `60` seconds of inactivity. Inactivity means no messages sent by the client. Send a `ping` request every `50` seconds to keep the connection alive: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 0, "method": "ping", "params": [] } ``` **Expected response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 0, "result": "pong", "error": null } ``` **Code example:** ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}} const socket = new WebSocket("wss://wss.whitebit.com/ws"); setInterval(() => { if (socket.readyState === WebSocket.OPEN) { socket.send(JSON.stringify({ id: 0, method: "ping", params: [] })); } }, 50000); ``` ## Error codes The server returns errors in the `error` field of a response message. The `error` object contains a `code` and a `message`. | Code | Message | | - | - | | `1` | invalid argument | | `2` | internal error | | `3` | service unavailable | | `4` | method not found | | `5` | service timeout | | `6` | require authentication | | `7` | too many requests | The server returns code `6` when a client invokes a protected method — a private-channel subscription or a balance query, for example — without first calling `authorize` on the connection. Send an `authorize` request before any private-channel subscription. See [WebSocket Authentication](/websocket/authentication) for the authorization flow. **Error response format:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": 1, "result": null, "error": { "code": 1, "message": "invalid argument" } } ``` The server closes the WebSocket connection immediately if the client sends invalid JSON. ## Best practices **Reuse connections**. Each subscription does not require a new connection. Subscribe to multiple channels on a single connection to stay within the `1,000` connections per minute limit. **Implement reconnection logic**. Handle unexpected disconnections with exponential backoff (for example, wait `1s`, `2s`, `4s`, `8s` between retries). Re-subscribe to all channels and re-authorize private channels after reconnecting. **Batch subscriptions**. Subscribe to all required channels immediately after connecting rather than one at a time. Batching reduces round-trips and keeps connection setup well inside the `12000` requests per `10` seconds budget. **Monitor ping latency**. A slow or missing `pong` response indicates network issues. Reconnect if the server does not return `pong` within `10` seconds after a `ping`. ## Related resources * [WebSocket Overview](/websocket/overview) — Connection endpoint, message format, and quickstart. * [WebSocket Authentication](/websocket/authentication) — Authorization flow for private channels. * [REST API Rate Limits & Error Codes](/api-reference/rate-limits) — REST-specific limits and error formats.