# Versions: Scarleta API reference

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

## GET /v1/audio/ungrouped

Operation id: `search_ungrouped_files`

**Find files that are not yet a version of a track**

Lists your own top-level files that do not belong to any track group, optionally filtered by a name search. Use it to pick files to add as versions of a track. Only your own files are ever returned. `limit` defaults to 50 and larger values are lowered to 100.

This route answers with the older body shape: success is `{ data }` with no `meta`.

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

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `q` | query | string | no | Keep files whose file name or display name contains this text. |
| `exclude` | query | string | no | An `audio_id` to leave out of the result. |
| `limit` | query | integer | no | Files to return. Defaults to 50; larger values are lowered to 100. Allowed: 1 to 100. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `[].audio_id` | string |   |
| `[].name` | string |   |
| `[].uploaded_at` | string | Upload time in milliseconds since the Unix epoch, as a string. |
| `[].file_size_bytes` | number \| string \| null |   |
| `[].format` | string \| null |   |

### Responses

200: The matching files. This response has no `meta`.

```json
{
  "data": [
    {
      "audio_id": "audio_3f9c1a7d2b60",
      "name": "demo-mix.wav",
      "uploaded_at": "1791333870854",
      "file_size_bytes": 5290044,
      "format": "wav"
    }
  ]
}
```

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 or the per-minute cap of this route. 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: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_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 "https://api.scarleta.ai/v1/audio/ungrouped" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```

## GET /v1/audio/versions/{versionId}/audio-url

Operation id: `get_version_audio_url`

**Get the audio URL of one version**

Returns the URL to pass as `audio_url` when running an analysis on one version of a track. `versionId` is the version's `id` or `audio_id` from the library list. `audio_url` is null when the original file is not stored. Only your own files are ever returned. On success this route answers `{ data }` without `meta`; errors use the standard error body.

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

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `versionId` | path | string | yes | The `id` or `audio_id` of a version in your library. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `audio_url` | string \| null | URL of the stored file, or null when only a link was stored. |

### Responses

200: The URL of that version. This response has no `meta`.

```json
{
  "data": {
    "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav"
  }
}
```

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 version with this id exists in your library.

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

429: Over the account request budget or the per-minute cap of this route. 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: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`db_unavailable`](https://www.scarleta.ai/docs/errors#db_unavailable), [`file_not_found`](https://www.scarleta.ai/docs/errors#file_not_found), [`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), [`invalid_version_id`](https://www.scarleta.ai/docs/errors#invalid_version_id), [`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
VERSIONID="YOUR_VERSIONID"
curl "https://api.scarleta.ai/v1/audio/versions/$VERSIONID/audio-url" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```

## POST /v1/audio/versions/add

Operation id: `add_version`

**Make a file a version of a track**

Groups `source_audio_id` as another version of the track that `target_audio_id` belongs to. If the target is not in a group yet, a group is created. Both files must be your own top-level files; a file that is already in a group, or the same file twice, is refused with 400 `invalid_grouping`. On success this route answers `{ data }` without `meta`; errors use the standard error body.

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

### Request body

| Field | Type | Description |
| --- | --- | --- |
| `target_audio_id` | string | A file of the track to add to. Allowed: at least 1 character. |
| `source_audio_id` | string | The file that becomes a version of that track. Allowed: at least 1 character. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `track_group_id` | string | Identifier of the track group. |
| `status` | "grouped" |   |

### Responses

200: The two files are now versions of one track. This response has no `meta`.

```json
{
  "data": {
    "track_group_id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
    "status": "grouped"
  }
}
```

400: A required field is missing or not a string (`invalid_body`), or the files cannot be grouped: the same file twice, a file already in a group, or a derived file (`invalid_grouping`).

```json
{
  "error": {
    "code": "invalid_grouping",
    "message": "Files cannot be grouped as requested",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_grouping"
  }
}
```

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: A file does not exist in your library.

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

429: Over the account request budget or the per-minute cap of this route. 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: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`db_unavailable`](https://www.scarleta.ai/docs/errors#db_unavailable), [`file_not_found`](https://www.scarleta.ai/docs/errors#file_not_found), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_body`](https://www.scarleta.ai/docs/errors#invalid_body), [`invalid_grouping`](https://www.scarleta.ai/docs/errors#invalid_grouping), [`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/versions/add" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_audio_id": "audio_3f9c1a7d2b60",
    "source_audio_id": "audio_a81e5c40d7f2"
  }'
```

## POST /v1/audio/versions/remove

Operation id: `remove_version`

**Remove a file from its track**

Takes a file out of its track group so it becomes a track of its own again. Calling it on a file that is not in a group succeeds and changes nothing. On success this route answers `{ data }` without `meta`; errors use the standard error body.

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

### Request body

| Field | Type | Description |
| --- | --- | --- |
| `audio_id` | string | The file to take out of its track. Allowed: at least 1 character. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `audio_id` | string |   |
| `status` | "ungrouped" |   |

### Responses

200: The file is a track of its own. This response has no `meta`.

```json
{
  "data": {
    "audio_id": "audio_a81e5c40d7f2",
    "status": "ungrouped"
  }
}
```

400: `audio_id` is missing or not a string, or the file cannot be ungrouped (`invalid_grouping`).

```json
{
  "error": {
    "code": "invalid_body",
    "message": "audio_id is required",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_body"
  }
}
```

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: The file does not exist in your library.

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

429: Over the account request budget or the per-minute cap of this route. 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: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`db_unavailable`](https://www.scarleta.ai/docs/errors#db_unavailable), [`file_not_found`](https://www.scarleta.ai/docs/errors#file_not_found), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_body`](https://www.scarleta.ai/docs/errors#invalid_body), [`invalid_grouping`](https://www.scarleta.ai/docs/errors#invalid_grouping), [`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/versions/remove" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audio_id": "audio_a81e5c40d7f2"
  }'
```
