Skip to content

Auth API Reference

Timbl auth is adapter-driven. Core routes are stable, but principal shape, provider cookies, provider redirects, and action bodies are owned by the runtime AuthAdapter. If an app does not configure one, the timbl runtime installs a default Better Auth adapter.

The generated OpenAPI document at GET /openapi.json includes auth endpoints, standard security schemes, and per-operation security requirements. The Scalar docs UI renders those schemes so protected requests can be authorized directly from /docs.

OpenAPI / Scalar Security

The generated spec defines two generic auth schemes:

SchemeTypeApplies to
sessionCookieapiKey in cookie sessionCookie/session based adapters. The concrete cookie name may vary by provider.
bearerAuthHTTP bearerToken based adapters that resolve Authorization: Bearer <token>.

Protected content routes declare both schemes as alternatives. Public auth routes, such as session lookup and auth actions, declare auth as optional so Scalar can send credentials when an action needs them (for example sign-out) without making sign-in impossible.

Timbl always emits baseline canonical action paths. Scalar therefore shows stable action routes such as:

POST /api/cms/auth/actions/login
POST /api/cms/auth/actions/register
POST /api/cms/auth/actions/logout

Those routes all use the same Timbl runtime handler and call AuthAdapter.invoke(action, body, authContext). The default Better Auth adapter implements login, register, and logout; custom adapters can override those actions or add their own. A custom adapter that omits invoke still returns 501 NOT_IMPLEMENTED for auth actions.

Capabilities

AuthAdapter.getCapabilities() returns AuthCapabilities, including:

  • provider: string identifier (e.g. better-auth)
  • providerRoutes: { enabled: boolean; basePath?: string } — when enabled, the adapter may handle provider HTTP traffic (Better Auth defaults to /api/auth)
  • actions: optional map of stable action names to descriptions plus Zod input/output schemas. Timbl always includes login, register, and logout, then merges adapter-provided actions on top so adapters can refine schemas or add more concrete action routes.
  • feature flags such as supportsAnonymous, supportsOrganizations, supportsImpersonation, and supportsServiceAccounts

GET /api/cms/auth/session

Returns whether the current request has a resolved principal, plus serialized principal and identity when authenticated.

This route is public and safe to call without credentials.

200 response

{
"authenticated": true,
"principal": {
"id": "user_123",
"email": "editor@example.com"
},
"identity": {
"provider": "better-auth",
"subject": "user_123",
"sessionId": "session_123",
"actorType": "human",
"expiresAt": "2026-05-12T12:00:00.000Z"
}
}

Unauthenticated response:

{
"authenticated": false,
"principal": null,
"identity": null
}

POST /api/cms/auth/actions/:action

Invokes adapter.invoke(action, body, authContext). The default Better Auth adapter implements the canonical actions. Custom adapters without invoke return 501 NOT_IMPLEMENTED.

The parsed JSON body (or form-derived object) is passed as the second argument to invoke—use whatever shape your adapter expects (e.g. flat fields or a nested input property by convention).

The login, register, and logout paths are always shown in /openapi.json and Scalar. Adapters should implement those names when they apply, and can advertise additional names through AuthCapabilities.actions. The generic :action path remains available for custom or unadvertised actions.

Common examples:

POST /api/cms/auth/actions/login
Content-Type: application/json
{
"email": "editor@example.com",
"password": "correct horse battery staple"
}
POST /api/cms/auth/actions/register
Content-Type: application/json
{
"name": "Editor",
"email": "editor@example.com",
"password": "correct horse battery staple"
}
POST /api/cms/auth/actions/logout
Cookie: session=...
{}

Responses

  • Determined by the adapter (status, optional headers, body / principal handling in the runtime handler)
  • 400 for invalid request bodies
  • 401 when the adapter action requires a session and none is present
  • 501 when a custom adapter does not implement invoke (NOT_IMPLEMENTED)

Provider passthrough routes

Adapters with capabilities.providerRoutes.enabled and handleRequest() are mounted under their provider base path. The default Better Auth adapter uses:

/api/auth/*

The generated OpenAPI document represents that catch-all as /api/auth/{path} so Scalar exposes the provider route family without pretending Timbl owns each provider-specific request or response shape.

Better Auth

Install @timbl/adapter-better-auth and pass an invoke implementation that maps action to Better Auth API calls. See Better Auth adapter.