# Rate limits and errors

## Rate limits

Limits apply per organization and per endpoint, measured in requests per minute.

| Plan | Requests per minute per endpoint |
|  --- | --- |
| Free | 10 |
| Pay-as-you-go | 60 |
| Enterprise | 1000, customizable per organization |


Above the limit the API returns `429 Too Many Requests`. Status endpoint calls count toward the limit, so poll at a sensible interval or use [webhooks](/getting-started/async-requests#webhooks). If you need more throughput, [contact us](https://bria.ai/contact-us) about an Enterprise plan.

### Handling 429

Retry with exponential backoff and jitter, honor `Retry-After` when present, and cap concurrency on your side so a burst does not turn into a wave of retries.

Python SDK
The SDK retries `429`, `502`, `503` and `504` responses to status polling automatically (3 attempts, exponential backoff). `run` and `submit` are never retried, so a job is never started twice. Tune it per client:

```python
from bria_client import BriaSyncClient
from httpx_retries import Retry

client = BriaSyncClient(retry=Retry(total=5, backoff_factor=2))
```

Keep your own concurrency bounded, for example with a thread pool of a few workers, so parallel jobs stay under the per-endpoint limit.

TypeScript SDK
The SDK retries `429`, `502`, `503` and `504` responses to status polling automatically (3 attempts, exponential backoff, honoring `Retry-After`). `run` and `submit` are never retried, so a job is never started twice. Tune the policy per client:

```typescript
import { BriaClient } from "@bria-ai/client";

const client = new BriaClient({ retry: { total: 5, backoffFactor: 2 } });
```

Keep your own concurrency bounded: submit in batches of a few jobs with `Promise.all` rather than everything at once, so parallel jobs stay under the per-endpoint limit.

## Error contract

Synchronous errors return a JSON body with an `error` object and the `request_id` to quote when contacting support:

```json
{
  "request_id": "9d4a1a2f5c7e4b6f8a0c2d3e4f5a6b7c",
  "error": {
    "code": 422,
    "message": "Unprocessable Entity",
    "details": "Prompt failed content moderation."
  }
}
```

Asynchronous jobs report failures through the [status endpoint](/status): `status` is `ERROR` and the same `error` object is included.

| HTTP status | When it happens |
|  --- | --- |
| `400 Bad Request` | Malformed JSON, an unknown parameter, an invalid value or an unsupported parameter combination. |
| `401 Unauthorized` | Missing or invalid `api_token`. See [Authentication](/getting-started/authentication). |
| `403 Forbidden` | The endpoint or option is not included in your plan. |
| `404 Not Found` | Unknown route, or an unknown or expired `request_id` on the status endpoint. |
| `413 Payload Too Large` | The image or request exceeds the endpoint's size limit. |
| `415 Unsupported Media Type` | The input file type or color mode is not supported. Use JPEG, PNG or WEBP. |
| `422 Unprocessable Entity` | The request is well formed but cannot be processed: [content moderation](/safety) failed, no object was detected for a prompt, or an async-only option was combined with `sync: true`. |
| `429 Too Many Requests` | Rate limit exceeded. Back off and retry. |
| `5xx` | A problem on Bria's side. Retry with backoff; check [status.bria.ai](https://status.bria.ai) if it persists. |


Each endpoint page lists its specific error responses and messages.