> ## Documentation Index
> Fetch the complete documentation index at: https://whitebit-mintlify-fix-broken-links-1777853396.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Broker Integration Guide

> Integration guide for the WhiteBIT Broker Program. Earn up to 40% of trading fees from referred customers via sub-accounts under a master account.

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 />

The WhiteBIT Broker Program enables trading platforms and fintechs to offer WhiteBIT exchange access to end users. Brokers earn up to **40% of trading fees** generated by referred customers. Each customer trades from a dedicated sub-account under the broker's master account, with fee-free internal transfers and per-customer API keys.

## Broker Program overview

The Broker Program offers a revenue-sharing model where brokers receive up to 40% of trading fees generated by referred users.

**Fee share model:**

The base fee share is **40% of the trading fee** generated by each referred user.

**Worked example:**

```
Referred user trades $10,000 on BTC_USDT (spot)
Standard trading fee: 0.1% taker = $10.00
Broker fee share (40%): $10.00 × 0.40 = $4.00
```

**WBT holding boost tiers:**

WBT is WhiteBIT's native utility token (WhiteBIT Token). Holding WBT in the broker's master account boosts the fee share percentage above the 40% base:

| WBT Holdings  | Fee Share |
| ------------- | --------- |
| 200 WBT       | 40%       |
| 4,000 WBT     | 42%       |
| 10,000 WBT    | 44%       |
| 30,000 WBT    | 46%       |
| 100,000 WBT   | 48%       |
| 2,000,000 WBT | 50%       |

