Invites
An invite is how a new member joins a team. An owner invites an email address; auth.is emails that address a single-use, time-limited join link; the recipient accepts it and becomes a member. The raw link is a capability — it is emailed to the invitee's inbox and never returned by any API.
Lifecycle
An invite's status is derived from its timestamps, not stored as a column. It is one of:
| Status | Meaning |
|---|---|
pending | Live and unaccepted; the link still works. |
accepted | The invitee joined; the link is spent (single-use). |
revoked | An owner cancelled it before acceptance. |
expired | The TTL elapsed before anyone accepted. |
Invites default to a 7-day lifetime.
Creating and revoking
invite_member (owner only) takes the teamId, the target email, and a role — member (default) or owner. It returns a masked view of the invite, never the link itself; only the invitee's inbox gets the real URL.
The join link is written only to the invitee's email and appears nowhere else — not in list_invites, not in an audit row, not in any log. If it did not arrive, you cannot re-fetch it: revoke the pending invite and send a fresh one.
invite_member is refused with a conflict if the email already belongs to a member or to a live pending invite. To re-send, revoke_invite the existing pending one first, then invite again.
revoke_invite (owner only) invalidates a still-pending invite so its link can no longer be redeemed. Only pending invites can be revoked — an already accepted, expired, or revoked invite returns a not-found error.
Accepting
The invitee opens the emailed link and accepts. Acceptance validates the token (hash match, still pending, unexpired, and email match on a verified address); every failure returns the same generic error, so a bad or stale link never reveals why. A successful accept adds them to the team with the invited role.