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

# Authorize

> Authorize a WebSocket connection to subscribe to private account data streams on WhiteBIT.

export const exAuthorizeResponse = {
  "id": 0,
  "result": {
    "status": "success"
  },
  "error": null
};

export const exAuthorizeRequest = {
  "id": 0,
  "method": "authorize",
  "params": ["<WEB_SOCKET_TOKEN>", "public"]
};

export const authorizeRequestParamsTupleFields = [{
  index: 0,
  field: "token",
  type: "string",
  description: "WebSocket Token (get via `/api/v4/profile/websocket_token` endpoint)",
  required: true,
  example: "<WEB_SOCKET_TOKEN>"
}, {
  index: 1,
  field: "scope",
  type: "string",
  description: "Constant string, always should be \"public\"",
  required: true,
  example: "public",
  enum: ["public"]
}];

export const channelMeta = {
  "authRequired": true,
  "rateLimits": {
    "connectionsPerMinute": 1000,
    "requestsPerMinute": 200
  },
  "errorCodes": "standard"
};

export const channelOperations = [{
  name: "Authorize",
  send: "authorize",
  receive: "Confirmation (status: success)",
  push: null
}];

export const WsErrorCodes = ({errorCodes}) => {
  if (Array.isArray(errorCodes)) {
    return <div>
        <table>
          <thead>
            <tr>
              <th>Code</th>
              <th>Message</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            {errorCodes.map((err, i) => <tr key={i}>
                <td><code>{err.code}</code></td>
                <td>{err.message}</td>
                <td>{err.description}</td>
              </tr>)}
          </tbody>
        </table>
        <p>
          Standard WebSocket error codes apply. See <a href="/websocket/overview">WebSocket overview</a> for error code reference.
        </p>
      </div>;
  }
  return <p>
      Standard WebSocket error codes apply. See <a href="/websocket/overview">WebSocket overview</a> for error code reference.
    </p>;
};

export const WsRateLimits = ({connectionsPerMinute, requestsPerMinute}) => {
  return <p>
      Standard connection-level rate limits apply. See{' '}
      <a href="/websocket/rate-limits">WebSocket Rate Limits</a> for details.
    </p>;
};

