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

# Rate limits

> Request limits are tracked per API key in independent groups. Find which group your endpoint belongs to and its per-minute, hour, and day budgets.

Rate limits are counted **per API key**, across three rolling windows — per minute, per hour, and per day. The most restrictive window wins: exhausting the per-minute budget returns `429` even with hourly and daily headroom left.

Limits are **grouped**. Each endpoint belongs to exactly one group with its own independent counters, so hammering search never eats into your feed throughput.

<Note>
  Rate limits are checked **before** credits are deducted, so a rate-limited request never costs you anything. See [Billing](/docs/billing).
</Note>

***

## Limits by group

The **Subscribed** column applies when your account has any active subscription. Otherwise the **Free** column applies.

| Group                 | Endpoints                                                                                                  | Free (min / hour / day) | Subscribed (min / hour / day) |
| --------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------- | ----------------------------- |
| `JobSearch`           | `GET /api/jobs`<br />`POST /api/jobs/search`<br />`GET /api/jobs/{id}`<br />`GET /api/companies/{id}/jobs` | 60 / 1,000 / 10,000     | 360 / 10,000 / 100,000        |
| `JobFeed`             | `POST /api/jobs/feed`<br />`POST /api/jobs/feed/managed`<br />`GET /api/jobs/expired`                      | 30 / 1,000 / 10,000     | 60 / 10,000 / 100,000         |
| `Geocode`             | `GET /api/locations/geocode`                                                                               | 60 / 1,000 / 10,000     | 360 / 10,000 / 100,000        |
| `AutoApply`           | `POST /api/auto-apply/applications`                                                                        | 5 / 100 / 1,000         | 30 / 600 / 5,000              |
| `AutoApplyManagement` | Auto Apply list, get, and cancel                                                                           | 60 / 1,000 / 10,000     | 360 / 10,000 / 100,000        |
| `Default`             | Anything not listed above                                                                                  | 60 / 1,000 / 10,000     | 360 / 10,000 / 100,000        |

The group that applied to a request is echoed back on every response as `X-RateLimit-Group`, so you never have to guess.

<Note>
  A **Jobs Feed subscription waives the wallet charge** on feed endpoints — it does not remove the rate limit. The `JobFeed` budgets above still apply. If you need more feed throughput than the subscribed tier allows, contact [support@jobo.world](mailto:support@jobo.world); per-key overrides are possible.
</Note>

<Info>
  `GET /api/companies/{id}` requires no API key and is **not rate limited** at the key level — it is served from CDN cache. Every other endpoint requires a key and is counted.
</Info>

***

## Reading the headers

Every authenticated response carries your current position in the window. See [Response headers](/docs/response-headers) for the full inventory.

| Header                  | Meaning                                                                        |
| ----------------------- | ------------------------------------------------------------------------------ |
| `X-RateLimit-Limit`     | Maximum requests allowed in the window being reported.                         |
| `X-RateLimit-Used`      | Requests consumed so far in that window.                                       |
| `X-RateLimit-Remaining` | Requests left. Never negative.                                                 |
| `X-RateLimit-Group`     | Which group's budget applied — match it against the table above.               |
| `X-RateLimit-Reset`     | Unix epoch seconds when the window resets. Present when a reset time is known. |
| `Retry-After`           | Seconds to wait. **Only on `429` and `503`.**                                  |

```bash theme={null}
curl -si "https://connect.jobo.world/api/jobs?q=engineer&page_size=1" \
  -H "X-Api-Key: $JOBO_API_KEY" | grep -i '^x-ratelimit'
```

***

## When you exceed a limit

You get `429` with `Retry-After` and a body naming the group and window. The envelope is documented in full under [Errors](/docs/errors#429-too-many-requests).

```json theme={null}
{
  "code": "rate_limit_exceeded",
  "error": "Rate limit exceeded",
  "detail": "Per-minute request limit reached.",
  "group": "JobSearch",
  "retry_after_seconds": 42
}
```

Wait exactly `Retry-After` seconds. Never hardcode a delay — see the [retry strategy](/docs/errors#retry-strategy) for a working implementation.

***

## Staying under the limits

<Steps>
  <Step title="Throttle on X-RateLimit-Remaining, not on 429">
    Treat `429` as a bug in your pacing rather than a signal to react to. When `X-RateLimit-Remaining` drops below roughly 10–20% of `X-RateLimit-Limit`, slow down — you avoid the round trips you would otherwise waste.
  </Step>

  <Step title="Use the feed for bulk, not paginated search">
    Walking search results to export the corpus burns `JobSearch` requests and costs more per job. `POST /api/jobs/feed` returns up to 1,000 jobs per request from a separate budget. See [Sync a database](/docs/guides/sync-a-database).
  </Step>

  <Step title="Cache geocode results">
    A location string always resolves to the same output, so results are indefinitely cacheable. Most integrations can eliminate nearly all repeat `Geocode` traffic.
  </Step>

  <Step title="Request only the fields you need">
    `include_fields` shrinks responses substantially — `description` alone dominates payload size. This does not change your request count but makes each one much faster.
  </Step>

  <Step title="Paginate the feed serially">
    One in-flight request per cursor. Parallel fan-out on a cursor is both unsupported and the fastest way to hit the per-minute wall. See [Pagination](/docs/pagination).
  </Step>
</Steps>

***

## Repeated authentication failures

Separately from the per-key limits above, an IP address that produces a large number of failed-authentication `401`s in a short window is temporarily blocked with `429` for a few minutes. This protects against key-guessing and only affects requests that were already failing — a correctly configured integration never encounters it.
