---
title: Rate limits
description: How Prefactor limits requests to the platform API, and what a
  rate-limited response looks like.
editUrl: true
head: []
template: doc
sidebar:
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

Prefactor rate limits requests to the platform API so that one busy integration cannot degrade the service for everyone else. This page lists how limits are applied and what a limited response looks like. If you use the TypeScript or Python SDK, retries are handled for you — see [Handle rate limiting](/sdks/handling-rate-limits).

## How limits are applied

Every HTTP request counts against a high per-IP ceiling that exists to absorb floods. Authenticated requests count against additional scopes, checked over fixed one-minute windows. Which scopes apply depends on the token: an [account token](/platform/concepts/api-token) counts against the token itself and the account; a deployment token counts against the token, its agent deployment, its agent, and the account.

A single request counts against every applicable scope at once, and exceeding any one of them limits the request. Reads (queries) have a higher allowance than writes (actions) and live subscriptions. The same limits apply to every account.

The web app and login are not rate limited beyond the per-IP ceiling.

## The 429 response

A limited HTTP request returns status `429` with a `Retry-After` header in whole seconds and a JSON body:

```json
{
  "status": "error",
  "code": "rate_limited",
  "message": "Rate limited on the API token",
  "retry_after_ms": 1500
}
```

| Field            | Type    | Description                                                              |
| ---------------- | ------- | ------------------------------------------------------------------------ |
| `status`         | string  | Always `"error"`.                                                        |
| `code`           | string  | Always `"rate_limited"`.                                                 |
| `message`        | string  | Names the scope that was exceeded — for example, "Rate limited on the account". |
| `retry_after_ms` | integer | Milliseconds to wait before retrying.                                    |

`Retry-After` and `retry_after_ms` carry the same wait; use either.

## WebSocket connections

The [WebSocket API](/api/websocket) (`/api/v1/ws`) speaks JSON-RPC, so a limited call returns a JSON-RPC error with code `-32000` instead of an HTTP status. The error's `data` object carries the same fields as the HTTP body above.

## Related

- [API token](/platform/concepts/api-token) — account tokens and deployment tokens, and where to manage them.
- [Handle rate limiting](/sdks/handling-rate-limits) — how the SDKs retry limited requests, and what happens when retries run out.
- [Configuration and environment variables](/sdks/configuration) — retry settings for both SDKs.