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

# Managing Tasks

> Create tasks, upload data, configure jobs, and manage the annotation lifecycle

Tasks are the core annotation units in CVAT. Each task contains uploaded data (images or videos) that will be annotated according to the project's label schema.

## Task Lifecycle

A task progresses through several stages:

1. **Creation**: Task is created with configuration
2. **Data upload**: Images/videos are uploaded to the task
3. **Job generation**: Task is split into jobs for annotators
4. **Annotation**: Annotators label the data
5. **Validation**: Quality review and corrections
6. **Acceptance**: Final approval
7. **Completion**: Task marked as complete

## Creating a Task

### Using the Web UI

1. Navigate to **Projects** → Select your project
2. Click **Create a new task**
3. Configure task settings:
   * **Name**: Descriptive task name
   * **Subset**: Optional subset identifier (e.g., "train", "val", "test")
   * **Advanced configuration**:
     * **Overlap**: Number of frames overlapping between jobs
     * **Segment size**: Frames per job (0 = single job)
     * **Image quality**: Compressed frame quality (0-100)
     * **Data chunk size**: Frames per chunk for streaming
4. Upload data (see [Uploading Data](#uploading-data))
5. Click **Submit**

### Using the REST API

Create a task with `POST /api/tasks`:

```bash theme={null}
curl -X POST "https://app.cvat.ai/api/tasks" \
  -H "Authorization: Token <your-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Traffic Scene Batch 1",
    "project_id": 1,
    "overlap": 5,
    "segment_size": 100,
    "subset": "train"
  }'
```

**Response** (201 Created):

```json theme={null}
{
  "id": 10,
  "name": "Traffic Scene Batch 1",
  "project_id": 1,
  "owner": {
    "id": 1,
    "username": "admin"
  },
  "assignee": null,
  "status": "annotation",
  "overlap": 5,
  "segment_size": 100,
  "subset": "train",
  "mode": "annotation",
  "dimension": "2d",
  "size": 0,
  "created_date": "2026-03-04T10:30:00.000Z",
  "updated_date": "2026-03-04T10:30:00.000Z",
  "jobs": {
    "count": 0,
    "completed": 0,
    "validation": 0
  }
}
```

### Using the Python SDK

```python theme={null}
from cvat_sdk import Client, models

client = Client(url="https://app.cvat.ai")
client.login(("username", "password"))

# Create task
task = client.tasks.create(
    spec=models.TaskWriteRequest(
        name="Street Scene Annotations",
        project_id=1,
        overlap=5,
        segment_size=100,
        subset="validation"
    )
)

print(f"Created task ID: {task.id}")
```

### Using the CLI

```bash theme={null}
# Create task in a project
cvat-cli --auth user:password task create \
  --project_id 1 \
  --overlap 5 \
  --segment_size 100 \
  --subset train \
  "Pedestrian Detection Task 1"

# Create standalone task with labels
cvat-cli --auth user:password task create \
  --labels '[{"name": "person"}, {"name": "bike"}]' \
  --overlap 0 \
  "Independent Task"
```

## Uploading Data

### Local Files

Upload images or videos from your computer:

**Using the SDK:**

```python theme={null}
from cvat_sdk.core.proxies.tasks import ResourceType

# Upload local images
task.upload_data(
    resources=[
        "path/to/image1.jpg",
        "path/to/image2.jpg",
        "path/to/image3.jpg"
    ],
    resource_type=ResourceType.LOCAL,
    params={
        "image_quality": 70,
        "chunk_size": 72,
        "sorting_method": "natural"
    }
)

# Upload video
task.upload_data(
    resources=["path/to/video.mp4"],
    resource_type=ResourceType.LOCAL,
    params={
        "frame_filter": "step=5",  # Every 5th frame
        "start_frame": 0,
        "stop_frame": 1000
    }
)
```

**Using the API:**

```bash theme={null}
curl -X POST "https://app.cvat.ai/api/tasks/{task_id}/data" \
  -H "Authorization: Token <your-token>" \
  -F "image_quality=70" \
  -F "client_files[0]=@image1.jpg" \
  -F "client_files[1]=@image2.jpg" \
  -F "client_files[2]=@image3.jpg"
```

### Server Files

Use files from a mounted share:

```python theme={null}
task.upload_data(
    resources=[
        "/mnt/share/dataset/image1.jpg",
        "/mnt/share/dataset/image2.jpg"
    ],
    resource_type=ResourceType.SHARE,
    params={"copy_data": True}
)
```

### Remote Files (URLs)

Provide URLs to download:

```python theme={null}
task.upload_data(
    resources=[
        "https://example.com/image1.jpg",
        "https://example.com/image2.jpg"
    ],
    resource_type=ResourceType.REMOTE
)
```

### Cloud Storage

Use files from cloud storage:

```python theme={null}
task.upload_data(
    resources=["manifest.jsonl"],
    resource_type=ResourceType.SHARE,
    params={
        "cloud_storage_id": 5,
        "filename_pattern": "*.jpg"
    }
)
```

### Data Upload Parameters

| Parameter        | Type    | Description                                          |
| ---------------- | ------- | ---------------------------------------------------- |
| `image_quality`  | integer | Compression quality 0-100 (default: 70)              |
| `chunk_size`     | integer | Frames per chunk (default: 72)                       |
| `start_frame`    | integer | First frame to include (default: 0)                  |
| `stop_frame`     | integer | Last frame to include                                |
| `frame_filter`   | string  | Frame filter: `step=N` to skip frames                |
| `sorting_method` | string  | `lexicographical`, `natural`, `predefined`, `random` |
| `use_cache`      | boolean | Enable server-side caching                           |
| `copy_data`      | boolean | Copy data from share to CVAT                         |

## Job Management

### Understanding Jobs

When data is uploaded, CVAT automatically splits the task into jobs based on `segment_size`. Jobs are assigned to annotators for parallel work.

**Job types:**

* `annotation`: Standard annotation job
* `ground_truth`: Ground truth validation job
* `consensus_replica`: Consensus annotation job

### Viewing Jobs

```python theme={null}
# Get all jobs for a task
jobs = task.get_jobs()

for job in jobs:
    print(f"Job {job.id}: frames {job.start_frame}-{job.stop_frame}")
    print(f"  Status: {job.status}")
    print(f"  Stage: {job.stage}")
    print(f"  State: {job.state}")
    print(f"  Assignee: {job.assignee}")
```

### Assigning Jobs

**Using the API:**

```bash theme={null}
curl -X PATCH "https://app.cvat.ai/api/jobs/{job_id}" \
  -H "Authorization: Token <your-token>" \
  -H "Content-Type: application/json" \
  -d '{"assignee_id": 5}'
```

**Using the SDK:**

```python theme={null}
job = client.jobs.retrieve(job_id=15)
job.update(models.PatchedJobWriteRequest(assignee_id=5))
```

### Job States and Stages

**Stages** (workflow phase):

* `annotation`: Initial annotation phase
* `validation`: Review and quality check phase
* `acceptance`: Final approval phase

**States** (completion status):

* `new`: Not started
* `in progress`: Work in progress
* `completed`: Finished
* `rejected`: Needs rework

```python theme={null}
# Move job to validation stage
job.update(models.PatchedJobWriteRequest(
    stage="validation",
    state="new"
))

# Mark job as completed
job.update(models.PatchedJobWriteRequest(
    state="completed"
))
```

## Task States

Tasks inherit their status from constituent jobs:

* `annotation`: Jobs are being annotated
* `validation`: Jobs are in validation/review
* `completed`: All jobs completed

**Deprecated status field** is computed from `stage` and `state`:

```python theme={null}
# Get task status
task_info = client.tasks.retrieve(task_id=10)
print(f"Status: {task_info.status}")
print(f"Jobs: {task_info.jobs['count']} total, {task_info.jobs['completed']} completed")
```

## Validation Modes

CVAT supports different validation configurations:

### Ground Truth Validation

Create a ground truth job for quality assessment:

```python theme={null}
# Create ground truth job
gt_job = client.jobs.create(
    spec=models.JobWriteRequest(
        task_id=10,
        type="ground_truth",
        frame_selection_method="random_uniform",
        frame_count=50,  # 50 random frames
        random_seed=42
    )
)
```

**Frame selection methods:**

* `random_uniform`: Random frames across entire task
* `random_per_job`: Random frames from each job
* `manual`: Manually specified frame list

```python theme={null}
# Manual frame selection
gt_job = client.jobs.create(
    spec=models.JobWriteRequest(
        task_id=10,
        type="ground_truth",
        frame_selection_method="manual",
        frames=[0, 10, 20, 30, 40]  # Specific frames
    )
)
```

### Honeypot Validation

Create tasks with hidden validation frames:

```python theme={null}
# Upload data with validation params
task.upload_data(
    resources=images,
    params={
        "validation_params": {
            "mode": "gt_pool",
            "frame_selection_method": "random_per_job",
            "frames_per_job_count": 10
        }
    }
)
```

## Consensus Annotation

Enable multiple annotators for the same data:

```python theme={null}
# Create task with consensus replicas
task = client.tasks.create(
    spec=models.TaskWriteRequest(
        name="Consensus Task",
        project_id=1,
        consensus_replicas=3  # 3 annotators per job
    )
)
```

This creates 3x jobs, allowing agreement analysis.

## Updating Tasks

### Update Task Properties

```python theme={null}
task.update(models.PatchedTaskWriteRequest(
    name="Updated Task Name",
    assignee_id=10,
    subset="test"
))
```

### Update Task Labels (Standalone Tasks)

For tasks not in a project:

```python theme={null}
task.update(models.PatchedTaskWriteRequest(
    labels=[
        models.PatchedLabelRequest(
            id=5,
            name="updated_label_name"
        ),
        models.PatchedLabelRequest(
            name="new_label",
            color="#ff00ff"
        )
    ]
))
```

<Warning>
  Tasks in a project inherit labels from the project. Update labels at the project level.
</Warning>

## Deleting Tasks

```bash theme={null}
# REST API
curl -X DELETE "https://app.cvat.ai/api/tasks/{task_id}" \
  -H "Authorization: Token <your-token>"
```

```python theme={null}
# Python SDK
task = client.tasks.retrieve(task_id=10)
task.remove()

# Or directly
client.tasks.remove_by_id(10)
```

```bash theme={null}
# CLI
cvat-cli --auth user:password task delete 10
```

## Best Practices

<AccordionGroup>
  <Accordion title="Optimize job segmentation">
    * Set `segment_size` to 100-500 frames per job
    * Use `overlap` (5-10 frames) for video tasks to ensure continuity
    * Smaller jobs = easier task management and recovery
    * Consider annotator capacity when sizing jobs
  </Accordion>

  <Accordion title="Configure data upload efficiently">
    * Use `chunk_size=72` (default) for optimal streaming
    * Set `image_quality` based on needs: 70-85 for most tasks
    * Use `frame_filter="step=N"` to reduce video frames
    * Enable `use_cache` for faster repeated access
  </Accordion>

  <Accordion title="Manage task organization">
    * Use `subset` field for train/val/test splits
    * Assign descriptive names with batch/date info
    * Group related tasks in projects
    * Assign tasks to appropriate team members
  </Accordion>

  <Accordion title="Monitor task progress">
    * Check `jobs.completed` count regularly
    * Review job states and stages
    * Use quality reports to track annotation quality
    * Set up validation workflows early
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Quality Control" icon="shield-check" href="/projects/quality-control">
    Set up validation and quality metrics
  </Card>

  <Card title="Annotation Guide" icon="pen" href="/annotation/editor-overview">
    Learn about annotation tools and workflows
  </Card>

  <Card title="Export Annotations" icon="download" href="/datasets/import-export">
    Export annotated data in various formats
  </Card>

  <Card title="API Reference" icon="code" href="/api/tasks">
    Complete task API documentation
  </Card>
</CardGroup>