export const WsTupleTable = ({title, fields}) => {
  const [isDark, setIsDark] = useState(typeof document !== 'undefined' ? document.documentElement.classList.contains('dark') : true);
  useEffect(() => {
    const check = () => setIsDark(document.documentElement.classList.contains('dark'));
    check();
    const observer = new MutationObserver(check);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
    return () => observer.disconnect();
  }, []);
  const T = isDark ? {
    border: '#374151',
    borderSubtle: '#1f2937',
    headerBg: '#1f2937',
    headerText: '#9ca3af',
    titleBg: '#1f2937',
    titleText: '#d1d5db',
    indexText: '#60a5fa',
    fieldText: '#e5e7eb',
    fieldBg: '#374151',
    descText: '#9ca3af',
    exampleText: '#d1d5db',
    exampleBg: 'rgb(55 65 81 / 0.4)',
    enumText: '#fbbf24',
    reqYes: '#f3f4f6',
    reqNo: '#4b5563'
  } : {
    border: '#e5e7eb',
    borderSubtle: '#f3f4f6',
    headerBg: '#f9fafb',
    headerText: '#6b7280',
    titleBg: '#f9fafb',
    titleText: '#374151',
    indexText: '#2563eb',
    fieldText: '#1f2937',
    fieldBg: '#f3f4f6',
    descText: '#6b7280',
    exampleText: '#374151',
    exampleBg: '#f3f4f6',
    enumText: '#92400e',
    reqYes: '#111827',
    reqNo: '#d1d5db'
  };
  const MONO = 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace';
  const HEADER = {
    padding: '0.5rem 0.75rem',
    fontSize: '0.6875rem',
    fontWeight: 600,
    textTransform: 'uppercase',
    letterSpacing: '0.05em',
    whiteSpace: 'nowrap',
    color: T.headerText,
    backgroundColor: T.headerBg
  };
  const CELL = {
    padding: '0.5rem 0.75rem',
    fontSize: '0.8125rem',
    display: 'flex',
    alignItems: 'center',
    minWidth: 0
  };
  const hasExample = fields.some(f => f.example !== undefined);
  const hasRequired = fields.some(f => f.required === true);
  const gridTemplateColumns = ['minmax(60px, auto)', 'minmax(100px, auto)', ...hasRequired ? ['minmax(70px, auto)'] : [], ...hasExample ? ['minmax(140px, auto)'] : [], '1fr'].join(' ');
  function formatDesc(f) {
    if (f.enumLabels && typeof f.enumLabels === 'object') {
      const mapping = Object.entries(f.enumLabels).map(([v, label]) => `${v} = ${label}`).join(', ');
      return f.description ? `${f.description}. ${mapping}` : mapping;
    }
    if (f.enum && f.enum.length > 0 && f.description) {
      const hasMapping = f.enum.some(v => f.description.includes(`${v}=`) || f.description.includes(`${v} =`));
      if (hasMapping) return f.description;
    }
    return f.description || '';
  }
  return <div style={{
    width: '100%',
    margin: '0.75rem 0',
    borderRadius: '0.5rem',
    border: `1px solid ${T.border}`,
    overflow: 'hidden',
    fontSize: '0.8125rem'
  }}>
      {title && <div style={{
    padding: '0.5rem 0.75rem',
    fontSize: '0.75rem',
    fontWeight: 600,
    letterSpacing: '0.02em',
    backgroundColor: T.titleBg,
    borderBottom: `1px solid ${T.border}`,
    color: T.titleText
  }}>
          {title}
        </div>}
      <div style={{
    display: 'grid',
    gridTemplateColumns,
    width: '100%',
    overflowX: 'auto'
  }}>

        <div style={{
    ...HEADER,
    borderBottom: `1px solid ${T.border}`
  }}>Index</div>
        <div style={{
    ...HEADER,
    borderBottom: `1px solid ${T.border}`
  }}>Field</div>
        {hasRequired && <div style={{
    ...HEADER,
    borderBottom: `1px solid ${T.border}`
  }}>Required</div>}
        {hasExample && <div style={{
    ...HEADER,
    borderBottom: `1px solid ${T.border}`
  }}>Example</div>}
        <div style={{
    ...HEADER,
    borderBottom: `1px solid ${T.border}`
  }}>Description</div>

        {fields.map((f, i) => {
    const borderTop = i > 0 ? `1px solid ${T.borderSubtle}` : undefined;
    const desc = formatDesc(f);
    return [<div key={`${i}-i`} style={{
      ...CELL,
      whiteSpace: 'nowrap',
      borderTop
    }}>
              <code style={{
      fontFamily: MONO,
      fontSize: '0.75rem',
      color: T.indexText
    }}>[{f.index}]</code>
            </div>, <div key={`${i}-f`} style={{
      ...CELL,
      whiteSpace: 'nowrap',
      borderTop
    }}>
              <span style={{
      padding: '0.125rem 0.375rem',
      borderRadius: '0.25rem',
      fontSize: '0.75rem',
      fontFamily: MONO,
      backgroundColor: T.fieldBg,
      color: T.fieldText
    }}>
                {f.field}
              </span>
            </div>, ...hasRequired ? [<div key={`${i}-r`} style={{
      ...CELL,
      borderTop,
      fontWeight: f.required ? 500 : 400,
      color: f.required ? T.reqYes : T.reqNo
    }}>
                {f.required ? 'Yes' : '—'}
              </div>] : [], ...hasExample ? [<div key={`${i}-e`} style={{
      ...CELL,
      whiteSpace: 'nowrap',
      borderTop
    }}>
                {f.example !== undefined ? <code style={{
      fontFamily: MONO,
      fontSize: '0.75rem',
      backgroundColor: T.exampleBg,
      color: T.exampleText,
      padding: '0.125rem 0.375rem',
      borderRadius: '0.25rem'
    }}>
                    {f.example}
                  </code> : null}
              </div>] : [], <div key={`${i}-d`} style={{
      ...CELL,
      borderTop,
      color: T.descText
    }}>
              {desc}
            </div>];
  })}

      </div>
    </div>;
};

