ClouisleClouisle

Teams API

Manage teams and memberships

Endpoints

MethodPathPurposeScope
GET/api/v1/teams/myList teams the current user belongs toteam:read
GET/api/v1/teams/{team_id}Get team details (includes member list)team:read
POST/api/v1/admin/teamsCreate a teamadmin:team:create
PUT/api/v1/teams/{team_id}Update team informationteam:update
DELETE/api/v1/admin/teams/{team_id}Delete a teamadmin:team:delete
POST/api/v1/teams/{team_id}/membersAdd a team memberteam:manage
PUT/api/v1/teams/{team_id}/members/{user_id}Update a member's roleteam:manage
DELETE/api/v1/teams/{team_id}/members/{user_id}Remove a team memberteam:manage

Base URLs

  • Platform: /api/v1/teams
  • Admin: /api/v1/admin/teams

Authentication

All team endpoints require an authenticated JWT user session. API-key authentication is not accepted.

Required scopes:

ScopeDescription
team:readView team information
team:updateUpdate team details
team:manageManage team members and membership operations
admin:team:createCreate teams (admin)
admin:team:deleteDelete teams (admin)

List My Teams

Get all teams the current user belongs to, with the user's role in each.

GET /api/v1/teams/my
curl -X GET "https://your-domain.com/api/v1/teams/my" \
  -H "Authorization: Bearer YOUR_TOKEN"

Success (200 OK):

{
  "code": 0,
  "data": [
    {
      "id": "team-123",
      "name": "Marketing Team",
      "description": "Marketing and content creation team",
      "avatar_url": null,
      "role": "member",
      "joined_at": "2026-01-15T10:00:00Z"
    }
  ],
  "msg": "success"
}

There is no GET /api/v1/teams list endpoint for all teams. Admins can list all teams (paginated, with search by name or description) via GET /api/v1/admin/teams (page/page_size, default page_size 50), which requires admin:team:read.

Get Team

Get details of a specific team, including the member list.

GET /api/v1/teams/{team_id}

Path Parameters:

ParameterTypeRequiredDescription
team_idstringYesTeam UUID
curl -X GET "https://your-domain.com/api/v1/teams/team-123" \
  -H "Authorization: Bearer YOUR_TOKEN"

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "team-123",
    "name": "Marketing Team",
    "description": "Marketing and content creation team",
    "avatar_url": null,
    "is_default": false,
    "owner": {
      "id": "user-456",
      "username": "alice",
      "email": "alice@example.com",
      "avatar_url": "https://example.com/avatars/alice.jpg"
    },
    "created_at": "2026-01-15T10:00:00Z",
    "updated_at": "2026-02-11T15:30:00Z",
    "members": [
      {
        "id": "membership-001",
        "user_id": "user-456",
        "username": "alice",
        "email": "alice@example.com",
        "avatar_url": "https://example.com/avatars/alice.jpg",
        "role": "owner",
        "joined_at": "2026-01-15T10:00:00Z"
      },
      {
        "id": "membership-002",
        "user_id": "user-789",
        "username": "bob",
        "email": "bob@example.com",
        "avatar_url": null,
        "role": "member",
        "joined_at": "2026-01-16T10:00:00Z"
      }
    ]
  },
  "msg": "success"
}

Create Team

Create a new team (admin only).

POST /api/v1/admin/teams

Request Body:

{
  "name": "Sales Team",
  "description": "Sales and customer relations team",
  "avatar_url": null
}

Request Fields:

FieldTypeRequiredDescription
namestringYesTeam name
descriptionstringNoTeam description
avatar_urlstringNoTeam avatar URL
curl -X POST "https://your-domain.com/api/v1/admin/teams" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sales Team",
    "description": "Sales and customer relations team"
  }'

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "team-456",
    "name": "Sales Team",
    "description": "Sales and customer relations team",
    "avatar_url": null,
    "is_default": false,
    "owner": null,
    "created_at": "2026-02-11T16:00:00Z",
    "updated_at": "2026-02-11T16:00:00Z"
  },
  "msg": "Team created successfully"
}

Update Team

Update team information.

PUT /api/v1/teams/{team_id}

Path Parameters:

ParameterTypeRequiredDescription
team_idstringYesTeam UUID

Request Body: All fields are optional. Only include fields you want to update.

{
  "name": "Updated Team Name",
  "description": "Updated description",
  "avatar_url": null
}
curl -X PUT "https://your-domain.com/api/v1/teams/team-123" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Team Name"
  }'

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "team-123",
    "name": "Updated Team Name",
    "description": null,
    "avatar_url": null,
    "is_default": false,
    "owner": {
      "id": "user-456",
      "username": "alice",
      "email": "alice@example.com",
      "avatar_url": null
    },
    "created_at": "2026-01-15T10:00:00Z",
    "updated_at": "2026-02-11T16:05:00Z"
  },
  "msg": "Team updated successfully"
}

Delete Team

Delete a team permanently (admin only).

DELETE /api/v1/admin/teams/{team_id}

