WF-005: User Invitation Workflow
Overview
This workflow handles team member invitations, allowing organization admins to invite new users to join their workspace. It validates seat limits based on subscription tier, generates secure invitation tokens, and sends branded invitation emails.
Trigger: HTTP POST to /invite-member endpoint
Duration: ~2-4 seconds
Related Workflows: WF-001 (Registration), WF-002 (Checkout for upgrades)
Prerequisites
Before starting, ensure you have:
- Required tools installed
- Access to necessary resources
- Basic understanding of concepts
Verify setup:
# Verification command
Workflow Diagram

Step-by-Step Narrative
Step 1: Invitation Request Received
- Node: Invitation Request
- Type: HTTP POST Endpoint
- Path:
/invite-member - Actions:
- Receives invitation request from web application
- Validates required fields:
org_id,invitee_email,role,inviter_id - Authenticates inviter via session token
- Checks inviter has admin/owner permissions
Step 2: Get Organization Details
- Node: Get Org Details
- Type: PostgreSQL Select
- Table:
public.organizations - Actions:
- Retrieves organization by ID
- Gets current subscription tier
- Gets current member count
- Retrieves organization name for email
Step 3: Validate Seat Limits
- Node: Validate and Generate Token
- Type: Code (JavaScript)
- Actions:
- Checks seat limits by tier:
- Free: 1 seat (no invitations)
- Starter: 5 seats
- Professional: 20 seats
- Business: 100 seats
- Enterprise: Unlimited
- If at limit, throws error with upgrade message
- Generates 64-character secure invitation token
- Sets expiration to 7 days from now
- Checks seat limits by tier:
Step 4: Create Invitation Record
- Node: Create Invitation Record
- Type: PostgreSQL Insert
- Table:
public.invitations - Actions:
- Inserts invitation with unique ID
- Stores organization ID and invitee email
- Records assigned role and optional team ID
- Stores hashed invitation token
- Sets status to
pending - Records inviter and timestamp
Step 5: Send Invitation Email
- Node: Send Invitation Email
- Type: Email Send
- Actions:
- Sends branded HTML invitation email
- Includes inviter name and organization name
- Shows assigned role (Developer, Admin, etc.)
- Contains "Accept Invitation" button with secure link
- Notes 7-day expiration
- Sent from:
invites@coditect.ai
Step 6: Publish Invitation Event
- Node: Publish Invitation Event
- Type: Google Cloud Pub/Sub
- Topic:
user-events - Actions:
- Publishes
invitation.sentevent - Includes org ID, invitee email, role
- Enables analytics tracking
- Triggers any notification integrations
- Publishes
Step 7: Return Success Response
- Node: Success Response
- Type: Webhook Response
- Actions:
- Returns HTTP 200 with confirmation
- Includes invitation ID for tracking
- Client shows success message to inviter
Data Flow
Input:
{
"org_id": "org-uuid",
"invitee_email": "newmember@example.com",
"role": "developer",
"team_id": "team-uuid", // optional
"inviter_id": "user-uuid",
"inviter_name": "John Doe"
}
Database Record:
{
"id": "invitation-uuid",
"organization_id": "org-uuid",
"email": "newmember@example.com",
"role": "developer",
"team_id": "team-uuid",
"token": "hashed-token",
"invited_by": "user-uuid",
"expires_at": "2024-01-22T10:00:00Z",
"status": "pending"
}
Output:
{
"success": true,
"message": "Invitation sent successfully",
"invitation_id": "invitation-uuid"
}
Seat Limits by Tier
| Tier | Max Seats | Can Invite? | Notes |
|---|---|---|---|
| Free | 1 | No | Solo user only |
| Starter | 5 | Yes | Small teams |
| Professional | 20 | Yes | Growing teams |
| Business | 100 | Yes | Large teams |
| Enterprise | Unlimited | Yes | Custom limits available |
Available Roles
| Role | Permissions |
|---|---|
| owner | Full access, billing, delete org |
| admin | Manage members, settings, projects |
| developer | Create/edit projects, use workstation |
| contractor | Limited project access, time-bound |
| viewer | Read-only access to assigned projects |
Invitation Acceptance Flow
When the invitee clicks the invitation link:
- Link format:
https://app.coditect.ai/invite/{token} - Token validated against database
- If invitee has account:
- Added to organization as member
- Invitation marked
accepted
- If invitee is new:
- Redirected to registration with pre-filled email
- After registration, added to organization
Error Handling
| Error | Cause | Response |
|---|---|---|
| 400 Bad Request | Missing fields | { "error": "Invitee email required" } |
| 403 Forbidden | Not admin/owner | { "error": "Permission denied" } |
| 409 Conflict | Already a member | { "error": "User already in organization" } |
| 402 Payment Required | Seat limit reached | { "error": "Seat limit reached. Upgrade to add more members." } |
Security Considerations
- Only admins/owners can send invitations
- Invitation tokens are cryptographically random
- Tokens hashed in database (bcrypt)
- Tokens expire after 7 days
- One-time use (marked
acceptedorexpired) - Rate limiting: 10 invitations per hour per org
Related Documents
Troubleshooting
Common Issue 1
Problem: Description of issue Solution: Steps to resolve
Common Issue 2
Problem: Description of issue Solution: Steps to resolve
Next Steps
After completing this guide:
- Explore: Additional related features
- Practice: Apply concepts in your project
- Reference: Related documentation