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

# REST API rate limits and error codes

> Reference for REST API rate limits, error formats, authentication error codes, and best practices.

export const authErrors = [{
  message: "Payload not provided.",
  cause: "X-TXC-PAYLOAD header missing or empty",
  resolution: "Include the base64-encoded request body as X-TXC-PAYLOAD"
}, {
  message: "Too many requests.",
  cause: "Nonce value is not greater than previous request",
  resolution: "Use incrementing nonce values"
}, {
  message: "This action is unauthorized. Enable your key in API settings",
  cause: "Using a disabled API key",
  resolution: "Enable the key in API settings or check IP restrictions"
}, {
  message: "You don't have permission to use this endpoint.",
  cause: "Endpoint access is restricted",
  resolution: "Update endpoint access in API key settings"
}, {
  message: "Invalid payload",
  cause: "Payload does not match the decoded value",
  resolution: "Ensure proper base64 encoding of the request body"
}, {
  message: "Unauthorized request.",
  cause: "Request signed incorrectly",
  resolution: "Verify the signature creation process"
}, {
  message: "Nonce not provided.",
  cause: "Missing nonce in request body",
  resolution: "Include nonce in all requests"
}, {
  message: "Your nonce is more than 5 seconds lesser than the current nonce",
  cause: "Invalid timestamp when using nonceWindow",
  resolution: "Use current Unix timestamp in milliseconds"
}, {
  message: "Invalid nonceWindow.",
  cause: "nonceWindow is not a boolean",
  resolution: "Set nonceWindow to `true` or `false`"
}, {
  message: "Request not provided.",
  cause: "Missing request path in body",
  resolution: "Include the request path in all requests"
}];

export const httpStatusCodes = [{
  status: 200,
  meaning: "Success"
}, {
  status: 400,
  meaning: "Bad request — invalid parameters"
}, {
  status: 401,
  meaning: "Unauthorized — missing or invalid authentication"
}, {
  status: 403,
  meaning: "Forbidden — insufficient permissions"
}, {
  status: 404,
  meaning: "Not found — endpoint does not exist"
}, {
  status: 429,
  meaning: "Too Many Requests — rate limit exceeded"
}, {
  status: 500,
  meaning: "Internal server error — retry with backoff"
}];

export const scopeLimits = [{
  scope: "/api/v4/public/*",
  limit: 20000,
  period: "10 sec",
  enforcement: "per IP address"
}, {
  scope: "/api/v4/trade-account/*",
  limit: 12000,
  period: "10 sec",
  enforcement: "per IP address"
}, {
  scope: "/api/v4/main-account/*",
  limit: 1000,
  period: "10 sec",
  enforcement: "per IP address"
}];

export const ConceptTable = ({title, columns, rows, codeColumns = []}) => {
  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',
    codeBg: '#374151',
    codeText: '#e5e7eb',
    cellText: '#d1d5db'
  } : {
    border: '#e5e7eb',
    borderSubtle: '#f3f4f6',
    headerBg: '#f9fafb',
    headerText: '#6b7280',
    titleBg: '#f9fafb',
    titleText: '#374151',
    codeBg: '#f3f4f6',
    codeText: '#1f2937',
    cellText: '#374151'
  };
  const MONO = 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace';
  const codeSet = new Set(codeColumns);
  const gridTemplateColumns = columns.map(col => col.width || '1fr').join(' ');
  const HEADER = {
    padding: '0.5rem 1rem',
    fontSize: '0.6875rem',
    fontWeight: 600,
    textTransform: 'uppercase',
    letterSpacing: '0.05em',
    whiteSpace: 'nowrap',
    color: T.headerText,
    backgroundColor: T.headerBg,
    borderBottom: `1px solid ${T.border}`
  };
  const CELL = {
    padding: '0.625rem 1rem',
    fontSize: '0.8125rem',
    display: 'flex',
    alignItems: 'center',
    minWidth: 0,
    color: T.cellText
  };
  return <div style={{
    margin: '1.25rem 0',
    borderRadius: '0.5rem',
    border: `1px solid ${T.border}`,
    overflow: 'hidden',
    fontSize: '0.8125rem'
  }}>
      {title && <div style={{
    padding: '0.5rem 1rem',
    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'
  }}>

        {columns.map(col => <div key={col.key} style={HEADER}>{col.header}</div>)}

        {rows.map((row, i) => {
    const borderTop = `1px solid ${i === 0 ? T.border : T.borderSubtle}`;
    return columns.map(col => {
      const value = row[col.key];
      const isCode = codeSet.has(col.key);
      const display = value != null ? String(value) : '—';
      return <div key={`${i}-${col.key}`} style={{
        ...CELL,
        borderTop
      }}>
                {isCode ? <span style={{
        padding: '0.125rem 0.375rem',
        borderRadius: '0.25rem',
        fontSize: '0.75rem',
        fontFamily: MONO,
        backgroundColor: T.codeBg,
        color: T.codeText,
        whiteSpace: 'nowrap'
      }}>
                    {display}
                  </span> : display}
              </div>;
    });
  })}

      </div>
    </div>;
};