Path Parameters:

ParameterTypeRequiredDescription
team_idstringYesTeam UUID
curl -X DELETE "https://your-domain.com/api/v1/admin/teams/team-123" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

Success (200 OK):

{
  "code": 0,
  "data": null,
  "msg": "Team deleted successfully"
}

Add Team Member

Add a member to a team.

POST /api/v1/teams/{team_id}/members

Path Parameters:

ParameterTypeRequiredDescription
team_idstringYesTeam UUID

Request Body:

{
  "user_id": "user-999",
  "role": "member"
}

Request Fields:

FieldTypeRequiredDescription
user_idstringYesUser UUID to add
rolestringNoMember role: admin, member, viewer (default: member)
curl -X POST "https://your-domain.com/api/v1/teams/team-123/members" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user-999",
    "role": "member"
  }'

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "membership-003",
    "user_id": "user-999",
    "username": "carol",
    "email": "carol@example.com",
    "avatar_url": null,
    "role": "member",
    "joined_at": "2026-02-11T16:00:00Z"
  },
  "msg": "Member added successfully"
}

Update Team Member

Update a team member's role.

PUT /api/v1/teams/{team_id}/members/{user_id}

Path Parameters:

ParameterTypeRequiredDescription
team_idstringYesTeam UUID
user_idstringYesUser UUID

Request Body:

{
  "role": "admin"
}
curl -X PUT "https://your-domain.com/api/v1/teams/team-123/members/user-999" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "admin"
  }'

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "membership-003",
    "user_id": "user-999",
    "username": "carol",
    "email": "carol@example.com",
    "avatar_url": null,
    "role": "admin",
    "joined_at": "2026-02-11T16:00:00Z"
  },
  "msg": "Member role updated successfully"
}

Remove Team Member

Remove a member from a team.

DELETE /api/v1/teams/{team_id}/members/{user_id}

Path Parameters:

ParameterTypeRequiredDescription
team_idstringYesTeam UUID
user_idstringYesUser UUID
curl -X DELETE "https://your-domain.com/api/v1/teams/team-123/members/user-999" \
  -H "Authorization: Bearer YOUR_TOKEN"

Success (200 OK):

{
  "code": 0,
  "data": null,
  "msg": "Member removed successfully"
}

Unimplemented Features

The following features are not yet implemented and are on the roadmap:

  • List team members: There is no separate GET /teams/{team_id}/members endpoint. The full member list is included in the GET /api/v1/teams/{team_id} response (see Get Team).
  • Team statistics: There is no team statistics endpoint.

Error Codes

CodeMessageDescription
4004Team not foundTeam does not exist
3000Permission deniedInsufficient permissions
3002Not team memberUser is not a team member
1001Validation failedInvalid request data
5102Name already existsTeam name is taken
5103Already team memberUser is already a member

No per-endpoint rate limits are implemented. There is no rate-limit middleware on these endpoints.

Code Examples

Python

import requests

def list_my_teams(token):
    """List teams the current user belongs to."""
    url = "https://your-domain.com/api/v1/teams/my"
    headers = {
        "Authorization": f"Bearer {token}"
    }

    response = requests.get(url, headers=headers)
    result = response.json()

    if result['code'] == 0:
        return result['data']
    else:
        raise Exception(f"Error: {result['msg']}")

def add_team_member(token, team_id, user_id, role="member"):
    """Add a member to a team."""
    url = f"https://your-domain.com/api/v1/teams/{team_id}/members"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    data = {
        "user_id": user_id,
        "role": role
    }

    response = requests.post(url, headers=headers, json=data)
    result = response.json()

    if result['code'] == 0:
        return result['data']
    else:
        raise Exception(f"Error: {result['msg']}")

# Usage
teams = list_my_teams("YOUR_TOKEN")
for team in teams:
    print(f"Team: {team['name']} (role: {team['role']})")

member = add_team_member("YOUR_TOKEN", "team-123", "user-999", "member")
print(f"Added member: {member['user_id']}")

JavaScript

async function listMyTeams(token) {
  const response = await fetch(
    'https://your-domain.com/api/v1/teams/my',
    {
      headers: {
        'Authorization': `Bearer ${token}`,
      },
    }
  );

  const result = await response.json();

  if (result.code === 0) {
    return result.data;
  } else {
    throw new Error(result.msg);
  }
}

async function addTeamMember(token, teamId, userId, role = 'member') {
  const response = await fetch(
    `https://your-domain.com/api/v1/teams/${teamId}/members`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        user_id: userId,
        role: role,
      }),
    }
  );

  const result = await response.json();

  if (result.code === 0) {
    return result.data;
  } else {
    throw new Error(result.msg);
  }
}

// Usage
const teams = await listMyTeams('YOUR_TOKEN');
teams.forEach(team => {
  console.log(`Team: ${team.name} (role: ${team.role})`);
});

const member = await addTeamMember('YOUR_TOKEN', 'team-123', 'user-999', 'member');
console.log('Added member:', member.user_id);

How is this guide?

On this page