# How to Export Recordings Using Frigate's Export API: Complete REST Guide

> Learn to export recordings using Frigate's export API. This guide covers queueing video exports, checking job status, and downloading archived cases via the REST API.

- Repository: [Blake Blackshear/frigate](https://github.com/blakeblackshear/frigate)
- Tags: how-to-guide
- Published: 2026-05-25

---

**Frigate provides a FastAPI-based REST API in [`frigate/api/export.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/api/export.py) that allows authenticated users to queue video exports, monitor job status via `/jobs/export/{export_id}`, and download archived cases as streaming ZIP files.**

The export system in the [blakeblackshear/frigate](https://github.com/blakeblackshear/frigate) repository enables programmatic extraction of surveillance footage from any configured camera. Built around the `ExportJob` class in [`frigate/jobs/export.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/jobs/export.py), the API manages FFmpeg processing, storage path generation, and batch operations through a set of authenticated HTTP endpoints.

## Export API Architecture

The export workflow operates through three distinct stages implemented across the codebase.

### Authentication and Authorization

All export endpoints require valid user authentication. The `require_camera_access` decorator (defined in [`frigate/api/auth.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/api/auth.py)) validates that the requesting user has read access to the specified camera. Administrative privileges are required for operations that modify export cases or delete records.

### Job Creation and Queuing

When you submit an export request, the API creates an `ExportJob` object through the `_build_export_job` helper function. This configuration includes the camera name, Unix timestamp range, optional friendly name, thumbnail image path, and playback source (either `recordings` or `previews`). The `start_export_job` function then enqueues this job onto Frigate's dedicated export queue for background processing.

### Result Retrieval

After queuing, the API returns a unique `export_id`. You can query `/jobs/export/{export_id}` to track progress through states including `queued`, `running`, `completed`, or `failed`. Final files are accessible individually or bundled intoexport cases downloadable via the `/cases/{case_id}/download` endpoint.

## Core Export Endpoints

The following routes in [`frigate/api/export.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/api/export.py) handle all export operations:

### Single Recording Export

The standard export endpoint creates MP4 clips from specific time ranges.

```bash
POST /api/export/{camera_name}/start/{start_time}/end/{end_time}

```

This route accepts an `ExportRecordingsBody` JSON payload defined in [`frigate/api/defs/request/export_recordings_body.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/api/defs/request/export_recordings_body.py). Parameters include `source` (enum: `recordings` or `previews`), `name` (max 256 characters), `image_path` for thumbnails, and optional `export_case_id` for grouping.

### Custom FFmpeg Export

For advanced users needing specific encoding parameters, the custom endpoint accepts additional FFmpeg arguments.

```bash
POST /api/export/custom/{camera_name}/start/{start_time}/end/{end_time}

```

This accepts `ExportRecordingsCustomBody`, extending the base model with `ffmpeg_input_args`, `ffmpeg_output_args`, and a boolean `cpu_fallback` flag. The validation logic in [`frigate/record/export.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/record/export.py) ensures these arguments are properly formatted before job creation.

### Batch Export Operations

To export multiple time ranges or cameras simultaneously, use the batch endpoint:

```bash
POST /api/exports/batch

```

This accepts a `BatchExportBody` (defined in [`frigate/api/defs/request/export_bulk_body.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/api/defs/request/export_bulk_body.py)) containing an array of `BatchExportItem` objects. Each item specifies camera, start/end times, and optional metadata. The endpoint can automatically create a new export case by providing `new_case_name` and `new_case_description` in the request body.

## Request Payload Models

Frigate uses Pydantic models for automatic request validation. Invalid payloads return HTTP 422 before job creation.

**ExportRecordingsBody** structure:

```python

# frigate/api/defs/request/export_recordings_body.py

class ExportRecordingsBody(BaseModel):
    source: PlaybackSourceEnum = Field(default=PlaybackSourceEnum.recordings)
    name: Optional[str] = Field(default=None, max_length=256)
    image_path: Union[str, None] = None
    export_case_id: Optional[str] = None

```

**ExportRecordingsCustomBody** adds:

```python
ffmpeg_input_args: Optional[str] = None
ffmpeg_output_args: Optional[str] = None
cpu_fallback: bool = False

```

## Practical Export Examples

### Export a Single Recording

Request a 10-second clip from the `front_door` camera:

```bash
curl -X POST "https://frigate.example.com/api/export/front_door/start/1698211200/end/1698211210" \
     -H "Authorization: Bearer <TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{
           "source": "recordings",
           "name": "Front Door Clip",
           "image_path": "/media/frigate/exports/thumbs/front_door_001.jpg"
         }'

```

**Response (202 Accepted):**

```json
{
  "export_id": "front_door_abc123",
  "message": "Export queued"
}

```

### Export with Custom FFmpeg Arguments

Apply specific encoding settings using the custom endpoint:

```bash
curl -X POST "https://frigate.example.com/api/export/custom/front_door/start/1698211200/end/1698211210" \
     -H "Authorization: Bearer <TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{
           "source": "recordings",
           "name": "Custom Clip",
           "ffmpeg_input_args": "-f lavfi -i testsrc=size=1280x720:rate=30",
           "ffmpeg_output_args": "-c:v libx264 -crf 23",
           "cpu_fallback": true
         }'

```

### Batch Export Multiple Cameras

Create a case containing exports from multiple cameras:

```bash
curl -X POST "https://frigate.example.com/api/exports/batch" \
     -H "Authorization: Bearer <TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{
           "items": [
             {
               "camera": "front_door",
               "start_time": 1698211200,
               "end_time": 1698211210,
               "friendly_name": "Front Door 1"
             },
             {
               "camera": "garage",
               "start_time": 1698211300,
               "end_time": 1698211315,
               "friendly_name": "Garage Motion"
             }
           ],
           "new_case_name": "Weekend Review",
           "new_case_description": "Exports for Saturday night"
         }'

```

The response includes `export_case_id`, an array of `export_ids`, and per-item success status.

## Monitoring Jobs and Downloading Results

### Check Export Status

Poll for completion using the export ID:

```bash
curl -H "Authorization: Bearer <TOKEN>" \
     "https://frigate.example.com/api/jobs/export/<export_id>"

```

The response includes `status` fields and download URLs for completed MP4 files.

### Download Case Archives

Retrieve all exports from a case as a single ZIP file:

```bash
curl -L -H "Authorization: Bearer <TOKEN>" \
     "https://frigate.example.com/api/cases/<case_id>/download" \
     -o case_export.zip

```

The `_stream_case_archive` function in [`frigate/api/export.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/api/export.py) (lines 13-38) generates this ZIP on-the-fly using Python's `zipfile` module with streaming support, ensuring minimal memory usage during large archive creation.

