Skip to main content
Keep API keys in environment variables, never in source or client-side code. Handle the common status codes explicitly: 401 (bad API key), 403 (bad project ID), and 429 (rate limit). Set sensible timeouts and retries with backoff on 429 and 5xx. For large, non-real-time jobs, use the Batch and Files API instead of the synchronous endpoint - streaming is not supported in batch mode. Already on the OpenAI SDK? The drop-in client shown in the Introduction is the recommended way to call ZeroGPU from application code.

Keep secrets out of source

Read your x-api-key and x-project-id from the environment (or a secrets manager) and inject them at deploy time. Never commit them, never ship them in a browser bundle or mobile app - a key embedded in client-side code is a public key.
ZeroGPU calls authenticate from your backend. If you need to call from a browser or mobile client, proxy the request through a server you control so the key stays server-side.

Handle status codes explicitly

Branch on the status code. Authentication and authorization errors are permanent - retrying them just burns time and quota. Rate limits and server errors are transient - those are the ones to retry.
Treat 408 (request timeout) and 409 (conflict) the same as 5xx for retry purposes. Network errors and client-side timeouts are retriable too.

Rate limits

Your organization has limits for each model, shared by all of its API keys:
  • Requests per minute
  • Tokens per minute - counted when a request is accepted: the estimated input tokens plus max_tokens (max_completion_tokens, or max_output_tokens on the Responses API) for each of n choices. Tokens a response doesn’t use are not given back, so set max_tokens close to the size of the response you expect.
  • Concurrent requests - requests still in progress, including open streams.
Counts reset at the start of each minute. Audio endpoints have request and concurrency limits, but no token limit. Responses carry your limits in headers. A header is left out when that limit doesn’t apply. A request over a limit is rejected with 429 before it runs, and error.code says which limit it hit:
Rejected requests still count toward your requests per minute, so retrying in a tight loop keeps you limited. Batch jobs use the same limits as your synchronous calls. To raise a limit, contact support.

Set timeouts and retries

Three rules cover almost every case:
  1. Set a per-request timeout so a stalled connection can’t hang your worker.
  2. Retry only the transient codes (408, 429, 5xx) and network failures - never 401, 403, or 400.
  3. Back off exponentially with jitter, cap the delay, cap the attempts, and honor the Retry-After header on 429.
If you call ZeroGPU through the drop-in OpenAI client, timeouts and retries are built in - set timeout and max_retries once on the client. The SDK retries 408, 409, 429, and 5xx with exponential backoff and respects Retry-After automatically.
You can override either value per request, for example a longer timeout on a heavy call: client.responses.create(..., timeout=60.0).

Rolling your own

When you call the HTTP API directly, implement the loop yourself: a per-request timeout, a retriable-status check, and exponential backoff with jitter that honors Retry-After.

Use the Batch API for large jobs

For large, non-real-time workloads, the Batch and Files API is the right tool instead of looping over the synchronous endpoint. It processes up to 50,000 requests within a 24-hour window at a discounted rate and sidesteps per-request rate limits entirely - so you don’t need a retry loop at all.

Next steps

Batch & Files API

Authentication

API Reference