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

# Create withdraw request

> The endpoint creates withdraw for the specified ticker.

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

<Warning>
Rate limit: 1000 requests/10 sec.
</Warning>

<Note>
The API does not cache the response.
</Note>

<Note>
Also, fiat currencies can't be withdrawn without KYC verification.
</Note>


export const signerFields = [{
  "name": "ticker",
  "type": "string",
  "required": true,
  "description": "Currency's ticker. Example: BTC ⚠️ Currencies ticker must have \"can_deposit\" status equal to \"true\". Use Asset Status endpoint to know more about currency.",
  "example": "ETH"
}, {
  "name": "amount",
  "type": "string",
  "required": true,
  "description": "Withdraw amount (including fee). To add the fee to the specified amount, use the /main-account/withdraw-pay request.",
  "example": "0.9"
}, {
  "name": "address",
  "type": "string",
  "required": true,
  "description": "Target address (wallet address for cryptocurrencies, identifier/card token for fiat currencies)",
  "example": "0x0964A6B8F794A4B8d61b62652dB27ddC9844FB4c"
}, {
  "name": "memo",
  "type": "string",
  "required": false,
  "description": "Memo. ⚠️ Required if currency is memoable.",
  "example": "48565488244493"
}, {
  "name": "uniqueId",
  "type": "string",
  "required": true,
  "description": "Unique transaction identifier. Any string up to 255 characters; not validated as a UUID. ⚠️ Generate a new unique ID for each withdrawal request.",
  "example": "24529041"
}, {
  "name": "provider",
  "type": "string",
  "required": false,
  "description": "Fiat currency provider. Example: VISAMASTER ⚠️ Required for fiat currencies. Currency provider should be taken from Asset Status endpoint response.",
  "example": "VISAMASTER"
}, {
  "name": "network",
  "type": "string",
  "required": false,
  "description": "Cryptocurrency network. Available for multi network currencies. Example: OMNI ⚠️ Currency network should be taken from Asset Status endpoint response. Default for USDT is ERC20",
  "example": "ERC20"
}, {
  "name": "partialEnable",
  "type": "boolean",
  "required": false,
  "description": "Optional parameter for FIAT withdrawals with increased Maximum Limit if set as \"true\". To use this parameter, the application must support \"Partially successful\" withdrawal stat…",
  "example": "false"
}, {
  "name": "customerIp",
  "type": "string",
  "required": false,
  "description": "End-customer IP address forwarded to the fiat provider for antifraud checks before the withdrawal is processed. ⚠️ Required if currency ticker is USD or EUR with VISAMASTER prov…",
  "example": "203.0.113.42"
}, {
  "name": "bankBic",
  "type": "string",
  "required": false,
  "description": "Beneficiary bank's BIC (SWIFT) code, identifying the destination bank for SEPA and other bank-rail fiat withdrawals. ⚠️ Required if the fiat provider is one of: SEPA, SEPA_CLEAR…",
  "example": "DEUTDEFF"
}, {
  "name": "beneficiary",
  "type": "object",
  "required": false,
  "description": "Beneficiary information. ⚠️ Required if currency ticker is one of: USD_VISAMASTER, EUR_VISAMASTER, USD, EUR. Per-field requirements vary by currency and provider. Card-related f…"
}, {
  "name": "travelRule",
  "type": "object",
  "required": false,
  "description": "Travel Rule information for regulatory compliance. ⚠️ Required if currency is crypto and the account is from EEA See Travel Rule Overview for complete documentation. **Legacy fo…"
}, {
  "name": "paymentDescription",
  "type": "string",
  "required": false,
  "description": "Description of withdrawal destination ⚠️ Required if currency is crypto and withdrawal from whitebit-tr.com",
  "example": "Payment description"
}];

