Developer API

Reliability, errors, and rate limits

Build retry-safe requests with idempotency, stable error codes, response headers, and cost safeguards.

Make every POST idempotent

Send an Idempotency-Key containing 8 to 255 letters, numbers, underscores, or hyphens. The key is scoped per API key and retained for 24 hours; retry the same logical operation with the same value.

The retry replays the stored response, marked Idempotent-Replay: true; nothing is generated or charged twice.
Try this
POST /api/v1/images Idempotency-Key: order-58213-hero-image {"prompt": "product photo of a walnut desk lamp on white", "n": 1} Then send the identical request again after a network timeout.
What you getThe second call returns the original response instead of generating and charging for a second image; a key shorter than 8 characters is rejected with OPMD_IDEMP_001.

Handle errors by meaning

400 means the request is invalid, 401 the key is missing or invalid, 402 credits are insufficient, 403 permission or IP policy blocked the call, 409 the same idempotent operation is still running, 429 the rate limit was exceeded, and 5xx indicates a gateway or server problem.

402 is stop-and-alert, never a retry; only a 5xx api_error is retried, with jitter.
Try this
Map status codes to actions in your client: 400 fix the request, 401 check the key, 402 top up credits, 403 check permission or IP allowlist, 409 wait and re-read with the same Idempotency-Key, 429 back off, 5xx retry with jitter.
What you getA run with an exhausted balance stops at 402 with error.code OPMD_BILLING_001 and alerts finance instead of retrying, while a 5xx retries a bounded number of times.

Use stable machine codes

Branch on error.code rather than parsing prose. Safe messages can be surfaced to users; keep X-Request-ID with logs and support reports.

Branch on error.code, show error.message to users as written, keep X-Request-ID for support.
Try this
switch (body.error.code) { case 'OPMD_RATE_001': backOff(); break; case 'OPMD_BILLING_001': notifyBilling(); break; default: log(res.headers['x-request-id'], body.error.code); }
What you getEach failure branches on the stable code, error.message can be shown to users as written, and the X-Request-ID sits in your logs for any support report.

Respect RateLimit headers

Every response carries RateLimit information. Slow down before exhausting the budget, add jitter to retryable backoff, and do not retry validation, authentication, permission, or billing failures unchanged.

Wait RateLimit-Reset seconds plus jitter before retrying; the default budget is 120 requests per minute per key.
Try this
After each response read the RateLimit-Remaining header; when it falls below 10 percent of RateLimit-Limit slow your queue, and on a 429 wait for RateLimit-Reset plus random jitter before retrying.
What you getBursts flatten before the limit is hit; a 429 with OPMD_RATE_001 waits out the window, while 400, 401, 402 and 403 responses are never retried unchanged.

Protect spend

Bound max_tokens, image count, duration, and concurrency in your own application. Monitor usage and credits, set billing alerts, and place expensive generation behind user authorization.

max_tokens bounds the worst case; usage.output_tokens reports what you actually paid for.
Try this
In your application, cap max_tokens at 1500, image n at 2 and video duration_seconds at 15, run at most 3 generations at once, and require a signed-in user before any /videos call.
What you getSpend stays inside the bounds you set no matter what a user types, and the Developer console's usage view and your billing alerts confirm the pattern rather than surprise you.
GUIDED LEARNING

Practise this in Oppermind Academy

Follow the related tutorial or course and apply the concept to a real task.

Open learning path