Skip to content

Errors & Rate Limits

All Presto APIs use standard HTTP status codes. Successful responses return 2xx; errors return the appropriate 4xx or 5xx code with a JSON body describing the problem.

StatusMeaning
200 OKRequest succeeded
201 CreatedResource created successfully
400 Bad RequestInvalid request body or missing required fields
401 UnauthorizedMissing, invalid, expired, or revoked API key
403 ForbiddenValid key, but not authorized for the requested operation
404 Not FoundResource does not exist
429 Too Many RequestsRate limit exceeded — back off and retry
500 Internal Server ErrorUnexpected server error

The API enforces per-key rate limiting. Each API key has its own request budget, independent of other keys.

The default limit is 600 requests in any rolling 60-minute window per API key. This is a sliding window, not a fixed hourly reset — capacity frees up continuously as earlier requests age past 60 minutes. For sustained bulk submissions, pace your client at one request per 6 seconds or slower to stay under the limit indefinitely. Contact your organization administrator if you need a higher limit.

When you exceed the limit, the API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait.

Every API response includes rate-limit headers following the IETF RateLimit header fields draft:

RateLimit-Policy: "default";q=600;w=3600
RateLimit: "default";r=277;t=42
HeaderParameterMeaning
RateLimit-PolicyqQuota — requests allowed per window
RateLimit-PolicywWindow duration in seconds
RateLimitrRequests remaining in the current window
RateLimittSeconds until capacity next increases

On a 429, the standard Retry-After header (seconds) is also present:

HTTP/1.1 429 Too Many Requests
Retry-After: 42
RateLimit-Policy: "default";q=600;w=3600
RateLimit: "default";r=0;t=42

Example: pacing a bulk submission (Python)

Section titled “Example: pacing a bulk submission (Python)”
import re
import time
import requests
def submit(session: requests.Session, url: str, payload: dict) -> requests.Response:
while True:
resp = session.post(url, json=payload)
if resp.status_code != 429:
return resp
wait = int(resp.headers.get("Retry-After", "60"))
time.sleep(wait)
def remaining(resp: requests.Response) -> int | None:
m = re.search(r"r=(\d+)", resp.headers.get("RateLimit", ""))
return int(m.group(1)) if m else None
  • 401/403: Do not retry — fix the authentication or authorization issue
  • 429: Wait the number of seconds in the Retry-After header, then retry. If absent, use exponential backoff
  • 500: Retry with backoff; if persistent, contact support