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

# Rate limits

> API request limits, capability-check quotas, and how to back off.

This page covers limits on API requests. They protect the API and are the same for everyone. Limits on sending, which protect each phone number's reputation, are on [Phone numbers and limits](/phone-numbers.md#sending-limits). The rules about what a message can contain before a contact replies are on [Sending rules](/messaging/sending-rules.md).

## Request limits

Limits count requests per API key, in fixed one-minute windows.

| Requests | Limit |
| - | - |
| Reads: `GET` requests, and capability checks | 600 per minute |
| Writes: `POST`, `PATCH`, `DELETE` | 120 per minute |
| Attachments: any `/v1/attachments` request | 60 per minute |
| Failed authentication, per IP address | 60 per minute |

Responses include `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` headers; `RateLimit-Reset` is the number of seconds until the window resets, on every response including a `429`. Over a limit, you get `429` [`RATE_LIMIT_EXCEEDED`](/errors/rate-limit-exceeded) with a `Retry-After` header:

```json theme={null}
{
  "status": "error",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded",
    "type": "rate_limit",
    "http_status": 429,
    "retryable": true,
    "doc_url": "https://docs.blujay.io/errors/rate-limit-exceeded",
    "details": [{ "limit_type": "public_api_write", "scope": "api_key", "limit": 120, "used": 121, "remaining": 0, "reset_at": "2026-10-14T17:31:00.000Z" }],
    "retry_after": 12,
    "reset_at": "2026-10-14T17:31:00.000Z"
  },
  "trace_id": "trc_6b2d9e0f1a3c",
  "timestamp": "2026-10-14T17:30:48.000Z"
}
```

`retry_after` and `reset_at` on the error match the `Retry-After` header. `details[0].limit_type` tells you which request limit you hit: `public_api_read`, `public_api_write` or `public_api_media`. The same error code with `scope: "phone_number"` and a `limit_type` of `new_contact_daily`, `recipient_loop` or `phone_number_sendability` is a sending limit on the number, not a request limit. See [Handle limit errors on sends](/phone-numbers.md#handle-limit-errors-on-sends).

## Capability checks

[`POST /v1/capability/evaluate_service`](/messaging/choosing-a-service) runs a fresh check on the phone number you name. Each number can run 30 fresh checks per clock hour and 100 per UTC day. An answer Blujay already has, from any check or send in the last 5 minutes (30 seconds for a check that didn't confirm anything), comes back with `source: "cached"`, and cached answers are free and unlimited.

Over the quota, the check returns `429` [`RATE_LIMIT_EXCEEDED`](/errors/rate-limit-exceeded) with `Retry-After`. Sending with Auto (no `preferred_service`) never needs a check first.

## Backing off

1. On `429` or a retryable `503`, wait for `Retry-After` seconds.
2. Retry with the same `Idempotency-Key`.
3. If it fails again, back off exponentially with jitter, up to a few minutes.
4. Don't retry non-retryable errors (`retryable: false`). Fix the request instead.

If `Retry-After` is longer than you want to wait (for example a sending limit that resets at midnight), schedule the send for later. An idempotency key is honored for 24 hours. See [Idempotency](/idempotency.md).

## Common questions

> **Are request limits per key or per workspace?**
>
> Per API key. A workspace has one key today, so that is the same thing.

> **Do cached capability checks count against the quota?**
>
> No. Only fresh checks count toward the 30 per hour and 100 per day. A cached answer has `source: "cached"`.

> **Why did a send return 429 when I'm well under 120 writes a minute?**
>
> The number hit a sending limit, not the API. Check `error.details[0].limit_type` and `scope`. See [Phone numbers and limits](/phone-numbers.md#handle-limit-errors-on-sends).

> **Why did my second message to someone return 400, not 429?**
>
> That is a sending rule, not a rate limit: links, attachments, contact cards and texts over 300 characters are rejected until the contact replies, and at most 6 texts go out in a row without a response. These are never retryable. See [Sending rules](/messaging/sending-rules.md).

## Next steps

> **[Phone numbers and limits](/phone-numbers.md)**
>
> Sending limits and the live fields that report them.

> **[Sending rules](/messaging/sending-rules.md)**
>
> What a message can contain before and after a reply.

> **[Idempotency](/idempotency.md)**
>
> Retry without sending twice.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.