> ## 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.

# Projects API

> API reference for project operations

List and retrieve annotation projects.

## List Projects

```
GET /api/v1/projects/{owner_name}/
```

Returns all projects belonging to a specific owner that are visible to the authenticated user.

### Parameters

| Name         | Type    | Required | Description                                    |
| ------------ | ------- | -------- | ---------------------------------------------- |
| `owner_name` | string  | Yes      | Username of the project owner (path parameter) |
| `name`       | string  | No       | Filter by project name (query 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/projects/johndoe/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY"
  ```

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

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

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.avala.ai/api/v1/projects/johndoe/",
    {
      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/projects/johndoe/", 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": "770a9600-a40d-63f6-c938-668877660000",
      "name": "Object Detection",
      "task_type": "image-annotation",
      "status": "active",
      "is_active": true,
      "visibility": "private",
      "is_imported": false,
      "owner_name": "johndoe",
      "short_description": "Detect vehicles and pedestrians",
      "industry_icon": "automotive"
    }
  ]
}
```

### Fields

| Field               | Type          | Description                                              |
| ------------------- | ------------- | -------------------------------------------------------- |
| `uid`               | string (UUID) | Unique identifier for the project                        |
| `name`              | string        | Project name (1-100 characters)                          |
| `task_type`         | string        | Type of annotation task assigned to this project         |
| `status`            | string        | Current project status                                   |
| `is_active`         | boolean       | Whether the project is currently active                  |
| `visibility`        | string        | `public` or `private`                                    |
| `is_imported`       | boolean       | Whether the project was imported from an external source |
| `owner_name`        | string        | Username of the project owner                            |
| `short_description` | string        | Brief description of the project                         |
| `industry_icon`     | string        | Industry category icon identifier                        |

***

## Task Types

| Type                     | Description                                                  |
| ------------------------ | ------------------------------------------------------------ |
| `image-annotation`       | 2D image annotation (bounding boxes, polygons, segmentation) |
| `video-annotation`       | Video frame-by-frame annotation                              |
| `point-cloud-annotation` | 3D point cloud annotation with cuboids                       |
| `point-cloud-objects`    | 3D object detection in point clouds                          |

***

## Project Statuses

| Status             | Description                                |
| ------------------ | ------------------------------------------ |
| `pending-approval` | Awaiting approval to start                 |
| `active`           | Currently active and accepting annotations |
| `paused`           | Temporarily paused                         |
| `canceled`         | Canceled and no longer active              |
| `archived`         | Archived for historical reference          |
| `completed`        | All annotation tasks have been completed   |

***

## Clone Project from Template

```
POST /api/v1/projects/create-from-existing/
```

Create a new project by cloning an existing template project onto a new dataset. The new project inherits the template's task definitions, annotation configuration, and industry settings. The project is created in `pending-approval` status.

<Note>
  Requires `IsCustomer` or `IsStaff` permission. Coworker accounts cannot clone projects.
</Note>

### Request Body

| Name                 | Type          | Required | Description                                          |
| -------------------- | ------------- | -------- | ---------------------------------------------------- |
| `source_project_uid` | string (UUID) | Yes      | UID of the template project to clone                 |
| `name`               | string        | Yes      | Name for the new project (must be unique per owner)  |
| `image_dataset_uid`  | string (UUID) | No       | UID of the image dataset to attach                   |
| `lidar_dataset_uid`  | string (UUID) | No       | UID of the LiDAR dataset (for 3D projects)           |
| `slice_uid`          | string (UUID) | No       | UID of a slice to attach instead of a full dataset   |
| `copy_collaborators` | boolean       | No       | Copy collaborators from the template (default: true) |

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.avala.ai/api/v1/projects/create-from-existing/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "source_project_uid": "770a9600-a40d-63f6-c938-668877660000",
      "name": "Batch 2026-04-09",
      "image_dataset_uid": "880b0700-b51e-74g7-d049-779988770000"
    }'
  ```

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

  response = requests.post(
      "https://api.avala.ai/api/v1/projects/create-from-existing/",
      headers={"X-Avala-Api-Key": "YOUR_API_KEY"},
      json={
          "source_project_uid": "770a9600-a40d-63f6-c938-668877660000",
          "name": "Batch 2026-04-09",
          "image_dataset_uid": "880b0700-b51e-74g7-d049-779988770000",
      },
  )
  project = response.json()
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "uid": "990c1800-c62f-85h8-e150-880099880000",
  "name": "Batch 2026-04-09",
  "status": "pending-approval",
  "task_type": "image-annotation",
  "owner_name": "dev@acme.com",
  "visibility": "private"
}
```

