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

# Queue API

> Asynchronous job-based video processing

The Queue API is the primary way to process videos with the Python SDK. Submit jobs that are processed asynchronously in the background, then poll for status and retrieve results when complete.

<Note>
  All video processing (video editing, restyling, motion control) uses the Queue API. For image editing, use the [Process API](/sdks/python-process).
</Note>

## Overview

The Queue API provides four main methods:

* `submit()` - Submit a job and get a job ID immediately
* `status()` - Check the status of a submitted job
* `result()` - Retrieve the completed video
* `submit_and_poll()` - Submit and automatically poll until completion

## Submit a Job

Submit a video editing job and receive a job ID immediately:

```python theme={null}
job = await client.queue.submit({
    "model": models.video("lucy-2.1"),
    "data": video_file,
    "prompt": "Transform into anime style",
})

print(f"Job ID: {job.job_id}")
print(f"Status: {job.status}")  # "pending"
```

**Returns:**

* `job_id` - Unique identifier for the job
* `status` - Initial status (`"pending"`)

***

## Check Job Status

Poll the status of a submitted job:

```python theme={null}
status = await client.queue.status(job.job_id)

print(f"Status: {status.status}")  # "pending", "processing", "completed", or "failed"
```

**Status Values:**

| Status       | Description                                        |
| ------------ | -------------------------------------------------- |
| `pending`    | Job is queued, waiting to be processed             |
| `processing` | Job is currently being processed                   |
| `completed`  | Job finished successfully                          |
| `failed`     | Job failed or timed out (timeout after 10 minutes) |

***

## Get Job Result

Retrieve the video once the job is completed:

```python theme={null}
# First check status
status = await client.queue.status(job.job_id)

if status.status == "completed":
    result = await client.queue.result(job.job_id)

    if result.status == "completed":
        with open("output.mp4", "wb") as f:
            f.write(result.data)
    else:
        print(f"Error: {result.error}")
```

**Returns:**

* `status` - Either `"completed"` or `"failed"`
* `data` - Video bytes (when completed)
* `error` - Error message (when failed)

***

## Submit and Poll

The easiest way to use the Queue API - submit a job and automatically poll until completion:

```python theme={null}
with open("input.mp4", "rb") as video_file:
    result = await client.queue.submit_and_poll({
        "model": models.video("lucy-2.1"),
        "data": video_file,
        "prompt": "Transform into anime style",
        "on_status_change": lambda job: print(f"Status: {job.status}"),
    })

if result.status == "completed":
    with open("output.mp4", "wb") as f:
        f.write(result.data)
else:
    print(f"Editing failed: {result.error}")
```

**Parameters:**

* All standard model parameters (prompt, resolution, etc.)
* `on_status_change` (optional) - Callback function called on each status change

***

## Complete Example

```python theme={null}
import asyncio
from decart import DecartClient, models

async def edit_video():
    async with DecartClient(api_key="your-api-key") as client:
        print("Submitting video editing job...")

        with open("input.mp4", "rb") as video_file:
            result = await client.queue.submit_and_poll({
                "model": models.video("lucy-2.1"),
                "data": video_file,
                "prompt": "Transform into anime style",
                "on_status_change": lambda job: print(f"  Status: {job.status}"),
            })

        if result.status == "completed":
            with open("output.mp4", "wb") as f:
                f.write(result.data)
            print("Video saved to output.mp4")
        else:
            print(f"Editing failed: {result.error}")

asyncio.run(edit_video())
```

**Output:**

```
Submitting video editing job...
  Status: pending
  Status: processing
  Status: completed
Video saved to output.mp4
```

***

## Video Editing with Queue

Transform videos with style transfer:

```python theme={null}
with open("input.mp4", "rb") as video_file:
    result = await client.queue.submit_and_poll({
        "model": models.video("lucy-2.1"),
        "prompt": "Convert to anime style with vibrant colors",
        "data": video_file,
        "on_status_change": lambda job: print(f"Status: {job.status}"),
    })
```

***

## Manual Polling

For custom polling logic, you can manually poll for status:

```python theme={null}
import asyncio

# Submit job
job = await client.queue.submit({
    "model": models.video("lucy-2.1"),
    "prompt": "A serene lake at sunset",
})

print(f"Job submitted: {job.job_id}")

# Manual polling loop
while True:
    status = await client.queue.status(job.job_id)
    print(f"Status: {status.status}")

    if status.status == "completed":
        result = await client.queue.result(job.job_id)
        with open("output.mp4", "wb") as f:
            f.write(result.data)
        print("Video saved!")
        break
    elif status.status == "failed":
        print("Generation failed")
        break

    # Wait before next poll
    await asyncio.sleep(2)
```

***

## Error Handling

```python theme={null}
from decart import (
    DecartClient,
    QueueSubmitError,
    QueueStatusError,
    QueueResultError,
    DecartSDKError,
)

try:
    result = await client.queue.submit_and_poll({
        "model": models.video("lucy-2.1"),
        "prompt": "A beautiful sunset",
    })
except QueueSubmitError as error:
    print(f"Failed to submit job: {error.message}")
except QueueStatusError as error:
    print(f"Failed to check status: {error.message}")
except QueueResultError as error:
    print(f"Failed to get result: {error.message}")
except DecartSDKError as error:
    print(f"SDK error: {error.message}")
```

***

## Supported Models

All non-realtime video models support queue processing:

| Model            | Type           | Description            |
| ---------------- | -------------- | ---------------------- |
| `lucy-2.1`       | Video-to-Video | Video editing (latest) |
| `lucy-2.1-vton`  | Video-to-Video | Virtual try-on         |
| `lucy-restyle-2` | Video-to-Video | Video restyling        |

<Accordion title="Latest aliases">
  | Alias                 | Description                            |
  | --------------------- | -------------------------------------- |
  | `lucy-latest`         | Always the latest editing model        |
  | `lucy-vton-latest`    | Always the latest virtual try-on model |
  | `lucy-restyle-latest` | Always the latest restyling model      |
  | `lucy-clip-latest`    | Always the latest legacy editing model |
</Accordion>

<Accordion title="Previous generation models">
  | Model       | Type           | Description           |
  | ----------- | -------------- | --------------------- |
  | `lucy-clip` | Video-to-Video | Transform video style |
</Accordion>

***

## API Reference

### `client.queue.submit(options)`

Submit a job for processing.

**Parameters:**

* `options: dict` - Model and input parameters

**Returns:** `JobSubmitResponse`

* `job_id: str` - Unique job identifier
* `status: str` - Initial status ("pending")

***

### `client.queue.status(job_id)`

Check the status of a job.

**Parameters:**

* `job_id: str` - The job identifier

**Returns:** `JobStatusResponse`

* `job_id: str` - Job identifier
* `status: str` - Current status

***

### `client.queue.result(job_id)`

Get the result of a completed job.

**Parameters:**

* `job_id: str` - The job identifier

**Returns:** `QueueJobResult`

* `status: str` - "completed" or "failed"
* `data: bytes` - Video data (when completed)
* `error: str` - Error message (when failed)

***

### `client.queue.submit_and_poll(options)`

Submit a job and poll until completion.

**Parameters:**

* `options: dict` - Model and input parameters
  * `on_status_change: Callable` (optional) - Status change callback

**Returns:** `QueueJobResult`

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Process API" icon="image" href="/sdks/python-process">
    Synchronous image editing
  </Card>

  <Card title="Realtime API" icon="bolt" href="/sdks/python-realtime">
    Transform video streams in realtime with WebRTC
  </Card>
</CardGroup>
