Team seats & invites
How seat quota is counted, how invites consume it, and how the gate re-checks at accept time to handle plan changes mid-flow.
Key points
- A seat is one active user (User.isActive=true) on the tenant. Soft-deleted users free the seat instantly.
- Issuing an invite does not consume a seat — only the accept does. Admins can have any number of pending invites.
- The seat gate fires at two moments: when the admin sends the invite, and again when the invitee clicks accept.
- If the tenant downgraded between invite and accept, the accept returns 402 and the invite is marked expired.
01
Plan caps
- Free: 1 seat. Starter: 3 seats. Pro: 10 seats. Enterprise: unlimited (contractually negotiated).
- Sales can hand-grant a custom seat count via TenantEntitlement; the override wins over the catalogue.
- Removing a member is a soft-delete (isActive=false); the audit chain stays intact.
02
Invite lifecycle
- Pending: token generated, email dispatched, expires_at = now + 7d.
- Accepted: user created, session issued, invite row updated; new user lands on /dashboard authenticated.
- Expired / revoked: terminal states. A new invite for the same email starts a new lifecycle.