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

# Create Projects

> Complete guide to creating annotation projects in Labellerr using the Python SDK with datasets, templates, and configuration.

## Overview

A **project** in Labellerr combines datasets with annotation guidelines to create a structured workflow for your team. This guide covers everything you need to create projects programmatically using the SDK.

<Card title="Project Creation Requirements" icon="circle-info">
  To create a project, you need three components:

  1. **Dataset(s)** - One or more datasets containing your files
  2. **Annotation Template** - Questions and labels defining your annotation schema
  3. **Project Configuration** - Settings for rotations, AI features, and workflow rules

  All components use validated schemas to catch errors before making API calls.
</Card>

<Card title="Supported Data Types" icon="database">
  * **image** - .jpg, .jpeg, .png, .bmp, .tiff
  * **video** - .mp4
  * **audio** - .mp3, .wav
  * **document** - .pdf
  * **text** - .txt
</Card>

***

## Quick Start

Here's the minimal code to create a project:

```python theme={"dark"}
from labellerr.client import LabellerrClient
from labellerr.core.datasets import create_dataset_from_local
from labellerr.core.annotation_templates import create_template
from labellerr.core.projects import create_project
from labellerr.core.schemas import *
import uuid

# Initialize client
client = LabellerrClient(
    api_key='your_api_key',
    api_secret='your_api_secret',
    client_id='your_client_id'
)

# 1. Create dataset
dataset = create_dataset_from_local(
    client=client,
    dataset_config=DatasetConfig(dataset_name="My Dataset", data_type="image"),
    folder_to_upload="path/to/images"
)

# Wait for dataset to be ready
dataset.status()  # Polls until dataset processing is complete

# 2. Create annotation template
template = create_template(
    client=client,
    params=CreateTemplateParams(
        template_name="My Template",
        data_type=DatasetDataType.image,
        questions=[
            AnnotationQuestion(
                question_number=1,
                question="Object",
                question_id=str(uuid.uuid4()),
                question_type=QuestionType.bounding_box,
                required=True,
                color="#FF0000"
            )
        ]
    )
)

# 3. Create project
project = create_project(
    client=client,
    params=CreateProjectParams(
        project_name="My Project",
        data_type=DatasetDataType.image,
        rotations=RotationConfig(
            annotation_rotation_count=1,
            review_rotation_count=1,
            client_review_rotation_count=1
        )
    ),
    datasets=[dataset],
    annotation_template=template
)

print(f"✓ Project created: {project.project_id}")
```

***

## Step-by-Step Guide

### Step 1: Prepare Your Dataset

You can either create a new dataset or use an existing one.

<Tabs>
  <Tab title="Create New Dataset">
    ```python theme={"dark"}
    from labellerr.core.datasets import create_dataset_from_local
    from labellerr.core.schemas import DatasetConfig

    # From local folder
    dataset = create_dataset_from_local(
        client=client,
        dataset_config=DatasetConfig(
            dataset_name="Training Images",
            data_type="image"
        ),
        folder_to_upload="path/to/images"
    )

    # Wait for dataset processing to complete
    dataset.status()
    ```
  </Tab>

  <Tab title="Use Existing Dataset">
    ```python theme={"dark"}
    from labellerr.core.datasets import LabellerrDataset

    # Reference existing dataset by ID
    dataset = LabellerrDataset(
        client=client,
        dataset_id="your_dataset_id"
    )
    ```
  </Tab>
</Tabs>

***

### Step 2: Create Annotation Template

Define the questions your annotators will answer.

