Handle task states and errors correctly
A stable integration distinguishes active states, terminal states, idempotency conflicts, and temporary service errors. Progress=100 alone is not success.
Task states
| Status | Terminal | Action |
|---|---|---|
| queued | No | Continue polling |
| in_progress | No | Continue polling |
| completed | Yes | Stop and read metadata.url |
| failed | Yes | Stop and record the error |
Idempotent creation
- Repeating the same request body with the same user and key returns or resumes the same task.
- Using the same key with a different request body returns 409.
- After a timeout, disconnect, or 5xx response, do not immediately retry with a new key.
- Keep the original key and query the task or contact support to avoid duplicate work and charges.
- After an explicit 400, 401, 403, or 429, fix the problem and retry with the same key.
HTTP errors
| HTTP | Meaning | Action |
|---|---|---|
| 400 | Invalid fields, model, or parameters | Use message to fix the request |
| 401 | Missing, invalid, disabled, or expired key | Use a valid API key |
| 402 | Insufficient balance or quota | Top up or adjust quota |
| 403 | Model, account, group, or source restriction | Check permissions and IP rules |
| 404 | Task not found | Confirm the task ID |
| 409 | Idempotency conflict | Compare the original request body and key |
| 429 | Rate or concurrency limit | Wait for Retry-After and retry |
| 5xx | Temporary server failure | Retry safely with the idempotency contract |
{
"code": "invalid_request",
"message": "prompt is required",
"data": null
}Log safety
Log only HTTP status, response body, request time, public task ID, and request ID. Never log a full API key, Authorization header, or a media URL containing credentials.
Node.js polling example
Handle terminal states in server code.
Security guidance
Review key isolation, limits, and material review.