# Create Job


POST /jobs

```
POST /jobs
```

Creates a job that processes a media file through a pipeline: probe → import → encode → export. This is the main way to process media — send a URL, pick a kind, and Ittybit handles the rest. For the CLI equivalent, see [`ittybit jobs create`](/cli/jobs).

## Request body

| Field      | Type   | Required | Description                                                  |
| ---------- | ------ | -------- | ------------------------------------------------------------ |
| `input`    | string | yes      | Input URL (`http://`, `https://`, or `s3://`)                |
| `kind`     | string | yes      | `video` · `audio` · `image` · `animation` · `adaptive_video` |
| `options`  | object | no       | Processing options                                           |
| `output`   | string | no       | S3 destination (`s3://bucket/key`)                           |
| `metadata` | object | no       | Arbitrary key-value pairs                                    |

## Options

### video

| Option       | Type          | Values                                                  |
| ------------ | ------------- | ------------------------------------------------------- |
| `format`     | string        | `mp4` · `webm` · `mov`                                  |
| `codec`      | string        | `h264` · `h265` · `vp9` · `av1`                         |
| `quality`    | string        | `very_low` · `low` · `medium` · `high` · `very_high`    |
| `width`      | int or string | Pixels or `"50%"`                                       |
| `height`     | int or string | Pixels or `"50%"`                                       |
| `fit`        | string        | `contain` · `cover` · `fill`                            |
| `position`   | string        | `center` · `top` · `bottom` · `left` · `right` etc.     |
| `background` | string        | Hex color (e.g. `"#000000"`) — only with `fit: contain` |
| `fps`        | number        | 1–60                                                    |
| `bitrate`    | integer       | 300,000–60,000,000 bps                                  |
| `start`      | number        | Seconds                                                 |
| `end`        | number        | Seconds                                                 |

### audio

| Option    | Type    | Values                                               |
| --------- | ------- | ---------------------------------------------------- |
| `format`  | string  | `mp3` · `aac` · `ogg` · `opus` · `wav` · `flac`      |
| `quality` | string  | `very_low` · `low` · `medium` · `high` · `very_high` |
| `bitrate` | integer | 32,000–320,000 bps                                   |
| `start`   | number  | Seconds                                              |
| `end`     | number  | Seconds                                              |

### image

| Option       | Type          | Values                                                  |
| ------------ | ------------- | ------------------------------------------------------- |
| `format`     | string        | `jpeg` · `png` · `webp` · `avif`                        |
| `quality`    | string        | `very_low` · `low` · `medium` · `high` · `very_high`    |
| `width`      | int or string | Pixels or `"50%"`                                       |
| `height`     | int or string | Pixels or `"50%"`                                       |
| `fit`        | string        | `contain` · `cover` · `fill`                            |
| `position`   | string        | `center` · `top` · `bottom` · `left` · `right` etc.     |
| `background` | string        | Hex color (e.g. `"#000000"`) — only with `fit: contain` |
| `start`      | number        | Frame time in seconds (video input)                     |

### animation

| Option       | Type          | Values                                                  |
| ------------ | ------------- | ------------------------------------------------------- |
| `format`     | string        | `gif` · `webp`                                          |
| `quality`    | string        | `very_low` · `low` · `medium` · `high` · `very_high`    |
| `width`      | int or string | Pixels or `"50%"`                                       |
| `height`     | int or string | Pixels or `"50%"`                                       |
| `fit`        | string        | `contain` · `cover` · `fill`                            |
| `position`   | string        | `center` · `top` · `bottom` · `left` · `right` etc.     |
| `background` | string        | Hex color (e.g. `"#000000"`) — only with `fit: contain` |
| `start`      | number        | Seconds                                                 |
| `end`        | number        | Seconds (required)                                      |
| `fps`        | number        | 1–60                                                    |

### adaptive_video

| Option       | Type          | Values                                                  |
| ------------ | ------------- | ------------------------------------------------------- |
| `format`     | string        | `hls`                                                   |
| `quality`    | string        | `very_low` · `low` · `medium` · `high` · `very_high`    |
| `width`      | int or string | Pixels or `"50%"`                                       |
| `height`     | int or string | Pixels or `"50%"`                                       |
| `fit`        | string        | `contain` · `cover` · `fill`                            |
| `position`   | string        | `center` · `top` · `bottom` · `left` · `right` etc.     |
| `background` | string        | Hex color (e.g. `"#000000"`) — only with `fit: contain` |
| `start`      | number        | Seconds                                                 |
| `end`        | number        | Seconds                                                 |

