Error reference

unauthenticated

HTTP 401 retryable: false REST and MCP

The request carried no usable bearer credential, so there is no principal to authorise and the server stopped before looking at what you asked for.

Why it happens

Credential resolution happens in one place and fails closed. A missing Authorization header, a key that does not verify, and an expired one all land on the same code, because distinguishing them in the response would tell an unauthenticated caller which of their guesses was closer. The MCP endpoint adds a second, stricter gate on top: it inspects the token shape before resolution and rejects human session tokens outright, with a WWW-Authenticate header naming the protected resource.

Every condition below was read in the implementation at the file and line given. They are the branches that raise this code, not a summary of what the name suggests.

How to fix it

  1. Send Authorization: Bearer <credential>. The scheme is checked case-insensitively but it must be present.
  2. Check the key prefix against the environment you are calling. A credential is efa_live_ or efa_test_ followed by eight hex characters and a 43-character body, and the secret is returned exactly once at creation.
  3. For /mcp, use the access token from a completed OAuth connection grant. A console session token is rejected by shape at the endpoint, before resolution.
  4. Rotate rather than retry. This code is not retryable and a credential that failed verification will keep failing.

Why it works this way

The MCP endpoint refuses a human session token by prefix rather than resolving it and refusing later. The gate is cheap, it cannot be reached by a token that happens to resolve to something surprising, and it produces a message that names the correct credential type instead of a generic denial.

Messages you will see

The message field is written for a human reading a log and is not a contract value. Branch on code instead. These are the exact strings this code is sent with today, listed so that a search for one of them lands here.

Where it appears

These are the documented surfaces that raise it. The REST base is https://api.emailforagents.ai/v1, and the remote MCP endpoint is https://mcp.emailforagents.ai/mcp.

The response

Read request_id off the body or the x-request-id header before doing anything else. It is the only handle on one specific attempt, and for a 503 it is the only handle at all, because the underlying detail stays server-side.

HTTP/1.1 401
content-type: application/json
x-request-id: req_...

{
  "error": {
    "code": "unauthenticated",
    "message": "Missing bearer credential.",
    "request_id": "req_...",
    "retryable": false
  }
}

Verified against packages/domain/src/services.ts:133. The status comes from ERROR_STATUS in packages/contracts/src/errors.ts, which is the one place a code is mapped to a status.

All error codes · Documentation · Quickstart