# Users & invitations Team management within a tenant. Backed by `users.py` (~2,300 lines). ## `GET /api/users` Lists users belonging to the caller's tenant. ## `POST /api/users/create` ```json { "email": "new.user@acme.com", "name": "New User", "password": "..." } ``` ## `DELETE /api/users/` Deactivates a user (soft — flips `active`, doesn't delete the record). ## `PUT /api/users//role` ```json { "role": "admin" } ``` ## Invitations Rather than creating a user directly, the more common flow is inviting one by email and letting them set their own password: | Route | Method | Purpose | |---|---|---| | `/api/users/invite` | `POST` | Invite a new user — `{"email", "name", "role", "instance_id"}` | | `/api/users/invitation` | `POST` | Same shape, used from the dedicated invitations UI | | `/api/users/invitation/` | `GET` | Public — look up an invitation by its token (renders the accept-invite screen) | | `/api/users/invitation/accept` | `POST` | Public — `{"token", "password"}`, completes signup | | `/api/users/invitation//resend` | `POST` | Resend the invite email | | `/api/users/invitation//cancel` | `POST` | Cancel a pending invitation | :::note `/api/users/invitation/` and `/api/users/invitation/accept` are the two invitation routes that don't require a bearer token — the invited person doesn't have an account yet, so the invitation `token` itself is the credential for that single accept step. :::