export const WsMessageExample = ({data, title}) => {
  const [isDark, setIsDark] = useState(typeof document !== 'undefined' ? document.documentElement.classList.contains('dark') : true);
  useEffect(() => {
    const check = () => setIsDark(document.documentElement.classList.contains('dark'));
    check();
    const observer = new MutationObserver(check);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
    return () => observer.disconnect();
  }, []);
  const COLORS = isDark ? {
    key: '#79c0ff',
    string: '#a5d6ff',
    number: '#e3b341',
    boolean: '#ff7b72',
    null: '#8b949e',
    punctuation: '#c9d1d9',
    ws: '#c9d1d9'
  } : {
    key: '#0550ae',
    string: '#0a3069',
    number: '#953800',
    boolean: '#cf222e',
    null: '#6e7781',
    punctuation: '#24292f',
    ws: '#24292f'
  };
  const tokenize = json => {
    const tokens = [];
    let i = 0;
    while (i < json.length) {
      if ((/\s/).test(json[i])) {
        let ws = '';
        while (i < json.length && (/\s/).test(json[i])) ws += json[i++];
        tokens.push({
          type: 'ws',
          value: ws
        });
        continue;
      }
      if (json[i] === '"') {
        let str = '"';
        i++;
        while (i < json.length) {
          if (json[i] === '\\') {
            str += json[i] + json[i + 1];
            i += 2;
          } else if (json[i] === '"') {
            str += '"';
            i++;
            break;
          } else {
            str += json[i++];
          }
        }
        let j = i;
        while (j < json.length && (/[ \t]/).test(json[j])) j++;
        const isKey = json[j] === ':';
        tokens.push({
          type: isKey ? 'key' : 'string',
          value: str
        });
        continue;
      }
      if (json[i] === '-' || (/\d/).test(json[i])) {
        let num = '';
        if (json[i] === '-') num += json[i++];
        while (i < json.length && (/[\d.eE+\-]/).test(json[i])) num += json[i++];
        tokens.push({
          type: 'number',
          value: num
        });
        continue;
      }
      if (json.slice(i, i + 4) === 'true') {
        tokens.push({
          type: 'boolean',
          value: 'true'
        });
        i += 4;
        continue;
      }
      if (json.slice(i, i + 5) === 'false') {
        tokens.push({
          type: 'boolean',
          value: 'false'
        });
        i += 5;
        continue;
      }
      if (json.slice(i, i + 4) === 'null') {
        tokens.push({
          type: 'null',
          value: 'null'
        });
        i += 4;
        continue;
      }
      tokens.push({
        type: 'punctuation',
        value: json[i++]
      });
    }
    return tokens;
  };
  const json = JSON.stringify(data, null, 2);
  const tokens = tokenize(json);
  return <div style={{
    marginBottom: '1rem'
  }}>
      {title && <p style={{
    fontWeight: 600,
    fontSize: '0.875rem',
    marginTop: '1rem',
    marginBottom: '0.5rem'
  }}>
          {title}
        </p>}
      <div className="border border-gray-200 dark:border-[#30363d]" style={{
    position: 'relative',
    borderRadius: '0.5rem',
    overflow: 'hidden'
  }}>
        <div className="bg-gray-50 dark:bg-[#161b22] border-b border-gray-200 dark:border-[#30363d]" style={{
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: '0.375rem 1rem'
  }}>
          <span className="text-gray-500 dark:text-[#8b949e]" style={{
    fontSize: '0.75rem',
    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
  }}>
            json
          </span>
        </div>
        <div className="bg-white dark:bg-[#0d1117]" style={{
    margin: 0,
    padding: '1rem 1.25rem',
    overflowX: 'auto',
    fontSize: '0.8125rem',
    lineHeight: '1.7',
    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace',
    whiteSpace: 'pre'
  }}>
          {tokens.map((t, idx) => <span key={idx} style={{
    color: COLORS[t.type]
  }}>{t.value}</span>)}
        </div>
      </div>
    </div>;
};

