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

# Organizations

> API reference for organization management

List and manage organizations, members, and invitations.

## List Organizations

```
GET /api/v1/organizations/
```

Returns all organizations the authenticated user belongs to.

### Parameters

| Name       | Type    | Required | Description                                  |
| ---------- | ------- | -------- | -------------------------------------------- |
| `ordering` | string  | No       | Field to order results by (query parameter)  |
| `cursor`   | string  | No       | Cursor for pagination (query parameter)      |
| `limit`    | integer | No       | Number of results per page (query parameter) |

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.avala.ai/api/v1/organizations/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.avala.ai/api/v1/organizations/",
      headers={"X-Avala-Api-Key": "YOUR_API_KEY"}
  )
  organizations = response.json()["results"]
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.avala.ai/api/v1/organizations/",
    {
      headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
    }
  );
  const { results } = await response.json();
  ```

  ```go Go theme={null}
  req, _ := http.NewRequest("GET", "https://api.avala.ai/api/v1/organizations/", nil)
  req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")

  resp, err := http.DefaultClient.Do(req)
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "next": null,
  "previous": null,
  "results": [
    {
      "uid": "ee4h6d00-n17k-30m3-j605-335544330000",
      "name": "Acme Robotics",
      "slug": "acme-robotics",
      "logo_url": "https://storage.avala.ai/orgs/acme-robotics/logo.png",
      "member_count": 12,
      "created_at": "2024-06-01T12:00:00Z"
    }
  ]
}
```

### Fields

| Field          | Type              | Description                                                |
| -------------- | ----------------- | ---------------------------------------------------------- |
| `uid`          | string (UUID)     | Unique identifier for the organization                     |
| `name`         | string            | Display name of the organization                           |
| `slug`         | string            | URL-friendly identifier                                    |
| `logo_url`     | string            | URL to the organization's logo image, or `null` if not set |
| `member_count` | integer           | Total number of members in the organization                |
| `created_at`   | string (datetime) | ISO 8601 timestamp of when the organization was created    |

***

## Get Organization

```
GET /api/v1/organizations/{org_slug}/
```

Returns detailed information about a specific organization.

### Parameters

| Name       | Type   | Required | Description                                          |
| ---------- | ------ | -------- | ---------------------------------------------------- |
| `org_slug` | string | Yes      | Slug identifier of the organization (path parameter) |

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.avala.ai/api/v1/organizations/acme-robotics/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.avala.ai/api/v1/organizations/acme-robotics/",
      headers={"X-Avala-Api-Key": "YOUR_API_KEY"}
  )
  organization = response.json()
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.avala.ai/api/v1/organizations/acme-robotics/",
    {
      headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
    }
  );
  const organization = await response.json();
  ```

  ```go Go theme={null}
  req, _ := http.NewRequest("GET", "https://api.avala.ai/api/v1/organizations/acme-robotics/", nil)
  req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")

  resp, err := http.DefaultClient.Do(req)
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "uid": "ee4h6d00-n17k-30m3-j605-335544330000",
  "name": "Acme Robotics",
  "slug": "acme-robotics",
  "logo_url": "https://storage.avala.ai/orgs/acme-robotics/logo.png",
  "member_count": 12,
  "created_at": "2024-06-01T12:00:00Z"
}
```

### Fields

| Field          | Type              | Description                                                |
| -------------- | ----------------- | ---------------------------------------------------------- |
| `uid`          | string (UUID)     | Unique identifier for the organization                     |
| `name`         | string            | Display name of the organization                           |
| `slug`         | string            | URL-friendly identifier                                    |
| `logo_url`     | string            | URL to the organization's logo image, or `null` if not set |
| `member_count` | integer           | Total number of members in the organization                |
| `created_at`   | string (datetime) | ISO 8601 timestamp of when the organization was created    |

***

## List Members

```
GET /api/v1/organizations/{org_slug}/members/
```

Returns all members of a specific organization, including their roles.

### Parameters

