https://api.runpod.io/v2. Requests to Serverless endpoints (https://api.runpod.ai/v2/ENDPOINT_ID/...) have separate per-endpoint limits, described in Send API requests.
How limits work
Each user has a quota for three windows:minute, hour, and day. A request counts against all three. When any window runs out, the API rejects further requests with 429 Too Many Requests until that window resets, even if the other windows still have quota left.
Rate limit headers
Responses to authenticated requests include two headers that follow the IETF RateLimit header fields draft. They’re present on successful responses as well as on 429 responses, so your client can track quota before it’s rejected. If your responses don’t include these headers, your requests aren’t subject to these limits.RateLimit-Policy describes the quota for each window. Each entry carries the quota q (requests allowed) and the window length w in seconds:
RateLimit describes the live state of each window. Each entry carries the remaining request count r and the seconds t until the window resets:
RateLimit-Policy header on your own responses, and don’t hardcode them in your client.
429 responses
When your client exceeds a window, the API returns429 Too Many Requests with a Retry-After header that gives the number of seconds to wait, plus the RateLimit and RateLimit-Policy headers. The body uses the same application/problem+json format as other v2 errors, and detail names the window you exceeded:
Build a client that respects limits
Design your integration to treat a 429 as an expected signal rather than a failure:- Wait for the number of seconds in
Retry-Afterbefore retrying. Retrying sooner returns another 429. - Watch the
RateLimitheader and slow down whenrfor any window gets close to zero, instead of waiting for a 429. - Cap the number of retries, and surface an error once the cap is reached.
- Add random jitter to retry delays so that multiple workers or processes that were rejected together don’t retry at the same moment.
- Reduce request volume where you can. For example, list resources once and reuse the result instead of fetching each resource in a loop. Cache data that changes rarely, such as the catalog.
- Share one rate-limit-aware client across your code. Quotas are per user, so separate processes using the same API key draw from the same quota.
5xx) and network timeouts are usually transient, so retrying GET requests with exponential backoff is safe. A POST that creates a resource, such as a Pod, may have succeeded even though your client didn’t receive the response. Before retrying it, list your resources to check whether the first attempt went through, or you may create a duplicate. Don’t retry other 4xx errors without changing the request, because they won’t succeed on their own.
Example
The following Python client honorsRetry-After on 429 responses and pauses when the minute window is almost empty. It also retries transient errors on GET requests with exponential backoff and jitter. It requires the requests package and a RUNPOD_API_KEY environment variable.
request function sends every call through one shared session and handles each outcome differently:
- A 429 response waits for the number of seconds in
Retry-After, plus up to one second of jitter, and then retries. If the header is missing, the client falls back to exponential backoff. - A network error or a
5xxresponse is retried with exponential backoff only forGETrequests. Other methods raise the error immediately, because aPOSTthat timed out may already have created a resource. - A successful response is passed to
seconds_until_reset, which reads theminuteentry of theRateLimitheader. When no requests remain in that window, the client sleeps until the window resets, so the next call doesn’t receive a 429.
MAX_RETRIES attempts, the client raises an error instead of retrying indefinitely.
Next steps
- Send API requests: Learn about the separate rate limits for Serverless endpoint requests.
- API v2 overview: Review the base URL, authentication, and available resources.
- Migrate from v1: Move an existing REST v1 or GraphQL integration to API v2.