Invitations
The invitation system allows adding users to organizations and teams.
Model
Invitation
├── email (invited user)
├── roleId (role to be assigned)
├── organizationId? (optional)
├── teamId? (optional)
├── token (unique JWT token)
├── status: pending | accepted | declined | cancelled | expired
└── expiresAt (expiration date)API Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /api/invitations | Yes | Create invitation |
GET | /api/invitations/my | Yes | My pending invitations |
GET | /api/invitations/pending | No | Find pending (?teamSlug=&orgSlug=) |
POST | /api/invitations/:id/accept | Yes | Accept invitation |
POST | /api/invitations/:id/decline | Yes | Decline invitation |
DELETE | /api/invitations/:id/cancel | Yes | Cancel invitation |
Invitation Flow
- Creation: A user with
members.invitepermission creates an invitation by email - Delivery: If a user with that email already exists — they receive a notification. If not — an email with a link is sent
- Anonymous flow: An unauthenticated user follows the link → sees invitation data via
GET /invitations/pending/:token→ registers → invitation is auto-accepted - Acceptance: The user is added to the org/team with the specified role, added to the team chat
- Notifications: The inviter receives a notification on acceptance
Frontend
Invitations Store
typescript
const store = useInvitationsStore()
const { myInvitations } = storeToRefs(store)
await store.fetchMy()
await store.create({ email, roleId, organizationId?, teamId? })
await store.accept(id)
await store.decline(id)
await store.cancel(id)Key Implementation Details
- Invitations use JWT tokens for secure anonymous links
- On user registration, all pending invitations for their email are auto-accepted
- Cannot invite a user who is already a member
- Invitations have an expiration date (
expiresAt)