CafébecDocs

Authentication

How humans and agents authenticate with the Cafébec API.

Cafébec runs two auth tracks side-by-side. They never share token infrastructure, but they resolve server-side into a unified Actor object so controllers and the audit log treat both identically.

Human users — Better Auth

Sign-up / sign-in / session endpoints are mounted at /auth/*:

POST /auth/sign-up/email   { email, password, name }
POST /auth/sign-in/email   { email, password }
POST /auth/sign-out
GET  /auth/get-session

On success the API sets an HTTP-only cafebec.session_token cookie scoped to .cafebec.ca in production. The operator console's fetch wrapper uses credentials: 'include' to carry it through; never send it in JavaScript.

Agents & services — API keys

Admins mint keys from the console; the plain value is shown once. Subsequent requests send:

Authorization: Bearer vnd_<32-chars>

Keys are bcrypt-hashed at rest, with the first 12 chars stored in the clear for identification. Scopes are attached at creation time and enforced by the @RequireScopes guard — a key with only clients:read can't invoke a write endpoint or a mutating MCP tool.

Error envelope

On 401, every endpoint returns:

{
  "code": "UNAUTHENTICATED",
  "message": "Authentication required",
  "next_actions": [
    "POST /auth/sign-in",
    "Authorization: Bearer vnd_..."
  ]
}

Agents should key off code, not HTTP status. FORBIDDEN means your credential is valid but lacks the right scope — a different recovery than UNAUTHENTICATED.

On this page