<Tabs>
  <Tab title="Simple Template">
    ```python theme={"dark"}
    from labellerr.core.annotation_templates import create_template
    from labellerr.core.schemas import *
    import uuid

    # Single bounding box question
    template = create_template(
        client=client,
        params=CreateTemplateParams(
            template_name="Object Detection",
            data_type=DatasetDataType.image,
            questions=[
                AnnotationQuestion(
                    question_number=1,
                    question="Detect Vehicle",
                    question_id=str(uuid.uuid4()),
                    question_type=QuestionType.bounding_box,
                    required=True,
                    color="#00FF00"
                )
            ]
        )
    )
    ```
  </Tab>

  <Tab title="Multiple Questions">
    ```python theme={"dark"}
    from labellerr.core.annotation_templates import create_template
    from labellerr.core.schemas import *
    import uuid

    questions = [
        # Object detection
        AnnotationQuestion(
            question_number=1,
            question="Vehicle",
            question_id=str(uuid.uuid4()),
            question_type=QuestionType.bounding_box,
            required=True,
            color="#FF0000"
        ),
        # Dropdown classification
        AnnotationQuestion(
            question_number=2,
            question="Vehicle Type",
            question_id=str(uuid.uuid4()),
            question_type=QuestionType.dropdown,
            required=True,
            options=[
                Option(option_name="Car"),
                Option(option_name="Truck"),
                Option(option_name="Motorcycle")
            ]
        ),
        # Yes/No question
        AnnotationQuestion(
            question_number=3,
            question="Good Image Quality?",
            question_id=str(uuid.uuid4()),
            question_type=QuestionType.boolean,
            required=False,
            options=[
                Option(option_name="Yes"),
                Option(option_name="No")
            ]
        )
    ]

    template = create_template(
        client=client,
        params=CreateTemplateParams(
            template_name="Detailed Vehicle Detection",
            data_type=DatasetDataType.image,
            questions=questions
        )
    )
    ```
  </Tab>

  <Tab title="Use Existing Template">
    ```python theme={"dark"}
    from labellerr.core.annotation_templates import LabellerrAnnotationTemplate

    # Reference existing template
    template = LabellerrAnnotationTemplate(
        client=client,
        annotation_template_id="your_template_id"
    )
    ```
  </Tab>
</Tabs>

***

### Step 3: Configure & Create Project

Now combine your dataset and template to create the project.

```python theme={"dark"}
from labellerr.core.projects import create_project
from labellerr.core.schemas import CreateProjectParams, RotationConfig, DatasetDataType

project = create_project(
    client=client,
    params=CreateProjectParams(
        project_name="Vehicle Detection Project",
        data_type=DatasetDataType.image,
        rotations=RotationConfig(
            annotation_rotation_count=1,  # Each file annotated once
            review_rotation_count=1,      # Reviewed once
            client_review_rotation_count=1  # Client review once
        ),
        use_ai=False,  # Optional: Enable AI assistance
        created_by="YOUR_EMAIL@company.com"  # Optional: Creator email
    ),
    datasets=[dataset],
    annotation_template=template
)

# Access project details
print(f"Project ID: {project.project_id}")
print(f"Data Type: {project.data_type}")
print(f"Template: {project.annotation_template_id}")
print(f"Datasets: {project.attached_datasets}")
```

***

## Common Scenarios

### Using Multiple Datasets

Attach multiple datasets to a single project for larger annotation workflows:

<Warning>
  **Homogeneous Data Requirement**

  All datasets attached to a single project **must be of the same data type** (e.g., all `image`, all `video`, etc.). You cannot mix different data types in the same project.
</Warning>

```python theme={"dark"}
from labellerr.core.datasets import LabellerrDataset

# Get multiple existing datasets
dataset1 = LabellerrDataset(client=client, dataset_id="dataset_id_1")
dataset2 = LabellerrDataset(client=client, dataset_id="dataset_id_2")
dataset3 = LabellerrDataset(client=client, dataset_id="dataset_id_3")

# Ensure all datasets are ready
for dataset in [dataset1, dataset2, dataset3]:
    dataset.status()

# Create project with all datasets
project = create_project(
    client=client,
    params=CreateProjectParams(
        project_name="Large Scale Annotation",
        data_type=DatasetDataType.image,
        rotations=RotationConfig(1, 1, 1)
    ),
    datasets=[dataset1, dataset2, dataset3],  # List of datasets
    annotation_template=template
)
```

***

### Multiple Annotation Rotations

For high-quality annotations, require multiple annotators per file:

```python theme={"dark"}
project = create_project(
    client=client,
    params=CreateProjectParams(
        project_name="High Quality Annotations",
        data_type=DatasetDataType.image,
        rotations=RotationConfig(
            annotation_rotation_count=3,  # 3 annotators per file
            review_rotation_count=2,      # 2 reviewers per file
            client_review_rotation_count=1
        )
    ),
    datasets=[dataset],
    annotation_template=template
)
```

***

### Video Project with Keyframes

For video annotation projects:

