> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whitebit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sub-Accounts Quickstart

> Create a sub-account, transfer funds, generate an API key, and check balances -- step by step.

export const RegionBaseUrl = ({className = "", showBaseUrl = true}) => {
  const [region, setRegionState] = useState(() => {
    if (typeof window !== 'undefined') {
      return localStorage.getItem("api-region-preference") || "com";
    }
    return "com";
  });
  const [mounted, setMounted] = useState(false);
  const observerRef = useRef(null);
  const isSyncingRef = useRef(false);
  const updateAllContentOnPage = targetRegion => {
    try {
      const domainFrom = targetRegion === "eu" ? "whitebit.com" : "whitebit.eu";
      const domainTo = targetRegion === "eu" ? "whitebit.eu" : "whitebit.com";
      const links = document.querySelectorAll('a');
      links.forEach(link => {
        let href = link.getAttribute('href');
        if (href && href.includes(domainFrom)) {
          link.setAttribute('href', href.replace(domainFrom, domainTo));
        }
      });
      const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
        acceptNode: node => {
          if (node.parentElement?.closest('.region-toggle-component')) {
            return NodeFilter.FILTER_REJECT;
          }
          return node.textContent.includes(domainFrom) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
        }
      });
      let currentNode;
      while (currentNode = walker.nextNode()) {
        currentNode.textContent = currentNode.textContent.replace(new RegExp(domainFrom, 'g'), domainTo);
      }
      console.log(`[RegionSync] Global content updated to ${domainTo}`);
    } catch (e) {
      console.error("[RegionSync] Error updating content:", e);
    }
  };
  const updateRegion = (newRegion, source) => {
    if (region === newRegion) return;
    console.log(`[RegionBaseUrl] Updating to "${newRegion}" (Source: ${source})`);
    if (source === 'observer') {
      isSyncingRef.current = true;
      setTimeout(() => isSyncingRef.current = false, 1000);
    }
    setRegionState(newRegion);
    localStorage.setItem("api-region-preference", newRegion);
    updateAllContentOnPage(newRegion);
    if (source === 'user-click') {
      window.dispatchEvent(new CustomEvent("regionChange", {
        detail: newRegion
      }));
      attemptToUpdateNativeDropdown(newRegion, 0);
      setTimeout(() => attemptToUpdateNativeDropdown(newRegion, 1), 500);
      setTimeout(() => attemptToUpdateNativeDropdown(newRegion, 2), 1500);
    }
  };
  const attemptToUpdateNativeDropdown = (targetRegion, attempt) => {
    if (isSyncingRef.current) return;
    try {
      const targetUrl = targetRegion === "eu" ? "https://whitebit.eu" : "https://whitebit.com";
      const targetDesc = targetRegion === "eu" ? "EU Server" : "Production Server";
      const selects = document.querySelectorAll('select');
      for (const select of selects) {
        if (select.innerHTML.includes('whitebit.com') || select.innerHTML.includes('whitebit.eu')) {
          select.value = targetUrl;
          select.dispatchEvent(new Event('change', {
            bubbles: true
          }));
          return;
        }
      }
      const buttons = Array.from(document.querySelectorAll('button, [role="combobox"]'));
      const serverSelector = buttons.find(btn => {
        if (btn.closest('a') || btn.closest('[class*="card"]') || btn.closest('nav')) {
          return false;
        }
        const txt = btn.textContent || "";
        const isServerDropdown = (txt.includes('Production Server') || txt.includes('EU Server') || txt.includes('WhiteBIT Global Server') || txt.includes('WhiteBIT EU Server')) && !txt.includes('Run') && !txt.includes('Send') || btn.getAttribute('role') === 'combobox';
        return isServerDropdown;
      });
      if (serverSelector) {
        const currentText = serverSelector.textContent || "";
        if (currentText.includes(targetDesc)) return;
        serverSelector.click();
        setTimeout(() => {
          const options = document.querySelectorAll('[role="option"], li, button');
          for (const opt of options) {
            const optText = opt.textContent || "";
            if (optText.includes(targetDesc) || optText.includes(targetUrl)) {
              opt.click();
              return;
            }
          }
        }, 100);
      }
    } catch (e) {
      console.error("[Sync] Error:", e);
    }
  };
  useEffect(() => {
    setMounted(true);
    updateAllContentOnPage(region);
    const handleStorageChange = e => {
      if (e.key === "api-region-preference" && e.newValue) {
        updateRegion(e.newValue, 'storage');
      }
    };
    const handleRegionChange = e => {
      if (e.detail !== region) {
        updateRegion(e.detail, 'event');
      }
    };
    window.addEventListener("storage", handleStorageChange);
    window.addEventListener("regionChange", handleRegionChange);
    observerRef.current = new MutationObserver(mutations => {
      if (isSyncingRef.current) return;
      updateAllContentOnPage(region);
      for (const mutation of mutations) {
        if (mutation.type !== 'childList' && mutation.type !== 'characterData') continue;
        const target = mutation.target;
        const el = target.nodeType === Node.TEXT_NODE ? target.parentElement : target;
        if (el && (el.getAttribute('role') === 'option' || el.closest('[role="listbox"]'))) continue;
        const text = target.textContent || "";
        if (text.includes('WhiteBIT EU Server') || text.includes('https://whitebit.eu') && text.includes('Server')) {
          if (el && el.tagName !== 'A' && !el.closest('.region-toggle-component')) {
            if (region !== 'eu') updateRegion('eu', 'observer');
          }
        } else if (text.includes('WhiteBIT Global Server') || text.includes('https://whitebit.com') && text.includes('Server')) {
          if (el && el.tagName !== 'A' && !el.closest('.region-toggle-component')) {
            if (region !== 'com') updateRegion('com', 'observer');
          }
        }
      }
    });
    observerRef.current.observe(document.body, {
      childList: true,
      subtree: true,
      characterData: true
    });
    if (typeof window !== 'undefined') {
      const current = localStorage.getItem("api-region-preference");
      if (current) attemptToUpdateNativeDropdown(current, 'init');
    }
    return () => {
      window.removeEventListener("storage", handleStorageChange);
      window.removeEventListener("regionChange", handleRegionChange);
      if (observerRef.current) observerRef.current.disconnect();
    };
  }, [region]);
  const apiBaseUrl = region === "eu" ? "https://whitebit.eu" : "https://whitebit.com";
  if (!mounted) return null;
  return <div className={`flex items-center gap-2 flex-wrap my-4 region-toggle-component ${className}`}>
            <span className="text-sm text-gray-500 dark:text-gray-400 font-mono">
                Base URL
            </span>
            <span className="text-sm text-gray-400">(</span>
            <div className="inline-flex bg-gray-100 dark:bg-gray-800 rounded-lg p-0.5 border border-gray-200 dark:border-gray-700">
                <button onClick={() => updateRegion("com", "user-click")} className={`px-2 py-0.5 text-xs font-medium rounded-md transition-all ${region === "com" ? "bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 shadow-sm" : "text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200"}`}>
                    .com
                </button>
                <button onClick={() => updateRegion("eu", "user-click")} className={`px-2 py-0.5 text-xs font-medium rounded-md transition-all ${region === "eu" ? "bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 shadow-sm" : "text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200"}`}>
                    .eu
                </button>
            </div>
            <span className="text-sm text-gray-400">)</span>
            {showBaseUrl && <>
                    <span className="text-sm text-gray-400">:</span>
                    <a href={apiBaseUrl} target="_blank" rel="noopener noreferrer" className="text-sm font-mono text-primary dark:text-primary-light hover:underline">
                        {apiBaseUrl}
                    </a>
                </>}
        </div>;
};

