How Workspace Invitations and Member Onboarding Work in Plane
Plane manages workspace invitations through the WorkspaceInvitationService class, which provides methods to invite users via email, list pending invitations for both admins and invitees, and accept invitations individually or in bulk through a RESTful API.
Plane (makeplane/plane) handles member onboarding through a dedicated invitation system that bridges project administrators and new collaborators. The system centers on the WorkspaceInvitationService, a TypeScript service class that extends the generic APIService to manage the full lifecycle of workspace invitations—from creation to acceptance.
The Core Service Architecture
The invitation logic lives in packages/services/src/workspace/invitation.service.ts. This service extends APIService (from packages/services/src/api.service.ts) and automatically reads the API_BASE_URL from @plane/constants to communicate with Plane’s backend. It wraps HTTP requests to the /api/workspaces/:slug/invitations/ endpoints, handling authentication headers and response parsing transparently.
Sending Workspace Invitations
Administrators (or users with appropriate permissions) initiate onboarding by calling the invite method. This method accepts a workspace slug and an IWorkspaceBulkInviteFormData payload containing email addresses and the desired role for each invitee.
According to the source code at invitation.service.ts#L55-L60, the service POSTs this data to the backend, which creates IWorkspaceMemberInvitation records and dispatches email links to the specified addresses.
const invitationSvc = new WorkspaceInvitationService();
// Invite multiple users with a specific role
await invitationSvc.invite("engineering", {
emails: ["alice@example.com", "bob@example.com"],
role: "member",
});
Listing Pending Invitations
The service distinguishes between administrative oversight and personal invitation management through two distinct methods.
Administrative View
Admins retrieve all pending invitations for a specific workspace using workspaceInvitations(workspaceSlug). As implemented in invitation.service.ts#L40-L45, this returns an array of invitation objects visible only to workspace administrators.
User View
Authenticated users check their own pending invitations via userInvitations(), defined at invitation.service.ts#L26-L31. This method returns IWorkspaceMemberInvitation[], allowing the frontend to display a "Join Workspace" interface for the current user.
Accepting Invitations and Completing Onboarding
When an invitee follows an email link, the client completes onboarding by accepting the invitation through one of two methods.
Single Acceptance
The join method handles individual workspace entry. Located at invitation.service.ts#L100-L107, it accepts the workspace slug, invitation ID, and optional data (such as a password or SSO token). The backend validates the token, creates a WorkspaceMember record, and marks the invitation as accepted.
// Accept a specific invitation
await invitationSvc.join("engineering", invitationId, { password: "secure123" });
Bulk Acceptance
Users with multiple pending invitations can batch-accept them using joinMany, implemented at invitation.service.ts#L16-L21. This method accepts an object containing an array of invitation_ids, minimizing API round-trips during initial user setup.
// Accept all pending invitations at once
const pending = await invitationSvc.userInvitations();
await invitationSvc.joinMany({
invitation_ids: pending.map(i => i.id),
});
Updating and Revoking Invitations
Administrators maintain invitation hygiene through modification and deletion endpoints.
The update method (invitation.service.ts#L70-L75) allows editing an invitation’s role or email address before acceptance. To remove stale invitations, admins call destroy (invitation.service.ts#L84-L89), which permanently deletes the invitation record.
Key Types and Supporting Files
The invitation system relies on several core files within the Plane monorepo:
packages/services/src/workspace/invitation.service.ts– The primary service class containing all invitation-related API methods.packages/types/src/workspace.ts– Defines TypeScript interfaces includingIWorkspaceMemberInvitationandIWorkspaceBulkInviteFormData.packages/services/src/api.service.ts– The base HTTP service thatWorkspaceInvitationServiceextends for request handling.packages/constants/src/index.ts– ExportsAPI_BASE_URLused to configure the service endpoint.
Summary
- WorkspaceInvitationService extends
APIServiceto manage the full invitation lifecycle inpackages/services/src/workspace/invitation.service.ts. - Creating invitations uses
invite()withIWorkspaceBulkInviteFormDatato send email invites to multiple users simultaneously. - Listing invitations separates concerns:
workspaceInvitations()for admins anduserInvitations()for individual users. - Accepting invitations supports both individual entry via
join()and bulk onboarding viajoinMany(). - Lifecycle management includes
update()for modifying invitation details anddestroy()for revocation before acceptance.
Frequently Asked Questions
How do I invite multiple users to a Plane workspace simultaneously?
Use the invite method with an IWorkspaceBulkInviteFormData payload containing an array of email addresses. The service handles batch creation of invitation records and email dispatch automatically, as implemented in invitation.service.ts#L55-L60.
What happens when a user clicks an invitation link in Plane?
The client application extracts the invitation token and calls the join method (or joinMany for multiple invites). The backend validates the token, creates a WorkspaceMember record linking the user to the workspace, and marks the corresponding IWorkspaceMemberInvitation as accepted, completing the onboarding flow.
Can a user accept multiple workspace invitations at once?
Yes. The joinMany method (invitation.service.ts#L16-L21) accepts an array of invitation IDs, allowing new users to join multiple workspaces in a single API call rather than processing each invitation individually.
How do I revoke a pending invitation before it is accepted?
Administrators can call the destroy method with the workspace slug and invitation ID. This endpoint, located at invitation.service.ts#L84-L89, permanently removes the invitation record from the database and invalidates the email link.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →