> ## 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 Swift 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/swift-process).
</Note>

## Overview

The Queue API is accessed via `client.queue` and 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
* `submitAndPoll()` - Submit and automatically poll until completion

## Submit a Job

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

```swift theme={null}
import Foundation
import DecartSDK

let videoData = try Data(contentsOf: videoURL)
let input = try VideoEditInput(
    prompt: "Transform into anime style",
    data: .video(data: videoData)
)

let job = try await client.queue.submit(model: .lucy_2, input: input)

print("Job ID: \(job.jobId)")
print("Status: \(job.status)")  // .pending
```

**Returns:**

* `jobId` - Unique identifier for the job
* `status` - Initial status (`.pending`)

***

## Check Job Status

Poll the status of a submitted job:

```swift theme={null}
let status = try await client.queue.status(jobId: job.jobId)

print("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                |

***

## Get Job Result

Retrieve the video data once the job is completed:

```swift theme={null}
let status = try await client.queue.status(jobId: job.jobId)

if status.status == .completed {
    let videoData = try await client.queue.result(jobId: job.jobId)
    try videoData.write(to: outputURL)
}
```

**Returns:** `Data` — the raw video bytes

***

## Submit and Poll

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

```swift theme={null}
let videoData = try Data(contentsOf: videoURL)
let input = try VideoEditInput(
    prompt: "Transform into anime style",
    data: .video(data: videoData)
)

let result = try await client.queue.submitAndPoll(
    model: .lucy_2,
    input: input
) { status in
    print("Status: \(status.status)")
}

switch result {
case .completed(let jobId, let data):
    try data.write(to: outputURL)
    print("Video saved!")
case .failed(let jobId, let error):
    print("Failed: \(error)")
}
```

**Parameters:**

* `model` (required) - Video model from `Models.video()`
* `input` (required) - Typed input for the model
* `onStatusChange` (optional) - Closure called on each status change

**Returns:** `QueueJobResult`

* `.completed(jobId: String, data: Data)` - Video data on success
* `.failed(jobId: String, error: String)` - Error message on failure

***

## Video Editing

Transform videos with prompt and optional reference image using `lucy_2`:

```swift theme={null}
let input = try VideoEditInput(
    prompt: "Convert to anime style with vibrant colors",
    data: .video(data: videoData),
    referenceImage: .image(data: refImageData),  // optional
    resolution: .res720p
)

let result = try await client.queue.submitAndPoll(
    model: .lucy_2,
    input: input
)
```

**`VideoEditInput` parameters:**

* `prompt` (required) - Text description of the transformation
* `data` (required) - Input video as `FileInput`
* `referenceImage` (optional) - Reference image as `FileInput`
* `seed` (optional) - Random seed for reproducible results
* `resolution` (optional) - Output resolution (`.res720p` or `.res480p`)
* `enhancePrompt` (optional) - Auto-enhance the prompt

***

## Video Restyling

Restyle videos using either a text prompt or a reference image (but not both) with `lucy_restyle_2`:

```swift theme={null}
// Option A: With text prompt
let promptInput = try VideoRestyleInput(
    prompt: "Studio Ghibli style",
    data: .video(data: videoData)
)

// Option B: With reference image
let imageInput = try VideoRestyleInput(
    data: .video(data: videoData),
    referenceImage: .image(data: refImageData)
)

let result = try await client.queue.submitAndPoll(
    model: .lucy_restyle_2,
    input: promptInput  // or imageInput
)
```

**`VideoRestyleInput` parameters:**

* `prompt` (optional) - Text description of style (required if no `referenceImage`)
* `data` (required) - Input video as `FileInput`
* `referenceImage` (optional) - Reference image (required if no `prompt`)
* `seed` (optional) - Random seed
* `resolution` (optional) - Output resolution
* `enhancePrompt` (optional) - Auto-enhance the prompt

<Note>You must provide either `prompt` or `referenceImage`, but not both. The SDK validates this at initialization.</Note>

***

## Manual Polling

For custom polling logic, use `submit()`, `status()`, and `result()` separately:

```swift theme={null}
import Foundation

// Submit job
let job = try await client.queue.submit(model: .lucy_2, input: input)
print("Job submitted: \(job.jobId)")

// Manual polling loop
while true {
    let status = try await client.queue.status(jobId: job.jobId)
    print("Status: \(status.status)")

    switch status.status {
    case .completed:
        let data = try await client.queue.result(jobId: job.jobId)
        try data.write(to: outputURL)
        print("Video saved!")
        return
    case .failed:
        print("Processing failed")
        return
    default:
        try await Task.sleep(for: .seconds(2))
    }
}
```

***

## Error Handling

```swift theme={null}
do {
    let result = try await client.queue.submitAndPoll(
        model: .lucy_2,
        input: input
    )
} catch let error as DecartError {
    switch error {
    case .invalidAPIKey:
        print("Invalid API key")
    case .invalidInput(let message):
        print("Invalid input: \(message)")
    case .queueError(let message):
        print("Queue error: \(message)")
    case .networkError(let underlying):
        print("Network error: \(underlying)")
    case .serverError(let message):
        print("Server error: \(message)")
    default:
        print("Error: \(error.localizedDescription)")
    }
}
```

***

## Supported Models

All video models support queue processing:

| Model          | Type           | Description                                    |
| -------------- | -------------- | ---------------------------------------------- |
| `lucy2_1`      | Video-to-Video | Video editing (latest)                         |
| `lucy2_1_vton` | Video-to-Video | Virtual try-on                                 |
| `lucyRestyle2` | Video-to-Video | Video restyling with prompt or reference image |
| `lucyMotion`   | Image-to-Video | Trajectory-based motion control                |

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

***

## API Reference

### `client.queue.submit(model:input:)`

Submit a job for processing.

**Parameters:**

* `model: VideoModel` - Video model
* `input` - Typed input (`VideoEditInput`, `VideoRestyleInput`, or `VideoToVideoInput`)

**Returns:** `JobSubmitResponse`

* `jobId: String` - Unique job identifier
* `status: JobStatus` - Initial status (`.pending`)

***

### `client.queue.status(jobId:)`

Check the status of a job.

**Parameters:**

* `jobId: String` - The job identifier

**Returns:** `JobStatusResponse`

* `jobId: String` - Job identifier
* `status: JobStatus` - Current status

***

### `client.queue.result(jobId:)`

Get the result of a completed job.

**Parameters:**

* `jobId: String` - The job identifier

**Returns:** `Data` - Video bytes

***

### `client.queue.submitAndPoll(model:input:onStatusChange:)`

Submit a job and poll until completion.

**Parameters:**

* `model: VideoModel` - Video model
* `input` - Typed input
* `onStatusChange: ((JobStatusResponse) -> Void)?` - Optional status callback

**Returns:** `QueueJobResult`

***

## Next Steps

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

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