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

# Refund deposit

> Refund a deposit.

The system processes refunds only for deposits with status `canceled`.

Obtain `transactionId` from the `deposit.canceled` webhook (`uniqueId`) or from the deposit/withdraw history in the WhiteBIT interface after support confirms refund availability.

The refund address must support the same network and asset as the original deposit. The refund address must not be a WhiteBIT address. The refund address can differ from the original deposit sender address.

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

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

<Note>
Refund processing does not complete instantly. Use the [refund.successful](/platform/webhook#whitebit-refund-successful) and [refund.failed](/platform/webhook#whitebit-refund-failed) webhooks to receive refund status updates, or check the current status with [Get refund history](/api-reference/account-wallet/get-refund-history).
</Note>


export const signerFields = [{
  "name": "transactionId",
  "type": "string",
  "required": true,
  "description": "Transaction UUID of the deposit. Obtain from the deposit.canceled webhook (uniqueId field) or from the deposit/withdraw history in the WhiteBIT interface.",
  "example": "54bffeb7-7a8f-43f8-bcd8-f14ec10fee85"
}, {
  "name": "address",
  "type": "string",
  "required": true,
  "description": "Destination wallet address for the refund. The address must support the same network and asset as the original deposit. Cannot be a WhiteBIT address. Does not have to match the …",
  "example": "0x1234567890abcdef1234567890abcdef12345678"
}, {
  "name": "memo",
  "type": "string",
  "required": false,
  "description": "Destination memo for the refund address. Optional — without it, the refund goes to the address with no memo. For a currency that uses memos, the system validates the value; an i…",
  "example": "1234567890"
}];

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/refund-deposit" fields={signerFields} />

## 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/refund-deposit
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/refund-deposit:
    post:
      tags:
        - Deposit
      summary: Refund a deposit
      description: >
        Refund a deposit.


        The system processes refunds only for deposits with status `canceled`.


        Obtain `transactionId` from the `deposit.canceled` webhook (`uniqueId`)
        or from the deposit/withdraw history in the WhiteBIT interface after
        support confirms refund availability.


        The refund address must support the same network and asset as the
        original deposit. The refund address must not be a WhiteBIT address. The
        refund address can differ from the original deposit sender address.


        <Warning>

        Rate limit: 1000 requests/10 sec.

        </Warning>


        <Note>

        The API does not cache the response.

        </Note>


        <Note>

        Refund processing does not complete instantly. Use the
        [refund.successful](/platform/webhook#whitebit-refund-successful) and
        [refund.failed](/platform/webhook#whitebit-refund-failed) webhooks to
        receive refund status updates, or check the current status with [Get
        refund history](/api-reference/account-wallet/get-refund-history).

        </Note>
      operationId: refundDeposit
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - transactionId
                - address
                - request
                - nonce
              properties:
                transactionId:
                  type: string
                  format: uuid
                  description: >
                    Transaction UUID of the deposit. Obtain from the
                    [deposit.canceled](/platform/webhook) webhook (`uniqueId`
                    field) or from the deposit/withdraw history in the WhiteBIT
                    interface.
                  example: 54bffeb7-7a8f-43f8-bcd8-f14ec10fee85
                address:
                  type: string
                  description: >
                    Destination wallet address for the refund. The address must
                    support the same network and asset as the original deposit.
                    Cannot be a WhiteBIT address. Does not have to match the
                    original deposit address.
                  example: '0x1234567890abcdef1234567890abcdef12345678'
                memo:
                  type: string
                  maxLength: 255
                  description: >
                    Destination [memo](/glossary#memodestination-tag) for the
                    refund address. Optional — without it, the refund goes to
                    the address with no memo.


                    For a currency that uses memos, the system validates the
                    value; an invalid memo fails the request with a validation
                    error. For other currencies, the value is not validated. It
                    is stored on the refund and returned in the [refund
                    history](/api-reference/account-wallet/get-refund-history)
                    and in the refund webhooks.
                  example: '1234567890'
                request:
                  type: string
                  description: >
                    Base64-encoded request body. See the [authentication
                    guide](/private/http-auth) for signature generation details.
                  example: '{{request}}'
                nonce:
                  type: integer
                  description: >
                    A unique identifier for the request. Use a monotonically
                    increasing value such as a Unix timestamp in milliseconds.
                  example: 1594297865000
            example:
              transactionId: 54bffeb7-7a8f-43f8-bcd8-f14ec10fee85
              address: '0x1234567890abcdef1234567890abcdef12345678'
              request: '{{request}}'
              nonce: 1594297865000
      responses:
        '200':
          description: System accepts refund request
          content:
            application/json:
              schema:
                type: object
                required:
                  - id
                properties:
                  id:
                    type: string
                    format: uuid
                    description: >-
                      Transaction UUID of the deposit, echoed from the request.
                      This is not a refund identifier — the refund's own
                      `refundId` is returned by [Get refund
                      history](/api-reference/account-wallet/get-refund-history).
                example:
                  id: 54bffeb7-7a8f-43f8-bcd8-f14ec10fee85
        '400':
          description: Validation fails or transaction does not qualify for refund
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                notRefundable:
                  summary: Transaction not refundable
                  value:
                    code: 0
                    message: Transaction not refundable
                validationFailed:
                  summary: Required fields missing
                  value:
                    code: 0
                    message: Validation failed
                    errors:
                      transactionId:
                        - The transaction id field is required.
                      address:
                        - The address field is required.
components:
  schemas:
    Error:
      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.