Seeing a message like "the api keys data are invalid" (or a similar variant your app surfaces) when calling hiapi means the request never got past authentication. Under the hood, hiapi's own API returns a specific error for this: HTTP 401 with error.code: "permission_denied" and the message "This API key is invalid. Check that it is correct or use another API key and try again." Any app that wraps hiapi — a backend proxy, an OpenAI-compatible client, an internal SDK — re-labels that same 401 in its own words, which is why the exact text you see rarely matches hiapi's. This guide walks through why it happens and how to confirm and fix it in a few minutes.
What the error actually looks like
A failed request to POST https://api.hiapi.ai/v1/tasks (or any other hiapi endpoint) returns:
{
"error": {
"code": "permission_denied",
"message": "This API key is invalid. Check that it is correct or use another API key and try again. If the issue persists, contact support with request ID: <id>",
"request_id": "<id>",
"type": "hiapi_error"
}
}
with HTTP status 401. If your framework or SDK doesn't surface the raw response, it may repackage this into a generic "API key(s) data are invalid," "unauthorized," or "invalid credentials" message — but the root cause on hiapi's side is always this same 401.
Common causes, most likely first
- The key value is wrong. A truncated copy-paste, an extra space, or a key copied from an old note instead of the live one in Dashboard → API Keys triggers this exact error — hiapi returns the identical message whether the key is garbled, empty, or simply doesn't exist.
- A placeholder key was never swapped out. Code copied from a tutorial or template often ships with a literal string like
sk-your-api-key— that 401s the same way a random string would. - The key was rotated or revoked. Creating a new key in the dashboard doesn't invalidate old ones automatically, but manually revoking or regenerating one does — if a deploy still references the old value (an env var that wasn't redeployed, a
.envthat wasn't reloaded), every request 401s. - The key is sent in the wrong header. hiapi only reads the key from the
Authorizationheader. Sending it asx-api-key,api-key, or a query parameter produces the identicalpermission_deniedresponse, because hiapi doesn't see a malformed key in that case — it just sees no key at all. - The environment variable is empty at runtime. If your process reads the key variable before your
.envfile is loaded, you send an empty string as the key — same 401. - Hidden whitespace or a newline got baked into the key. This is subtle: piping a secret through
echoin a shell script appends a trailing newline to the value. If that lands inside anAuthorizationheader, it can corrupt the request in a different way — instead of a clean 401, you get a400with a garbledinvalid json bodymessage, because the broken header bleeds into the request body. If your error looks like a malformed request rather than a clean "invalid key," check for stray whitespace or line breaks in the key before anything else.
Fix it in order
- Open Dashboard → API Keys and copy the key fresh. Don't reuse a value from old terminal history or a message — copy it directly from the page.
- Confirm the header format matches exactly:
Authorization: Bearer YOUR_API_KEY. If you're assembling this value in a shell script, useprintfrather thanecho—echoappends a trailing newline thatprintfdoesn't. - Print the value right before the request fires (a
console.log,print, or debug log) to confirm it's non-empty and free of stray quotes, spaces, or line breaks. - Isolate the key from your app by testing it with a plain
curlcall (below). If curl succeeds and your app still fails, the bug is in how your app builds the request, not the key itself. - Check the exact HTTP status you're getting. A
401is this error. A402means the account balance is empty rather than the key being wrong. A403means the key is valid but lacks permission for that specific model. A429means you're being rate limited. None of those three should be treated as an invalid-key problem.
Minimal verification example
Run this directly, with your real key swapped in, to confirm whether the key itself is the problem:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-image-2", "input": {"prompt": "a small red apple on a white background"}}'
A working key returns a task ID immediately:
{"code": 200, "data": {"taskId": "tk-hiapi-..."}, "message": "success"}
A bad key returns the 401 shown above instead. If curl returns the taskId response but your application still throws an "invalid key" error, the problem is in your application's request-building code, not the key.
Related
- Authentication docs — the full header format, key rotation guidance, and status-code reference.
- Dashboard → API Keys — where to create, copy, and revoke keys.
- Rate limits — how a 429 differs from a 401 and what triggers it.
- Quickstart — a full first-request walkthrough if you're setting up hiapi for the first time.
FAQ
Is "invalid API key" the same as being rate limited?
No. A 401 permission_denied means the key itself wasn't accepted. A 429 with error_code: "RATE_LIMITED" means the key is fine but requests are arriving too fast — see the rate limits docs for the threshold.
I just created a new key and it's still invalid — why? Make sure the new key was actually copied into whatever is making the request. A new key in the dashboard doesn't retroactively fix a hardcoded old value, an unset environment variable, or a config file that wasn't redeployed.
Does hiapi require the literal word "Bearer" in the header?
The documented and supported format is Authorization: Bearer YOUR_API_KEY — always use it. Don't rely on any leniency you might observe while testing; undocumented behavior can change without notice.
Why does curl work but my app doesn't?
If curl with the same key succeeds, the key is valid and the problem is in how your app assembles the request — usually a missing Bearer prefix in code, an environment variable read before .env loads, or the key passed to the wrong parameter in a wrapper library.
What does error.type: "hiapi_error" mean?
It's hiapi's generic error envelope, used for this authentication failure and other request errors alike. Check error.code (permission_denied here) to know what's actually wrong, not just the envelope type.









