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

# Rate Limits & Request Limits

> Every rate-limit bucket the Voxworks API enforces, how the sliding window works, the headers a 429 returns, and the request-size and list-pagination caps.

## Overview

The Voxworks API protects itself with two layers of defence: rate limits that cap how many requests you can send in a rolling window, and hard limits on request size and list-endpoint page size. This page documents every bucket, the exact headers returned on a `429`, and the `413` body-size cap so you can build retry logic that behaves correctly.

All limits below apply to endpoints under `/api/v1`. They're enforced per minute unless stated otherwise.

***

## How the sliding window works

Each rate-limit bucket tracks a rolling 60-second window rather than resetting on a fixed clock boundary. Every request that counts against a bucket is timestamped; a check counts how many timestamps fall inside the last 60 seconds and rejects the request once that count reaches the bucket's limit. As the oldest timestamps age out of the window, capacity frees up continuously rather than all at once — there's no "top of the minute" reset to wait for.

If a request is rejected, the `Retry-After` header tells you the minimum number of seconds until the oldest request in that bucket ages out and a slot opens up.

***

## Rate-limit buckets

A single request can be checked against several buckets at once — an IP-level bucket, an endpoint-level bucket, a write-specific bucket, and (once your API key is authenticated) an API-key and team bucket. The request is rejected by whichever bucket runs out first.

### Checked before authentication

These buckets apply to every request that reaches the API, including ones with an invalid or missing API key, based on the caller's IP address and method/endpoint pair.

| Bucket                            | Limit        | Window     | Applies to                                                                                                                           |
| --------------------------------- | ------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Per IP                            | 300 requests | 60 seconds | Every request from that IP address, across all endpoints                                                                             |
| Per IP + endpoint                 | 120 requests | 60 seconds | Requests from that IP to a specific method/endpoint pair                                                                             |
| Per IP + endpoint, write requests | 60 requests  | 60 seconds | `POST`, `PUT`, `PATCH`, `DELETE` requests from that IP to a specific method/endpoint pair (`GET`, `HEAD`, and `OPTIONS` don't count) |
| Per bearer token + endpoint       | 60 requests  | 60 seconds | Requests carrying an `Authorization: Bearer` header, keyed by a hash of the token, even before the key is validated                  |
| Per IP + webhook endpoint         | 60 requests  | 60 seconds | Requests to a webhook trigger URL, keyed by IP                                                                                       |

### Checked after authentication

Once your API key has been validated, two further buckets apply, keyed by your API key and your team:

| Bucket                      | Limit        | Window     | Applies to                                                      |
| --------------------------- | ------------ | ---------- | --------------------------------------------------------------- |
| Per API key                 | 120 requests | 60 seconds | All authenticated requests using that key, across all endpoints |
| Per API key, write requests | 60 requests  | 60 seconds | Write requests (`POST`/`PUT`/`PATCH`/`DELETE`) using that key   |
| Per team                    | 300 requests | 60 seconds | All authenticated requests from any key belonging to that team  |
| Per team, write requests    | 120 requests | 60 seconds | Write requests from any key belonging to that team              |

Because both the API-key and team buckets are checked, a single busy key on a team with several keys can still be throttled by the team-wide bucket even if its own key-level bucket has room left.

<Note>
  Webhook trigger URLs (`POST /api/v1/hooks/{token}`) authenticate with a path token rather than a bearer API key, so they're only subject to the pre-authentication IP and webhook buckets above — not the API-key or team buckets.
</Note>

***

## The 429 response

When any bucket is exceeded, the API returns `429 Too Many Requests` with a JSON body and three headers:

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
Content-Type: application/json
```

```json theme={null}
{
  "success": false,
  "message": "Rate limit exceeded"
}
```

| Header                  | Type              | Example | Description                                                                                   |
| ----------------------- | ----------------- | ------- | --------------------------------------------------------------------------------------------- |
| `Retry-After`           | integer (seconds) | `12`    | Minimum time to wait before retrying. Reflects the specific bucket that rejected the request. |
| `X-RateLimit-Limit`     | integer           | `120`   | The limit for the bucket that rejected the request.                                           |
| `X-RateLimit-Remaining` | integer           | `0`     | Always `0` on a `429` response — the bucket had no capacity left.                             |

Build your retry logic around `Retry-After` rather than a fixed backoff, since different buckets have different windows and remaining times.

***

## Request body size limit

Request bodies are capped at **1MB (1,048,576 bytes)**. A request body larger than that is rejected before your endpoint logic runs, with:

```http theme={null}
HTTP/1.1 413 Payload Too Large
Content-Type: application/json
```

```json theme={null}
{
  "success": false,
  "message": "Request body too large",
  "maxBytes": 1048576
}
```

This applies to the raw request body — for example a large `create-object` payload or a bulk `add-contacts-to-list` call. If you're hitting this limit on a bulk-import style endpoint, split the payload into smaller batches.

***

## List-endpoint pagination caps

Endpoints that return a list of records accept a `limit` query parameter and cap it at **500** regardless of what you request. Each of these endpoints defaults to **100** when `limit` is omitted:

| Endpoint                   | Default `limit` | Maximum `limit` |
| -------------------------- | --------------- | --------------- |
| `GET /api/v1/calls`        | 100             | 500             |
| `GET /api/v1/lists`        | 100             | 500             |
| `GET /api/v1/object-types` | 100             | 500             |

`GET /api/v1/calls` also accepts a `cursor` parameter for keyset pagination — the response's `meta.next_cursor` gives you the value to pass on the next request, and it's `null` once you've reached the last page.

Requesting a non-integer `limit` returns `400 Bad Request` on all three endpoints. A `limit` outside `1`–`500` also returns `400 Bad Request` on `GET /api/v1/calls` and `GET /api/v1/object-types` — but on `GET /api/v1/lists` it's silently clamped into the `1`–`500` range instead of being rejected.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="API Overview" href="/api-reference/overview">
    Base URL, authentication, content type, and the standard error shape.
  </Card>

  <Card title="API Keys & Authentication" href="/api-reference/authentication">
    Generate and manage the API keys your requests authenticate with.
  </Card>

  <Card title="API Quickstart" href="/api-reference/quickstart">
    Send your first authenticated request end to end.
  </Card>

  <Card title="Receiving Webhooks from Voxworks" href="/api-reference/receiving-webhooks">
    How outbound webhook deliveries, retries, and signatures work.
  </Card>
</CardGroup>
