> ## Documentation Index
> Fetch the complete documentation index at: https://docs.get-exo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication error

> The request carried no credential, or one Exo could not validate.

This page is the resolution target of the RFC 9457 `type` URI on every `authentication_error` problem body: `https://docs.get-exo.com/errors/authentication_error`.

**HTTP status: `401` Unauthorized**.

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
{
  "type": "https://docs.get-exo.com/errors/authentication_error",
  "title": "Authentication error",
  "status": 401,
  "detail": "Missing or invalid credentials.",
  "code": "authentication_error",
  "requestId": "req_9f2c41ab7d0e5c18",
  "suggestedAction": "Send a valid API key as the X-Exo-API-Key header or as Authorization: Bearer exo_..."
}
```

## Why it happens

There is no anonymous surface. Every route resolves a principal before it does anything else, so a missing header, a malformed key, a revoked key and an expired key all land here.

A credential that is valid but insufficient is not this code. That is `permission_denied` with a 403.

## How to fix it

* Send the key as `X-Exo-API-Key: exo_<env>_<token>`, or as `Authorization: Bearer exo_<env>_<token>`. Both are accepted and equivalent.
* Check the key is still active with `GET /v1/keys`. A revoked key authenticates as nothing.
* If the credential is a dashboard session token rather than an API key, confirm it has not expired.

## Related

* [`permission_denied`](/errors/permission_denied)
* [`service_degraded`](/errors/service_degraded)
* [Errors](/platform/errors) for the envelope and the full catalogue
