Tenant invitations
The tenant invitations resource manages pending invites — emails sent to someone outside the tenant offering a role on it. Accepted invitations turn into tenant member rows; until then they sit here, viewable + revocable + resendable.
The only resource that sends email
Unlike most of this API — which is pure data-plane CRUD —
POST /v1/tenant_invitations and
POST /v1/tenant_invitations/{id}/resend both send a real email via
Resend. The email send is awaited synchronously so the API
response status reflects whether the email actually went out: a
successful row insert followed by a Resend failure returns
502 email_send_failed with the new invite ID in the response, so
you can retry via /resend without re-creating the row (and
double-emailing on success).
Token never appears in API responses
The plaintext invite token only ever lives in (a) the email body and (b) the URL the recipient clicks. The database stores only a SHA-256 hash; the API response shape doesn't include the token at all. There is no programmatic path to retrieve a sent invite's token — by design.
Notes
- Invites expire after 7 days by default.
- Resend is rate-limited to one call per 60 seconds per invite (server-side, in the underlying RPC).
- Capability-gated to owner/admin (or any member in flat-mode tenants).
- The invite email currently shows
(unknown)as the inviter's identity for API-driven invites; the JWT minted for API requests doesn't carry the user's email and we don't want a per-request lookup just for personalisation. Dashboard-issued invites still show the inviter's email.
Endpoints
- POST
/v1/tenant_invitations— Create a tenant invitation - DELETE
/v1/tenant_invitations/{id}— Revoke a tenant invitation - GET
/v1/tenant_invitations/{id}— Retrieve a tenant invitation - GET
/v1/tenant_invitations— List tenant invitations - POST
/v1/tenant_invitations/{id}/resend— Resend a tenant invitation