Limits

Two kinds of limits apply: request rates and field sizes. Both return machine-readable errors, so your code can back off or fix the request.

Rate limits

The API enforces 10,000 requests per minute per account across all /api/v2 endpoints, shared by all API keys and dashboard sessions on the account. Authenticated responses include tracking headers:

Every figure on this page is the allowance you can rely on, not an exact ceiling: you will never be throttled below it, and in some deployments we allow more. Design against the published number and use the response headers below for the live figure.

HeaderDescription
X-RateLimit-LimitMaximum requests allowed per minute
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the limit resets

Past the limit, requests return 429 with a Retry-After header (seconds to wait):

JSON

The SDKs retry 429 and 5xx responses with exponential backoff for idempotent methods (GET, PUT, DELETE), and for the run-creating POSTs, which carry an idempotency key so a retry can never start a second run. Any other POST or PATCH is not retried, to prevent duplicate side effects. A RateLimitError only reaches your code once all retries are exhausted.

Idempotency

A run costs money, so a request that times out must never leave you guessing whether you were charged. Send an Idempotency-Key header on any run-creating POST and retrying it returns the run the first attempt made, instead of starting a second one:

cURL

Supported on POST /runs, POST /runs/with-files, POST /runs/{id}/reply, POST /runs/{id}/reply/with-files, and POST /tasks/{id}/runs.

  • Same key, same request200 with the original run's current state and an Idempotent-Replay: true header. Safe to repeat as often as you like.
  • Same key, different request409 with error.details.error_code = "idempotency_key_reuse". A key is never silently replayed against a call you did not make.
  • Keys last 24 hours and are scoped to your account, so two accounts can use the same key string without interfering.
  • Failed requests do not bind the key. A 402, 429, or 500 leaves the key free — fix the cause and retry with the same one.

The SDKs generate a key for every runs.create, runs.reply, and tasks.run automatically, which is what makes their retries safe. Pass your own when a retry must survive a process restart:

Python

A replayed streaming call is answered as JSON rather than SSE — a run that already exists has no fresh stream to emit — and the SDKs handle that for you by joining the existing run's stream. If that run has already finished there is nothing to join, so they raise with the run id (idempotent_replay_terminal); fetch its result with runs.get(id).

Multi-tenant: per-end-user rate limits

Rate-limit each end-user's agent turns (run starts and replies) independently, so one end-user bursting can't consume the account:

Python

Past the rate, run creation and replies for that user_id return 429 with error.details.error_code = "END_USER_RATE_LIMITED" (plus end_user_id, limit_per_minute, retry_after, and a Retry-After header). Other end-users and your own runs are unaffected. Off by default (null); send null to turn it off again. Related per-end-user run and cost caps: Users.

Advanced: auth endpoint limits (IP-based)

Login, registration, and password reset endpoints have a separate limit of 10 requests per minute per IP address:

  • POST /v1/auth/login
  • POST /v1/auth/register
  • POST /v1/auth/forgot-password
  • POST /v1/auth/reset-password
  • POST /v1/auth/verify-email

POST /api/v2/signup (agent-driven signup) has its own IP limit of 10 requests per minute.

Any other /api/v2 request we cannot authenticate — no key, an expired or revoked session, a key that does not exist — is throttled per IP, with an allowance of 120 requests per minute. Most of these can only return 401, so a working integration rarely reaches this limit; fix the credential rather than retrying. Verifying an unrecognised credential is metered by this same allowance — charged before the check and given back when it turns out to be a real account — so a burst of bad keys from one address is what exhausts it, not ordinary authenticated traffic. A few genuinely public endpoints (the plan catalogue, the agent-template list, and POST /api/v2/token) are also counted here, since they take no credential. Note that a credential you revoke keeps counting against the account it belonged to for up to ten seconds — rate-limit attribution is cached, so it catches up shortly after, and only then does the credential count against your IP instead. It is rejected with a 401 on every request throughout either way.

These endpoints do not require authentication, so limiting is keyed by IP rather than account, and the response uses a different format:

JSON

Field limits

Request fields have size and count caps:

FieldLimit
name255 characters
instructions50,000 characters
metadata10 KB serialized
allowed_senders100 items
tools50 items

Webhook payloads and inbound events are capped at 256 KB; larger requests return 413.

The metadata field accepts any JSON object under 10 KB serialized. Use it for IDs, labels, and lightweight state, not for large blobs or document content. When a field exceeds its limit, the API returns 422:

JSON

Next: Errors · Going Live

Was this page helpful?