Skip to content

Invitations & Webhooks

Invitations

Invitations are webhook-only — this template does not send emails. When an admin invites someone, the app creates an invitations row and fires an invitation.created webhook to the team's configured webhook_url (set in Settings → General). The webhook payload includes the invite_url, and it is up to the receiving system to deliver it (email, Slack, internal tool, etc.).

If no webhook_url is configured, the invitation is still created and the admin can copy the invite link manually from Settings → Members → Pending invitations → "Copy invite link". Nothing is ever sent automatically.

Adding email delivery later

If you want to send invitation emails directly from the app instead of via the webhook, add your provider (Resend, Postmark, etc.) in server/api/teams/[teamId]/invitations/index.post.ts alongside the fireWebhook call. The invite URL is already constructed there — just reuse it.

Webhooks

All team-scoped mutations fire a webhook. Payloads always include event, team_id, team_name, and timestamp; event-specific fields are listed below.

EventFired whenExtra fields
invitation.createdAdmin invites someoneemail, role, invite_url, invited_by
invitation.acceptedInvitee accepts the invitationemail, role, member_name
invitation.revokedAdmin revokes a pending invitationemail, role, revoked_by
member.removedAdmin removes a membermember_email, member_name, removed_by
member.role_changedAdmin changes a member's rolemember_email, member_name, old_role, new_role, changed_by
team.updatedTeam settings are savedchanges (object of updated fields), updated_by
team.deletedOwner deletes a teamdeleted_by

Webhook delivery is fire-and-forget: failures are silently ignored and do not block the originating request. If you need retries or delivery guarantees, replace server/utils/fireWebhook.ts with a queue-backed implementation.