> ## Documentation Index
> Fetch the complete documentation index at: https://docs.riseworks.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Teams

> Learn about team management, roles, and permissions in Rise B2B

Teams are the core organizational unit in Rise B2B. They represent groups of users who can collaborate on payments, manage shared funds, and control access to resources.

## Team Structure

<Steps>
  <Step title="Create Team">
    Establish a new team with a name and initial admin
  </Step>

  <Step title="Add Members">
    Invite users with specific roles and permissions
  </Step>

  <Step title="Manage Funds">
    Control shared entity balances and payment limits
  </Step>

  <Step title="Set Permissions">
    Configure access levels for different team members
  </Step>
</Steps>

## Team Roles

Rise B2B supports four distinct team roles with different permission levels:

### Team Admin

* **Full control** over team settings and members
* Can create, modify, and delete team configurations
* Manages all team funds and payment limits
* Can invite and remove team members
* Access to all team features and data

### Finance Admin

* **Financial management** capabilities
* Can create and execute payments
* Manages team budgets and spending limits
* Can view financial reports and transaction history
* Cannot modify team structure or member permissions

### Team Employee

* **Standard team member** with payment capabilities
* Can create and execute payments within limits
* Access to team funds for authorized transactions
* Can view relevant team information
* Cannot modify team settings or invite new members

### Team Viewer

* **Read-only access** to team information
* Can view team members, payments, and balances
* Cannot create payments or modify any settings
* Useful for auditors, accountants, or stakeholders

## Creating Teams

### Step 1: Create a New Team

<RequestExample>
  ```bash theme={null}
  curl -X POST "${this.baseUrl}/v2/teams" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Engineering Team",
      "description": "Core engineering team for product development",
      "entity_nanoid": "entity_123",
      "admin_wallet": "0x1234567890abcdef..."
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "success": true,
    "data": {
      "team_nanoid": "team_123456789",
      "name": "Engineering Team",
      "description": "Core engineering team for product development",
      "entity_nanoid": "entity_123",
      "admin_wallet": "0x1234567890abcdef...",
      "created_at": "2024-01-01T12:00:00Z",
      "member_count": 1,
      "status": "active"
    }
  }
  ```
</ResponseExample>

### Step 2: Add Team Members

<RequestExample>
  ```bash theme={null}
  curl -X POST "${this.baseUrl}/v2/teams/team_123456789/members" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "user_nanoid": "user_456",
      "role": "team_employee",
      "permissions": ["pay", "view"]
    }'
  ```
</RequestExample>

## Team Management Examples