<RegionBaseUrl />

Each sub-account holds its own balance and API keys. Funds and signing scopes are isolated from the main account; transfers between them 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)

<Steps>
  <Step title="Create a sub-account">
    Create a new sub-account with an alias and permissions.

    <Tabs>
      <Tab title="cURL">
        ```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
          }'
        ```
      </Tab>

      <Tab title="Python">
        ```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))
        ```
      </Tab>
    </Tabs>

    For Go and PHP 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.
  </Step>

  <Step title="Transfer funds to the sub-account">
    Move assets from the main account to the newly created sub-account.

    <Tabs>
      <Tab title="cURL">
        ```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": "<sub-account-id-from-step-1>",
            "direction": "main_to_sub",
            "ticker": "USDT",
            "amount": "100",
            "request": "/api/v4/sub-account/transfer",
            "nonce": 1709340000001
          }'
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
        # Transfer funds to sub-account
        response = make_request("/api/v4/sub-account/transfer", {
            "id": "<sub-account-id-from-step-1>",
            "direction": "main_to_sub",
            "ticker": "USDT",
            "amount": "100",
        })
        print(response.json())
        ```
      </Tab>
    </Tabs>

    **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_..."
    }
    ```
  </Step>

  <Step title="Create an API key for the sub-account">
    Generate a dedicated API key for the sub-account to enable independent trading.

    <Tabs>
      <Tab title="cURL">
        ```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": "<sub-account-id-from-step-1>",
            "type": 1,
            "title": "Trading Bot Key",
            "request": "/api/v4/sub-account/api-key/create",
            "nonce": 1709340000002
          }'
        ```
      </Tab>

      <Tab title="Python">
        ```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": "<sub-account-id-from-step-1>",
            "type": 1,
            "title": "Trading Bot Key",
        })
        print(response.json())
        ```
      </Tab>
    </Tabs>

    **Required fields:** `subAccountId` (UUID), `type` (1 = info and trading, 2 = info, trading, deposits, withdrawals). **Optional:** `title` (custom name for the key).

    <Warning>
      Save the `secretKey` immediately -- the API does not return the secret key again after creation.
    </Warning>

    <Note>
      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 them for the account and its sub-accounts, contact your 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.
    </Note>
  </Step>

  <Step title="Check sub-account balances">
    Verify that the transferred funds appear in the sub-account balance.

    <Tabs>
      <Tab title="cURL">
        ```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": "<sub-account-id-from-step-1>",
            "request": "/api/v4/sub-account/balances",
            "nonce": 1709340000003
          }'
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
        # Check sub-account balances
        response = make_request("/api/v4/sub-account/balances", {
            "id": "<sub-account-id-from-step-1>",
        })
        print(json.dumps(response.json(), indent=2))
        ```
      </Tab>
    </Tabs>

    **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.
  </Step>
</Steps>

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.

## What's Next

<CardGroup cols={2}>
  <Card title="Sub-Accounts Overview" icon="book-open" href="/products/sub-accounts/overview">
    Integration patterns for fund managers, brokers, and prop trading firms.
  </Card>

  <Card title="Broker Guide" icon="handshake" href="/guides/broker-guide">
    Fee share model up to 50%, sub-account-per-customer onboarding, KYC URL generation, and per-customer API keys with up to 50 IP addresses.
  </Card>
</CardGroup>

For Go and PHP examples, see [SDKs](/sdks).
