You call POST https://api.hiapi.ai/v1/tasks (or poll GET /v1/tasks/{id}) and, instead of the usual 200 with a taskId, the response comes back as 502 Bad Gateway or 503 Service Unavailable. Both are 5xx responses, which means the problem is on the server or transport side, not in your request: you did not send a bad parameter, a bad key, or a malformed payload. A 503 is HiAPI's documented "platform temporarily unavailable" signal and tells you to retry; a 502 is a gateway-level response from somewhere on the path. This guide shows how to confirm that, retry safely without double work, and tell a 502/503 apart from a 504 timeout and a TASK_FAILED result.
What a 502 or 503 actually looks like
You see one of these on the HTTP status line, in place of the normal 200:
503 Service Unavailable— this one is documented. HiAPI's async-API docs list503as "Platform temporarily unavailable; retry later with exponential backoff," and the matching business code isTEMPORARILY_UNAVAILABLE("Generation service is temporarily unavailable. Retry later; contact support if the problem persists."). HiAPI's synchronous errors use a flat JSON envelope — documented as{"code": 400, "message": "...", "data": null, "error_code": "INVALID_REQUEST"}for a 400 — so a 503 carries the same shape witherror_code: "TEMPORARILY_UNAVAILABLE".502 Bad Gateway— this one is not in HiAPI's documented status codes. In standard HTTP, a 502 means a gateway or proxy received an invalid or empty response from the next hop it tried to reach. So a 502 you receive is produced by a gateway on the path — an edge/CDN layer, a load balancer, or a proxy on your own network — rather than by the HiAPI application returning its usual JSON envelope. The body is frequently a short HTML or plain-text gateway page, and that non-JSON body is itself a signal that this is a transport/gateway condition, not an application error with a fixed, documented payload.
Either way the status is 5xx: the server or transport side, not your request. That is the opposite of a 4xx — a 400 (bad parameter), a 401 (bad key; HiAPI returns a nested {"error": {"code": "permission_denied", "type": "hiapi_error", "request_id": "..."}}), or a 402 (low balance) — all of which you fix by changing something on your side. A 502/503 is not fixed by editing your payload.
Common causes, most likely first
- A brief platform overload or maintenance window →
503TEMPORARILY_UNAVAILABLE. This is the expected, documented case. It clears on its own, and a backed-off retry succeeds. - A momentary hiccup at a gateway or proxy on the path →
502. An edge/CDN layer, a load balancer, or a proxy on your own network briefly failed to relay the response. Also transient. - A traffic burst that tripped a limit. Under load you may instead see
429RATE_LIMITED("retry later; avoid immediately resubmitting the same request"). If the status is 429, the fix is to slow your send rate, not to retry harder. - The requested model backend being momentarily unavailable. HiAPI documents this at the task level as
MODEL_UNAVAILABLE("Retry shortly, or switch models"); a platform-level blip serving that model can also surface as a 503. - Not a bad key, a malformed body, or low balance. Those are
401/400/402respectively, and none of them present as a 502 or 503.
How to fix it, in order
- Confirm it is a 5xx, not a 4xx. Read the status code first.
502/503are server/transport side;400,401,402,404,409,415,422, and429are your side. If it is genuinely a 502/503, do not start rewriting your request body — that only helps for 4xx. - Retry with exponential backoff and jitter. The docs prescribe exponential backoff for 503 explicitly. A safe client pattern is to start around 1s, double each attempt (2s, 4s, 8s, …), cap at roughly 30–60s, and add random jitter so many clients do not retry in lockstep. These intervals are a recommended client-side pattern, not a HiAPI-published timing guarantee.
- Make the submit idempotent. On
POST /v1/tasks, set anIdempotency-Keyheader (any UTF-8 string up to 255 bytes). If a 502/503 leaves you unsure whether the task was actually created, retrying with the same key is safe: same key + same body returns the originaltaskIdwith the headerIdempotent-Replay: trueinstead of creating a second task or a second charge. Keys are scoped to your account and expire after 24 hours. The full contract is in the Unified Async API docs. - Do not blindly re-POST without a key. If you submitted with no
Idempotency-Keyand got a 502/503, you may have created a task you cannot see — you have notaskIdto poll, so a naive retry risks duplicate work and duplicate charges. Add the key before you retry at any scale. - If the 502/503 happened while polling, just keep polling. A 5xx from
GET /v1/tasks/{id}does not change the task. Terminal states (success/fail) are fixed once reached and never convert to each other, so back off and poll again. Alternatively, register acallback.urlso you are notified at the terminal state instead of polling through transient 5xx — deliveries are at-least-once, so deduplicate bytaskId. - Separate it from a task-level failure. If you instead get HTTP
200with"status": "fail", that is not a 502/503 — the task was accepted, ran, and failed. HandleTASK_FAILED("Retry once; contact support if the problem persists") orTASK_TIMEOUT("Retry the task") on their own terms, not with blind gateway retries. - If it persists, escalate instead of hammering. If a 502/503 continues across several backoff retries over a few minutes, treat it as a transient platform incident rather than something to brute-force. Stop retrying aggressively and contact support with the
request_idfrom the error body when one is present. You can confirm your own account and connectivity are healthy from your HiAPI dashboard.
502 / 503 vs 504 vs TASK_FAILED
These are easy to conflate because they all mean "it didn't come back clean," but they need different handling:
| Response | HTTP code | Where it comes from | Task charged? | What to do |
|---|---|---|---|---|
503 Service Unavailable | 503 (documented) | HiAPI platform — temporarily unavailable or overloaded | No task created, nothing charged | Retry later with exponential backoff |
502 Bad Gateway | 502 (not in HiAPI's docs) | A gateway/proxy on the path (edge, load balancer, or your own proxy) | Usually no task created | Idempotent retry with backoff; if it only happens from your network, suspect a proxy on your side |
504 Gateway Timeout | 504 (not in HiAPI's docs) | A proxy/CDN on your side — not HiAPI's API | n/a to HiAPI | See the 504 guide below; HiAPI's own timeout is TASK_TIMEOUT, not a raw 504 |
TASK_TIMEOUT | 200 + "status": "fail" | HiAPI — the task ran but exceeded its time budget | No (reserved amount refunded) | Retry the task as a new request |
TASK_FAILED | 200 + "status": "fail" | HiAPI — the task was accepted and ran, then failed | No (reserved amount refunded) | Retry once, then read error.message |
429 RATE_LIMITED | 429 | HiAPI — you are sending too fast | No task | Back off; do not immediately resubmit |
400 / 401 / 402 | 4xx | HiAPI — client-side (bad body / key / balance) | No | Fix the request, key, or balance; retrying will not help |
The one-line test: a 502/503/504 is an HTTP transport error that carries no task result, while a TASK_FAILED / TASK_TIMEOUT arrives as HTTP 200 with "status": "fail" and an error object. The first is "the request didn't get through"; the second is "the request got through, the task ran, and it failed."
Minimal verification example
Use one clean submit to prove your key and connectivity are fine and isolate the 502/503 as transient. Use the bare model id (for example gpt-image-2, with no /text-to-image suffix), and include an Idempotency-Key so a retry is safe:
# A healthy submit returns 200 with a taskId. If this works but a specific
# call just 502/503'd, that 502/503 was transient — not your setup.
curl -sS -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-job-0001" \
-d '{"model":"gpt-image-2","input":{"prompt":"a red bicycle on a white background"}}'
# Then poll the task you just created (swap in the returned id):
curl -sS https://api.hiapi.ai/v1/tasks/TASK_ID \
-H "Authorization: Bearer $HIAPI_API_KEY"
If the submit itself returns 200 and a taskId, your authentication and network path are working, and the earlier 502/503 was a transient server/transport condition — retry the failed call (reusing the same Idempotency-Key returns the original task instead of a duplicate). If the submit returns 401 or 400 instead, that is a client-side problem, not a 502/503.
Related
- HiAPI Task Timeout and 504 Errors: How to Fix Them — why a raw
504isn't from HiAPI, and whatTASK_TIMEOUTmeans. - HiAPI TASK_FAILED Error: Causes and How to Fix It — handling a task that returns
200+"status": "fail". - When a hiapi /v1/tasks Job Hangs or Times Out: Diagnosis and Retry — polling intervals and retry strategy in depth.
- How to Fix HiAPI Rate Limit (429) Errors — when the real problem is send rate, not availability.
- Why Do Failed HiAPI Requests Still Get Charged? — how reservations and refunds work for failed tasks.
FAQ
Is a 502 or 503 my fault?
No. Both are 5xx responses, which are server-side or transport-side. Your API key and request body were not the trigger — a 4xx (400/401/402) is the family you cause and can fix. The right response to a 502/503 is an idempotent retry, not a code change.
What is the difference between a 502 and a 503 on HiAPI?
A 503 is HiAPI's documented "platform temporarily unavailable" code (error_code: TEMPORARILY_UNAVAILABLE) and comes from the platform itself. A 502 is not in HiAPI's documented status codes; in standard HTTP it is emitted by a gateway or proxy on the path when it gets an invalid response from its upstream. Both are transient and both call for a backed-off retry, but a 502 can also point to a proxy on your own network.
How is a 503 different from a 504?
A 503 means the service is temporarily unavailable or overloaded right now. A 504 Gateway Timeout means something waited too long for a response. HiAPI does not emit a raw 504 — a client-seen 504 comes from a proxy/CDN on your side. HiAPI's own "took too long" state is a task result, TASK_TIMEOUT (HTTP 200 + "status": "fail"). See the 504 guide above.
How do I tell a 502/503 apart from a TASK_FAILED result?
By the HTTP status. A 502/503 is an HTTP error with no task payload. A TASK_FAILED comes back as HTTP 200 with "status": "fail" and an error object — the task was accepted and ran. Retry a 502/503 with backoff; retry a TASK_FAILED once and then read error.message.
Will retrying after a 502/503 charge me twice or create duplicate tasks?
Not if you send an Idempotency-Key header on POST /v1/tasks. Reusing the same key + body returns the original taskId (Idempotent-Replay: true) instead of creating a duplicate. And failed tasks are never charged — the amount reserved at creation is refunded in full once a task reaches the failed terminal state.
How long should I back off, and when should I escalate?
Use exponential backoff with jitter (for example 1s, 2s, 4s, 8s, capped, with randomness). If 502/503 keeps coming back across several retries over a few minutes, stop retrying aggressively and contact support with the request_id from the error body — persistent 5xx usually means a transient platform incident rather than anything a faster retry loop will fix.
Should I change my request payload when I see a 502/503?
No. A 502/503 is not a validation error, so editing your parameters will not help and can mask the real, transient cause. Keep the request identical, add an Idempotency-Key if you have not, and retry with backoff.


