Why your hiapi task callback isn't firing
You submitted a job to POST https://api.hiapi.ai/v1/tasks with a callback object, the task finished (you can see status: "success" when you GET /v1/tasks/{taskId}), but your endpoint never received the terminal notification. No request hit your server. No retry. Nothing in your logs.
The hiapi callback is delivered as a server-to-server HTTPS POST from outside your network. If anything in that path is off — the URL isn't reachable from the public internet, TLS won't negotiate, your handler doesn't return 2xx quickly enough, or the signature check on your side rejects the request — the notification looks "silent" from your application's point of view. The good news: this is almost always one of a small set of misconfigurations, and every one of them is straightforward to verify.
Common causes, in order of likelihood
- The callback URL isn't reachable from the public internet.
localhost,127.0.0.1, an IP inside your VPC, or an ngrok tunnel that has already expired — hiapi can't reach any of them. - HTTPS / TLS problems. Self-signed cert, expired cert, missing intermediate, or hostname mismatch. hiapi only POSTs to
https://URLs and validates the chain. - Your handler doesn't return
2xxwithin the timeout. If you do heavy work synchronously inside the callback handler (DB writes, image downloads, sending notifications), the request times out before you return200. From hiapi's side, that looks like a failure. - You never registered a Webhook Sign Key, and your handler rejects unsigned requests. Without a sign key generated in Settings, hiapi delivers the body without a signature header — and any verification middleware you wrote will treat the request as invalid and drop it.
- The
callbackobject was omitted at submission. It's optional. If you didn't include it onPOST /v1/tasks, there is nothing to fire. You must pollGET /v1/tasks/{taskId}instead. - The task is still running. Callback fires on a terminal state (
successorfail). Whilestatusisqueued,handling, orarchiving, no callback is sent yet. - The callback URL host is on a denylist / corporate firewall is blocking egress to it. Less common, but worth checking if you're behind a strict perimeter.
Fix it: a 7-step checklist
- Confirm the task actually reached a terminal state.
curl -H "Authorization: Bearer $HIAPI_KEY" https://api.hiapi.ai/v1/tasks/tk-hiapi-.... Ifstatusisqueuedorhandling, the callback hasn't fired yet — wait, don't debug. - Confirm you submitted a
callbackobject. Re-read the request body you sent toPOST /v1/tasks. Ifcallbackis missing, that's the answer — add it and resubmit, or switch to polling. - Test the callback URL from the public internet. From any machine outside your network (your phone on cellular, a cloud shell, an online curl tool), run
curl -i -X POST https://your.domain.example/hiapi/callback -d '{}' -H "Content-Type: application/json". You must get back HTTP2xxfrom your own server. If you get connection refused, DNS errors, or anything other than2xx, fix that first. - Validate the TLS chain.
curl -vI https://your.domain.example/hiapi/callback 2>&1 | grep -i 'ssl\|cert'. Look forSSL certificate problem. If you see one, install the full chain (leaf + intermediate) or use a managed cert (Let's Encrypt, CDN, ACM). - Return
200immediately, then process asynchronously. Inside your handler: write the payload to a queue / table, return200 OK, and process the work in a background worker. Don't block the response on slow downstream calls. - Generate a Webhook Sign Key and align your verification. Go to
/en/dashboard/settings→ Webhook Sign Key → Generate, save the key. If your handler checks signatures, use the saved key; if not, disable the check for now and re-enable after you've confirmed delivery. - Check
/en/dashboard/logs. The call log shows the request and its terminal status. Comparing therequest_idfrom your call log to what (if anything) your server received is the fastest way to localize "did the callback leave hiapi" vs "did it reach my server".
Minimum verification example
Use this to confirm your API key, the create-task path, and your callback endpoint end-to-end. Pick a quick image model for the smoke test; per the public docs, the model id includes the capability suffix:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/text-to-image",
"input": {"prompt": "a cute cat"},
"callback": {"url": "https://your.domain.example/hiapi/callback"}
}'
You should get back a JSON response with a taskId like tk-hiapi-... immediately. Then watch your server logs for an inbound POST to /hiapi/callback once the task transitions to success or fail. If the create-task step itself returns 401 Unauthorized instead, the key is the problem — see Why hiapi returns 429 (and what to do) for how hiapi's error envelope works (the same hiapi_error shape applies across status codes).
Related links
- API Keys — verify your key is active and scoped correctly
- Settings — generate or rotate your Webhook Sign Key
- Call Logs — confirm hiapi sent the callback and the response status
- API Reference — full
POST /v1/tasksandGET /v1/tasks/{id}specs - hiapi 429 rate limit — error envelope walkthrough for the related "you got a status but no callback" cousin problem
FAQ
Will hiapi retry a failed callback?
A callback is considered delivered only when your endpoint returns a 2xx response. If your handler returns 5xx, times out, or the TLS handshake fails, treat the callback as not delivered. The most robust pattern is: always poll GET /v1/tasks/{taskId} as a fallback for any task you submitted with a callback. That way one outage on your callback path doesn't lose the result.
Can I use HTTP instead of HTTPS for the callback URL?
No. Only https:// URLs are accepted. If you're testing locally, use a tunnel that terminates TLS for you (Cloudflare Tunnel, ngrok, tailscale funnel) and point the callback at the public HTTPS endpoint.
Why does my handler receive the body but signature verification fails? Either (a) you generated the Webhook Sign Key after you submitted the task — the request was signed with the older key (or no key) — so regenerate, save, and submit a fresh task; or (b) your verification code is rebuilding the canonical string differently than hiapi does. Log the exact bytes of the request body your server received and re-run the HMAC over those exact bytes, no JSON re-serialization in between.
The taskId says success but I got no callback and no result URLs.
Re-fetch GET /v1/tasks/{taskId} and look at the output array. URLs in output[*].url are time-limited (expireAt); download immediately. The callback delivery and the URL freshness are two separate concerns — even with no callback, the GET endpoint is the source of truth.
I see the callback in /en/dashboard/logs but my server never logged it.
That points at your perimeter, not at hiapi. Common culprits: CDN / WAF rules blocking POSTs with no User-Agent your team recognizes, IP allowlists on your firewall, or your reverse proxy rewriting the path. Allow the inbound POST on the firewall and rerun.
Does the callback URL count against my account's rate limit?
No. The callback is a delivery from hiapi to you and is independent of your POST /v1/tasks rate budget.



