# Archives: Scarleta API reference

Page: https://www.scarleta.ai/docs/reference/archives
Base URL: https://api.scarleta.ai. Authentication: `Authorization: Bearer $SCARLETA_API_KEY`.
Operations: 4.

## POST /v1/audio/archives

Operation id: `create_archive`

**Download files as a zip**

Packs files you choose into a zip. Send up to 5000 `audio_ids` of your own files. A selection of at most 1000 files and 2 GiB is answered at once with `mode: "stream"` and a `download_url`: fetch it with a plain `GET` and no API key within 10 minutes; it works once and returns the zip. A larger selection returns `202` with `mode: "async"`: the zip is built in the background in parts, read the archive until it is `completed`, then fetch each part (the archive stays downloadable for 7 days). Every id must be one of your files, otherwise nothing is packed and the call returns 404 `files_not_found` naming the ids it could not find. Counts against the hourly account request budget. Available to free and paid accounts.

Access: API key required; free and paid accounts. Cost: no token cost.

### Request body

| Field | Type | Description |
| --- | --- | --- |
| `audio_ids` | array<string> | Library identifiers (`audio_id`) of the files to pack, 1 to 5000. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `mode` | "stream" |   |
| `job_id` | string | Identifier of the archive. |
| `download_url` | string | Address to `GET` the zip from, with no API key. Works once. |
| `expires_at` | string | When the link stops working, as an ISO 8601 timestamp. |

### Responses

200: A one-time download link. The body is `{ data }` without `meta`. The response carries `Cache-Control: no-store`.

```json
{
  "data": {
    "mode": "stream",
    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
    "download_url": "https://api.scarleta.ai/v1/audio/archives/stream/Zk3p0q8vN1x2Y4b6C8d0E2f4G6h8J0kL2mN4pQ6rS8t",
    "expires_at": "2026-10-20T12:03:45.938Z"
  }
}
```

202: The archive is being built. Read it until it is completed. Same body shape rules as the 200.

```json
{
  "data": {
    "mode": "async",
    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e"
  }
}
```

400: `audio_ids` is empty, too long, or has an entry that is not a non-empty string.

```json
{
  "error": {
    "code": "invalid_audio_ids",
    "message": "audio_ids must be a list of 1–5000 file ids",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_audio_ids"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

404: At least one id is not one of your files; `error.details.missing` lists them.

```json
{
  "error": {
    "code": "files_not_found",
    "message": "Some of these files were not found.",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#files_not_found"
  }
}
```

409: A file in the selection has no readable content at the moment.

```json
{
  "error": {
    "code": "file_unavailable",
    "message": "“morning-session.wav” can't be downloaded right now.",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#file_unavailable"
  }
}
```

429: Over the account request budget. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: The background build could not start. Retry shortly.

```json
{
  "error": {
    "code": "archive_unavailable",
    "message": "Your download couldn't start. Try again.",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#archive_unavailable"
  }
}
```

### Error codes

[`archive_unavailable`](https://www.scarleta.ai/docs/errors#archive_unavailable), [`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`db_unavailable`](https://www.scarleta.ai/docs/errors#db_unavailable), [`file_unavailable`](https://www.scarleta.ai/docs/errors#file_unavailable), [`files_not_found`](https://www.scarleta.ai/docs/errors#files_not_found), [`invalid_audio_ids`](https://www.scarleta.ai/docs/errors#invalid_audio_ids), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_json`](https://www.scarleta.ai/docs/errors#invalid_json), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
curl -X POST "https://api.scarleta.ai/v1/audio/archives" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audio_ids": [
      "audio_bbb14949dc19"
    ]
  }'
