Skip to content

Teams

Teams in Albert allow organizations to manage groups of users that can be assigned in bulk to projects.

albert.collections.teams.TeamCollection

TeamCollection(*, session: AlbertSession)

Bases: BaseCollection

TeamCollection manages Team entities in the Albert platform.

Parameters:

Name Type Description Default
session AlbertSession

The Albert session instance.

required

Attributes:

Name Type Description
base_path str

The base URL for team API requests.

Methods:

Name Description
get_all

Lists all teams with optional filters.

get_by_id

Retrieves a team by its ID.

create

Creates a new team, optionally with initial members.

update

Updates a team's name and membership.

delete

Deletes a team by its ID.

add_users

Adds users to a team.

remove_users

Removes users from a team.

Parameters:

Name Type Description Default
session AlbertSession

The Albert session instance.

required
Source code in src/albert/collections/teams.py
def __init__(self, *, session: AlbertSession):
    """Initialize the TeamCollection.

    Parameters
    ----------
    session : AlbertSession
        The Albert session instance.
    """
    super().__init__(session=session)
    self.base_path = f"/api/{TeamCollection._api_version}/teams"

base_path

base_path = f'/api/{_api_version}/teams'

get_all

get_all(
    *,
    name: str | list[str] | None = None,
    exact_match: bool = True,
    created_by: str | None = None,
    updated_by: str | None = None,
    user_id: str | list[str] | None = None,
    max_items: int | None = None,
) -> Iterator[Team]

List all teams with optional filters.

Parameters:

Name Type Description Default
name str or list[str]

Filter teams by one or more names.

None
exact_match bool

Whether to match the name(s) exactly. Default is True.

True
created_by str

Filter teams by the user ID of their creator.

None
updated_by str

Filter teams by the user ID of their last updater.

None
user_id str or list[str]

Filter teams by user membership.

None
max_items int

Maximum total number of items to return. If None, fetches all available items.

None

Returns:

Type Description
Iterator[Team]

An iterator of Team entities matching the filters.

Source code in src/albert/collections/teams.py
def get_all(
    self,
    *,
    name: str | list[str] | None = None,
    exact_match: bool = True,
    created_by: str | None = None,
    updated_by: str | None = None,
    user_id: str | list[str] | None = None,
    max_items: int | None = None,
) -> Iterator[Team]:
    """List all teams with optional filters.

    Parameters
    ----------
    name : str or list[str], optional
        Filter teams by one or more names.
    exact_match : bool, optional
        Whether to match the name(s) exactly. Default is True.
    created_by : str, optional
        Filter teams by the user ID of their creator.
    updated_by : str, optional
        Filter teams by the user ID of their last updater.
    user_id : str or list[str], optional
        Filter teams by user membership.
    max_items : int, optional
        Maximum total number of items to return. If None, fetches all available items.

    Returns
    -------
    Iterator[Team]
        An iterator of Team entities matching the filters.
    """
    params: dict = {}
    if name is not None:
        params["name"] = ensure_list(name)
        params["exactMatch"] = exact_match
    if created_by is not None:
        params["createdBy"] = created_by
    if updated_by is not None:
        params["updatedBy"] = updated_by
    if user_id is not None:
        params["userId"] = ensure_list(user_id)

    return AlbertPaginator(
        mode=PaginationMode.KEY,
        path=self.base_path,
        session=self.session,
        params=params,
        max_items=max_items,
        deserialize=lambda items: [Team(**item) for item in items],
    )

get_by_id

get_by_id(*, id: TeamId) -> Team

Retrieve a team by its ID.

Parameters:

Name Type Description Default
id TeamId

The ID of the team.

required

Returns:

Type Description
Team

The Team entity.

Source code in src/albert/collections/teams.py
@validate_call
def get_by_id(self, *, id: TeamId) -> Team:
    """Retrieve a team by its ID.

    Parameters
    ----------
    id : TeamId
        The ID of the team.

    Returns
    -------
    Team
        The Team entity.
    """
    url = f"{self.base_path}/{id}"
    response = self.session.get(url)
    return Team(**response.json())

create

create(
    *, name: str, members: list[TeamMember] | None = None
) -> Team

Create a new team, optionally with initial members.

Parameters:

Name Type Description Default
name str

The name of the team.

required
members list[TeamMember]

Members to add to the team on creation, each with an ID and role.

None

Returns:

Type Description
Team

The created Team.

Source code in src/albert/collections/teams.py
@validate_call
def create(
    self,
    *,
    name: str,
    members: list[TeamMember] | None = None,
) -> Team:
    """Create a new team, optionally with initial members.

    Parameters
    ----------
    name : str
        The name of the team.
    members : list[TeamMember], optional
        Members to add to the team on creation, each with an ID and role.

    Returns
    -------
    Team
        The created Team.
    """
    payload: dict = {"name": name}
    if members:
        acl_entries = [{"id": m.id, "fgc": m.role or "TeamViewer"} for m in members]
        payload["ACL"] = acl_entries

    response = self.session.post(self.base_path, json=payload)
    return Team(**response.json())

update

update(*, team: Team) -> Team

Update a team's name and membership.

Parameters:

Name Type Description Default
team Team

The team with desired changes applied. Modify the name, add or remove entries from members, or change a member's role before calling this method.

required

Returns:

Type Description
Team

The updated Team.