| Name       | Type    | Required | Description                                          |
| ---------- | ------- | -------- | ---------------------------------------------------- |
| `org_slug` | string  | Yes      | Slug identifier of the organization (path parameter) |
| `ordering` | string  | No       | Field to order results by (query parameter)          |
| `cursor`   | string  | No       | Cursor for pagination (query parameter)              |
| `limit`    | integer | No       | Number of results per page (query parameter)         |

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.avala.ai/api/v1/organizations/acme-robotics/members/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.avala.ai/api/v1/organizations/acme-robotics/members/",
      headers={"X-Avala-Api-Key": "YOUR_API_KEY"}
  )
  members = response.json()["results"]
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.avala.ai/api/v1/organizations/acme-robotics/members/",
    {
      headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
    }
  );
  const { results } = await response.json();
  ```

  ```go Go theme={null}
  req, _ := http.NewRequest("GET", "https://api.avala.ai/api/v1/organizations/acme-robotics/members/", nil)
  req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")

  resp, err := http.DefaultClient.Do(req)
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "next": null,
  "previous": null,
  "results": [
    {
      "uid": "aa0d2900-c73a-96b9-f261-991100990000",
      "username": "janedoe",
      "email": "jane@acmerobotics.com",
      "role": "owner",
      "joined_at": "2024-06-01T12:00:00Z"
    },
    {
      "uid": "ff5i7e00-o28l-41n4-k716-446655440000",
      "username": "bobsmith",
      "email": "bob@acmerobotics.com",
      "role": "admin",
      "joined_at": "2024-07-15T09:00:00Z"
    },
    {
      "uid": "gg6j8f00-p39m-52o5-l827-557766550000",
      "username": "alicejones",
      "email": "alice@acmerobotics.com",
      "role": "member",
      "joined_at": "2024-08-20T11:30:00Z"
    }
  ]
}
```

### Fields

| Field       | Type              | Description                                                       |
| ----------- | ----------------- | ----------------------------------------------------------------- |
| `uid`       | string (UUID)     | Unique identifier for the member                                  |
| `username`  | string            | Member's username                                                 |
| `email`     | string            | Member's email address                                            |
| `role`      | string            | Member's role in the organization (`owner`, `admin`, or `member`) |
| `joined_at` | string (datetime) | ISO 8601 timestamp of when the member joined the organization     |

***

## Invite User

```
POST /api/v1/organizations/{org_slug}/invitations/
```

Sends an invitation to a user to join the organization. The invited user will receive an email with instructions to accept.

### Parameters

| Name       | Type   | Required | Description                                                              |
| ---------- | ------ | -------- | ------------------------------------------------------------------------ |
| `org_slug` | string | Yes      | Slug identifier of the organization (path parameter)                     |
| `email`    | string | Yes      | Email address of the user to invite (body parameter)                     |
| `role`     | string | Yes      | Role to assign to the invited user: `admin` or `member` (body parameter) |

<Info>
  Only users with the `owner` or `admin` role can invite new members. The `owner` role cannot be assigned through invitations.
</Info>

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.avala.ai/api/v1/organizations/acme-robotics/invitations/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "email": "newuser@example.com",
      "role": "member"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.avala.ai/api/v1/organizations/acme-robotics/invitations/",
      headers={
          "X-Avala-Api-Key": "YOUR_API_KEY",
          "Content-Type": "application/json"
      },
      json={
          "email": "newuser@example.com",
          "role": "member"
      }
  )
  invitation = response.json()
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.avala.ai/api/v1/organizations/acme-robotics/invitations/",
    {
      method: "POST",
      headers: {
        "X-Avala-Api-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        email: "newuser@example.com",
        role: "member",
      }),
    }
  );
  const invitation = await response.json();
  ```

  ```go Go theme={null}
  body := strings.NewReader(`{
      "email": "newuser@example.com",
      "role": "member"
  }`)

  req, _ := http.NewRequest("POST", "https://api.avala.ai/api/v1/organizations/acme-robotics/invitations/", body)
  req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
  req.Header.Set("Content-Type", "application/json")

  resp, err := http.DefaultClient.Do(req)
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "uid": "hh7k9g00-q40n-63p6-m938-668877660000",
  "email": "newuser@example.com",
  "role": "member",
  "status": "pending",
  "invited_by": "aa0d2900-c73a-96b9-f261-991100990000",
  "created_at": "2025-01-21T10:00:00Z"
}
```

### Fields

| Field        | Type              | Description                                                |
| ------------ | ----------------- | ---------------------------------------------------------- |
| `uid`        | string (UUID)     | Unique identifier for the invitation                       |
| `email`      | string            | Email address of the invited user                          |
| `role`       | string            | Role that will be assigned when the invitation is accepted |
| `status`     | string            | Invitation status (`pending`, `accepted`, or `expired`)    |
| `invited_by` | string (UUID)     | UID of the user who sent the invitation                    |
| `created_at` | string (datetime) | ISO 8601 timestamp of when the invitation was created      |

***

## Member Roles

Organizations support three roles with different permission levels.

| Role     | Description                | Permissions                                                                                                                  |
| -------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `owner`  | Organization owner         | Full access. Can manage billing, delete the organization, transfer ownership, and manage all members including admins.       |
| `admin`  | Organization administrator | Can manage projects, datasets, and members. Can invite and remove members. Cannot delete the organization or manage billing. |
| `member` | Standard member            | Can view and work on assigned projects and datasets. Cannot manage organization settings or invite new members.              |

<Warning>
  Each organization must have exactly one owner. Ownership can only be transferred by the current owner through the Mission Control interface.
</Warning>

***

## Error Responses

### Not Found (404)

```json theme={null}
{
  "detail": "Not found."
}
```

Returned when the specified organization does not exist or the user is not a member.

### Permission Denied (403)

```json theme={null}
{
  "detail": "You do not have permission to perform this action."
}
```

Returned when the authenticated user does not have the required role to perform the action (e.g., a member attempting to invite users).

### Unauthorized (401)

```json theme={null}
{
  "detail": "Invalid API key."
}
```

Returned when the `X-Avala-Api-Key` header is missing or contains an invalid key.

### Validation Error (400)

```json theme={null}
{
  "email": ["Enter a valid email address."],
  "role": ["\"superadmin\" is not a valid choice."]
}
```

Returned when the request body is missing required fields or contains invalid values.

### Conflict (409)

```json theme={null}
{
  "detail": "An invitation for this email address already exists."
}
```

Returned when attempting to invite a user who has already been invited or is already a member of the organization.
