Returns UserLoginResponse: status, message, access_token, token_type, org_id, role, organisations (a list of {org_id, name, role}), and is_first_login. A duplicate email returns 400.
Returns UserLoginResponse. Bad credentials return 401.is_first_login is what the dashboard uses to decide whether to show onboarding, and it is asymmetric across the three routes that share this schema:
true from POST /users/signup, always.
true from POST /users/login only when the user document has no last_logged_in_at — an account created before that field existed. Login writes the timestamp before responding, so a given account can see true at most once.
false from POST /users/switch-organisation, which returns the same schema but never sets the flag.
X-API-Key. The one route that trades the internal key for a JWT. The runtime and the campaign workers use it to call everything else.
{ "org_id": "org_abc123" }
Returns BotTokenResponse: access_token, token_type, org_id, role. The role is always admin and the token’s subject is the synthetic bot@voicera.internal. An unknown org_id returns 404.
Bearer. Returns UserResponse for the active organisation: email, org_id, role, organisation_name, organisations (every membership as {org_id, name, role}), and created_at. The joined fields are computed at read time, not stored on the user document.
Bearer, self only. Any email other than the token’s own returns 403 Not authorized to access this user's data. Returns UserResponse.
/users/check/{email} is public and unauthenticated. It confirms whether an email has an account. That is deliberate — the invite form needs it — but it is an enumeration surface. Rate-limit it at your proxy.
apps/api/app/routers/members.py, prefix /api/v1/members. Members are the join between a user and an organisation, carrying a role. See Multi-tenancy and roles.
Bearer, super_admin, and org_id must equal the token’s active organisation. Deletes the organisation and its memberships.
There is no create-organisation endpoint — only POST /users/signup makes one. Deleting an organisation is not reversible and does not clean up the agents, call logs, campaigns, or MinIO objects that referenced it.