<CodeGroup>
  ```javascript theme={null}
  class RiseTeams {
    constructor(baseUrl, jwtToken) {
      this.baseUrl = baseUrl;
      this.headers = {
        'Authorization': `Bearer ${jwtToken}`,
        'Content-Type': 'application/json'
      };
    }

    async createTeam(name, description, entity_nanoid, admin_wallet) {
      const teamData = {
        name,
        description,
        entity_nanoid: entity_nanoid,
        admin_wallet: admin_wallet
      };

      const response = await fetch(`${this.baseUrl}/v2/teams`, {
        method: 'POST',
        headers: this.headers,
        body: JSON.stringify(teamData)
      });

      return response.json();
    }

    async getTeam(teamNanoid) {
      const response = await fetch(
        `${this.baseUrl}/v2/teams/${teamNanoid}`,
        { headers: this.headers }
      );
      return response.json();
    }

    async addMember(teamNanoid, userNanoid, role, permissions) {
      const memberData = {
        user_nanoid: userNanoid,
        role,
        permissions
      };

      const response = await fetch(`${this.baseUrl}/v2/teams/${teamNanoid}/members`, {
        method: 'POST',
        headers: this.headers,
        body: JSON.stringify(memberData)
      });

      return response.json();
    }

    async updateMemberRole(teamNanoid, userNanoid, newRole, newPermissions) {
      const updateData = {
        role: newRole,
        permissions: newPermissions
      };

      const response = await fetch(`${this.baseUrl}/v2/teams/${teamNanoid}/members/${userNanoid}`, {
        method: 'PUT',
        headers: this.headers,
        body: JSON.stringify(updateData)
      });

      return response.json();
    }

    async removeMember(teamNanoid, userNanoid) {
      const response = await fetch(`${this.baseUrl}/v2/teams/${teamNanoid}/members/${userNanoid}`, {
        method: 'DELETE',
        headers: this.headers
      });

      return response.json();
    }
  }

  // Usage example
  const teamsApi = new RiseTeams(
    'https://b2b-api.riseworks.io', // or your environment URL
    'your-jwt-token'
  );
  ```

  ```python theme={null}
  import requests
  from typing import List, Optional

  class RiseTeams:
      def __init__(self, base_url: str, jwt_token: str = None):
          self.base_url = base_url
          self.headers = {
              "Authorization": f"Bearer {jwt_token}",
              "Content-Type": "application/json"
          }
      
      def create_team(
          self, 
          name: str, 
          description: str, 
          entity_nanoid: str, 
          admin_wallet: str
      ) -> dict:
          """Create a new team"""
          team_data = {
              "name": name,
              "description": description,
              "entity_nanoid": entity_nanoid,
              "admin_wallet": admin_wallet
          }
          
          response = requests.post(
              f"{self.base_url}/v2/teams",
              headers=self.headers,
              json=team_data
          )
          return response.json()
      
      def get_team(self, team_nanoid: str) -> dict:
          """Get team details"""
          response = requests.get(
              f"{self.base_url}/v2/teams/{team_nanoid}",
              headers=self.headers
          )
          return response.json()
      
      def add_member(
          self, 
          team_nanoid: str, 
          user_nanoid: str, 
          role: str, 
          permissions: List[str]
      ) -> dict:
          """Add a member to the team"""
          member_data = {
              "user_nanoid": user_nanoid,
              "role": role,
              "permissions": permissions
          }
          
          response = requests.post(
              f"{self.base_url}/v2/teams/{team_nanoid}/members",
              headers=self.headers,
              json=member_data
          )
          return response.json()

  # Usage example
  teams_api = RiseTeams(
      "https://b2b-api.riseworks.io",  # or your environment URL
      "your-jwt-token"
  )
  ```
</CodeGroup>

## Team Permissions Matrix

| Permission  | Team Admin | Finance Admin | Employee | Viewer |
| ----------- | ---------- | ------------- | -------- | ------ |
| **View**    | ✅          | ✅             | ✅        | ✅      |
| **Pay**     | ✅          | ✅             | ✅        | ❌      |
| **Finance** | ✅          | ✅             | ❌        | ❌      |
| **Manage**  | ✅          | ❌             | ❌        | ❌      |
| **Invite**  | ✅          | ❌             | ❌        | ❌      |

## Error Handling

Common team management errors and solutions:

| Error Code                 | Description                      | Solution                                        |
| -------------------------- | -------------------------------- | ----------------------------------------------- |
| `INVALID_TEAM_NAME`        | Team name is invalid or too long | Use a valid team name (2-50 characters)         |
| `INVALID_ADMIN_WALLET`     | Admin wallet address is invalid  | Ensure wallet address is valid Ethereum address |
| `INSUFFICIENT_PERMISSIONS` | User lacks permission for action | Check user's role and permissions               |
| `TEAM_NOT_FOUND`           | Team does not exist              | Verify team\_nanoid is correct                  |
| `MEMBER_ALREADY_EXISTS`    | User is already a team member    | Check existing team membership                  |
| `CANNOT_REMOVE_ADMIN`      | Cannot remove the last admin     | Ensure at least one admin remains               |

## Best Practices

<Warning>
  **Always maintain at least one team admin** to prevent losing access to team management capabilities.
</Warning>

* **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

See [Permissions](/concepts/permissions) for details on role-based access control.