## Examples

### Video

Convert and resize a video. Smaller files mean faster page loads and lower CDN costs.

<CodeGroup labels={["CLI", "TypeScript", "Python", "curl"]}>
```bash
ittybit video \
  -i https://example.com/upload.mov \
  --width 1280 \
  --height 720 \
  --format mp4 \
  --quality high \
```

```typescript
const task = {
  input: 'https://example.com/upload.mov',
  kind: 'video',
  options: {
    width: 1280,
    height: 720,
    format: 'mp4',
    quality: 'high',
  },
};

const res = await fetch('https://api.ittybit.com/jobs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ITTYBIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(task),
});
const data = await res.json();
```

```python

task = {
    "input": "https://example.com/upload.mov",
    "kind": "video",
    "options": {
        "width": 1280,
        "height": 720,
        "format": "mp4",
        "quality": "high",
    },
}

res = requests.post(
    "https://api.ittybit.com/jobs",
    headers={"Authorization": f"Bearer {api_key}"},
    json=task,
)
data = res.json()
```

```bash
JOB='{
  "input": "https://example.com/upload.mov",
  "kind": "video",
  "options": {
    "width": 1280,
    "height": 720,
    "format": "mp4",
    "quality": "high"
  }
}'

curl -X POST https://api.ittybit.com/jobs \
  -H "Authorization: Bearer $ITTYBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$JOB"
```

</CodeGroup>

### Audio

Extract an audio track from a video file.

<CodeGroup labels={["CLI", "TypeScript", "Python", "curl"]}>
```bash
ittybit audio \
  -i https://example.com/interview.mp4 \
  --format mp3 \
  --quality high \
```

```typescript
const job = {
  input: 'https://example.com/interview.mp4',
  kind: 'audio',
  options: {
    format: 'mp3',
    quality: 'high',
  },
};

const res = await fetch('https://api.ittybit.com/jobs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ITTYBIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(job),
});
const data = await res.json();
```

```python

job = {
    "input": "https://example.com/interview.mp4",
    "kind": "audio",
    "options": {
        "format": "mp3",
        "quality": "high",
    },
}

res = requests.post(
    "https://api.ittybit.com/jobs",
    headers={"Authorization": f"Bearer {api_key}"},
    json=job,
)
data = res.json()
```

```bash
JOB='{
  "input": "https://example.com/interview.mp4",
  "kind": "audio",
  "options": {
    "format": "mp3",
    "quality": "high"
  }
}'

curl -X POST https://api.ittybit.com/jobs \
  -H "Authorization: Bearer $ITTYBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$JOB"
```

</CodeGroup>

### Image

Extract a poster frame from a video at the 5-second mark.

<CodeGroup labels={["CLI", "TypeScript", "Python", "curl"]}>
```bash
ittybit image \
  -i https://example.com/video.mp4 \
  --start 5 \
  --format webp \
  --width 640 \
```

```typescript
const job = {
  input: 'https://example.com/video.mp4',
  kind: 'image',
  options: {
    start: 5,
    format: 'webp',
    width: 640,
  },
};

const res = await fetch('https://api.ittybit.com/jobs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ITTYBIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(job),
});
const data = await res.json();
```

```python

job = {
    "input": "https://example.com/video.mp4",
    "kind": "image",
    "options": {
        "start": 5,
        "format": "webp",
        "width": 640,
    },
}

res = requests.post(
    "https://api.ittybit.com/jobs",
    headers={"Authorization": f"Bearer {api_key}"},
    json=job,
)
data = res.json()
```

```bash
JOB='{
  "input": "https://example.com/video.mp4",
  "kind": "image",
  "options": {
    "start": 5,
    "format": "webp",
    "width": 640
  }
}'

curl -X POST https://api.ittybit.com/jobs \
  -H "Authorization: Bearer $ITTYBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$JOB"
```

</CodeGroup>

### Adaptive video

Create an HLS stream so players can switch quality based on viewer bandwidth. Adaptive streams prevent buffering for users on slow connections.

<CodeGroup labels={["CLI", "TypeScript", "Python", "curl"]}>
```bash
ittybit adaptive \
  -i https://example.com/video.mp4 \
  --format hls \
  --quality high \
```

```typescript
const job = {
  input: 'https://example.com/video.mp4',
  kind: 'adaptive_video',
  options: {
    format: 'hls',
    quality: 'high',
  },
};

const res = await fetch('https://api.ittybit.com/jobs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ITTYBIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(job),
});
const data = await res.json();
```

