Skip to main content
Learn how to manage teams and users with the Rise B2B API using the official SDK. The SDK provides methods for team updates, user management, and team invitations.

Team Management Flow

1

Initialize SDK

Set up the Rise SDK with authentication
2

Get User Teams

Retrieve teams associated with the current user
3

Update Team Settings

Modify team information and settings
4

Manage Team Members

Send invitations and manage team membership

SDK Installation

First, install the Rise SDK:
npm install @riseworks/sdk

Getting Started

Initialize the SDK

const { RiseApiClient } = require('@riseworks/sdk');
require('dotenv').config();

// Initialize with Rise ID and private key (recommended)
const client = new RiseApiClient({
  environment: 'prod',
  riseIdAuth: {
    riseId: process.env.RISE_ID,
    privateKey: process.env.PRIVATE_KEY
  }
});

// Alternative: Initialize with JWT token
const jwtClient = new RiseApiClient({
  environment: 'prod',
  jwtToken: process.env.JWT_TOKEN
});

Team Management Operations

Get User’s Teams

Retrieve all teams associated with the current user:
// Get all teams for the current user
const teams = await client.user.getTeams();
console.log('User teams:', teams.data);

// Example response structure
// {
//   "success": true,
//   "data": {
//     "teams": [
//       {
//         "nanoid": "te-abc123def456",
//         "name": "Engineering Team",
//         "description": "Core engineering team",
//         "member_count": 5,
//         "status": "active"
//       }
//     ]
//   }
// }

Update Team Information

Update team settings and information:
// Update team information
await client.team.update({
  nanoid: 'te-abc123def456',
  name: 'Updated Engineering Team',
  description: 'Updated team description'
});

console.log('Team updated successfully');

Team Invitations

The SDK provides different approaches for sending team invitations depending on the role:

Regular Team Invitations

For regular team members (employees, viewers), no signing is required:
// Send invitation to regular team members (no signing required)
const invitation = await client.invites.send({
  nanoid: 'te-abc123def456',
  invites: [
    {
      email: 'john.doe@example.com',
      role: 'team_employee',
      permissions: ['pay', 'view']
    },
    {
      email: 'jane.smith@example.com',
      role: 'team_viewer',
      permissions: ['view']
    }
  ],
  role: 'team_employee',
  anonymous: false
});

console.log('Invitations sent:', invitation.data);
What the SDK does automatically:
  1. Validates invitation data and permissions
  2. Sends invitations to the specified email addresses
  3. Handles authentication and JWT token management
  4. Provides error handling and validation

Manager Invitations (Requires Signing)

For manager-level invitations (team_admin, finance_admin), signing is required. The SDK must be initialized with a private key for automatic signing:
// Initialize SDK with private key for automatic signing
const client = new RiseApiClient({
  environment: 'prod',
  riseIdAuth: {
    riseId: process.env.RISE_ID,
    privateKey: process.env.PRIVATE_KEY  // Required for automatic signing
  }
});

// Send manager invitation with automatic signing
const managerInvite = await client.invites.sendManagerInvite({
  emails: ['manager@example.com'],
  role: 'team_admin',
  nanoid: 'te-abc123def456'
});

console.log('Manager invitation sent:', managerInvite.data);
What the SDK does automatically:
  1. Generates typed data for EIP-712 signing
  2. Signs the typed data using your private key
  3. Submits the signed invitation to the Rise API
  4. Handles authentication and JWT token management
  5. Provides error handling and retry logic

Manual Manager Invitations

For more control over manager invitation signing, you can handle the signing manually:
// Initialize SDK (private key not required for manual flow)
const client = new RiseApiClient({
  environment: 'prod',
  jwtToken: process.env.JWT_TOKEN  // JWT token is sufficient for manual flow
});

// Step 1: Get typed data for signing
const typedDataResponse = await client.invites.getManagerInviteTypedData({
  emails: ['manager@example.com'],
  role: 'team_admin',
  nanoid: 'te-abc123def456'
});

console.log('Typed data received:', typedDataResponse.data);

// Step 2: Sign the typed data (if you want custom signing logic)
const { ethers } = require('ethers');
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY);
const signature = await wallet.signTypedData(
  typedDataResponse.data.typed_data.domain,
  typedDataResponse.data.typed_data.types,
  typedDataResponse.data.typed_data.typed_data
);

// Step 3: Execute with signature
const executeResponse = await client.invites.executeManagerInviteWithSignedData({
  invites: typedDataResponse.data.invites,
  signer: wallet.address,
  typed_data: typedDataResponse.data.typed_data.typed_data,
  signature: signature
});

console.log('Manager invitation executed:', executeResponse.data);
What the manual flow provides:
  1. Custom signing logic - You control when and how to sign
  2. Typed data inspection - You can examine the data before signing
  3. Signature verification - You can verify the signature before submission
  4. Error handling control - Custom error handling for each step
  5. Integration flexibility - Easier integration with existing signing workflows

Complete Team Management Example

Here’s a complete example using the Rise SDK:
const { RiseApiClient } = require('@riseworks/sdk');
require('dotenv').config();

class RiseTeamManager {
  constructor() {
    this.client = new RiseApiClient({
      environment: 'prod',
      riseIdAuth: {
        riseId: process.env.RISE_ID,
        privateKey: process.env.PRIVATE_KEY
      }
    });
  }