export const WhitebitSigner = ({path: defaultPath = "/api/v4/order/market", defaultParams = "{}", fields = null}) => {
  const {useState, useMemo} = React;
  const [baseUrl, setBaseUrl] = useState("https://whitebit.com");
  const getApiHost = () => baseUrl;
  const hex = buf => Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, "0")).join("");
  const b64 = s => {
    const bytes = new TextEncoder().encode(s);
    let bin = "";
    bytes.forEach(b => bin += String.fromCharCode(b));
    return btoa(bin);
  };
  const hmacSha512Hex = async (secret, msg) => {
    const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), {
      name: "HMAC",
      hash: "SHA-512"
    }, false, ["sign"]);
    const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(msg));
    return hex(sig);
  };
  const queryFields = fields ? fields.filter(function (f) {
    return f.paramIn === "query" || f.paramIn === "path";
  }) : [];
  const bodyFields = fields ? fields.filter(function (f) {
    return !f.paramIn || f.paramIn === "body";
  }) : [];
  const [open, setOpen] = useState(false);
  const [authOpen, setAuthOpen] = useState(true);
  const [paramsOpen, setParamsOpen] = useState(true);
  const [apiKey, setApiKey] = useState("");
  const [apiSecret, setApiSecret] = useState("");
  const [showSecret, setShowSecret] = useState(false);
  const [path, setPath] = useState(defaultPath);
  const initFieldValues = fieldDefs => {
    if (!fieldDefs) return {};
    const vals = {};
    for (const f of fieldDefs) {
      vals[f.name] = f.default !== undefined ? String(f.default) : "";
    }
    return vals;
  };
  const [fieldValues, setFieldValues] = useState(function () {
    return initFieldValues(fields);
  });
  const [showRaw, setShowRaw] = useState(false);
  const [params, setParams] = useState(defaultParams === "{}" ? "" : defaultParams);
  const [computed, setComputed] = useState(null);
  const [response, setResponse] = useState(null);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [urlCopied, setUrlCopied] = useState(false);
  const useFieldsMode = fields !== null && fields !== undefined && !showRaw;
  const setFieldValue = (name, value) => setFieldValues(function (prev) {
    return {
      ...prev,
      [name]: value
    };
  });
  const toggleRaw = () => {
    if (fields === null || fields === undefined) return;
    if (!showRaw) {
      const obj = {};
      for (const f of bodyFields) {
        const val = fieldValues[f.name];
        if (val !== "" && val !== null && val !== undefined) {
          obj[f.name] = f.type === "integer" || f.type === "number" ? Number(val) : val;
        }
      }
      setParams(Object.keys(obj).length ? JSON.stringify(obj, null, 2) : "");
      setShowRaw(true);
    } else {
      try {
        const parsed = JSON.parse(params.trim() || "{}");
        const next = {
          ...fieldValues
        };
        for (const f of bodyFields) {
          if (parsed[f.name] !== undefined) next[f.name] = String(parsed[f.name]);
        }
        setFieldValues(next);
      } catch (e) {}
      setShowRaw(false);
    }
  };
  const compute = async () => {
    setError("");
    setComputed(null);
    setResponse(null);
    try {
      if (!apiKey.trim()) throw new Error("API key is required");
      if (!apiSecret.trim()) throw new Error("API secret is required");
      let extraBodyParams = {};
      let queryString = "";
      if (useFieldsMode) {
        const qParams = {};
        for (const f of fields) {
          const val = fieldValues[f.name];
          const empty = val === "" || val === null || val === undefined;
          if (empty) {
            if (f.required) throw new Error('"' + f.name + '" is required');
            continue;
          }
          if (f.paramIn === "query" || f.paramIn === "path") {
            qParams[f.name] = String(val);
          } else {
            if (f.type === "integer" || f.type === "number") {
              const num = Number(val);
              if (isNaN(num)) throw new Error('"' + f.name + '" must be a number');
              extraBodyParams[f.name] = num;
            } else {
              extraBodyParams[f.name] = val;
            }
          }
        }
        if (Object.keys(qParams).length > 0) {
          queryString = "?" + Object.entries(qParams).map(function (kv) {
            return encodeURIComponent(kv[0]) + "=" + encodeURIComponent(kv[1]);
          }).join("&");
        }
      } else if (params.trim()) {
        try {
          extraBodyParams = JSON.parse(params.trim());
        } catch (e) {
          throw new Error("Body params is not valid JSON");
        }
      }
      const bodyObj = {
        request: path,
        nonce: Date.now(),
        nonceWindow: true
      };
      for (const k in extraBodyParams) bodyObj[k] = extraBodyParams[k];
      const bodyStr = JSON.stringify(bodyObj);
      const payload = b64(bodyStr);
      const signature = await hmacSha512Hex(apiSecret.trim(), payload);
      const result = {
        payload,
        signature,
        bodyStr,
        queryString
      };
      setComputed(result);
      return result;
    } catch (e) {
      setError(e && e.message ? e.message : String(e));
      return null;
    }
  };
  const send = async () => {
    setBusy(true);
    setResponse(null);
    try {
      const out = await compute();
      if (!out) return;
      const res = await fetch("/_mintlify/api/request", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          method: "post",
          url: getApiHost() + path + out.queryString,
          header: {
            "content-type": "application/json",
            "X-TXC-APIKEY": apiKey.trim(),
            "X-TXC-PAYLOAD": out.payload,
            "X-TXC-SIGNATURE": out.signature
          },
          body: JSON.parse(out.bodyStr),
          cookie: {},
          query: {}
        })
      });
      const text = await res.text();
      let status = res.status;
      let pretty = text;
      try {
        const json = JSON.parse(text);
        if (json.statusCode !== undefined) {
          status = json.statusCode;
          const raw = typeof json.body === "string" ? json.body : JSON.stringify(json.body);
          try {
            pretty = JSON.stringify(JSON.parse(raw), null, 2);
          } catch (e2) {
            pretty = raw;
          }
        } else {
          pretty = JSON.stringify(json, null, 2);
        }
      } catch (e2) {}
      setResponse({
        status,
        body: pretty
      });
    } catch (e) {
      setError(e && e.message ? e.message : String(e));
    } finally {
      setBusy(false);
    }
  };
  const copy = text => {
    if (navigator && navigator.clipboard) navigator.clipboard.writeText(text);
  };
  const headerRows = useMemo(function () {
    if (!computed) return [];
    return [{
      key: "X-TXC-APIKEY",
      value: apiKey.trim()
    }, {
      key: "X-TXC-PAYLOAD",
      value: computed.payload
    }, {
      key: "X-TXC-SIGNATURE",
      value: computed.signature
    }];
  }, [computed, apiKey]);
  const INPUT_CLS = "w-full rounded-xl border-standard px-3 py-2 text-sm font-mono bg-background-light dark:bg-background-dark outline-none focus:ring-1 focus:ring-[#3064E3]/40 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-white/20";
  const SECTION_CLS = "rounded-2xl border border-zinc-200 dark:border-zinc-800";
  const SECTION_BTN_CLS_OPEN = "flex w-full pt-3.5 pb-3 px-3.5 items-center justify-between cursor-pointer hover:bg-gray-50 dark:hover:bg-white/5 transition-colors rounded-t-2xl";
  const SECTION_BTN_CLS_CLOSED = "flex w-full pt-3.5 pb-3 px-3.5 items-center justify-between cursor-pointer hover:bg-gray-50 dark:hover:bg-white/5 transition-colors rounded-2xl";
  const renderField = function (f) {
    return <div key={f.name}>
        <div className="flex items-center gap-1.5 mb-1 mt-2.5">
          <span className="text-xs font-mono font-medium text-gray-700 dark:text-gray-300">{f.name}</span>
          {f.required ? <span className="text-xs text-red-500 dark:text-red-400">required</span> : <span className="text-xs text-gray-400 dark:text-gray-500">optional</span>}
          <span className="text-xs text-gray-400 dark:text-gray-500 ml-auto">{f.type}{f.enum ? " · enum" : ""}</span>
        </div>
        {f.description && <div className="text-xs text-gray-400 dark:text-gray-500 mb-1">{f.description}</div>}
        {f.enum ? <select className={INPUT_CLS} value={fieldValues[f.name] || ""} onChange={function (e) {
      setFieldValue(f.name, e.target.value);
    }}>
            {!f.required && <option value="">— leave empty —</option>}
            {f.enum.map(function (v) {
      return <option key={v} value={v}>{v}</option>;
    })}
          </select> : <input type={f.type === "integer" || f.type === "number" ? "number" : "text"} className={INPUT_CLS} value={fieldValues[f.name] || ""} onChange={function (e) {
      setFieldValue(f.name, e.target.value);
    }} placeholder={f.example !== undefined ? String(f.example) : f.required ? f.name : "optional"} spellCheck={false} autoComplete="off" />}
      </div>;
  };
  return <div className="not-prose my-6 flex w-full flex-col bg-background-light dark:bg-background-dark border-standard rounded-2xl p-1.5">

      {}
      <div className="flex w-full items-center space-x-1.5 rounded-xl p-1.5 border-standard">

        {}
        <div className="flex items-center gap-1.5 flex-1 min-w-0">
          <span className="rounded-lg font-bold px-1.5 py-0.5 text-xs leading-5 shrink-0 bg-blue-400/20 text-blue-700 dark:text-blue-400">
            POST
          </span>
          <div className="flex items-center flex-1 min-w-0 text-sm font-mono overflow-hidden">
            {}
            <div className="relative shrink-0 flex items-center">
              <select value={baseUrl} onChange={function (e) {
    setBaseUrl(e.target.value);
  }} onClick={function (e) {
    e.stopPropagation();
  }} className="appearance-none bg-transparent outline-none font-mono text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors cursor-pointer pr-4">
                <option value="https://whitebit.com">https://whitebit.com</option>
                <option value="https://whitebit.eu">https://whitebit.eu</option>
              </select>
              <svg className="absolute right-0 top-1/2 -translate-y-1/2 pointer-events-none text-gray-400 dark:text-gray-500" width="10" height="10" viewBox="0 0 10 10" fill="none">
                <path d="M2 3.5L5 6.5L8 3.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
            {}
            <button type="button" title="Copy URL" onClick={function () {
    var url = baseUrl + path;
    if (navigator && navigator.clipboard) navigator.clipboard.writeText(url);
    setUrlCopied(true);
    setTimeout(function () {
      setUrlCopied(false);
    }, 1500);
  }} className="truncate text-left text-black dark:text-white transition-colors">
              {path}
            </button>
          </div>
        </div>

        <div className="flex items-center gap-1.5 shrink-0">
          {}
          <button type="button" title="Copy URL" onClick={function () {
    var url = getApiHost() + path;
    if (navigator && navigator.clipboard) navigator.clipboard.writeText(url);
    setUrlCopied(true);
    setTimeout(function () {
      setUrlCopied(false);
    }, 1500);
  }} className="flex items-center justify-center w-6 h-6 rounded-lg hover:bg-gray-200 dark:hover:bg-white/10 text-gray-400 dark:text-gray-500 transition-colors">
            {urlCopied ? <svg width="13" height="13" viewBox="0 0 13 13" fill="none">
                <path d="M2 7L5 10L11 3" stroke="#2AB673" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
              </svg> : <svg width="13" height="13" viewBox="0 0 13 13" fill="none">
                <rect x="4.5" y="1.5" width="7" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.2" />
                <path d="M2 4.5H1.5A1 1 0 0 0 .5 5.5v6A1 1 0 0 0 1.5 12.5h6A1 1 0 0 0 8.5 11.5V11" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
              </svg>}
          </button>

          {}
          <button type="button" onClick={function () {
    setOpen(function (v) {
      return !v;
    });
  }} className="text-sm font-semibold px-3 py-1.5 rounded-lg bg-[#2AB673] text-white hover:bg-[#239660] active:bg-[#1e7d52] transition-colors hidden sm:inline-flex items-center gap-1.5 cursor-pointer">
            {open ? <>
                Close
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" className="shrink-0">
                  <path d="M2 9L6 5L10 9" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </> : <>
                Try it
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" className="shrink-0">
                  <polygon points="2,1 11,6 2,11" fill="currentColor" />
                </svg>
              </>}
          </button>
        </div>
      </div>

      {}
      {open && <div className="mt-1.5 space-y-1.5">

          {}
          <div className={SECTION_CLS}>
            <button type="button" onClick={function () {
    setAuthOpen(function (v) {
      return !v;
    });
  }} className={authOpen ? SECTION_BTN_CLS_OPEN : SECTION_BTN_CLS_CLOSED}>
              <div className="flex items-center gap-x-1.5">
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" className="text-gray-400 dark:text-gray-500 transition-transform shrink-0" style={{
    transform: authOpen ? "rotate(90deg)" : "rotate(0deg)"
  }}>
                  <path d="M4 2.5L8 6L4 9.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                <span className="text-sm font-medium text-gray-800 dark:text-gray-200 leading-6">Authentication</span>
              </div>
            </button>
            {authOpen && <div className="px-3.5 pb-3.5 pt-0 border-t border-zinc-100 dark:border-zinc-800/60">
                <div className="flex items-center gap-1.5 mb-1 mt-2.5">
                  <span className="text-xs font-mono font-medium text-gray-700 dark:text-gray-300">X-TXC-APIKEY</span>
                  <span className="text-xs text-red-500 dark:text-red-400">required</span>
                  <span className="text-xs text-gray-400 dark:text-gray-500 ml-auto">string</span>
                </div>
                <input className={INPUT_CLS} value={apiKey} onChange={function (e) {
    setApiKey(e.target.value);
  }} placeholder="your-api-key" autoComplete="off" spellCheck={false} />

                <div className="flex items-center gap-1.5 mb-1 mt-2.5">
                  <span className="text-xs font-mono font-medium text-gray-700 dark:text-gray-300">API secret</span>
                  <span className="text-xs text-red-500 dark:text-red-400">required</span>
                  <span className="text-xs text-gray-400 dark:text-gray-500 ml-auto">string</span>
                </div>
                <div className="flex gap-1.5">
                  <input type={showSecret ? "text" : "password"} className={INPUT_CLS + " flex-1"} value={apiSecret} onChange={function (e) {
    setApiSecret(e.target.value);
  }} placeholder="your-api-secret" autoComplete="off" spellCheck={false} />
                  <button type="button" onClick={function () {
    setShowSecret(function (v) {
      return !v;
    });
  }} className="text-xs px-2.5 rounded-xl border-standard bg-background-light dark:bg-background-dark hover:bg-gray-50 dark:hover:bg-white/5 text-gray-500 dark:text-gray-400 shrink-0 transition-colors">
                    {showSecret ? "hide" : "show"}
                  </button>
                </div>
                <p className="text-xs text-gray-400 dark:text-gray-500 mt-1.5">
                  Credentials stay in memory only — never written to localStorage or cookies.
                </p>
              </div>}
          </div>

          {}
          <div className={SECTION_CLS}>
            <button type="button" onClick={function () {
    setParamsOpen(function (v) {
      return !v;
    });
  }} className={paramsOpen ? SECTION_BTN_CLS_OPEN : SECTION_BTN_CLS_CLOSED}>
              <div className="flex items-center gap-x-1.5">
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" className="text-gray-400 dark:text-gray-500 transition-transform shrink-0" style={{
    transform: paramsOpen ? "rotate(90deg)" : "rotate(0deg)"
  }}>
                  <path d="M4 2.5L8 6L4 9.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                <span className="text-sm font-medium text-gray-800 dark:text-gray-200 leading-6">Body</span>
              </div>
              {fields !== null && fields !== undefined && bodyFields.length > 0 && <button type="button" onClick={function (e) {
    e.stopPropagation();
    toggleRaw();
  }} className="text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 underline mr-1">
                  {showRaw ? "form fields" : "edit as JSON"}
                </button>}
            </button>
            {paramsOpen && <div className="px-3.5 pb-3.5 pt-0 border-t border-zinc-100 dark:border-zinc-800/60">
                {queryFields.length > 0 && <div className="mb-1">
                    <p className="text-xs font-medium text-gray-500 dark:text-gray-400 mb-1 mt-2.5">Query parameters</p>
                    {queryFields.map(renderField)}
                  </div>}

                {useFieldsMode ? bodyFields.length > 0 ? <div>
                      {bodyFields.map(renderField)}
                      <p className="text-xs text-gray-400 dark:text-gray-500 mt-2">
                        <code className="font-mono">request</code>, <code className="font-mono">nonce</code>, <code className="font-mono">nonceWindow</code> added automatically.
                      </p>
                    </div> : <p className="text-xs text-gray-400 dark:text-gray-500 mt-2.5">
                      No body parameters required.{" "}
                      <code className="font-mono">request</code>, <code className="font-mono">nonce</code>, <code className="font-mono">nonceWindow</code> added automatically.
                    </p> : <div>
                    <p className="text-xs text-gray-400 dark:text-gray-500 mt-2.5 mb-1.5">
                      <code className="font-mono">request</code>, <code className="font-mono">nonce</code>, <code className="font-mono">nonceWindow</code> added automatically.
                    </p>
                    <textarea className={INPUT_CLS + " min-h-[80px] resize-y"} rows={4} value={params} onChange={function (e) {
    setParams(e.target.value);
  }} placeholder="{ &quot;market&quot;: &quot;BTC_USDT&quot; }" spellCheck={false} />
                  </div>}
              </div>}
          </div>

          {}
          <div className="flex flex-wrap items-center gap-1.5 px-0.5">
            <button type="button" onClick={send} disabled={busy} className="flex items-center justify-center px-3 h-9 text-sm font-medium rounded-xl hover:opacity-80 gap-1.5 transition-opacity disabled:opacity-50 disabled:pointer-events-none bg-[#3064E3] text-white">
              {busy ? <svg className="animate-spin w-4 h-4" viewBox="0 0 24 24" fill="none">
                  <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
                  <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z" />
                </svg> : "Send request"}
            </button>
            <button type="button" onClick={compute} disabled={busy} className="flex items-center justify-center px-3 h-9 text-sm font-medium rounded-xl border-standard hover:bg-gray-50 dark:hover:bg-white/5 transition-colors disabled:opacity-50 disabled:pointer-events-none text-gray-700 dark:text-gray-300 bg-background-light dark:bg-background-dark">
              Compute headers
            </button>
          </div>

          {}
          {error && <div className="px-3.5 py-2.5 rounded-2xl border border-red-200 dark:border-red-900/40 bg-red-50 dark:bg-red-950/20 text-sm text-red-600 dark:text-red-400 break-words">
              {error}
            </div>}

          {}
          {computed && <div className={SECTION_CLS + " overflow-hidden"}>
              <div className="flex items-center justify-between pt-3 pb-2.5 px-3.5 border-b border-zinc-100 dark:border-zinc-800/60">
                <span className="text-sm font-medium text-gray-800 dark:text-gray-200">Computed headers</span>
              </div>
              <div className="px-3.5 pb-3.5">
                {headerRows.map(function (row) {
    return <div key={row.key} className="mt-2.5">
                      <div className="flex items-center justify-between mb-1">
                        <span className="text-xs font-mono text-gray-500 dark:text-gray-400">{row.key}</span>
                        <button type="button" onClick={function () {
      copy(row.value);
    }} className="text-xs px-2 py-0.5 rounded-lg border-standard hover:bg-gray-50 dark:hover:bg-white/5 text-gray-500 dark:text-gray-400 transition-colors">
                          copy
                        </button>
                      </div>
                      <input readOnly value={row.value} className="w-full rounded-xl border-standard px-3 py-2 text-xs font-mono bg-gray-50 dark:bg-white/[0.03] text-gray-500 dark:text-gray-400 outline-none select-all cursor-default" />
                    </div>;
  })}
                <details className="mt-2.5">
                  <summary className="text-xs text-gray-400 dark:text-gray-500 cursor-pointer select-none hover:text-gray-600 dark:hover:text-gray-300 transition-colors">
                    full request body
                  </summary>
                  <pre className="text-xs font-mono whitespace-pre-wrap break-all mt-2 text-gray-600 dark:text-gray-400 m-0">
                    {(function () {
    try {
      return JSON.stringify(JSON.parse(computed.bodyStr), null, 2);
    } catch (e) {
      return computed.bodyStr;
    }
  })()}
                  </pre>
                </details>
                {computed.queryString && <p className="text-xs text-gray-400 dark:text-gray-500 font-mono mt-1">
                    query: {computed.queryString}
                  </p>}
              </div>
            </div>}

          {}
          {response && <div className={SECTION_CLS + " overflow-hidden"}>
              <div className="flex items-center gap-2 pt-3 pb-2.5 px-3.5 border-b border-zinc-100 dark:border-zinc-800/60">
                <span className="text-sm font-medium text-gray-800 dark:text-gray-200">Response</span>
                <span className={"text-xs font-mono font-medium px-1.5 py-0.5 rounded-lg " + (response.status < 400 ? "bg-[#2AB673]/10 text-[#2AB673]" : "bg-red-100/50 dark:bg-red-400/10 text-red-600 dark:text-red-300")}>
                  {response.status}
                </span>
              </div>
              <pre className="text-xs font-mono whitespace-pre-wrap overflow-auto max-h-80 m-0 px-3.5 py-3 text-gray-700 dark:text-gray-300">
                {response.body}
              </pre>
            </div>}

        </div>}

    </div>;
};

