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.

Status Meaning
200 OK Request succeeded
201 Created Resource created successfully
400 Bad Request Invalid request body or missing required fields
401 Unauthorized Missing, invalid, expired, or revoked API key
403 Forbidden Valid key, but not authorized for the requested operation
404 Not Found Resource does not exist
429 Too Many Requests Rate limit exceeded — back off and retry
500 Internal Server Error Unexpected 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
Header Parameter Meaning
RateLimit-Policy q Quota — requests allowed per window
RateLimit-Policy w Window duration in seconds
RateLimit r Requests remaining in the current window
RateLimit t Seconds 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