Skip to content

API Auth

The API mounts Better Auth under:

/api/auth/*

The auth instance is created in apps/api/src/routes/auth/create_auth.ts using the shared auth package.

flowchart TD
    A[Incoming Request] --> B{Has x-api-key header?}
    B -->|Yes| C{Valid API key?}
    C -->|No| D[403 INVALID_API_KEY\nno fallback]
    C -->|Yes| E[Set request.user]
    B -->|No| F{Valid session cookie?}
    F -->|No| G[401 Unauthorized]
    F -->|Yes| E
    E --> H{Is /api/v1/admin/* route?}
    H -->|Yes| I{Has x-acting-org-id?}
    I -->|No| J[403 Missing acting org]
    I -->|Yes| K{org.type allowed?}
    K -->|No| L[403 Insufficient org type]
    K -->|Yes| M[Route handler]
    H -->|No| M

Protected routes use auth_middleware_if_enabled.

Behavior:

  • in production, auth middleware is always enabled
  • in development, AUTH_MIDDLEWARE_ENABLED=false can disable protected route checks
  • item creation and local item fetch require an authenticated user when middleware is enabled
  • action/event list endpoints use the authenticated user to filter ownership snapshots

The UI uses:

POST /api/auth/unified-otp/check-user
POST /api/auth/unified-otp/request
POST /api/auth/unified-otp/verify
GET /api/auth/get-session
POST /api/auth/sign-out

CREATE_TEST_OTP=true enables predictable OTP behavior for development/testing.

Trusted origins are derived from:

  • configured allowed origins
  • origins discovered from network config instances for served domains

This allows instance-aware CORS while keeping browser clients constrained to known origins.