<WhitebitSigner path="/api/v4/main-account/withdraw" fields={signerFields} />

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

<Warning>
  **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).
</Warning>

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

<Warning>
  The legacy flat format (`type`, `vasp`, `name`, `address`) is still accepted but will **not pass Travel Rule verification**. Use the new structured format.
</Warning>

For detailed requirements, field mapping, and request examples, see [Travel Rule](/concepts/travel-rule#withdrawal-examples).

### 🔹 Fiat Withdrawals (KYC Required)

<Note>
  All fiat withdrawals require KYC verification. Ensure the account is verified before attempting fiat withdrawals.
</Note>

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

<Tip>
  The `amount` field in the request **includes** the withdrawal fee. The recipient receives `amount - fee`.
</Tip>

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

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

Check current fees via [Get Fees endpoint](/api-reference/account-wallet/get-fees) before creating withdrawals.

***

## Common Pitfalls & Best Practices

### ⚠️ Unique ID Management

<Warning>
  **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."]
    }
  }
  ```
</Warning>

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

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

<Warning>
  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).
</Warning>

### ⚠️ 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)

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

***

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

<Tip>
  **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.
</Tip>

***

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

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

<Tip>
  **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)
</Tip>

***

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


## OpenAPI

````yaml openapi/private/main_api_v4.yaml POST /api/v4/main-account/withdraw
openapi: 3.0.3
info:
  title: WhiteBIT Private HTTP API V4
  description: |
    WhiteBIT Private HTTP API V4 for Main balance changes.

    Base URL: https://whitebit.com

    All endpoints return time in Unix-time format.
    All endpoints return either a JSON object or array.
    For receiving responses from API calls please use http method POST.
  version: 4.0.0
  contact:
    name: WhiteBIT Support
    email: support@whitebit.com
    url: https://whitebit.com
servers:
  - url: https://whitebit.com
    description: WhiteBIT Global Server
  - url: https://whitebit.eu
    description: WhiteBIT EU Server
  - url: https://whitebit.tr
    description: WhiteBIT TR Server
  - url: https://whitebit.ge
    description: WhiteBIT GE Server
security:
  - ApiKeyAuth: []
    PayloadAuth: []
    SignatureAuth: []
tags:
  - name: Main Account
    description: Main account balance and operations
  - name: Deposit
    description: Cryptocurrency and fiat deposit operations
  - name: Withdraw
    description: Cryptocurrency and fiat withdrawal operations
  - name: Transfer
    description: Balance transfer operations
  - name: Codes
    description: WhiteBIT codes operations
  - name: Crypto Lending - Fixed
    description: Fixed crypto lending plans
  - name: Crypto Lending - Flex
    description: Flexible crypto lending plans
  - name: Fees
    description: Fee information
  - name: Sub-Account
    description: Sub-account management
  - name: Sub-Account API Keys
    description: Sub-account API key management
  - name: Mining Pool
    description: Mining pool operations
  - name: Credit Line
    description: Credit line information
  - name: JWT
    description: JWT token management
  - name: Travel Rule
    description: Travel Rule compliance endpoints for deposits and withdrawals
paths:
  /api/v4/main-account/withdraw:
    post:
      tags:
        - Withdraw
      summary: Create withdraw request
      description: >
        The endpoint creates withdraw for the specified ticker.


        <Note>

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

        </Note>


        <Warning>

        Rate limit: 1000 requests/10 sec.

        </Warning>


        <Note>

        The API does not cache the response.

        </Note>


        <Note>

        Also, fiat currencies can't be withdrawn without KYC verification.

        </Note>
      operationId: createWithdraw
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - ticker
                - amount
                - address
                - uniqueId
                - request
                - nonce
              properties:
                ticker:
                  type: string
                  description: >
                    Currency's [ticker](/glossary#ticker). Example: BTC


                    ⚠️ Currencies ticker must have "can_deposit" status equal to
                    "true". Use [Asset Status
                    endpoint](/public/http-v4/asset-status-list) to know more
                    about currency.
                  example: ETH
                amount:
                  type: string
                  description: >
                    Withdraw amount (including [fee](/glossary#fee)). To add the
                    fee to the specified amount, use the
                    /main-account/withdraw-pay request.
                  example: '0.9'
                address:
                  type: string
                  description: >-
                    Target address (wallet address for cryptocurrencies,
                    identifier/[card token](/glossary#card-token) for
                    [fiat](/glossary#fiat) currencies)
                  example: '0x0964A6B8F794A4B8d61b62652dB27ddC9844FB4c'
                memo:
                  type: string
                  description: |
                    [Memo](/glossary#memodestination-tag).

                    ⚠️ Required if currency is memoable.
                  example: '48565488244493'
                uniqueId:
                  type: string
                  description: >
                    Unique transaction identifier. Any string up to 255
                    characters; not validated as a UUID.


                    ⚠️ Generate a new unique ID for each withdrawal request.
                  example: '24529041'
                provider:
                  type: string
                  description: >
                    [Fiat](/glossary#fiat) currency
                    [provider](/glossary#provider). Example: VISAMASTER


                    ⚠️ Required for fiat currencies. Currency provider should be
                    taken from [Asset Status
                    endpoint](/public/http-v4/asset-status-list) response.
                  example: VISAMASTER
                network:
                  type: string
                  description: >
                    Cryptocurrency network. Available for multi network
                    currencies. Example: OMNI


                    ⚠️ Currency network should be taken from [Asset Status
                    endpoint](/public/http-v4/asset-status-list) response.
                    Default for USDT is ERC20
                  example: ERC20
                partialEnable:
                  type: boolean
                  description: >-
                    Optional parameter for [FIAT](/glossary#fiat) withdrawals
                    with increased Maximum Limit if set as "true". To use this
                    parameter, the application must support "Partially
                    successful" withdrawal status and latest updates in
                    deposit/withdrawal history.
                  example: false
                customerIp:
                  type: string
                  description: >
                    End-customer IP address forwarded to the
                    [fiat](/glossary#fiat) [provider](/glossary#provider) for
                    antifraud checks before the withdrawal is processed.


                    ⚠️ Required if currency [ticker](/glossary#ticker) is USD or
                    EUR with VISAMASTER [provider](/glossary#provider).
                  example: 203.0.113.42
                bankBic:
                  type: string
                  description: >
                    Beneficiary bank's BIC (SWIFT) code, identifying the
                    destination bank for SEPA and other bank-rail
                    [fiat](/glossary#fiat) withdrawals.


                    ⚠️ Required if the fiat [provider](/glossary#provider) is
                    one of: SEPA, SEPA_CLEAR_JUNCTION, SEPA_BCB_GROUP, FINCI,
                    ZEN, BANKING_CIRCLE.
                  example: DEUTDEFF
                beneficiary:
                  type: object
                  description: >
                    Beneficiary information.


                    ⚠️ Required if currency [ticker](/glossary#ticker) is one
                    of: USD_VISAMASTER, EUR_VISAMASTER, USD, EUR.


                    Per-field requirements vary by currency and provider.
                    Card-related fields (`cardToken`, `card.*`, `cardTokenSave`,
                    `fingerprintSession`) apply only to card-acquiring rails;
                    bank-related fields (`bank.*`) apply to bank-rail
                    withdrawals; `phone`, `email`, and `birthDate` are required
                    for VISAMASTER/Mercuryo rails. See `/asset-status-list` for
                    the active provider per currency.
                  properties:
                    firstName:
                      type: string
                      description: >
                        Beneficiary first name. Max length: 40 symbols, latin
                        letters and special characters.


                        ⚠️ Required if currency [ticker](/glossary#ticker) is
                        one of: USD_VISAMASTER, USD, EUR
                      example: Firstname
                    lastName:
                      type: string
                      description: >
                        Beneficiary last name. Max length: 40 symbols, latin
                        letters and special characters.


                        ⚠️ Required if currency [ticker](/glossary#ticker) is
                        one of: USD_VISAMASTER, USD, EUR
                      example: Lastname
                    phone:
                      type: string
                      description: >
                        Beneficiary phone number.


                        ⚠️ Required if currency [ticker](/glossary#ticker) is
                        one of: USD_VISAMASTER, EUR_VISAMASTER
                      example: '1234567891'
                    email:
                      type: string
                      description: >
                        Beneficiary email.


                        ⚠️ Required if currency [ticker](/glossary#ticker) is
                        one of: USD_VISAMASTER, EUR_VISAMASTER
                      example: john_doe@email.com
                    birthDate:
                      type: string
                      format: date
                      description: >
                        Beneficiary birth date. Format: YYYY-MM-DD.


                        ⚠️ Required if currency [ticker](/glossary#ticker) is
                        one of: USD_VISAMASTER, EUR_VISAMASTER, or when
                        withdrawing through Mercuryo.
                      example: '1990-01-01'
                    code:
                      type: string
                      description: >
                        Beneficiary verification code returned by a prior
                        verification step. Used by some card-acquiring flows
                        that require a one-time verification challenge before
                        settlement.
                      example: '123456'
                    cardToken:
                      type: string
                      description: >
                        Tokenized payment-card identifier for card-acquiring
                        rails. Use instead of raw PAN; obtain from the
                        card-tokenisation endpoint or from a prior successful
                        settlement on the same card.
                      example: tok_4f7c8e2a
                    cardTokenSave:
                      type: boolean
                      description: >
                        If `true`, request the acquiring provider to persist the
                        card token for reuse on subsequent withdrawals to the
                        same beneficiary.
                      example: false
                    fingerprintSession:
                      type: string
                      description: >
                        Anti-fraud device-fingerprint session identifier
                        captured at the partner's checkout surface and forwarded
                        to the acquiring provider. Required by some VISAMASTER
                        configurations.
                      example: fps_abc123
                    card:
                      type: object
                      description: >
                        Card details for card-acquiring rails. Use `cardToken`
                        instead when available; raw card details apply only when
                        a fresh card is being added.
                      properties:
                        save:
                          type: boolean
                          description: >-
                            If `true`, persist the card for reuse on subsequent
                            withdrawals.
                          example: false
                        name:
                          type: string
                          description: Cardholder name as embossed on the card.
                          example: John Doe
                        firstName:
                          type: string
                          description: Cardholder first name.
                          example: John
                        lastName:
                          type: string
                          description: Cardholder last name.
                          example: Doe
                        number:
                          type: string
                          description: >-
                            Primary Account Number (PAN). Treat as PCI-scope
                            sensitive data on the partner side.
                          example: '4111111111111111'
                        month:
                          type: string
                          description: Card expiry month as a two-digit string (`01`-`12`).
                          example: '12'
                        year:
                          type: string
                          description: Card expiry year as a four-digit string.
                          example: '2030'
                    address:
                      type: object
                      description: >
                        Beneficiary postal address. Required for several
                        VISAMASTER/SEPA configurations.
                      properties:
                        line1:
                          type: string
                          description: Street address line 1.
                          example: Martinez Campos 37
                        line2:
                          type: string
                          description: Street address line 2.
                          example: ''
                        city:
                          type: string
                          description: City.
                          example: Madrid
                        zip:
                          type: string
                          description: Postal / ZIP code.
                          example: '28010'
                        country:
                          type: string
                          description: ISO country code.
                          example: ES
                    bank:
                      type: object
                      description: >
                        Beneficiary bank details for bank-rail withdrawals (used
                        when the destination is an account number rather than an
                        IBAN).
                      properties:
                        routingNumber:
                          type: string
                          description: >-
                            Bank routing number (ABA, BSB, sort code, or
                            equivalent for the destination country).
                          example: '021000021'
                        name:
                          type: string
                          description: Bank name.
                          example: Example Bank
                        address:
                          type: string
                          description: Bank postal address.
                          example: 1 Bank Street, London
                        country:
                          type: string
                          description: Bank country (ISO code).
                          example: GB
                travelRule:
                  type: object
                  description: >
                    Travel Rule information for regulatory compliance.


                    ⚠️ Required if currency is crypto and the account is from
                    [EEA](/glossary#european-economic-area-eea)


                    See [Travel Rule
                    Overview](/api-reference/travel-rule/overview) for complete
                    documentation.


                    **Legacy format:** The API still accepts the old flat format
                    (`type`, `vasp`, `name`, `address` fields), but this format
                    will not pass Travel Rule verification. To complete Travel
                    Rule compliance, use the new structured format with
                    `walletType`, `beneficiary`, and `vasp` objects.
                  properties:
                    walletType:
                      type: string
                      enum:
                        - hosted
                        - unhosted
                      description: >
                        Destination wallet type:

                        - `hosted` - VASP-hosted wallet (exchange, custodian).
                        Requires `vasp` object.

                        - `unhosted` - Self-custody wallet (hardware, software).
                        No `vasp` required.
                      example: hosted
                    beneficiary:
                      type: object
                      description: Beneficiary information.
                      properties:
                        type:
                          type: string
                          enum:
                            - individual
                            - entity
                          description: >
                            Beneficiary type:

                            - `individual` - Natural person. Requires
                            `firstName`, `lastName`.

                            - `entity` - Legal entity. Requires `fullName`.
                          example: individual
                        firstName:
                          type: string
                          description: First name. Required if `type` is `individual`.
                          example: John
                        lastName:
                          type: string
                          description: Last name. Required if `type` is `individual`.
                          example: Doe
                        fullName:
                          type: string
                          description: Full legal name. Required if `type` is `entity`.
                          example: Acme Trading Ltd
                        residenceCountry:
                          type: string
                          description: >-
                            Beneficiary's country of residence. ISO 3166-1
                            alpha-3 code (3 letters).
                          example: DEU
                        address:
                          type: object
                          description: Physical address.
                          properties:
                            country:
                              type: string
                              description: ISO 3166-1 alpha-3 country code.
                              example: DEU
                            city:
                              type: string
                              description: City name.
                              example: Berlin
                            postCode:
                              type: string
                              description: Postal code.
                              example: '10178'
                            addressLine1:
                              type: string
                              description: Street address.
                              example: Alexanderplatz 1
                    vaspData:
                      type: object
                      description: >
                        VASP (Virtual Asset Service Provider) information.
                        Required if `walletType` is `hosted`.


                        Use `vaspId` if the destination VASP is in the list from
                        [Get VASPs](/api-reference/travel-rule/get-vasps),
                        otherwise use `vaspName`.
                      properties:
                        vaspId:
                          type: string
                          description: >-
                            VASP ID from the [Get
                            VASPs](/api-reference/travel-rule/get-vasps)
                            endpoint. Use this if the VASP is in the list.
                          example: vasp-001
                        vaspName:
                          type: string
                          description: >-
                            VASP name as a string. Use this if the VASP is not
                            in the list.
                          example: Famous Vasp Inc
                paymentDescription:
                  type: string
                  description: >
                    Description of withdrawal destination


                    ⚠️ Required if currency is crypto and withdrawal from
                    whitebit-tr.com
                  example: Payment description
                request:
                  type: string
                  description: Request signature
                  example: '{{request}}'
                nonce:
                  type: integer
                  description: Unique request identifier
                  example: 1594297865000
            examples:
              crypto:
                summary: Crypto withdrawal
                value:
                  ticker: ETH
                  amount: '0.9'
                  address: '0x0964A6B8F794A4B8d61b62652dB27ddC9844FB4c'
                  uniqueId: '24529041'
                  request: '{{request}}'
                  nonce: 1594297865000
              multiNetwork:
                summary: Multinetwork currency (USDT)
                value:
                  ticker: USDT
                  amount: '0.9'
                  address: '0x0964A6B8F794A4B8d61b62652dB27ddC9844FB4c'
                  uniqueId: '24529042'
                  network: ERC20
                  request: '{{request}}'
                  nonce: 1594297865000
              fiatUsdVisamaster:
                summary: Fiat USD/EUR with VISAMASTER (customerIp required)
                value:
                  ticker: USD
                  amount: '150.00'
                  address: t6XIpyirkiLP+I++XHWfSeGrn5p38g==
                  provider: VISAMASTER
                  uniqueId: ab12cd34-9101-4abc-9def-1234567890ab
                  customerIp: 203.0.113.42
                  request: '{{request}}'
                  nonce: 1594297865000
              fiatIban:
                summary: Fiat IBAN transfer (EUR)
                value:
                  ticker: EUR
                  amount: '500'
                  address: DE89370400440532013000
                  beneficiary:
                    firstName: Firstname
                    lastName: Lastname
                  provider: SEPA_BCB_GROUP
                  uniqueId: '24529046'
                  request: '{{request}}'
                  nonce: 1594297865000
              fiatVisamaster:
                summary: Fiat USD/EUR VISAMASTER
                value:
                  ticker: USD
                  amount: '30000'
                  address: t6XIpyirkiLP+I++XHWfSeGrn5p38g==
                  beneficiary:
                    firstName: Firstname
                    lastName: Lastname
                    phone: '1234567891'
                    email: john_doe@email.com
                  provider: USD_VISAMASTER
                  uniqueId: '24529045'
                  request: '{{request}}'
                  nonce: 1594297865000
              fiatSepa:
                summary: Fiat SEPA / bank-rail (bankBic required)
                value:
                  ticker: EUR
                  amount: '100'
                  address: DE89370400440532013000
                  provider: SEPA
                  bankBic: DEUTDEFF
                  beneficiary:
                    firstName: Firstname
                    lastName: Lastname
                  uniqueId: '24529046'
                  request: '{{request}}'
                  nonce: 1594297865000
              travelRuleIndividualHosted:
                summary: Travel rule - individual to hosted wallet
                value:
                  ticker: BTC
                  amount: '0.5'
                  address: bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh
                  uniqueId: '24529048'
                  travelRule:
                    walletType: hosted
                    beneficiary:
                      type: individual
                      firstName: John
                      lastName: Doe
                      residenceCountry: DEU
                      address:
                        country: DEU
                        city: Berlin
                        addressLine1: Alexanderplatz 1
                    vaspData:
                      vaspId: vasp-001
                  request: '{{request}}'
                  nonce: 1594297865000
              travelRuleEntityHosted:
                summary: Travel rule - entity to hosted wallet
                value:
                  ticker: USDT
                  amount: '10000'
                  address: '0x742d35Cc6634C0532925a3b844Bc9e7595f8a2B1'
                  network: ERC20
                  uniqueId: '24529049'
                  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
                  request: '{{request}}'
                  nonce: 1594297865000
              travelRuleIndividualUnhosted:
                summary: Travel rule - individual to unhosted wallet
                value:
                  ticker: ETH
                  amount: '2.5'
                  address: '0xabcdef1234567890abcdef1234567890abcdef12'
                  uniqueId: '24529050'
                  travelRule:
                    walletType: unhosted
                    beneficiary:
                      type: individual
                      firstName: Jane
                      lastName: Smith
                      residenceCountry: NLD
                      address:
                        country: NLD
                        city: Amsterdam
                        addressLine1: Damrak 1
                  request: '{{request}}'
                  nonce: 1594297865000
              travelRuleLegacyIndividual:
                summary: Travel rule - legacy format (won't pass verification)
                value:
                  ticker: BTC
                  amount: '0.5'
                  address: bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh
                  uniqueId: '24529051'
                  travelRule:
                    type: individual
                    vasp: Binance
                    name: John
                    address: Doe
                  request: '{{request}}'
                  nonce: 1594297865000
              travelRuleLegacyEntity:
                summary: Travel rule - legacy format entity (won't pass verification)
                value:
                  ticker: BTC
                  amount: '1.0'
                  address: bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh
                  uniqueId: '24529052'
                  travelRule:
                    type: entity
                    vasp: Kraken
                    name: Acme Corp
                    address: 123 Business Street, London, UK
                  request: '{{request}}'
                  nonce: 1594297865000
      responses:
        '201':
          description: >-
            Validation succeeded and withdraw creation process is started. Check
            the request status by uniqueId in deposit/withdraw history.
          content:
            application/json:
              schema:
                type: array
                items: {}
                description: Empty array indicates success
              example: []
        '400':
          description: >
            Request validation failed. Request-shape errors always carry `code:
            0`; the

            business-rule codes 1–9 are returned with HTTP 422 (see below), not
            400.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missingFields:
                  summary: Missing required fields
                  value:
                    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.
                duplicateUniqueId:
                  summary: Duplicate uniqueId
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      uniqueId:
                        - The unique id has already been taken.
                unconfirmedUser:
                  summary: Unconfirmed user (without KYC)
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      amount:
                        - >-
                          This currency has no active pairs or it may have been
                          delisted. Its rate cannot be calculated at the moment.
                        - Current limit exceeded
                accountVerification:
                  summary: Account must be verified for fiat currencies
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      amount:
                        - Your account must be verified
                invalidTicker:
                  summary: Invalid ticker
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      ticker:
                        - The selected ticker is invalid.
                providerRequired:
                  summary: Provider required for fiat currency
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      provider:
                        - Provider is required for fiat currency
                memoRequired:
                  summary: Memo required for memoable currency
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      memo:
                        - The memo field is required.
                invalidPartialEnable:
                  summary: Invalid partialEnable value
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      partialEnable:
                        - The partial enable field must be true or false.
                throttling:
                  summary: Rate limiting/throttling
                  value:
                    message: Too Many Attempts.
                    code: 0
        '401':
          description: >
            The API key is not authorized for this endpoint. Occurs with a
            [sub-account](/glossary#sub-account)

            key whose `/api/v4/main-account/withdraw` URL is still `enable:
            false`. Enable it with

            [Edit Sub-Account API
            Key](/api-reference/sub-accounts/edit-sub-account-api-key), then
            retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: 4
                message: This API Key is not authorized to perform this action.
        '412':
          description: >
            Two-Factor Authentication (2FA) is required for this action but is
            not enabled on

            the account. Enable 2FA in account security settings, then retry.
            The HTTP 412

            status distinguishes this precondition failure from the
            business-rule codes at 422.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorInner'
              example:
                code: 1
                message: >-
                  This action is unauthorized. Please, enable Two-Factor
                  authentication.
        '422':
          description: >
            Inner validation failed.


            Business-rule codes (returned with HTTP 422):

            - 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](/glossary#fee)

            - 7 - amount should be integer (can happen for currencies with zero
            [precision](/glossary#precision) like Neo)

            - 8 - target withdraw amount without [fee](/glossary#fee) equals
            zero

            - 9 - address is unavailable (occurs for withdraws to own address)

            - 20 - the amount is not withdrawable yet because deposits credited
            before full network confirmation are still held back; see
            [Withdrawable
            balance](/api-reference/account-wallet/withdrawable-balance)


            Additional account-state outcomes are also returned here with `code:
            0`

            (the message is localized, so match on the condition rather than the
            exact string):

            - **Daily / monthly withdrawal limit reached** — on field `amount`.

            - **Withdrawals temporarily restricted** — after a security event
            (e.g. password
              change); on field `error`, e.g. `Withdrawals restricted until {time}`.
            - **Address blocked by compliance** — the request is accepted but
            the withdrawal
              transitions to an `AML_FROZEN` state (no distinct error body); check the request
              status by `uniqueId` in deposit/withdraw history.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorInner'
              examples:
                invalidAddress:
                  summary: Invalid address
                  value:
                    code: 2
                    message: Inner validation failed
                    errors:
                      address:
                        - The address is invalid
                pendingDeposit:
                  summary: Amount still held back by an unconfirmed deposit
                  value:
                    code: 20
                    message: Inner validation failed
                    errors:
                      amount:
                        - >-
                          Insufficient available balance. Recent deposits are
                          awaiting final network confirmation.
                notEnoughBalance:
                  summary: Not enough balance
                  value:
                    code: 5
                    message: Inner validation failed
                    errors:
                      amount:
                        - Not enough money, Ethereum balance = 1
components:
  schemas:
    Error:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    ErrorInner:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-TXC-APIKEY
      description: The public WhiteBIT API key.
    PayloadAuth:
      type: apiKey
      in: header
      name: X-TXC-PAYLOAD
      description: Base64-encoded JSON request body.
    SignatureAuth:
      type: apiKey
      in: header
      name: X-TXC-SIGNATURE
      description: >-
        HMAC-SHA512 signature of the payload, hex-encoded. Computed as
        hex(HMAC-SHA512(payload, api_secret)).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.