
If a call to https://api.hiapi.ai/v1/tasks comes back with a body like:
{
"error": {
"code": "model_not_found",
"message": "The model `gpt-image-2/text-to-image` does not exist.",
"type": "invalid_request_error",
"request_id": "20260626-…"
}
}
…or, if the model exists but your key isn't entitled to it:
{
"error": {
"code": "permission_denied",
"message": "This API key cannot use the selected model.",
"type": "hiapi_error",
"request_id": "20260626-…"
}
}
the call never reached generation — hiapi rejected the request at the routing layer. The fix is almost always one of four things below. Work them in order; the higher items account for most of these tickets.
model string — extra path suffix. Since the 2026-06 migration to the unified /v1/tasks endpoint, every model is referenced by its bare id only (e.g. gpt-image-2, nano-banana-pro, flux-1-1-pro). Older clients sometimes still send gpt-image-2/text-to-image or gpt-image-2:image; those used to work on the legacy /v1/chat/completions route but return model_not_found on /v1/tasks.gpt-image-2 ≠ gpt_image_2 ≠ GPT-image-2. A trailing newline from a .env read or a stray space pasted from a chat tool will fail with the same model_not_found message.-beta → stable, 1.0 → 1.5, etc.). hiapi keeps the model card live during a deprecation window, then removes the id — calls then 404 even though the spelling is correct.permission_denied for it — a different error code than model_not_found, and the fix is on the billing / key-scope side, not in the model string.model. Send only the bare id. If your old code did model: "gpt-image-2/text-to-image", change it to model: "gpt-image-2". The task endpoint discriminates image vs. video by the model id itself, not by a suffix.model string from there. This eliminates typos and stale ids in one step.model = os.environ["MODEL"].strip(). In Node: model.trim(). A trailing newline is the #1 silent killer of model strings read from .env files.model_not_found means the string is wrong — go back to steps 1–3. permission_denied means the string is fine but your key isn't entitled — check Dashboard → Billing and confirm your tier covers that model, or pick a model in your current tier from the catalog.request_id to any support email. Every hiapi error body carries one — paste it verbatim and we can trace the routing decision in one query instead of guessing from your local logs.Use a model id taken from the catalog and your hiapi key from Dashboard → API Keys. Replace $HIAPI_KEY:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"input": {
"prompt": "a small ceramic mug on a wooden table, soft window light",
"aspect_ratio": "1:1",
"resolution": "1K"
}
}'
Interpreting the response:
HTTP 200 with {"data":{"taskId":"…"}} → routing is healthy. Poll GET /v1/tasks/{taskId} until status: success, then read output[0].url for the final image.HTTP 400 / 404 with code: model_not_found → the model string is still wrong. Re-copy from the catalog page and check for a stray suffix or whitespace.HTTP 403 with code: permission_denied → the string is right, but your billing tier or key scope doesn't include the model. Adjust at Billing or pick another model.model field.model string and per-call pricing.Does model_not_found ever mean my key is wrong?
No. model_not_found is purely about the string in the model field. A bad key returns HTTP 401 with code: invalid_api_key, or HTTP 403 with code: permission_denied. If you see both kinds of error from the same script, the key and the model id are two separate problems — fix them in that order (key first, then model).
Why did gpt-image-2/text-to-image work last month but not now?
The 2026-06 platform migration unified all generation calls onto /v1/tasks, which keys models by bare id only. The path-suffix style was a hold-over from the older /v1/chat/completions route and is no longer accepted. Strip the suffix and the request goes through.
Can I list all valid model ids programmatically?
The models catalog page is the source of truth — the id shown on each model card is the exact string to pass in the model field. We don't expose a separate /v1/models listing endpoint; the catalog page is the contract.
The catalog still shows my model but I get permission_denied. What gives?
That's not a model error — it's a billing / scope problem. Some models are restricted to higher tiers or to keys explicitly allowlisted by the account owner. Pick a model in your current tier, or adjust the plan at Dashboard → Billing.
The error includes request_id — should I send it in?
Yes. Email support@hiapi.ai with the request_id from the JSON body and the exact model string you sent. That lets us trace the routing decision in a single query instead of asking you for repro steps.
Key Takeaways