Tutorial
HiAPI Returns 403 No Model Permission: Troubleshooting and Fix Guide
Distinguish 403 from 401, and locate in three steps which Key lacks permission
When calling HiAPI's /v1/tasks endpoint, if you receive HTTP 403, the response body usually has this structure: {"error": {"code": "permission_denied", "message": "...", "request_id": "...", "type": "hiapi_error"}}. This indicates that your API Key itself is valid and authentication has passed, but this Key is not authorized to call the model or endpoint you requested—this is a different kind of problem from the 401 for "invalid or missing Key": 401 means the identity was not recognized at all, while 403 means it was recognized but this Key is not allowed to use the current resource. Most 403 fixes are straightforward: verify that the Key matches the model, then retry with a Key that has permission.
Common Causes
- The API Key is not authorized to use the requested model—the official documentation defines 403 as "the API key does not have this permission," which is the most common trigger scenario, usually occurring when the same Key is used to call a model outside its permission scope.
- The wrong Key was used—for example, a primary Key should have been used, but a Key with a smaller permission scope under another account or project was used by mistake; copying and pasting can also easily introduce extra spaces or truncation.
- Confusing "invalid key" (401) with "key has no permission" (403)—both may contain wording related to "permission" in their error messages, so troubleshooting them with the same approach leads in the wrong direction. See below for how to distinguish them.
Fix Steps
- First confirm that the response really is 403, not 401—look at the HTTP status code itself, not just the error message text, because the
permission_deniederror code can appear under both 401 and 403; the distinguishing factor is the status code, not the wording. - Go to API Key Management to verify which Key this is—confirm that the Key actually used in the request is indeed the intended one, not a Key under a test account, an old project, or someone else's account.
- Verify whether the current model is within the scope available to this Key—check the authentication documentation and HiAPI pricing to confirm that the model itself actually exists and is within your callable scope; if the model ID itself is misspelled or has been retired, the error should be a different error code rather than
permission_denied—you can use this to help distinguish the type of problem. - Switch to a Key confirmed to have permission, and retry once with all other parameters exactly the same, to verify whether the problem disappears when the Key is switched.
- If the Key and model both check out but the 403 still reproduces consistently, note the
request_idin the response body and contact support; do not repeatedly retry the same request without confirming the cause.
Minimal Verification Example
Below is a request that triggers 403 and a retry after the fix, showing the actual response structures in both states (replace MODEL_ID with the model you are actually calling and suspect lacks permission):
curl https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MODEL_ID",
"prompt": "a simple test prompt"
}'
Response when there is no permission:
{
"error": {
"code": "permission_denied",
"message": "The current API Key cannot use this model for now. Please check permissions or change the Key.",
"request_id": "req_xxxxxxxx",
"type": "hiapi_error"
}
}
Retry with a Key that has permission, with all other parameters unchanged:
{
"code": 200,
"data": { "taskId": "tk-hiapi-xxxxxxxx" },
"message": "success"
}
Note that the two response bodies have different structures: authentication/permission-level errors such as 403 are uniformly wrapped in an error object; whereas errors that occur after the Key passes the permission check and actually enters the specific business rule evaluation (such as a 402 for insufficient balance) return a flat structure of code / data / message. Seeing which structure is returned roughly tells you whether the problem is at the authentication permission layer or the specific business rule layer.
Related Internal Links
FAQ
What exactly is the difference between 403 and 401?
401 means the Key itself is invalid, or the request did not include a Key at all—the identity authentication step did not pass. 403 means identity authentication passed (the Key itself is valid), but this Key is not authorized to use the model or resource you requested. Both have the same response body structure (both wrap an object in error.code); the key to distinguishing them is the HTTP status code itself, not the text in the error message.
Still getting 403 after switching Keys—is there a problem with the account?
First confirm that the new Key really belongs to the same account or project that has permission, and that there are no extra spaces, line breaks, or truncation from copying and pasting. If it still reproduces after verification, contact support with the request_id from the response body.
Is 403 caused by insufficient balance?
No. Insufficient balance corresponds to a different error code (INSUFFICIENT_QUOTA, HTTP 402) and is a separate matter from permissions—403 only indicates "whether this Key is eligible to call this model" and has nothing to do with the account balance.
If the word "permission" appears in the error message, does that necessarily mean 403?
Not necessarily. The permission_denied error code can appear under both 401 and 403; you cannot judge based only on text keywords—you must look directly at the HTTP status code itself.
Related articles
View all articles →-
Tutorial
How to Call hailuo-2.3-fast/image-to-video via the HiAPI API: curl and Python
A first working request for the fast, low-cost image-to-video tier — from model ID to downloaded MP4
9 min read -
Tutorial
How to Use hailuo-2.3/text-to-video via the HiAPI API: curl, Python, and a Working Request
11 min read -
Tutorial
Kandinsky 6.0 Pro Text-to-Video on HiAPI: curl and Python Tutorial
A request-first walkthrough: build the prompt-to-clip call, submit it, poll for completion, and download the result
11 min read