  async getUserTeams() {
    try {
      const teams = await this.client.user.getTeams();
      return teams.data;
    } catch (error) {
      console.error('Failed to get user teams:', error.message);
      throw error;
    }
  }

  async updateTeam(teamNanoid, updates) {
    try {
      await this.client.team.update({
        nanoid: teamNanoid,
        ...updates
      });
      console.log('Team updated successfully');
    } catch (error) {
      console.error('Failed to update team:', error.message);
      throw error;
    }
  }

  async inviteTeamMembers(teamNanoid, members) {
    try {
      const invitation = await this.client.invites.send({
        nanoid: teamNanoid,
        invites: members,
        role: 'team_employee',
        anonymous: false
      });
      
      console.log('Team invitations sent:', invitation.data);
      return invitation.data;
    } catch (error) {
      console.error('Failed to send invitations:', error.message);
      throw error;
    }
  }

  async inviteManager(teamNanoid, email, role = 'team_admin') {
    try {
      const managerInvite = await this.client.invites.sendManagerInvite({
        emails: [email],
        role: role,
        nanoid: teamNanoid
      });
      
      console.log('Manager invitation sent:', managerInvite.data);
      return managerInvite.data;
    } catch (error) {
      console.error('Failed to send manager invitation:', error.message);
      throw error;
    }
  }

  async getTeamInvites(teamNanoid) {
    try {
      const invites = await this.client.invites.get({
        nanoid: teamNanoid
      });
      return invites.data;
    } catch (error) {
      console.error('Failed to get team invites:', error.message);
      throw error;
    }
  }
}

// Usage example
const teamManager = new RiseTeamManager();

async function main() {
  try {
    // Get user's teams
    const teams = await teamManager.getUserTeams();
    console.log('User teams:', teams);

    if (teams.teams && teams.teams.length > 0) {
      const firstTeam = teams.teams[0];

      // Update team information
      await teamManager.updateTeam(firstTeam.nanoid, {
        name: 'Updated Engineering Team',
        description: 'Updated team description'
      });

      // Invite new team members
      const newMembers = [
        {
          email: 'developer1@example.com',
          role: 'team_employee',
          permissions: ['pay', 'view']
        },
        {
          email: 'developer2@example.com',
          role: 'team_employee',
          permissions: ['pay', 'view']
        }
      ];

      await teamManager.inviteTeamMembers(firstTeam.nanoid, newMembers);

      // Invite a manager
      await teamManager.inviteManager(
        firstTeam.nanoid,
        'manager@example.com',
        'team_admin'
      );

      // Get team invitations
      const invites = await teamManager.getTeamInvites(firstTeam.nanoid);
      console.log('Team invitations:', invites);
    }

  } catch (error) {
    console.error('Team management error:', error.message);
  }
}

// Run the example
if (require.main === module) {
  main();
}

Team Roles and Permissions

RolePermissionsDescription
Team Adminpay, view, manage, inviteFull control over team settings and members
Finance Adminpay, view, financeFinancial management capabilities
Team Employeepay, viewStandard team member with payment capabilities
Team ViewerviewRead-only access to team information

Error Handling

The SDK provides comprehensive error handling:
try {
  const teams = await client.user.getTeams();
  console.log('Teams retrieved successfully:', teams.data);
} catch (error) {
  console.error('Team management error:', error.message);
  
  // Handle specific error types based on message content
  if (error.message.includes('401')) {
    console.error('Authentication failed');
  } else if (error.message.includes('403')) {
    console.error('Insufficient permissions for this operation');
  } else if (error.message.includes('404')) {
    console.error('Team not found');
  } else if (error.message.includes('invalid')) {
    console.error('Invalid team data provided');
  } else {
    console.error('Team operation failed:', error.message);
  }
}
Common team management errors:
Error MessageDescriptionSolution
401Authentication failedCheck your credentials and JWT token
403Insufficient permissionsVerify user has required role and permissions
404Team not foundCheck team nanoid is correct
invalid team dataInvalid team informationVerify team data format and requirements
invitation failedFailed to send invitationCheck email format and team permissions

Best Practices

Always maintain at least one team admin to prevent losing access to team management capabilities.

Team Management Best Practices

  • Role Hierarchy: Use the principle of least privilege when assigning roles
  • Regular Audits: Periodically review team members and their permissions
  • Documentation: Keep records of team structure and permission changes
  • Backup Admins: Always have multiple admins for critical teams
  • Permission Reviews: Regularly review and update member permissions

SDK Best Practices

  • Error Handling: Implement proper error handling for all team operations
  • Authentication: Use Rise ID authentication for automatic JWT management
  • Environment: Use staging environment for testing team operations
  • Logging: Log team management operations for audit purposes

Testing Team Management

For testing, use the staging environment:
// Staging configuration for testing
const stagingClient = new RiseApiClient({
  environment: 'stg',
  riseIdAuth: {
    riseId: process.env.RISE_ID,
    privateKey: process.env.PRIVATE_KEY
  }
});

// Test team operations
const testTeams = await stagingClient.user.getTeams();
console.log('Test teams:', testTeams.data);

Next Steps

Need help? See the Teams page for detailed team management concepts or contact support at Hello@Riseworks.io
I