Source code in src/albert/collections/teams.py
@validate_call
def update(self, *, team: Team) -> Team:
    """Update a team's name and membership.

    Parameters
    ----------
    team : Team
        The team with desired changes applied. Modify the ``name``,
        add or remove entries from ``members``, or change a member's
        ``role`` before calling this method.

    Returns
    -------
    Team
        The updated Team.
    """
    current = self.get_by_id(id=team.id)
    url = f"{self.base_path}/{team.id}"
    operations = []

    # Name diff
    if current.name != team.name:
        operations.append(
            {
                "operation": "update",
                "attribute": "name",
                "oldValue": current.name,
                "newValue": team.name,
            }
        )

    # Member diff — None means "no change", empty list means "remove all"
    if team.members is not None:
        current_ids = {m.id for m in current.members or []}
        updated_ids = {m.id for m in team.members}

        added = updated_ids - current_ids
        removed = current_ids - updated_ids

        updated_members = {m.id: m for m in team.members}

        for uid in added:
            member = updated_members[uid]
            role = member.role or "TeamViewer"
            operations.append(
                {
                    "operation": "add",
                    "attribute": "ACL",
                    "newValue": [{"id": uid, "fgc": role}],
                }
            )

        for uid in removed:
            operations.append(
                {
                    "operation": "delete",
                    "attribute": "ACL",
                    "oldValue": [{"id": uid}],
                }
            )

        # Role changes for existing members
        current_members = {m.id: m for m in current.members or []}
        for uid in current_ids & updated_ids:
            updated_role = updated_members[uid].role
            current_role = current_members[uid].role
            if current_role is None or updated_role is None:
                continue
            if updated_role != current_role:
                operations.append(
                    {
                        "operation": "update",
                        "attribute": "fgc",
                        "oldValue": current_role,
                        "newValue": updated_role,
                        "id": uid,
                    }
                )

    if operations:
        payload = {"data": operations}
        self.session.patch(url, json=payload)

    return self.get_by_id(id=team.id)

delete

delete(*, id: TeamId) -> None

Delete a team by its ID.

Parameters:

Name Type Description Default
id TeamId

The ID of the team to delete.

required

Returns:

Type Description
None
Source code in src/albert/collections/teams.py
@validate_call
def delete(self, *, id: TeamId) -> None:
    """Delete a team by its ID.

    Parameters
    ----------
    id : TeamId
        The ID of the team to delete.

    Returns
    -------
    None
    """
    url = f"{self.base_path}/{id}"
    self.session.delete(url)

add_users

add_users(*, id: TeamId, members: list[TeamMember]) -> Team

Add users to a team.

Parameters:

Name Type Description Default
id TeamId

The ID of the team.

required
members list[TeamMember]

The members to add, each with an ID and role.

required

Raises:

Type Description
AlbertException

If any of the provided users is already a member. Use update to change an existing member's role.

Returns:

Type Description
Team

The updated Team.

Source code in src/albert/collections/teams.py
@validate_call
def add_users(
    self,
    *,
    id: TeamId,
    members: list[TeamMember],
) -> Team:
    """Add users to a team.

    Parameters
    ----------
    id : TeamId
        The ID of the team.
    members : list[TeamMember]
        The members to add, each with an ID and role.

    Raises
    ------
    AlbertException
        If any of the provided users is already a member. Use ``update``
        to change an existing member's role.

    Returns
    -------
    Team
        The updated Team.
    """
    current = self.get_by_id(id=id)
    existing_ids = {m.id for m in current.members or []}

    new_ids = [m.id for m in members]
    already_present = [uid for uid in new_ids if uid in existing_ids]
    if already_present:
        raise AlbertException(
            f"Users already in team {id}: {already_present}. Use update() to change roles."
        )

    acl_entries = [{"id": m.id, "fgc": m.role or "TeamViewer"} for m in members]
    url = f"{self.base_path}/{id}"
    payload = {
        "data": [
            {
                "operation": "add",
                "attribute": "ACL",
                "newValue": acl_entries,
            }
        ],
    }
    self.session.patch(url, json=payload)
    return self.get_by_id(id=id)

remove_users

remove_users(
    *, id: TeamId, users: list[User | UserId]
) -> Team

Remove users from a team.

Parameters:

Name Type Description Default
id TeamId

The ID of the team.

required
users list[User | UserId]

The users to remove. Accepts User objects or user ID strings.

required

Raises:

Type Description
AlbertException

If none of the provided users are members of the team.

Returns:

Type Description
Team

The updated Team.

Source code in src/albert/collections/teams.py
@validate_call
def remove_users(
    self,
    *,
    id: TeamId,
    users: list[User | UserId],
) -> Team:
    """Remove users from a team.

    Parameters
    ----------
    id : TeamId
        The ID of the team.
    users : list[User | UserId]
        The users to remove. Accepts User objects or user ID strings.

    Raises
    ------
    AlbertException
        If none of the provided users are members of the team.

    Returns
    -------
    Team
        The updated Team.
    """
    current = self.get_by_id(id=id)
    existing_ids = {m.id for m in current.members or []}

    user_ids = [self._resolve_user_id(u) for u in users]
    present = [uid for uid in user_ids if uid in existing_ids]
    if not present:
        raise AlbertException(f"None of the provided users are members of team {id}.")

    acl_entries = [{"id": uid} for uid in present]
    url = f"{self.base_path}/{id}"
    payload = {
        "data": [
            {
                "operation": "delete",
                "attribute": "ACL",
                "oldValue": acl_entries,
            }
        ],
    }
    self.session.patch(url, json=payload)
    return self.get_by_id(id=id)