> ## 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.

# Webhook HTTP API

> Configure webhook callbacks to receive real-time notifications for deposits and withdrawals on WhiteBIT.

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

<CardGroup>
  <Card title="How to use" href="#how-to-use" icon="question" horizontal />

  <Card title="Requirements" href="#requirements" icon="clipboard" horizontal />

  <Card title="Webhook methods" href="#webhook-methods" icon="rss" horizontal />

  <Card title="WhiteBIT withdraw from main balance" href="#whitebit-withdraw-from-main-balance" icon="arrow-down" horizontal />
</CardGroup>

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

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

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

1. Log in to whitebit.com.
2. Open the API keys tab.
3. Select the web-hook configuration tab for the API keys.
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".

<Warning>
  The secret key is shown only once. Save it in a secure key store.
</Warning>

## 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: `["<public-webhook-key>"]`

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))`

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": "<SOME_WHITE_BIT_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 events (EEA)

For EEA users, deposits may be frozen pending Travel Rule verification. When a deposit is frozen, the webhook delivers deposit.updated events with Travel Rule-specific status codes. The end user must complete Travel Rule verification through the WhiteBIT platform UI — the partner cannot submit Travel Rule data via API.

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 — Travel Rule verification required (EEA) |
| 28   | Travel Rule Frozen Processing | Travel Rule 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. 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...",
    "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,
    "nonce": 0
  },
  "id": "uuid"
}
```

## What's Next

<CardGroup cols={2}>
  <Card title="Payment Integration" icon="credit-card" href="/guides/payment-integration">
    End-to-end guide for deposit and withdrawal processing with webhook reconciliation.
  </Card>

  <Card title="Security Best Practices" icon="shield" href="/best-practices/security">
    HMAC-SHA512 signature verification, API key management, and production hardening.
  </Card>
</CardGroup>