### List All Exports

Query existing exports with optional filters:

```bash
GET /api/exports?camera=front_door&case_id=<id>&start_date=<timestamp>&end_date=<timestamp>

```

This queries the `Export` and `ExportCase` models defined in [`frigate/models.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/models.py).

## Summary

- **Authentication**: All endpoints require valid tokens and camera-specific access rights enforced by `require_camera_access` in [`frigate/api/auth.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/api/auth.py).
- **Job Creation**: The `_build_export_job` function in [`frigate/jobs/export.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/jobs/export.py) constructs export configurations with camera names, timestamps, and playback sources.
- **Standard vs Custom**: Use `/export/` for simple exports or `/export/custom/` when providing specific FFmpeg input/output arguments.
- **Batch Operations**: The `/exports/batch` endpoint accepts multiple items and can automatically organize them into export cases.
- **Retrieval**: Monitor progress via `/jobs/export/{export_id}` and download completed cases as streaming ZIP archives from `/cases/{case_id}/download`.

## Frequently Asked Questions

### What authentication is required to use Frigate's export API?

All export endpoints require the caller to be an authenticated user with a valid Bearer token. The `require_camera_access` decorator ensures the user has read permissions for the requested camera, while administrative operations on export cases require elevated privileges.

### How can I check if my export job is complete?

Send a GET request to `/api/jobs/export/{export_id}` to retrieve the current status, which returns states including `queued`, `running`, `completed`, or `failed`. The endpoint queries the active job queue managed in [`frigate/jobs/export.py`](https://github.com/blakeblackshear/frigate/blob/main/frigate/jobs/export.py).

### Can I customize FFmpeg settings when exporting recordings?

Yes. Use the `/api/export/custom/{camera_name}/start/{start_time}/end/{end_time}` endpoint with an `ExportRecordingsCustomBody` payload containing `ffmpeg_input_args` and `ffmpeg_output_args` strings. Set `cpu_fallback: true` to force CPU encoding if hardware acceleration fails.

### How do I download multiple exported clips at once?

Group exports into a case using the `export_case_id` parameter or the `new_case_name` field in batch requests. Then use the `/api/cases/{case_id}/download` endpoint to stream a ZIP archive containing all related MP4 files, generated efficiently without loading the entire archive into memory.