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

# Rate Limits

> Bucket-based rate limiting and 429 handling

Rate limiting is **partner-scoped**: limits are shared across all tenants under the same API key and environment. Each request is classified into 1 of 7 buckets.

## Buckets

| Bucket                   | Limit                            | Endpoints                                                                                              |
| ------------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `criteria_ai`            | 2 req/s + 4 concurrent in-flight | `POST /v1/jobs/{jobId}/question-sets`, `POST /v1/jobs/{jobId}/criteria/generate`                       |
| `criteria_current_reads` | 60 req/s                         | `GET /v1/jobs/{jobId}/criteria/versions/current`                                                       |
| `scoring_intake_batch`   | 1 req/s                          | `POST /v1/jobs/{jobId}/scoring-batches`                                                                |
| `scoring_intake_single`  | 10 req/s                         | `POST /v1/jobs/{jobId}/applications/{applicationId}/scoring-jobs`                                      |
| `read_and_ops`           | 20 req/s                         | Other read/write `/v1/*` endpoints (except `criteria_current_reads`, analytics, and rate-limit status) |
| `analytics`              | 20 req/s                         | `GET /v1/analytics/*`                                                                                  |
| `rate_limit_status`      | 2 req/s                          | `GET /v1/rate-limit-status`                                                                            |

Buckets are isolated: exhausting one doesn't affect others.

The `criteria_ai` bucket has an extra concurrency cap. At most 4 requests can process simultaneously, returning 429 even if RPS tokens are available.

<Info>
  If you need higher limits, contact us through the Embed Portal.
</Info>

## Trial accounts

Trial accounts may have configured monthly limits for scoring jobs, question generation, and criteria generation. These limits are shared across all tenants in the same partner environment and reset on the first day of each UTC month.

If a request exceeds the configured monthly trial limit, the API returns HTTP 429 with `MONTHLY_TRIAL_QUOTA_EXCEEDED` and `retryable: false`. Contact your Nova account manager or `nova@dweet.com` to upgrade your plan. We share exact trial limits during onboarding.

## Response headers

All `/v1/*` responses include:

```http theme={null}
X-RateLimit-Bucket: scoring_intake_single
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 8
X-RateLimit-Reset: 1734187201
```

| Header                  | Description                                     |
| ----------------------- | ----------------------------------------------- |
| `X-RateLimit-Bucket`    | Which bucket the request was classified into    |
| `X-RateLimit-Limit`     | Max requests per second for this bucket         |
| `X-RateLimit-Remaining` | Requests remaining in the current window        |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets           |
| `X-RateLimit-Degraded`  | `"true"` when rate limiting is in degraded mode |

## Checking status

[`GET /v1/rate-limit-status`](/embed-api/endpoints/rate-limit-status) returns all buckets at once without consuming tokens from other buckets. Only needs `Authorization`, not `X-Tenant-Id`.

## Handling 429

When short-window rate-limited with `RATE_LIMITED`, the response includes a `Retry-After` header (seconds to wait).

<Note>
  If you use `Idempotency-Key` on criteria or library mutations, reuse the same key when retrying after `429 RATE_LIMITED`. Rate limiting runs before the idempotency replay layer. Scoring submissions use built-in scoring idempotency instead, so retry the same scoring request directly.
</Note>

```json theme={null}
{
  "type": "https://docs.nova.dweet.com/embed-api/errors#rate-limited",
  "code": "RATE_LIMITED",
  "status": 429,
  "message": "Rate limit exceeded. Retry after 2 seconds.",
  "retryable": true,
  "traceId": "5c2f4f5b2c0a4ce0b6a31a1a18f8e9a1"
}
```

<Tip>
  For high-volume backfills, use `POST /v1/jobs/{jobId}/scoring-batches` with up to 25 applications per request.
</Tip>

## Degraded mode

If Redis is temporarily unavailable, the system enters degraded mode: requests are **allowed through** (fail-open), `X-RateLimit-Degraded: true` is set, and header values are best-effort estimates. Normal limiting resumes automatically when Redis recovers.