export const WsChannelOverview = ({operations}) => {
  const hasPush = operations.some(op => op.push);
  const Th = ({children}) => <th className="text-left text-gray-500 dark:text-gray-400 border-b border-gray-200 dark:border-gray-700" style={{
    padding: "0.5rem 1rem",
    fontSize: "0.6875rem",
    fontWeight: 600,
    textTransform: "uppercase",
    letterSpacing: "0.05em",
    whiteSpace: "nowrap"
  }}>
      {children}
    </th>;
  const PushBadge = ({value}) => {
    const dashIdx = value.indexOf(" — ");
    const method = dashIdx !== -1 ? value.slice(0, dashIdx) : value;
    const desc = dashIdx !== -1 ? value.slice(dashIdx + 3) : null;
    return <span style={{
      display: "inline-flex",
      alignItems: "center",
      gap: "0.375rem",
      flexWrap: "wrap"
    }}>
        <code className="bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-400" style={{
      padding: "0.125rem 0.375rem",
      borderRadius: "0.25rem",
      fontSize: "0.75rem",
      whiteSpace: "nowrap"
    }}>
          {method}
        </code>
        {desc && <span className="text-gray-500 dark:text-gray-400" style={{
      fontSize: "0.75rem"
    }}>
            — {desc}
          </span>}
      </span>;
  };
  return <div style={{
    margin: "1.25rem 0",
    borderRadius: "0.5rem",
    border: "1px solid",
    overflow: "hidden",
    fontSize: "0.8125rem"
  }} className="border-gray-200 dark:border-gray-700">
      <table className="w-full" style={{
    margin: 0,
    borderCollapse: "collapse",
    tableLayout: "auto"
  }}>
        <thead>
          <tr className="bg-gray-50 dark:bg-gray-800/60 border-b border-gray-200 dark:border-gray-700">
            {Th({
    children: "Operation"
  })}
            {Th({
    children: <span><span style={{
      color: "#16a34a"
    }}>→</span> You send</span>
  })}
            {Th({
    children: "← Server responds"
  })}
            {hasPush && Th({
    children: <span><span style={{
      color: "#2563eb"
    }}>⟵</span> Server pushes</span>
  })}
          </tr>
        </thead>
        <tbody>
          {operations.map((op, i) => <tr key={i} className="border-b border-gray-100 dark:border-gray-800" style={{
    borderBottom: i === operations.length - 1 ? "none" : undefined
  }}>
              {}
              <td className="text-gray-900 dark:text-gray-100" style={{
    padding: "0.625rem 1rem",
    fontWeight: 500,
    whiteSpace: "nowrap"
  }}>
                {op.name}
              </td>

              {}
              <td style={{
    padding: "0.625rem 1rem",
    whiteSpace: "nowrap"
  }}>
                <code className="bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-400" style={{
    padding: "0.125rem 0.375rem",
    borderRadius: "0.25rem",
    fontSize: "0.75rem"
  }}>
                  {op.send}
                </code>
              </td>

              {}
              <td className="text-gray-500 dark:text-gray-400" style={{
    padding: "0.625rem 1rem"
  }}>
                {op.receive}
              </td>

              {}
              {hasPush && <td style={{
    padding: "0.625rem 1rem"
  }}>
                  {op.push ? PushBadge({
    value: op.push
  }) : <span className="text-gray-300 dark:text-gray-600">—</span>}
                </td>}
            </tr>)}
        </tbody>
      </table>
    </div>;
};

Authorize the WebSocket connection for private channel access. Send a WebSocket token obtained from the REST API. This channel handles WebSocket connection authorization. Authorize once per connection — all private channels become accessible after a single successful authorization.

<WsChannelOverview operations={channelOperations} />

<Note>Connect to `wss://api.whitebit.com/ws` — see [WebSocket Overview](/websocket/overview) for protocol details and keepalive requirements.</Note>

## Rate limits

<WsRateLimits {...channelMeta.rateLimits} />

## Authorization flow

**Step 1 — Get a WebSocket token**

Call the REST endpoint to obtain a short-lived token:

```text theme={null}
POST /api/v4/profile/websocket_token
```

See [WebSocket Authentication](/websocket/authentication) for the full flow including request signing.

**Step 2 — Send authorization request**

<WsTupleTable fields={authorizeRequestParamsTupleFields} />

<WsMessageExample data={exAuthorizeRequest} />

**Step 3 — Receive confirmation**

<WsMessageExample data={exAuthorizeResponse} />

The connection is authorized. Subscribe to any private channel on the same connection.

<Note>
  Authorization is per connection, not per subscription. Authorize once, then subscribe to as many private channels as needed on the same WebSocket connection.
</Note>

## Update frequency

Client-initiated. Send an `authorize` request after each new WebSocket connection.

## Error codes

<WsErrorCodes errorCodes={channelMeta.errorCodes} />
