> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thehog.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate limits

# Rate Limits for The Hog API

> The Hog enforces rate limits per organization and user to ensure fair usage. Polling operations has a separate dedicated throttle. Learn limits and retry behavior.

The Hog enforces rate limits on all API endpoints to ensure reliable service for every organization. Limits are tracked per organization and user, not per API key alone. When you exceed a limit, the API returns HTTP 429 and you must wait before retrying.

## Global rate limit

Every authenticated endpoint is covered by a global, per-organization-and-user rate limit of **600 requests per minute**. The limit applies across all endpoints combined, so a burst of company searches counts against the same bucket as a burst of enrichment requests for the same caller.

## Polling rate limit

`GET /api/operations/:id` has its own **dedicated rate limit** — separate from the global bucket — of **300 requests per minute per organization-and-user**. This limit exists because polling is the highest-frequency access pattern and must not crowd out other API traffic.

<Warning>
  Do not poll `GET /api/operations/:id` in a tight loop or on every tick of a UI
  refresh cycle. Aggressive polling will trigger HTTP 429 responses and block
  other requests your organization is making simultaneously.
</Warning>

<Tip>
  Poll at **2–5 second intervals** for short jobs such as enrichment and search.
  Use **10–30 second intervals** for deep research jobs, which routinely take 30
  seconds to several minutes to complete. If you receive a 429 on the poll
  endpoint, honor the `Retry-After` header before resuming.
</Tip>

## HTTP 429 response

When you hit a rate limit, the API returns:

```json theme={null} theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "statusCode": 429,
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Please slow down and retry.",
  "path": "/api/operations/op_01HZ9K2QW3RV4M5N6P7Q8R9S0T",
  "requestId": "3f7a1c2e-88b4-4d0e-a1f5-0c9e2b3d7f4a",
  "timestamp": "2025-06-10T09:14:33.000Z"
}
```

429 responses include `Retry-After` and `X-RateLimit-*` headers. Treat
`Retry-After` as the minimum wait before the next request to that bucket.

## Retrying after 429

Use **exponential backoff** when you receive a 429. Do not retry immediately — the limit window must pass before your request will succeed.

<Steps>
  <Step title="Catch the 429">
    Detect `statusCode === 429` in the error body or `response.status === 429`.
  </Step>

  <Step title="Wait with exponential backoff">
    If the response includes `Retry-After`, wait at least that long. Otherwise start with a short delay and double it on each consecutive 429, up to a maximum. Add random jitter to avoid thundering-herd retries from parallel processes.

    ```javascript theme={null} theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

    async function retryWithBackoff(fn, maxRetries = 5) {
      let attempt = 0;
      while (attempt < maxRetries) {
        try {
          return await fn();
        } catch (err) {
          if (err.status !== 429 || attempt === maxRetries - 1) throw err;
          const retryAfterSeconds = Number(err.headers?.['Retry-After']);
          const baseDelay = Number.isFinite(retryAfterSeconds)
            ? retryAfterSeconds * 1000
            : 1000 * Math.pow(2, attempt); // 1s, 2s, 4s, 8s, 16s
          const jitter = Math.random() * 500;
          await sleep(baseDelay + jitter);
          attempt++;
        }
      }
    }
    ```
  </Step>

  <Step title="Resume polling at a slower interval">
    After a 429 on the poll endpoint, resume at a slower interval after the `Retry-After` window.
  </Step>
</Steps>

## Recommended polling intervals

| Job type                                  | Recommended interval |
| ----------------------------------------- | -------------------- |
| Enrichment (`POST /api/enrichments`)      | 2-5 seconds          |
| Search jobs (`POST /api/v1/search`)       | 5-10 seconds         |
| Deep research (`POST /api/deep-research`) | 10-30 seconds        |

These intervals keep you well within the 300 requests/minute polling limit even when running multiple concurrent jobs.
