Authentication
Every /api/v1 endpoint requires authentication. Only the health probes (GET /api/v1/health, GET /api/v1/health/ready), login (POST /api/v1/auth/login), and the first-run setup endpoints (GET/POST /api/v1/auth/setup, valid only while no users exist) are open. The dashboard signs in with email + password and holds a session JWT; CI, the MCP server, and scripts authenticate with a long-lived API token. Both are sent the same way:
Authorization: Bearer <jwt-or-api-token>Run artifacts (per-step screenshots) are served from GET /api/v1/artifacts/... and are also authenticated — the dashboard passes the token as a ?token= query param because <img> tags can't send an Authorization header.
Repeated failed logins from one IP are rate-limited (10 failures / 5 min → 429). For multi-replica deployments, add rate limiting at your reverse proxy too.
First-run admin
A fresh instance has no users. The first time you open the dashboard it shows a "Create your admin account" screen — set an email + password and you're signed in as the admin. From there you can add everyone else (see Managing users).
For headless / Docker / CI, pre-seed the admin from the environment instead — when both are set on first boot, the admin is created automatically and the setup screen is skipped:
TRIPWIRE_ADMIN_EMAIL=admin@yourco.com
TRIPWIRE_ADMIN_PASSWORD=change-me-nowPasswords must be at least 8 characters (enforced on the browser setup screen) and are hashed with argon2 — never stored or logged in plaintext.
Roles
| Role | Can do |
|---|---|
admin | Everything, including managing users and writing Settings (the integration credentials). |
member | Author/run suites, view runs, issues, plans, and analytics. Cannot manage users or change settings. |
Sessions (dashboard)
POST /auth/login with { "email", "password" } returns a JWT and the user record. The dashboard stores the token and attaches it to every request; a 401 clears it and bounces back to the login screen. Tune the session lifetime with TRIPWIRE_JWT_TTL_SECONDS (default 7 days), and set TRIPWIRE_JWT_SECRET in production so sessions survive a restart.
curl -s localhost:8400/api/v1/auth/login \
-H 'content-type: application/json' \
-d '{"email":"admin@yourco.com","password":"change-me-now"}'
# → { "token": "eyJ…", "user": { "id": "…", "email": "…", "role": "admin" } }API tokens (CI / MCP / scripts)
Create a token from Settings → API tokens in the dashboard, or via the API. The raw token (prefixed tw_) is shown once at creation — store it in your secret manager; only a hash is kept server-side.
# create (uses your session JWT)
curl -s localhost:8400/api/v1/auth/tokens \
-H "Authorization: Bearer $JWT" \
-H 'content-type: application/json' -d '{"name":"ci"}'
# → { "id": "…", "name": "ci", "token": "tw_…" } ← copy the token now
# then use it anywhere
curl -s localhost:8400/api/v1/suites -H "Authorization: Bearer tw_…"| Method | Path | Purpose |
|---|---|---|
POST | /auth/tokens | Create a token (returns the raw tw_… once). |
GET | /auth/tokens | List your tokens (metadata only — no secret). |
DELETE | /auth/tokens/{id} | Revoke a token. |
Managing users (admin)
From the dashboard, an admin provisions teammates under Settings → Team: enter an email + a temporary password, pick Member or Admin, and Add user. They sign in with those credentials; share the password with them and have them change it. (Members can author and run tests; admins can also change settings and manage users.)
The same is available over the API:
| Method | Path | Purpose |
|---|---|---|
GET | /auth/me | The current user. |
GET | /auth/users | List users (admin). |
POST | /auth/users | Create a user { email, password, role } (admin). |
Related: Settings & env · REST API · Deploying