Skip to navigation

Limits

Ada’s API enforces rate and data limits to ensure stability and prevent abuse. These limits are applied per Ada instance.

Rate limits

Default rate limits

Unless otherwise specified, the following default rate limits apply across all Platform API endpoints:

  • Requests per day: 10,000
  • Requests per minute: 100
  • Requests per second: 10

Exceeding these limits will result in a 429 Too Many Requests error. Implement retry logic with exponential backoff and jitter to handle these responses and minimize disruptions.

API-specific rate limits

Some APIs have their own specific rate limits that differ from the defaults:

APIPer-Second LimitPer-Minute LimitPer-Day Limit
Data Export API (v2)10 requests/second (per endpoint)100 requests/minute15,000 requests/day
Data Export API (v1.4)10 requests/second (per endpoint)No per-minute limitNo daily limit
MCP server (per AI Agent; per user for OAuth sign-in)50 requests/second200 requests/minute30,000 requests/day

The Data Export API (v1.4) endpoints return no rate limit headers. See rate limit headers.

The MCP server also refuses every request from an IP address for the rest of the minute, after 300 requests from that address fail authentication or exceed the budget in one minute.

Refer to the documentation for each API endpoint for complete details on rate limits and any additional restrictions.

Rate limit headers

Every /v2/ Platform API endpoint and the MCP server return these headers on every successful authenticated response. The legacy Data Export v1.4 endpoints (/data_api/v1.x/) return no rate limit headers.

  • X-RateLimit-Limit: the request cap for the current window.
  • X-RateLimit-Remaining: the requests left in the current window.
  • X-RateLimit-Reset: the Unix timestamp when the window resets.

On a successful response, these headers describe the longest window that applies to the endpoint. That is the per-day limit where one exists, or the per-minute limit otherwise. A Platform API 429 from the rate limiter carries only Retry-After. An MCP 429 from the rate limiter also carries the three headers, and they describe the window that was exceeded.

A 429 response caused by rate limiting includes a Retry-After header. It gives the number of seconds to wait before you retry. Other 429 responses, for example an application cooldown, do not carry Retry-After. Use Retry-After to pace retries. Use X-RateLimit-Remaining and X-RateLimit-Reset to avoid hitting the limit.

X-RateLimit-Remaining tracks the longest window only. Pace per-second and per-minute traffic from the documented limits, not from this header.

Responses to requests that fail authentication, such as a request with an invalid token, carry no X-RateLimit-* headers. A 429 from the rate limiter still carries Retry-After.

Working with rate limits

Read the rate limit headers on every response, not only on a 429 response. When X-RateLimit-Remaining is low, slow down. Spread the remaining requests over the time left until X-RateLimit-Reset. Do not sleep until the reset time on an endpoint with a daily limit. That wait can be hours.

On a 429 response with Retry-After, wait the number of seconds it gives. Then retry once. Treat Retry-After as a minimum wait, not an exact one. Do not retry in a tight loop. Do not use a fixed short delay instead of the header value.

Do not blind-retry a request that timed out with no response. On a write such as POST /v2/conversations/, the server may have accepted the request before the connection dropped.

Spread a bulk job across the window. Do not send it in one burst. For example, a job of 10,000 calls against a 300-per-minute limit sends about 5 requests per second when spread evenly. It finishes in about 33 minutes. A job that sends as fast as possible spends most of its run being rejected with 429 responses.

A 200 response can carry X-RateLimit-Limit: 300, X-RateLimit-Remaining: 12, and X-RateLimit-Reset: 1758112860. A later 429 response can carry Retry-After: 17.

Retry only when Retry-After is present. A 429 without it from a /v2/ endpoint is an application limit. Handle it as an error. A 429 from a legacy /data_api/v1.x/ endpoint carries no headers. Back off exponentially there, starting at one second.

Use this pattern to pace your requests:

response = send_request()
if response.status_code == 429:
retry_after = response.headers.get("Retry-After")
if retry_after is None:
raise ApplicationLimitError(response)
time.sleep(int(retry_after))
response = send_request()
elif response.ok:
remaining = response.headers.get("X-RateLimit-Remaining")
reset_at = response.headers.get("X-RateLimit-Reset")
if remaining is not None and reset_at is not None:
seconds_left = max(1, int(reset_at) - time.time())
if int(remaining) < THRESHOLD:
time.sleep(min(seconds_left / max(1, int(remaining)), 60))

Data limits

  • Max request body size: 10MB

Exceeding this size will result in a 413 Content Too Large error.

Some endpoints may also enforce local data limits. Refer to the documentation for each API endpoint for details on additional restrictions.