```python theme={"dark"}
from labellerr.core.schemas import DatasetDataType

# Create video dataset
video_dataset = create_dataset_from_local(
    client=client,
    dataset_config=DatasetConfig(
        dataset_name="Traffic Videos",
        data_type="video"
    ),
    folder_to_upload="path/to/videos"
)

# Wait for dataset processing to complete
video_dataset.status()

# Create video template
video_template = create_template(
    client=client,
    params=CreateTemplateParams(
        template_name="Vehicle Tracking",
        data_type=DatasetDataType.video,
        questions=[
            AnnotationQuestion(
                question_number=1,
                question="Track Vehicle",
                question_id=str(uuid.uuid4()),
                question_type=QuestionType.bounding_box,
                required=True,
                color="#FF0000"
            )
        ]
    )
)

# Create video project
video_project = create_project(
    client=client,
    params=CreateProjectParams(
        project_name="Vehicle Tracking Project",
        data_type=DatasetDataType.video,
        rotations=RotationConfig(1, 1, 1)
    ),
    datasets=[video_dataset],
    annotation_template=video_template
)
```

***

## Schema Reference

### CreateProjectParams

<Card title="Project Configuration Parameters" icon="list">
  | Parameter      | Type            | Required | Description                          | Example                                                    |
  | -------------- | --------------- | -------- | ------------------------------------ | ---------------------------------------------------------- |
  | `project_name` | str             | Yes      | Display name for your project        | "Vehicle Detection"                                        |
  | `data_type`    | DatasetDataType | Yes      | Type of data being annotated         | DatasetDataType.image                                      |
  | `rotations`    | RotationConfig  | Yes      | Annotation and review cycle settings | RotationConfig(1, 1, 1)                                    |
  | `use_ai`       | bool            | No       | Enable AI-assisted annotation        | True / False (default)                                     |
  | `created_by`   | str             | No       | Email of project creator             | "[YOUR\_EMAIL@company.com](mailto:YOUR_EMAIL@company.com)" |

  <Note>
    The `data_type` must match the data type of all attached datasets.
  </Note>
</Card>

***

### RotationConfig

<Card title="Rotation Configuration" icon="arrows-rotate">
  Defines how many times each file goes through annotation and review cycles.

  **Constructor:**

  ```python theme={"dark"}
  RotationConfig(
      annotation_rotation_count: int,
      review_rotation_count: int,
      client_review_rotation_count: int
  )
  ```

  | Parameter                      | Type | Min Value | Description                   |
  | ------------------------------ | ---- | --------- | ----------------------------- |
  | `annotation_rotation_count`    | int  | 1         | Number of annotators per file |
  | `review_rotation_count`        | int  | 1         | Number of reviewers per file  |
  | `client_review_rotation_count` | int  | 1         | Number of client reviewers    |

  **Examples:**

  ```python theme={"dark"}
  # Standard workflow: 1 annotator, 1 reviewer
  RotationConfig(1, 1, 1)

  # High quality: 3 annotators, 2 reviewers
  RotationConfig(3, 2, 1)

  # Review-focused: 1 annotator, 3 reviewers
  RotationConfig(1, 3, 1)
  ```

  <Tip>
    Higher rotation counts improve annotation quality but increase project time and cost. Balance based on your accuracy requirements.
  </Tip>

  <Warning>
    **Free User Rotation Limitations**

    For users on the **Free Plan**, rotation configuration is limited to the basic workflow:

    **Available Configuration:**

    * `RotationConfig(1, 1, 1)` - Only 1:1:1 rotation is available

    This means:

    * ✅ 1 annotator per file
    * ✅ 1 reviewer per file
    * ✅ 1 client reviewer per file

    **Upgrade for Advanced Rotations:**

    * `RotationConfig(3, 2, 1)` - Requires paid plan
    * `RotationConfig(2, 2, 1)` - Requires paid plan
    * Any configuration with values > 1 - Requires paid plan

    To unlock higher rotation counts and improve annotation quality through multiple annotators/reviewers, please upgrade your plan.
  </Warning>
</Card>

***

### QuestionType Enum