```

## GET /v1/audio/archives/{jobId}

Operation id: `get_archive`

**Get an archive**

Returns the state of an archive you requested: its status, progress and, once finished, its parts. Only your own archives can be read; any other id returns 404. Counts against the hourly account request budget. Available to free and paid accounts.

Access: API key required; free and paid accounts. Cost: no token cost.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `jobId` | path | string | yes | The `job_id` returned when the archive was requested. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `job_id` | string | Identifier of the archive. |
| `kind` | "selection" \| "takeout" | `selection` for files you chose, `takeout` for your whole library. |
| `mode` | "stream" \| "async" | `stream` is a one-time download link; `async` is built in the background in parts. |
| `status` | "queued" \| "running" \| "completed" \| "failed" \| "expired" |   |
| `file_count` | integer | Allowed: -9007199254740991 to 9007199254740991. |
| `total_bytes` | number | Total size of the files in bytes. |
| `progress_bytes` | number | Bytes processed so far. |
| `parts` | array<object> | The finished zip parts, once `completed`. |
| `parts[].n` | integer | Allowed: -9007199254740991 to 9007199254740991. |
| `parts[].bytes` | number |   |
| `parts[].file_count` | integer | Allowed: -9007199254740991 to 9007199254740991. |
| `error` | string \| null |   |
| `created_at` | string | ISO 8601 timestamp. |
| `completed_at` | string \| null |   |
| `expires_at` | string \| null | When the download stops working. |

### Responses

200: The archive. The body is `{ data }` without `meta`.

```json
{
  "data": {
    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
    "kind": "selection",
    "mode": "stream",
    "status": "queued",
    "file_count": 1,
    "total_bytes": 1920044,
    "progress_bytes": 0,
    "parts": [],
    "error": null,
    "created_at": "2026-10-20T11:53:45.938Z",
    "completed_at": null,
    "expires_at": "2026-10-20T12:03:45.938Z"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

404: No archive with this id in your account.

```json
{
  "error": {
    "code": "archive_not_found",
    "message": "Download not found",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#archive_not_found"
  }
}
```

429: Over the account request budget. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: The archive could not be read. Retry shortly.

```json
{
  "error": {
    "code": "db_unavailable",
    "message": "Database not available; try again",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
  }
}
```

### Error codes

[`archive_not_found`](https://www.scarleta.ai/docs/errors#archive_not_found), [`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`db_unavailable`](https://www.scarleta.ai/docs/errors#db_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
JOBID="YOUR_JOBID"
curl "https://api.scarleta.ai/v1/audio/archives/$JOBID" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```

## GET /v1/audio/archives/{jobId}/parts/{n}/url

Operation id: `get_archive_part_url`

**Get the download link of an archive part**

For an archive that is built in the background (`mode: "async"`), returns a link for one finished zip part. Fetch `url` with a plain `GET` and no API key within 60 minutes; ask again for a fresh link when it expires. Part numbers start at 1 and are listed in the archive's `parts`. A one-time download link (`mode: "stream"`) has no parts. The response carries `Cache-Control: no-store`. Counts against the hourly account request budget. Available to free and paid accounts.

Access: API key required; free and paid accounts. Cost: no token cost.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `jobId` | path | string | yes | The `job_id` of the archive. |
| `n` | path | string | yes | Part number, starting at 1. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `url` | string | Where to `GET` the part. Opaque; use it as returned. |
| `expires_at` | string | ISO 8601 timestamp. |

### Responses

200: A link for the part. The body is `{ data }` without `meta`.

```json
{
  "data": {
    "url": "https://storage.example.com/archives/part-1.zip?signature=…",
    "expires_at": "2026-10-21T05:00:00.000Z"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

404: No archive with this id in your account (`archive_not_found`), or it has no such part.

```json
{
  "error": {
    "code": "archive_part_not_found",
    "message": "Download part not found",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#archive_part_not_found"
  }
}
```

409: The archive has not finished building. Read it until its status is `completed`.

```json
{
  "error": {
    "code": "archive_not_ready",
    "message": "This download is not ready yet.",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#archive_not_ready"
  }
}
```

410: The archive is past its retention time. Start a new one.

```json
{
  "error": {
    "code": "archive_expired",
    "message": "This download has expired.",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#archive_expired"
  }
}
```

429: Over the account request budget. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: Storage cannot create the link at the moment (`storage_unavailable`), or the database is unavailable (`db_unavailable`). Retry shortly.

```json
{
  "error": {
    "code": "storage_unavailable",
    "message": "Download links are not available right now; try again",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#storage_unavailable"
  }
}
```

### Error codes

[`archive_expired`](https://www.scarleta.ai/docs/errors#archive_expired), [`archive_not_found`](https://www.scarleta.ai/docs/errors#archive_not_found), [`archive_not_ready`](https://www.scarleta.ai/docs/errors#archive_not_ready), [`archive_part_not_found`](https://www.scarleta.ai/docs/errors#archive_part_not_found), [`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`db_unavailable`](https://www.scarleta.ai/docs/errors#db_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`storage_unavailable`](https://www.scarleta.ai/docs/errors#storage_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
JOBID="YOUR_JOBID"
N="YOUR_N"
curl "https://api.scarleta.ai/v1/audio/archives/$JOBID/parts/$N/url" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```

## POST /v1/audio/archives/takeout

Operation id: `start_takeout`

**Download your whole library**

Starts a background build of a zip of your entire library (originals and their renders), split into parts of at most 50 GiB. Read the archive with the returned `job_id` until it is `completed`, then fetch each part with the part URL route; the parts stay downloadable for 7 days. Only one takeout can be in progress at a time: asking again while one is queued or running returns the same `job_id` with HTTP 200 instead of 202. Counts against the hourly account request budget. Available to free and paid accounts.

Access: API key required; free and paid accounts. Cost: no token cost.

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `job_id` | string | Identifier of the takeout already in progress. |
| `status` | "queued" \| "running" |   |

### Responses

200: A takeout is already in progress; this is its identifier.

```json
{
  "data": {
    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
    "status": "running"
  }
}
```

202: A new takeout was started. The body is `{ data }` without `meta`.

```json
{
  "data": {
    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
    "status": "queued"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

429: Over the account request budget. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: The background build could not start. Retry shortly.

```json
{
  "error": {
    "code": "archive_unavailable",
    "message": "Your download couldn't start. Try again.",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#archive_unavailable"
  }
}
```

### Error codes

[`archive_unavailable`](https://www.scarleta.ai/docs/errors#archive_unavailable), [`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`db_unavailable`](https://www.scarleta.ai/docs/errors#db_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
curl -X POST "https://api.scarleta.ai/v1/audio/archives/takeout" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```