Reference for REST API rate limits, error formats, and error codes.

## REST API rate limits

All rate limits are **per IP address**.

| Scope                     | Limit                    |
| ------------------------- | ------------------------ |
| Default (all endpoints)   | 10,000 requests / 10 sec |
| `/api/v4/public/*`        | 20,000 requests / 10 sec |
| `/api/v4/trade-account/*` | 12,000 requests / 10 sec |
| `/api/v4/main-account/*`  | 1,000 requests / 10 sec  |

Scope-specific limits override the default where listed. Some endpoints have tighter limits that override the defaults above. These are documented on the respective endpoint pages.

When the rate limit is exceeded, the API returns HTTP status `429` (Too Many Requests). Use exponential backoff before retrying (see Best practices below).

## REST API error format

All v4 endpoints return errors as JSON. The format differs between public and private APIs.

### Public endpoints

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "success": false,
  "message": "ERROR MESSAGE",
  "params": []
}
```

### Private endpoints

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": 0,
  "message": "MESSAGE",
  "errors": {
    "PARAM1": ["MESSAGE"],
    "PARAM2": ["MESSAGE"]
  }
}
```

## Authentication error reference

The following errors are returned by private REST endpoints when the request signature or credentials are invalid.

<ConceptTable
  columns={[
{ key: 'message', header: 'Error message', width: 'minmax(200px, 1.5fr)' },
{ key: 'cause', header: 'Cause', width: '1fr' },
{ key: 'resolution', header: 'Resolution', width: '1fr' },
]}
  rows={authErrors}
/>

## HTTP status codes

<ConceptTable
  columns={[
{ key: 'status', header: 'Status', width: 'auto' },
{ key: 'meaning', header: 'Meaning', width: '1fr' },
]}
  rows={httpStatusCodes}
  codeColumns={['status']}
/>

## Best practices

### Retry strategy by error type

| Error type           | Retry? | Strategy                                                                             |
| -------------------- | ------ | ------------------------------------------------------------------------------------ |
| Rate limit (429)     | Yes    | Exponential backoff: start at 1s, double on each retry, cap at 30s. Add jitter.      |
| Authentication error | No     | Fix the root cause: check API key validity, signature computation, and header names. |
| Validation error     | No     | Fix the request parameters. Read the `errors` field for field-level feedback.        |
| Insufficient balance | No     | Check the account balance and wait for pending operations to settle.                 |
| Server error (5xx)   | Yes    | Exponential backoff. If persistent, check platform status or contact support.        |

### Exponential backoff

When rate limited, wait before retrying. Double the wait time after each failed attempt (1s → 2s → 4s → 8s).

### Batch requests

Combine multiple operations when the API supports batch endpoints. Use [Bulk Limit Order](/api-reference/spot-trading/bulk-limit-order) to place up to 20 orders at once, or [Cancel Bulk Orders](/api-reference/spot-trading/cancel-bulk-order) to cancel up to 100 orders at once, instead of issuing one request per order.

### Nonce management

For private endpoints, ensure each request uses a unique, incrementing nonce. Use Unix timestamp in milliseconds when `nonceWindow` is enabled. Avoid concurrent requests with the same nonce.

### Reduce REST polling

* **Use WebSocket for real-time data** — Subscribe to price, orderbook, and balance channels instead of polling REST endpoints. One WebSocket connection replaces hundreds of REST requests. See [WebSocket Quickstart](/guides/websocket-quickstart).
* **Cache public data** — Market info, asset statuses, and fee structures change infrequently. Cache responses and refresh periodically (for example, every 60 seconds).
* **Use conditional requests** — Check local state before making API calls. Avoid redundant balance checks when no trades have executed.
* **Distribute requests** — Spread requests evenly across the 10-second window instead of sending bursts.

## Related resources

* [API Reference Overview](/api-reference/overview) — Base URL and endpoint groups
* [Authentication](/api-reference/authentication) — Signing and header requirements
* [WebSocket Rate Limits](/websocket/rate-limits) — WebSocket connection limits, error codes, and timeout behavior