***

## Approve Project

```
POST /api/v1/projects/{uid}/approve/
```

Approve a project to start annotation work. This triggers the full task creation pipeline: tasks, work units, and work batches are created automatically. Coworkers can then claim and annotate the tasks.

<Warning>
  Approving a project starts billable annotation work. This action cannot be undone — use pause or cancel to stop work after approval.
</Warning>

### Requirements

* **Plan**: Your organization must be on the **PRO** or **ENTERPRISE** plan. BASIC plan organizations receive a `403` error.
* **Scope**: API keys must include the `projects.write` scope.
* **Ownership**: You must own the project (or be staff).
* **Status**: The project must be in `pending-approval` status.

### Parameters

| Name  | Type          | Required | Description                  |
| ----- | ------------- | -------- | ---------------------------- |
| `uid` | string (UUID) | Yes      | Project UID (path parameter) |

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.avala.ai/api/v1/projects/990c1800-c62f-85h8-e150-880099880000/approve/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY"
  ```

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

  response = requests.post(
      "https://api.avala.ai/api/v1/projects/990c1800-c62f-85h8-e150-880099880000/approve/",
      headers={"X-Avala-Api-Key": "YOUR_API_KEY"},
  )
  project = response.json()
  print(f"Project {project['name']} is now {project['status']}")
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "uid": "990c1800-c62f-85h8-e150-880099880000",
  "name": "Batch 2026-04-09",
  "status": "active",
  "task_type": "image-annotation",
  "owner_name": "dev@acme.com",
  "visibility": "private"
}
```

### Error Responses

| Status | Code                | Description                                                             |
| ------ | ------------------- | ----------------------------------------------------------------------- |
| `403`  | `plan_insufficient` | Organization is on BASIC plan. Upgrade to PRO or ENTERPRISE.            |
| `403`  | `scope_required`    | API key is missing the `projects.write` scope.                          |
| `400`  | —                   | Project is not in `pending-approval` status (invalid state transition). |
| `404`  | —                   | Project not found or not owned by the authenticated user.               |

```json theme={null}
{
  "detail": "Project approval requires a PRO or ENTERPRISE plan.",
  "code": "plan_insufficient",
  "doc_url": "https://docs.avala.ai/api/errors#plan_insufficient"
}
```

***

## Pause / Resume / Cancel / Archive Project

```
POST /api/v1/projects/{uid}/{action}/
```

Change a project's status. Available actions depend on the current status.

| Action    | From Status             | To Status  | Description                      |
| --------- | ----------------------- | ---------- | -------------------------------- |
| `pause`   | `active`                | `paused`   | Temporarily stop annotation work |
| `resume`  | `paused`                | `active`   | Resume paused annotation work    |
| `cancel`  | `active`, `paused`      | `canceled` | Permanently stop annotation work |
| `archive` | `completed`, `canceled` | `archived` | Archive for historical reference |

<Note>
  Pause, resume, cancel, and archive do not require specific API key scopes. Only the `approve` action requires the `projects.write` scope.
</Note>

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.avala.ai/api/v1/projects/990c1800-c62f-85h8-e150-880099880000/pause/" \
    -H "X-Avala-Api-Key: $AVALA_API_KEY"
  ```

  ```python Python theme={null}
  response = requests.post(
      "https://api.avala.ai/api/v1/projects/990c1800-c62f-85h8-e150-880099880000/pause/",
      headers={"X-Avala-Api-Key": "YOUR_API_KEY"},
  )
  ```
</CodeGroup>

### Response

Returns the updated project object (same shape as the approve response).

***

## Error Responses

### Not Found (404)

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

Returned when the specified owner does not exist or has no visible projects.

### Permission Denied (403)

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

Returned when the authenticated user does not have access to the requested projects.

### Unauthorized (401)

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

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