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

# Teams API - List and Create Teams in Your Hierarchy

> Retrieve your full team hierarchy or create new child teams using the Examino Teams API. Requires an API key with the appropriate scope.

The Teams API lets you inspect the team tree associated with your API key and provision new teams beneath it. Every API key is bound to a root team, all read and write operations are scoped to that root and its descendants. You can use this API to mirror your institution's organizational structure (campuses, departments, cohorts) inside Examino.

## List Teams

<ParamField header="Authorization" type="string" required>
  Bearer token. Format: `Bearer $EXAMINO_API_KEY`
</ParamField>

<Note>
  Required scope: `teams:read`
</Note>

Returns your key's root team and every descendant team, regardless of nesting depth.

### Request

```bash theme={null}
curl https://app.examino.ai/api/v1/teams \
  -H "Authorization: Bearer $EXAMINO_API_KEY"
```

### Response

```json theme={null}
{
  "rootTeamId": "6b0b1f1a-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
  "items": [
    {
      "id": "6b0b1f1a-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
      "name": "Groupe Exemple",
      "slug": "groupe-exemple",
      "kind": "workspace",
      "parentTeamId": null,
      "createdAt": "2026-01-12T09:31:04.221Z"
    },
    {
      "id": "d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9",
      "name": "Campus Lyon",
      "slug": "campus-lyon",
      "kind": "workspace",
      "parentTeamId": "6b0b1f1a-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
      "createdAt": "2026-02-03T14:02:57.880Z"
    }
  ],
  "total": 2
}
```

### Response Fields

<ResponseField name="rootTeamId" type="string">
  The UUID of the team the API key is bound to. Every other item in `items` is a direct or indirect descendant of this team.
</ResponseField>

<ResponseField name="items" type="array">
  Flat list of all teams in scope, the root team plus all descendants.

  <Expandable title="items[]">
    <ResponseField name="items[].id" type="string">
      UUID of the team.
    </ResponseField>

    <ResponseField name="items[].name" type="string">
      Human-readable display name of the team.
    </ResponseField>

    <ResponseField name="items[].slug" type="string">
      URL-safe identifier derived from the team name. Used in Examino dashboard URLs.
    </ResponseField>

    <ResponseField name="items[].kind" type="string">
      Team type. `workspace` teams can hold exams and be assigned credits. `folder` teams are purely organizational nodes and cannot hold exams directly.
    </ResponseField>

    <ResponseField name="items[].parentTeamId" type="string | null">
      UUID of this team's parent, or `null` if this is the root team.
    </ResponseField>

    <ResponseField name="items[].createdAt" type="string">
      ISO 8601 timestamp recording when the team was created.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="total" type="integer">
  Total number of teams returned in `items`.
</ResponseField>

***

## Create a Team

<ParamField header="Authorization" type="string" required>
  Bearer token. Format: `Bearer $EXAMINO_API_KEY`
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`.
</ParamField>

<Note>
  Required scope: `teams:write`
</Note>

Creates a new team as a child of an existing team within your key's scope. On success, returns the newly created team object with HTTP `201 Created`.

### Request Parameters

<ParamField body="name" type="string" required>
  Display name for the new team. Must be between 1 and 120 characters.
</ParamField>

<ParamField body="parentTeamId" type="string">
  UUID of the team that will become the parent. Must belong to your key's scope. Defaults to your key's root team if omitted.
</ParamField>

<ParamField body="kind" type="string" default="workspace">
  Team type. Pass `workspace` for teams that will hold exams, or `folder` for purely organizational grouping nodes. Defaults to `workspace`.
</ParamField>

### Request

```bash theme={null}
curl -X POST https://app.examino.ai/api/v1/teams \
  -H "Authorization: Bearer $EXAMINO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Campus Lille",
    "parentTeamId": "6b0b1f1a-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
    "kind": "workspace"
  }'
```

### Response

```json theme={null}
{
  "id": "0a1b2c3d-4e5f-4061-8273-84950a1b2c3d",
  "name": "Campus Lille",
  "slug": "campus-lille",
  "kind": "workspace",
  "parentTeamId": "6b0b1f1a-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
  "createdAt": "2026-09-17T08:14:22.019Z"
}
```

### Response Fields

<ResponseField name="id" type="string">
  UUID assigned to the newly created team.
</ResponseField>

<ResponseField name="name" type="string">
  Display name as provided in the request.
</ResponseField>

<ResponseField name="slug" type="string">
  Auto-generated URL-safe identifier derived from `name`.
</ResponseField>

<ResponseField name="kind" type="string">
  `workspace` or `folder`, as specified in the request (or the default).
</ResponseField>

<ResponseField name="parentTeamId" type="string">
  UUID of the parent team. Matches the value you provided, or your key's root team if you omitted `parentTeamId`.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 timestamp of when the team was created.
</ResponseField>

### Error Responses

<AccordionGroup>
  <Accordion title="404 - Parent team not found">
    The `parentTeamId` you provided either does not exist or is outside your API key's scope. Verify that the UUID belongs to a team within your key's hierarchy.

    ```json theme={null}
    {
      "error": "not_found",
      "message": "parentTeamId not found within key scope"
    }
    ```
  </Accordion>

  <Accordion title="400 - Invalid request">
    The request body is malformed or the specified parent would create an impossible hierarchy (for example, making a team its own ancestor). Check your payload and team relationships before retrying.

    ```json theme={null}
    {
      "error": "invalid_request",
      "message": "The specified parent would create a circular hierarchy"
    }
    ```
  </Accordion>

  <Accordion title="409 - Name conflict">
    A team with the same `name` already exists under the same parent. Team names must be unique at each level of the hierarchy.

    ```json theme={null}
    {
      "error": "conflict",
      "message": "A team with this name already exists under the specified parent"
    }
    ```
  </Accordion>
</AccordionGroup>

<Tip>
  Slugs are derived automatically from the team name at creation time. If you later rename a team through the dashboard, the slug does not change, existing integrations using the slug remain stable.
</Tip>
