API Reference

Authentication

Session validation, API keys, and permission checks — auth is owned by Better Auth in the platform app

Authentication

Wardn splits auth in two: Better Auth inside the platform app owns registration, login, logout, OAuth, and org/team management. The Go API doesn't issue sessions — it validates the Better Auth session cookie or an API key on every request.

There are no POST /api/v1/auth/register, /login, or /logout endpoints — those routes return 404 on the API server. Sign up and sign in through the platform UI (or its Better Auth endpoints under /api/auth/*).

Authentication Flow

┌──────────┐  signup/login   ┌──────────────────┐
│ Browser  │ ───────────────▶│  Platform app    │
└──────────┘                 │  /api/auth/*     │
     │                       │  (Better Auth)   │
     │ better-auth.          └────────┬─────────┘
     │ session_token cookie           │ writes user/session rows
     ▼                                ▼
┌──────────┐                  ┌────────────┐
│  Go API  │── validates ────▶│  Postgres  │
│ /api/v1  │   cookie signed  │  session   │
└──────────┘   by             └────────────┘
               BETTER_AUTH_SECRET

The server verifies the signed better-auth.session_token cookie with BETTER_AUTH_SECRET (must match the platform's BETTER_AUTH_SECRET) — no shared session store needed.

Endpoints

All paths below are under /api/v1. Every response is JSON; errors are {"error": "…"}.

GET /api/v1/auth/me

Current authenticated user. Works with a session cookie or an API key.

curl -b "better-auth.session_token=…" http://localhost:8080/api/v1/auth/me
{ "user": { "id": "…", "email": "…", "name": "…", "role": "Owner", "orgId": "…" } }

401 when not authenticated.

GET /api/v1/auth/sessions

The caller's active sessions (signed-in devices). Session-only — not callable with an API key.

{ "sessions": [ { "id": "…", "current": true, "createdAt": "…", "expiresAt": "…" } ] }

DELETE /api/v1/auth/sessions/:id

Revoke one of the caller's sessions — the evicted device loses access immediately.

{ "revoked": true }

POST /api/v1/auth/can-i

A kubectl auth can-i-style permission check so the frontend can hide actions the caller can't perform.

curl -X POST http://localhost:8080/api/v1/auth/can-i \
  -b cookies.txt -H "Content-Type: application/json" \
  -d '{"permission": "deployment:sync", "scope": "deployment", "scope_id": "prod-cluster/default"}'
FieldValues
permissionresource:action — see RBAC for the full list (deployment:sync, cluster:register, webhook:manage, …)
scopeorg (default) | cluster | deployment
scope_id"" | cluster name | "cluster/namespace"
{ "allowed": true }

API-key callers are additionally bounded by the key's scope ceiling — same rule as the can_i MCP tool.

API Keys

Long-lived wrd_-prefixed tokens for CI, scripts, and MCP agents — minted per user with a role ceiling and optional scope.

MethodPathDescription
POST/api/v1/auth/api-keysCreate a key — returns the plaintext wrd_… once
GET/api/v1/auth/api-keysList the caller's keys (prefix + metadata only)
DELETE/api/v1/auth/api-keys/:idRevoke a key
curl -X POST http://localhost:8080/api/v1/auth/api-keys \
  -b cookies.txt -H "Content-Type: application/json" \
  -d '{"name": "ci-pipeline", "role": "sync", "scope": "deployment", "scope_id": "prod-cluster/default", "expires_days": 90}'

Authenticate API requests with the key:

curl http://localhost:8080/api/v1/apps -H "Authorization: Bearer wrd_…"
FieldValues
roleCeiling: read | sync | admin — the key can never exceed it even when the owning user can
scopeorg (default) | cluster | deployment
scope_id"" | cluster name | "cluster/namespace"
expires_days0 = never expires

Some endpoints are session-only even with a key — secret-store and registry writes (secretstore:manage, registry:manage), and /auth/sessions. A leaked key can't register credential stores.

Sessions

PropertyValue
Cookiebetter-auth.session_token (override via SESSION_COOKIE_NAME)
Issued byBetter Auth in the platform app
Verified byThe Go API — HMAC signature against BETTER_AUTH_SECRET

MCP Access

Agents use the same API-key mechanism over JSON-RPC — see MCP Server.

On this page