Team Invitations API
Base path: /api
POST /teams/{team_id}/invite-member/
- Auth: user must be the team owner.
- Purpose: Send an invitation email, create inactive user if email is new, store pending invite with optional permissions.
- Body keys:
email(string, required)first_name(string, optional)last_name(string, optional)role(string, optional, defaults tomember; cannot beowner)permission_ids(array, optional; must be in assignable permissions for inventory/curation/products) group_ids(array, optional; must be in assignable non-internal groups) inventory_ids(array, optional; must belong to the team owner and will be granted as object-level access on acceptance) inventory_permissions(arraymessage(string, optional)- Responses:
- 201:
{ "detail": "...", "invitation": { id, email, first_name, last_name, role, status, token, expires_at, permission_ids, group_ids, inventory_ids, inventory_permissions, ... } } - 400: validation errors, duplicate pending invite, member limit reached, or user already in another team.
- 403: caller is not the team owner.
GET /teams/{team_id}/available-groups/
- Auth: team owner.
- Purpose: List assignable Django groups that can be attached to an invitation.
GET /teams/{team_id}/available-inventories/
- Auth: team owner.
- Purpose: List owner inventories that can be attached to an invitation for object-level access.
POST /teams/{team_id}/add-member/
- Auth: team owner.
- Purpose: Directly add an existing user to the team without invitation.
- Body keys:
user_id(int, required),role(string, optional, defaultsmember).
POST /teams/accept-invitation/
- Auth: AllowAny (token-based acceptance).
- Purpose: Accept a pending invitation, activate user, create membership, apply stored permissions, assign stored groups, and grant stored inventory object-level access.
- Stock rules: accepted invitations also persist any
inventory_permissions, so team members can be limited to stock increase only (check_in), stock decrease only (check_out), or both. - Body keys:
token(string, required) — from the invitation link.password(string, optional) — set if the invited account needs a password.- Responses:
- 200:
{ "detail": "...", "member": { id, team, user, role, ... } } - 400: invalid/expired invitation, member limit reached, or user already in another team.
- 404: invitation not found.
POST /teams/{team_id}/remove-member/
- Auth: team owner (can remove others) or member removing self.
- Body keys:
user_id(int, required).
Notes:
- Team member limit is enforced using the owner’s plan and team member_limit.
- Assignable permissions are restricted to inventory, curation, and products apps.
- Assignable groups exclude internal groups whose names start with private:.
- Invitation tokens expire after 7 days by default; expired invites return 400 on acceptance.