```python

job = {
    "input": "https://example.com/video.mp4",
    "kind": "adaptive_video",
    "options": {
        "format": "hls",
        "quality": "high",
    },
}

res = requests.post(
    "https://api.ittybit.com/jobs",
    headers={"Authorization": f"Bearer {api_key}"},
    json=job,
)
data = res.json()
```

```bash
JOB='{
  "input": "https://example.com/video.mp4",
  "kind": "adaptive_video",
  "options": {
    "format": "hls",
    "quality": "high"
  }
}'

curl -X POST https://api.ittybit.com/jobs \
  -H "Authorization: Bearer $ITTYBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$JOB"
```

</CodeGroup>

### Output to S3

Send processed media to your own storage instead of Ittybit-managed storage. Requires a [connection](/cli/connections).

<CodeGroup labels={["CLI", "TypeScript", "Python", "curl"]}>
```bash
ittybit video \
  -i https://example.com/upload.mov \
  -o s3://my-bucket/processed/video.mp4 \
```

```typescript
const job = {
  input: 'https://example.com/upload.mov',
  kind: 'video',
  output: 's3://my-bucket/processed/video.mp4',
};

const res = await fetch('https://api.ittybit.com/jobs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ITTYBIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(job),
});
const data = await res.json();
```

```python

job = {
    "input": "https://example.com/upload.mov",
    "kind": "video",
    "output": "s3://my-bucket/processed/video.mp4",
}

res = requests.post(
    "https://api.ittybit.com/jobs",
    headers={"Authorization": f"Bearer {api_key}"},
    json=job,
)
data = res.json()
```

```bash
JOB='{
  "input": "https://example.com/upload.mov",
  "kind": "video",
  "output": "s3://my-bucket/processed/video.mp4"
}'

curl -X POST https://api.ittybit.com/jobs \
  -H "Authorization: Bearer $ITTYBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$JOB"
```

</CodeGroup>

## Response `201`

```json
{
  "id": "job_abc123",
  "object": "job",
  "kind": "video",
  "input": "https://example.com/upload.mov",
  "output": null,
  "options": { "width": 1280, "height": 720, "format": "mp4", "quality": "high" },
  "metadata": {},
  "status": "queued",
  "error": null,
  "tasks": [
    {
      "id": "task_001",
      "object": "task",
      "kind": "probe",
      "input": null,
      "options": {},
      "output": null,
      "status": "waiting",
      "progress": null,
      "error": null,
      "created_at": 1711900000000,
      "started_at": null,
      "finished_at": null,
      "updated_at": 1711900000000
    },
    {
      "id": "task_002",
      "object": "task",
      "kind": "import",
      "input": null,
      "options": {},
      "output": null,
      "status": "waiting",
      "progress": null,
      "error": null,
      "created_at": 1711900000000,
      "started_at": null,
      "finished_at": null,
      "updated_at": 1711900000000
    },
    {
      "id": "task_003",
      "object": "task",
      "kind": "video",
      "input": null,
      "options": {},
      "output": null,
      "status": "waiting",
      "progress": null,
      "error": null,
      "created_at": 1711900000000,
      "started_at": null,
      "finished_at": null,
      "updated_at": 1711900000000
    },
    {
      "id": "task_004",
      "object": "task",
      "kind": "export",
      "input": null,
      "options": {},
      "output": null,
      "status": "waiting",
      "progress": null,
      "error": null,
      "created_at": 1711900000000,
      "started_at": null,
      "finished_at": null,
      "updated_at": 1711900000000
    }
  ],
  "created_at": 1711900000000,
  "started_at": null,
  "finished_at": null,
  "updated_at": 1711900000000
}
```

## Errors

| Status | Kind             | Cause                             |
| ------ | ---------------- | --------------------------------- |
| `400`  | `input_required` | Missing `input`                   |
| `400`  | `invalid_input`  | Bad URL scheme                    |
| `400`  | `invalid_format` | Unknown format for kind           |
| `400`  | `invalid_codec`  | Codec incompatible with container |
| `401`  | `token_missing`  | No Authorization header           |
| `401`  | `token_invalid`  | Bad API key                       |

## See also

- [CLI `video`](/cli/video), [`audio`](/cli/audio), [`image`](/cli/image), [`animation`](/cli/animation), [`adaptive`](/cli/adaptive) — process files locally with the same options
- [Get Job](/api/get-job) — check job status and task results
- [Create Task](/api/create-task) — run individual operations for custom workflows
- [Convert uploads for web playback](/guides/web-video)
- [Extract thumbnails](/guides/thumbnail)
- [Extract audio](/guides/extract-audio)