# Console sign-in

People sign in to the Console with an e-mail link. There are no passwords. Programs keep using API keys.

| Route | What it does |
|---|---|
| `POST /v1/auth/email {email}` | Sends a sign-in link (one use, 15 minutes). The answer is the same for every address |
| `POST /v1/auth/email/verify {token}` | Signs in: sets the session cookie and returns `csrf`, the team and the role. A new address also gets its own team |
| `POST /v1/auth/mfa {code}` | With 2FA on: the authenticator code (or a backup code) completes the sign-in |
| `POST /v1/auth/totp {action: begin \| confirm \| disable, code}` | Turns 2FA on (shows the secret, then 10 one-use backup codes) or off |
| `GET /v1/auth/me` | The person, their teams and roles, 2FA on / off |
| `POST /v1/auth/switch {tenant}` · `POST /v1/auth/logout {everywhere}` | Another team · sign out (here or everywhere) |

- **Every write from the Console** sends the `X-Prism-CSRF` header (the `csrf` value from the sign-in). Without it: `403`.
- **Roles:** owner and admin may do everything; developer: read, write, import; viewer: read.
- **Team:** `GET /v1/auth/team` (members: role, 2FA, last active + open invites) · `POST /v1/auth/team {action}` (owners, admins): `invite {emails, role}` (an existing account joins now; a new address is e-mailed and joins on its first sign-in), `role {account, role}` (only an owner makes or changes an owner; never the last owner), `remove {account}` (their sessions for the team end), `cancel_invite`, `resend_invite {email}`, `remind_2fa {account}`.
- **Security:** `GET /v1/auth/sessions` (where you are signed in: device, address, current) · `POST /v1/auth/sessions {action: end, id}` or `{action: others}` · `POST /v1/auth/totp {action: codes, code}` makes 10 new backup codes · `GET|POST /v1/auth/team2fa {on}` (owners, admins): everyone must sign in with two steps; a member without it has 7 days, then reaches only the screens that turn it on (`403`).
- **Wrong keys:** an address that sends more than 30 wrong keys or tokens in a minute gets `429` + `Retry-After` before any key is checked.
- **During testing,** sign-up is by invitation only (the operator runs `allow-signup <email>`).
