Minctrl Docs
Reference

Authentication

Bearer JWTs, how to register and log in, token lifetime, open registration, and how a platform admin is bootstrapped.

Minctrl authenticates with bearer JWTs. Every endpoint except /auth/* and /health requires an Authorization: Bearer <token> header. A missing or expired token returns 401.

Getting a token

Two ways to obtain a token; both return { token, user, company } on success.

Register (open)

Registration is open — anyone can sign up — and auto-creates a company with you as its owner:

curl -s -X POST "$API/auth/register" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane.doe@acme-health.com",
    "password": "<your-password>",
    "company_name": "Acme Health"
  }'

company_name and name are optional. When the closed-beta whitelist gate is off (open registration), personal-email domains (gmail, outlook, …) are accepted.

Log in

curl -s -X POST "$API/auth/login" \
  -H "Content-Type: application/json" \
  -d '{ "email": "jane.doe@acme-health.com", "password": "<your-password>" }'

Invalid credentials return 401. Login is rate-limited to 5 requests/minute per IP — see Rate limits.

Passwordless one-time code (OTP)

An email one-time-code flow is also available: POST /auth/otp/request emails a 6-digit code (10-minute TTL, max 5 attempts), and POST /auth/otp/verify exchanges the code for a token. otp/request always returns {sent: true} regardless of whether the email exists, to defend against enumeration.

Using the token

TOKEN="<token from the response>"
curl -s "$API/process-templates/" -H "Authorization: Bearer $TOKEN"

Token lifetime

Tokens are HMAC-SHA256 JWTs that expire 24 hours after issue. After that, calls return 401 and you re-authenticate. POST /auth/logout revokes the current token immediately (server-side blacklist, 24h TTL). Confirm the authenticated identity any time with:

curl -s "$API/auth/me" -H "Authorization: Bearer $TOKEN"

/auth/me returns your user, primary company, membership status/role, and platform role.

Roles vs. platform admin

There are two distinct role dimensions:

  • Company (membership) roleowner / admin / manager / member / viewer. Governs what you can do within your company. See Set up your team.
  • Platform roleadmin or user on the users record. Gates platform-owner endpoints such as GET /auth/users (list every user) and the whitelist admin endpoints, which return 403 for non-admins.

Admin bootstrap (whitelist)

A platform admin is bootstrapped via the whitelist: an email marked is_admin=true in user_whitelist is granted users.role='admin' on its first signup. Under open registration the whitelist is consulted only for this bootstrap — it never blocks a signup. When the closed-beta gate is enabled, the whitelist additionally gates who may register: unlisted emails are waitlisted, rejected emails get 403, and bootstrap admins skip the personal-email block. Admins manage the waitlist via GET /auth/whitelist, POST /auth/whitelist/{email}/approve, and POST /auth/whitelist/{email}/reject.

See the Auth reference for the full request/response schemas.

On this page