INVALID_API_KEY: API key invalid or revoked
{
"error": {
"type": "unauthorized",
"code": "INVALID_API_KEY",
"message": "API key invalid or revoked"
}
}
The header was well-formed — that part is fine. The key inside it did not verify.
Invalid and revoked return the same error on purpose
The message says “invalid or revoked” because the response does not distinguish between them. Telling an unauthenticated caller “that key used to exist” is a small information leak with no upside for a legitimate user, who can see the key’s real status on their own dashboard.
So the checklist is the same either way.
What to check, in order
- Whitespace. Copying a key out of a terminal or a JSON blob commonly picks up a trailing newline. It is invisible in most logs and breaks verification.
- The right environment. Keys do not move between accounts. A key from a different account, or from a teammate’s, will fail here.
- Revoked. Check the key list on your dashboard. If it is gone or marked revoked, issue a new one — the old string will never work again.
- Truncation. Some secret managers silently cut values at a length limit. Compare the length of what your process actually received against the original.
A quick isolation test
curl -i https://genace.ai/api/v1/models \
-H "Authorization: Bearer YOUR_API_KEY"
/v1/models needs authentication but costs nothing and touches no quota. If
this returns 200 and your real call still fails, the key is fine and the
problem is elsewhere in that request.
If it returns MISSING_API_KEY instead, the header never arrived in the shape
you think it did — see MISSING_API_KEY.
Where these facts come from
- codebase: src/ai/api/auth.ts — key verification path