<Card title="Available Question Types" icon="question">
  Choose the appropriate question type for your annotation needs.

  <Tip>
    **New to annotation types?** Learn more about each annotation type with visual examples in our [Annotation Types Guide](https://docs.labellerr.com/actions/annotations-guide#these-are-the-annotation-types-that-you-can-use-on-labellerr).
  </Tip>

  **Object-Based Questions (Drawing):**

  | Type                        | Value         | Use Case                             | Requires Color |
  | --------------------------- | ------------- | ------------------------------------ | -------------- |
  | `QuestionType.bounding_box` | "BoundingBox" | Rectangular object detection         | ✅ Yes          |
  | `QuestionType.polygon`      | "polygon"     | Irregular shape segmentation         | ✅ Yes          |
  | `QuestionType.polyline`     | "polyline"    | Line/path annotation                 | ✅ Yes          |
  | `QuestionType.dot`          | "dot"         | Point marking (landmarks, keypoints) | ✅ Yes          |

  **Classification Questions (Selection):**

  | Type                    | Value      | Use Case                              | Requires Options  |
  | ----------------------- | ---------- | ------------------------------------- | ----------------- |
  | `QuestionType.dropdown` | "dropdown" | Single selection from many options    | ✅ Yes             |
  | `QuestionType.radio`    | "radio"    | Single selection with visible options | ✅ Yes             |
  | `QuestionType.select`   | "select"   | Multiple selections allowed           | ✅ Yes             |
  | `QuestionType.boolean`  | "boolean"  | Yes/No or True/False questions        | ✅ Yes (2 options) |
  | `QuestionType.input`    | "input"    | Free text entry                       | ❌ No              |

  **Example Usage:**

  ```python theme={"dark"}
  # Object detection (requires color)
  AnnotationQuestion(
      question_type=QuestionType.bounding_box,
      color="#FF0000",  # Required for object types
      ...
  )

  # Classification (requires options)
  AnnotationQuestion(
      question_type=QuestionType.dropdown,
      options=[  # Required for classification types
          Option(option_name="Option 1"),
          Option(option_name="Option 2")
      ],
      ...
  )

  # Text input (no options needed)
  AnnotationQuestion(
      question_type=QuestionType.input,
      # No color or options required
      ...
  )
  ```
</Card>

***

## Import Users from Another Project

Copy the user list (with roles/permissions) from one project to another in the same workspace-existing users are not duplicated.

```python theme={"dark"}
from labellerr.client import LabellerrClient
from labellerr.core.projects import LabellerrProject
import os

# Initialize client
client = LabellerrClient(
    api_key=os.getenv("API_KEY"),
    api_secret=os.getenv("API_SECRET"),
    client_id=os.getenv("CLIENT_ID"),
)

# Target project (already created)
target_project = LabellerrProject(
    client=client,
    project_id="your_target_project_id",
)

# Source project to import users from
source_project = LabellerrProject(
    client=client,
    project_id=os.getenv("IMPORT_USERS_FROM_PROJECT_ID"),
)

# Import users (roles/permissions preserved; no duplicates)
target_project.import_users(from_project=source_project)
print("Users imported successfully")
```

<Info>
  * Same-workspace only; roles/permissions are preserved.
  * If a user already exists in the target project, they are not duplicated.
</Info>

***

## Complete End-to-End Example

Here's a production-ready example with error handling:

```python theme={"dark"}
from labellerr.client import LabellerrClient
from labellerr.core.datasets import create_dataset_from_local
from labellerr.core.annotation_templates import create_template
from labellerr.core.projects import create_project
from labellerr.core.schemas import *
from labellerr.core.exceptions import LabellerrError
import uuid

def create_annotation_project():
    """Create a complete annotation project from scratch."""
    
    # Initialize client
    client = LabellerrClient(
        api_key='your_api_key',
        api_secret='your_api_secret',
        client_id='your_client_id'
    )
    
    try:
        # Step 1: Create dataset
        print("📦 Creating dataset...")
        dataset = create_dataset_from_local(
            client=client,
            dataset_config=DatasetConfig(
                dataset_name="Production Images Q1 2024",
                dataset_description="Customer submitted images for annotation",
                data_type="image"
            ),
            folder_to_upload="data/images"
        )
        print(f"   ✓ Dataset created: {dataset.dataset_id}")
        print(f"   Files count: {dataset.files_count}")
        
        # Wait for dataset processing to complete
        print("\n⏳ Waiting for dataset to be ready...")
        dataset.status()
        print("   ✓ Dataset is ready!")
        
        # Step 2: Create annotation template
        print("\n📋 Creating annotation template...")
        questions = [
            AnnotationQuestion(
                question_number=1,
                question="Vehicle Detection",
                question_id=str(uuid.uuid4()),
                question_type=QuestionType.bounding_box,
                required=True,
                color="#FF5733"
            ),
            AnnotationQuestion(
                question_number=2,
                question="Vehicle Category",
                question_id=str(uuid.uuid4()),
                question_type=QuestionType.dropdown,
                required=True,
                options=[
                    Option(option_name="Sedan"),
                    Option(option_name="SUV"),
                    Option(option_name="Truck"),
                    Option(option_name="Van"),
                    Option(option_name="Motorcycle")
                ]
            ),
            AnnotationQuestion(
                question_number=3,
                question="Image Clear?",
                question_id=str(uuid.uuid4()),
                question_type=QuestionType.radio,
                required=True,
                options=[
                    Option(option_name="Clear"),
                    Option(option_name="Blurry"),
                    Option(option_name="Dark")
                ]
            )
        ]
        
        template = create_template(
            client=client,
            params=CreateTemplateParams(
                template_name="Vehicle Detection Template Q1",
                data_type=DatasetDataType.image,
                questions=questions
            )
        )
        print(f"   ✓ Template created: {template.annotation_template_id}")
        
        # Step 3: Create project
        print("\n🚀 Creating project...")
        project = create_project(
            client=client,
            params=CreateProjectParams(
                project_name="Vehicle Detection - Q1 2024",
                data_type=DatasetDataType.image,
                rotations=RotationConfig(
                    annotation_rotation_count=2,  # Double annotation for quality
                    review_rotation_count=1,
                    client_review_rotation_count=1
                ),
                use_ai=True,  # Enable AI assistance
                created_by="YOUR_EMAIL@company.com"  # Replace with actual email
            ),
            datasets=[dataset],
            annotation_template=template
        )
        
        print(f"\n{'='*60}")
        print(f"✅ PROJECT CREATED SUCCESSFULLY")
        print(f"{'='*60}")
        print(f"Project ID:       {project.project_id}")
        print(f"Project Name:     Vehicle Detection - Q1 2024")
        print(f"Data Type:        {project.data_type}")
        print(f"Template ID:      {project.annotation_template_id}")
        print(f"Datasets:         {len(project.attached_datasets)}")
        print(f"{'='*60}")
        
        return project
        
    except LabellerrError as e:
        print(f"\n❌ Error creating project: {str(e)}")
        raise
    except Exception as e:
        print(f"\n❌ Unexpected error: {str(e)}")
        raise

# Run the function
if __name__ == "__main__":
    project = create_annotation_project()
```

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Dataset has no files error" icon="circle-exclamation">
    **Error:** `Dataset {dataset_id} has no files`

    **Cause:** The dataset was created but files haven't finished uploading or processing.

    **Solution:**

    * Always call `dataset.status()` before creating a project to ensure dataset is ready
    * This method polls until dataset processing is complete

    ```python theme={"dark"}
    dataset = create_dataset_from_local(...)
    dataset.status()  # Wait for completion
    project = create_project(...)  # Now safe to create
    ```

    * Verify folder path is correct and contains files
    * Check `dataset.files_count` to confirm files were uploaded
  </Accordion>

  <Accordion title="Data type mismatch" icon="exclamation-triangle">
    **Error:** Data type conflicts between project, dataset, and template

    **Solution:**

    * Ensure all components use the same data type:

    ```python theme={"dark"}
    # All must match
    dataset_config = DatasetConfig(data_type="image")
    template_params = CreateTemplateParams(data_type=DatasetDataType.image)
    project_params = CreateProjectParams(data_type=DatasetDataType.image)
    ```
  </Accordion>

  <Accordion title="Template creation fails" icon="file-circle-xmark">
    **Cause:** Missing required fields in questions (color for objects, options for classifications)

    **Solution:**

    * Object types require `color` field
    * Classification types require `options` list
    * Use `required=True` for mandatory questions
  </Accordion>

  <Accordion title="Authentication errors" icon="lock">
    **Solution:**

    * Verify API key and secret are correct
    * Check key hasn't expired
    * Ensure you have permissions to create projects
  </Accordion>
</AccordionGroup>

***

## Related Documentation

<CardGroup cols={3}>
  <Card title="Create Dataset" icon="database" href="/sdk/create-dataset-sdk">
    Learn how to create and manage datasets
  </Card>

  <Card title="Annotation Questions" icon="circle-question" href="/sdk/add-annotation-questions">
    Detailed guide on crafting annotation questions
  </Card>

  <Card title="Upload Pre-annotations" icon="upload" href="/sdk/upload-preannotation-sdk">
    Import existing annotations into your project
  </Card>

  <Card title="Export Annotations" icon="download" href="/sdk/create-export-sdk">
    Export completed annotations in various formats
  </Card>

  <Card title="Video Operations" icon="video" href="/sdk/video-project-operations-sdk">
    Special operations for video projects
  </Card>

  <Card title="Getting Started" icon="rocket" href="/sdk/getting-started">
    SDK installation and initialization guide
  </Card>
</CardGroup>

***

## Need Help?

<Note>
  For technical support or questions about project creation, contact us at [support@tensormatics.com](mailto:support@tensormatics.com)
</Note>
