Pattern A: Single Organization, Multiple Programs
Complete implementation guide for onboarding nonprofits with multiple internal programs using team-based segmentation.
π― When to Use This Patternβ
Use Pattern A when:
- β Single legal entity (one nonprofit organization)
- β Multiple internal programs/departments
- β Shared senior leadership needs visibility across all programs
- β Individual program teams need isolation from each other
- β Centralized billing with program-level usage tracking
Example: Nevada Senior Services (NSS) with RAMP program, Adult Day Care, Home Health services.
ποΈ Architecture Overviewβ
Key Components:
- Single Twilio Account with subaccounts for billing segmentation
- Single Auth0 Tenant with user metadata for team assignment
- One Flex Instance with Teams View filtering
- One Vanity Domain for entire organization
- SAML Attributes passing team and program information to Flex
π Prerequisitesβ
Before beginning setup:
- β Twilio account credentials (Account SID and Auth Token)
- β Auth0 tenant access with admin privileges
- β List of programs/teams within the nonprofit
- β Organizational structure (who should see what)
- β
Vanity domain configured (e.g.,
nss.connie.team) - β User email addresses for initial staff setup
π Implementation Stepsβ
Step 1: Create Twilio Subaccounts (Optional but Recommended)β
Subaccounts provide billing and usage transparency for each program without creating separate Flex instances.
1.1 Navigate to Twilio Console
- URL:
https://console.twilio.com/ - Login with main account credentials
1.2 Create Subaccount
- Go to Account β Subaccounts
- Click Create new subaccount
- Enter details:
- Friendly Name:
NSS_RAMP(or your program name) - Purpose: Billing and usage tracking for RAMP program
- Friendly Name:
Subaccount friendly names can be changed anytime via Console or API without affecting functionality. The friendly name is just a label for reference.
1.3 Note the Subaccount SID
Example: AC[EXAMPLE_SUBACCOUNT_SID_32_CHARS]
You'll use this for associating program-specific usage later.
πΈ Screenshot Placeholder:
[Screenshot: Twilio Console - Subaccounts Page]
Description: Shows the "Create new subaccount" button and form with Friendly Name field
Location: Console β Account β Subaccounts
Step 2: Configure Auth0 Users with Team Metadataβ
2.1 Access Auth0 Dashboard
- URL:
https://manage.auth0.com/dashboard/ - Navigate to User Management β Users
2.2 Create or Update User
For each staff member, configure their app_metadata with Flex roles and team assignment.
Example: RAMP Supervisor (Jessica Buckley)
{
"flex": {
"roles": ["supervisor"],
"team": "RAMP"
},
"program": "RAMP"
}
Example: RAMP Agent (Afia Kambon)
{
"flex": {
"roles": ["agent"],
"team": "RAMP"
},
"program": "RAMP"
}
Example: Senior Executive (No Team - Sees All)
{
"flex": {
"roles": ["admin"]
}
}
Metadata Field Definitions:
| Field | Purpose | Values |
|---|---|---|
flex.roles | Flex permission level | admin, supervisor, agent |
flex.team | Team visibility filter | RAMP, ProgramB, etc. (omit for admin) |
program | Usage tracking attribute | Program name for reporting |
πΈ Screenshot Placeholder:
[Screenshot: Auth0 - User Metadata Editor]
Description: Shows the app_metadata JSON editor with example RAMP supervisor metadata
Location: Auth0 Dashboard β Users β [User] β Raw JSON tab
Step 3: Update Auth0 Action for SAML Attributesβ
Auth0 Actions pass user metadata to Twilio Flex via SAML attributes. This is critical for team-based visibility.
3.1 Navigate to Auth0 Actions
- Dashboard:
https://manage.auth0.com/dashboard/ - Go to Actions β Library
- Find: "Add Flex Roles to SAML"
- Action ID:
4753bc91-8906-450d-b1fd-d8259aade890
- Action ID:
3.2 Update Action Code
Replace existing code with:
/**
* Auth0 Post-Login Action: Add Flex Roles to SAML Response
*
* Purpose: Pass user metadata to Twilio Flex via SAML attributes
* Critical for: Team-based visibility filtering in Flex Teams View
*/
exports.onExecutePostLogin = async (event, api) => {
// Get Flex roles from user's app_metadata
const flexRoles = event.user.app_metadata?.flex?.roles || ['agent'];
const flexTeam = event.user.app_metadata?.flex?.team;
const program = event.user.app_metadata?.program;
// Set SAML attributes that Twilio Flex requires
api.samlResponse.setAttribute('email', event.user.email);
// Build full name from available user data
const fullName = event.user.name ||
[event.user.given_name, event.user.family_name].filter(Boolean).join(' ') ||
event.user.email.split('@')[0];
api.samlResponse.setAttribute('full_name', fullName);
api.samlResponse.setAttribute('roles', flexRoles.join(','));
// Add team attribute (critical for Teams View filtering)
if (flexTeam) {
api.samlResponse.setAttribute('team', flexTeam);
}
// Add program attribute (for billing/reporting)
if (program) {
api.samlResponse.setAttribute('program', program);
}
};
Why This Matters:
- The
teamattribute enables Flex's native Teams View filtering - Jessica (RAMP supervisor with
team: "RAMP") only sees RAMP team members - Senior staff without
teamattribute see ALL teams (admin override) programattribute enables usage tracking by program
3.3 Deploy the Action
- Click Deploy in top right
- Verify action is deployed to the login flow
πΈ Screenshot Placeholders:
[Screenshot: Auth0 Actions - Library View]
Description: Shows the Actions Library with "Add Flex Roles to SAML" action highlighted
Location: Auth0 Dashboard β Actions β Library
[Screenshot: Auth0 Actions - Code Editor]
Description: Shows the action code editor with the updated SAML attribute code
Location: Actions β Add Flex Roles to SAML β Code tab
[Screenshot: Auth0 Actions - Deploy Button]
Description: Shows the Deploy button and deployment confirmation
Location: Actions β Add Flex Roles to SAML β Top right
Step 4: Configure Twilio Flex SSOβ
See: Twilio Flex SSO Configuration for detailed SSO setup steps.
Quick Reference:
- Configure SAML application in Auth0
- Set Auth0 callback URLs for Flex
- Configure Flex SSO settings in Twilio Console
- Set vanity domain (
nss.connie.team)
Step 5: Test Team Visibilityβ
After configuration, validate that team-based visibility works correctly.
Test Scenarios:
β Test 1: Supervisor Sees Only Their Team
- Login: Jessica Buckley (RAMP supervisor)
- Expected: Only sees RAMP team members (Afia) in Teams View
- Expected: Does NOT see members from other programs
β Test 2: Agent Has Appropriate Permissions
- Login: Afia Kambon (RAMP agent)
- Expected: No supervisor controls visible
- Expected: Can accept tasks and change status
β Test 3: Admin Sees All Teams
- Login: Senior executive (no team attribute)
- Expected: Sees ALL program teams in Teams View
- Expected: Full administrative controls
See: Testing Checklist for comprehensive testing protocol.
π Adding Additional Programsβ
Once Pattern A is established, adding new programs follows the same process:
For Each New Program:
-
Create Subaccount (optional)
- Friendly Name:
NSS_ProgramB - Purpose: Usage tracking for new program
- Friendly Name:
-
Add Users to Auth0
- Set
flex.teamto new program name - Set
programattribute for tracking
- Set
-
Update User Roles
- Assign appropriate
flex.roles(admin/supervisor/agent)
- Assign appropriate
-
Test Isolation
- Verify new program team only sees their members
- Verify existing teams unaffected
Example: Adding Adult Day Care Program
{
"flex": {
"roles": ["supervisor"],
"team": "AdultDayCare"
},
"program": "AdultDayCare"
}
No changes to Auth0 Action or Flex configuration requiredβteam attributes handle everything automatically.
π Usage Tracking by Programβ
Viewing Program-Specific Usage:
- Twilio Console β Navigate to specific subaccount
- Usage Dashboard β Filter by date range
- View Metrics:
- Task Router usage
- Flex Active User Hours
- Call/conversation volumes
- Separate billing line items
Timeline: Usage data typically populates within 24-48 hours.
Reporting: Program attribute in user metadata enables custom reporting by program across the single Flex instance.
π’ Real-World Example: NSS RAMP Setupβ
Organization: Nevada Senior Services (NSS) Program: RAMP (Resource Assistance for Marginalized Populations) Architecture: Pattern A (Multi-Program)
Configuration:
| Component | Value |
|---|---|
| Twilio Main Account | AC[MAIN_ACCOUNT_SID] |
| Flex Instance | copper-wolverine-2008 |
| RAMP Subaccount | AC[RAMP_SUBACCOUNT_SID] |
| Auth0 Tenant | dev-kvn1kviua124ipex |
| Vanity Domain | nss.connie.team |
Users:
Jessica Buckley (RAMP Supervisor)
- Email:
jbuckley@nevadaseniorservices.org - User ID:
auth0|691e32d4889ef6e2a3f0626f - Metadata:
{"flex": {"roles": ["supervisor"], "team": "RAMP"}, "program": "RAMP"} - Visibility: Only sees RAMP team members
Afia Kambon (RAMP Agent)
- Email:
akambon@nevadaseniorservices.org - User ID:
auth0|691f64260d15618957163e44 - Metadata:
{"flex": {"roles": ["agent"], "team": "RAMP"}, "program": "RAMP"} - Visibility: Agent-level access, visible to Jessica
Result: Jessica can supervise only her RAMP team while senior NSS executives with admin role see all programs.
β οΈ Common Mistakesβ
β Forgetting Team Attributeβ
Symptom: All users see all teams
Cause: flex.team not set in user metadata
Fix: Add team attribute to all non-admin users
β Auth0 Action Not Deployedβ
Symptom: Team attributes not working after metadata update Cause: Action code updated but not deployed Fix: Click "Deploy" button in Auth0 Actions
β Case Sensitivity Issuesβ
Symptom: Team filtering not working Cause: Team names in metadata don't match exactly (e.g., "ramp" vs "RAMP") Fix: Use consistent team naming (recommend: CamelCase or UPPERCASE)
π Troubleshootingβ
See: Authentication Troubleshooting Guide for detailed debugging steps.
Quick Checks:
- Verify user metadata in Auth0 includes
flex.team - Confirm Auth0 Action is deployed
- Check SAML attributes in Auth0 login logs
- Verify user logged in at least once after Action update
- Confirm Flex Worker attributes in Twilio Console
π Next Stepsβ
- Configure Auth0: Auth0 Configuration Reference
- Setup Flex SSO: Twilio Flex SSO Guide
- Test Deployment: Testing Checklist
If your client requires complete organizational isolation (separate legal entities), use Pattern B: Isolated Organizations instead.