Saltar al contenido

Errors and limits

Every non-2xx response uses the same envelope. The request_id matches the X-Request-ID header, and it is what makes a specific failure traceable.

The envelope

json
{
  "error": {
    "code": "not_found",
    "message": "Resource not found",
    "request_id": "b3f1c2a4-..."
  }
}

Validation errors return 422 with code "validation_error". The message lists the offending fields, as field: reason.

json
{
  "error": {
    "code": "validation_error",
    "message": "body.email: value is not a valid email address; body.name: field required",
    "request_id": "b3f1c2a4-..."
  }
}
StatusCodeWhen it shows up
401unauthorizedToken missing, invalid or expired.
403forbiddenAuthenticated, but not allowed to do that.
404not_foundIt does not exist, or you are not a member of its organization.
409conflictState conflict: a duplicated unique value, for instance.
422validation_errorThe body or the parameters fail validation.
429too_many_requestsYou went over the limit. Retry later.

Usage limits

Sensitive endpoints —authentication above all— are limited by source IP and by account, on a fixed window. Go over it and the API answers 429 with the usual envelope.

The limiter is fail-open: if the service that counts them is unavailable, the request is not blocked — availability wins. Even so, design your clients to retry with exponential backoff on a 429, and avoid bursts you do not need.

Quotas for calls made with a token

On top of the per-IP ceiling, calls made with a token (or over OAuth from an assistant) count against their own quotas, per person and per organization. These are the server defaults.

QuotaLimitCounted per
Reads120 per minuteactor and person, in each organization
Writes20 per minuteactor and person, in each organization
Financial operations that modify data5 per houractor and person, in each organization
Whole organization600 reads, 120 writes per minute and 30 financial per hourall of the organization’s agents together
Global agent ceiling300 requests per minuteperson, across all their organizations
Opening streams (SSE)60 per minuteperson, agent or IP

Minting more tokens does not buy more quota: the person is counted too. These figures are tuned under real load, so do not hardcode them: read the Retry-After header.

What to do on a 429

A 429 carries a Retry-After header with the seconds left until another request fits. Wait that long, not a blind full window, and retry a few times. The API does not send X-RateLimit-* headers: the 429 itself is the signal.

javascript
async function call(url, token, attempts = 4) {
  for (let i = 0; i < attempts; i++) {
    const r = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
    if (r.status !== 429) return r;
    const wait = Number(r.headers.get('Retry-After')) || 2 ** i;
    await new Promise((ok) => setTimeout(ok, wait * 1000));
  }
  throw new Error('Still rate limited after several attempts');
}
Errors and limits · Projekt Republic