The 200 WBT entry matches the no-WBT 40% base; the first uplift starts at 4,000 WBT. The canonical tier table is published on the [Broker Program page](https://institutional.whitebit.com/broker-program).

**How to apply:** Contact **[institutional@whitebit.com](mailto:institutional@whitebit.com)** with the business description and expected user volume.

**Program benefits:**

* Per-customer sub-accounts: each end customer trades from a dedicated sub-account with its own balance, order history, and API credentials
* Per-customer API keys
* Fee-free internal transfers between master and sub-accounts
* Joint marketing activities: social media co-posts, blog posts, targeted email newsletters, AMA sessions, and trading competitions, scheduled with WhiteBIT during onboarding

## Customer onboarding flow

Each end customer is onboarded as a sub-account under the broker's master account.

<Steps>
  <Step title="Create a sub-account">
    Call the sub-account creation endpoint to create a new sub-account for the customer. Each sub-account receives an independent balance and can have dedicated API keys.

    **Endpoint:** `POST /api/v4/sub-account/create` — [API Reference](/api-reference/sub-accounts/create-sub-account)
  </Step>

  <Step title="Generate a KYC verification URL">
    Generate a KYC URL for the sub-account holder. The end customer completes KYC verification through the WhiteBIT interface (WhiteBIT-branded, not white-label).

    **Endpoint:** `POST /api/v4/sub-account/kyc-url` — [API Reference](/api-reference/sub-accounts/kyc-url)
  </Step>

  <Step title="Customer completes KYC">
    The end customer opens the KYC URL and completes identity verification. The broker monitors KYC status via the sub-account details endpoint.
  </Step>

  <Step title="Enable trading">
    Once KYC is approved, transfer initial funds to the sub-account (fee-free) and create an API key for the sub-account if the customer needs direct API access.
  </Step>
</Steps>

<Note>
  The KYC verification flow is WhiteBIT-branded. The broker cannot white-label the KYC interface.
</Note>

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    # Create a sub-account
    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",
        "request": "/api/v4/sub-account/create",
        "nonce": "YOUR_NONCE"
      }'

    # Generate a KYC URL for the sub-account
    curl -X POST "https://whitebit.com/api/v4/sub-account/kyc-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 '{
        "id": "SUB_ACCOUNT_ID",
        "request": "/api/v4/sub-account/kyc-url",
        "nonce": "YOUR_NONCE"
      }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    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"] = str(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)

    # Create a sub-account
    response = send_request("/api/v4/sub-account/create", {
        "alias": "customer-001",
    })
    sub_account = response.json()
    print(sub_account)

    # Generate a KYC URL
    response = send_request("/api/v4/sub-account/kyc-url", {
        "id": sub_account.get("id"),
    })
    print(response.json())
    ```
  </Tab>
</Tabs>

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

## Sub-account management

Each sub-account holds an independent balance (scoped to spot, collateral, or both at creation), order history, and API credential set with its own IP whitelist and permission scope. Trades on one sub-account do not affect another. Withdrawal approval remains under the broker's master account.

**CRUD operations:**

| Operation | Endpoint                           | Description                      |
| --------- | ---------------------------------- | -------------------------------- |
| Create    | `POST /api/v4/sub-account/create`  | Create a new sub-account         |
| List      | `POST /api/v4/sub-account/list`    | List all sub-accounts            |
| Block     | `POST /api/v4/sub-account/block`   | Suspend trading for a customer   |
| Unblock   | `POST /api/v4/sub-account/unblock` | Re-enable trading for a customer |

**Fee-free transfers:**

Transfer funds between the master account and any sub-account without fees using `POST /api/v4/sub-account/transfer` — see the [API Reference](/api-reference/sub-accounts/sub-account-transfer).

* Master to sub-account: funding a customer account
* Sub-account to master: revenue collection

**Balance monitoring:**

Query balances across all sub-accounts in a single call via `POST /api/v4/sub-account/balances` — see the [API Reference](/api-reference/sub-accounts/sub-account-balances). For per-sub-account balance queries scoped to a single customer, call the balance endpoint using the sub-account's own API key.

See the [Sub-Accounts Overview](/products/sub-accounts/overview) for the full sub-account product reference.

## Per-customer API keys

Each sub-account can have dedicated API keys with independent IP whitelists and permissions.

* Create API keys per sub-account for customers who need direct API access
* **IP whitelisting:** up to **50 IP addresses** per API key
* **Permissions:** configure per-key permissions (`Info + Trading` vs. `Info + Trading + Deposit + Withdraw`)

<Warning>
  Create separate API keys for each customer sub-account. Do not share the master account's API keys with customers.
</Warning>

See [Security Best Practices](/best-practices/security) for API key management guidance.

For structured order tracking across customer sub-accounts, use `clientOrderId` naming
conventions — see [Client Order ID: Broker Implementation](/guides/client-order-id#example-broker-implementation).

## Revenue monitoring

The Broker Program does not currently 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, trading volumes, WBT Holding tier, and VIP level in real time. Fee-share payouts are credited to the broker's main account on a monthly cadence.

**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 — see the [API Reference](/api-reference/spot-trading/query-executed-order-history).
3. For each executed deal, multiply the fee charged by the broker's active fee-share percentage from the WBT tier table.
4. Sum across all sub-accounts to produce the broker's earnings for the reporting window.

**Reporting recommendations:**

* Reconcile against the dashboard monthly so dashboard-credited payouts match locally computed totals.
* Track each referred user's trading volume separately — a single high-volume customer can change the master account's effective fee tier and lift the absolute fee share without any new customers being added.
* Export per-sub-account trade history into a ledger column matching the monthly settlement statement.

## Fiat for broker end users

European broker end users frequently expect EUR deposit and withdrawal capabilities.

Fiat operations (EUR/SEPA) require institutional onboarding with fiat access approval. The broker's master account must complete the two-phase onboarding process (crypto access via KYB, then fiat access via fiat processing partner review). Once fiat access is approved on the master account, sub-accounts can process fiat deposits and withdrawals.

See [Institutional Onboarding](/institutional/onboarding) for the two-phase process. See [Payment Integration](/guides/payment-integration) for fiat endpoint details.

<Note>
  Fiat deposit and withdrawal access requires completion of institutional onboarding including the fiat provider approval phase. Contact [institutional@whitebit.com](mailto:institutional@whitebit.com) to begin the process.
</Note>

## Integration checklist

Complete the following checklist before going live with the Broker Program integration.

* [ ] **Program enrollment** — Application submitted to [institutional@whitebit.com](mailto:institutional@whitebit.com) and approved.
* [ ] **Master account KYB** — KYB verification completed for the broker entity.
* [ ] **API key generated** — Master account API key created with appropriate permissions.
* [ ] **Sub-account creation** — Successfully created at least one test sub-account.
* [ ] **KYC URL generation** — KYC URL generated and tested for a sub-account.
* [ ] **Fund transfer** — Fee-free transfer between master and sub-account verified.
* [ ] **Per-customer API key** — API key created for a sub-account with IP whitelist configured.
* [ ] **Balance monitoring** — Sub-account balance query working.
* [ ] **Fee share tracking** — Revenue monitoring process established.
* [ ] **Fiat access** (if applicable) — Institutional onboarding Phase 2 completed for SEPA access.
* [ ] **Security review** — IP whitelists, API 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

<CardGroup cols={3}>
  <Card title="Sub-Accounts" icon="users" href="/products/sub-accounts/overview">
    Sub-account isolation model, transfer mechanics, and per-key permission scopes.
  </Card>

  <Card title="Institutional Onboarding" icon="building" href="/institutional/onboarding">
    Step-by-step KYB and fiat onboarding process.
  </Card>

  <Card title="Go-Live Checklist" icon="clipboard-check" href="/best-practices/go-live-checklist">
    Pre-production readiness verification.
  </Card>
</CardGroup>
