---
title: "Exports API"
description: "Render one section or a project's selected sections into downloadable MP3, WAV, M4B, synchronized EPUB, or SRT files. Poll a project job for every child export, then download files individually and fetch each child's immutable manifest for matching timings. No ZIP is produced. Freshness compares document, cast, and mastering versions only, not newer audio takes or artifact readiness."
canonical_url: https://lyricwinter.com/docs/api/exports
markdown_url: https://lyricwinter.com/docs/api/exports.md
last_updated: 2026-10-01
status: beta
---
# LyricWinter API reference: Exports

> Render one section or a project's selected sections into downloadable MP3, WAV, M4B, synchronized EPUB, or SRT files. Poll a project job for every child export, then download files individually and fetch each child's immutable manifest for matching timings. No ZIP is produced. Freshness compares document, cast, and mastering versions only, not newer audio takes or artifact readiness.

The LyricWinter API is in beta. Base URL: `https://lyricwinter.com/api/v1`. Authenticate every request with `Authorization: Bearer lw_...`. Successful responses are wrapped as `{ "data": ..., "request_id": "req_..." }`. Machine-readable contract: https://lyricwinter.com/api/v1/openapi.json.

## Endpoints

- [Get the mastering profile](https://lyricwinter.com/docs/api/exports#get-studio-mastering-profile): `GET /studio/projects/{projectId}/mastering-profile`
- [Export a project's sections](https://lyricwinter.com/docs/api/exports#create-studio-project-export): `POST /studio/projects/{projectId}/exports`
- [List project export jobs](https://lyricwinter.com/docs/api/exports#list-studio-project-exports): `GET /studio/projects/{projectId}/exports`
- [Poll a project export job](https://lyricwinter.com/docs/api/exports#get-studio-project-export): `GET /studio/projects/{projectId}/exports/{exportId}`
- [Compare section export versions](https://lyricwinter.com/docs/api/exports#get-studio-project-export-freshness): `GET /studio/projects/{projectId}/export-freshness`
- [List exports](https://lyricwinter.com/docs/api/exports#list-studio-exports): `GET /studio/exports`
- [Create an export](https://lyricwinter.com/docs/api/exports#create-studio-export): `POST /studio/exports`
- [Get an export](https://lyricwinter.com/docs/api/exports#get-studio-export): `GET /studio/exports/{exportId}`
- [Get an export's immutable timeline](https://lyricwinter.com/docs/api/exports#get-studio-export-manifest): `GET /studio/exports/{exportId}/manifest`
- [Cancel an export](https://lyricwinter.com/docs/api/exports#cancel-studio-export): `POST /studio/exports/{exportId}/cancel`

### Get the mastering profile

`GET /studio/projects/{projectId}/mastering-profile`

Scope: `studio:read` · Operation ID: `getStudioMasteringProfile`

Returns the project's loudness and mastering settings and its `mastering_version`, which exports require.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string, uuid | Yes |  |

#### Response 200

Current mastering authority and profile.

Fields inside `data`:

- `schema_version` (1; required)
- `project_id` (string, uuid; required)
- `project_kind` (string, one of `standalone`, `named`; required)
- `mastering_version` (integer, ≥ 1; required)
- `scope` (string, one of `document`, `project`; required)
- `profile` (object; required)
  - `schema_version` (1; required)
  - `enabled` (boolean; required)
  - `target_lufs` (number, -30–-10; required)
  - `strength` (number, 0–1; required)
  - `max_boost_db` (number, 0–24; required)
  - `max_reduction_db` (number, 0–24; required)
  - `silence_threshold_lufs` (number, -120–-20; required)
  - `peak_ceiling_db` (number, -12–-0.1; required)
  - `speaker_adjustments_db` (map of number; required)
  - `sfx_bus_gain_db` (number, -24–24, default 0; required)
- `sfx_adjustments` (object; optional)
  - `nonzero_count` (integer, ≥ 0; required)
  - `nonzero_section_count` (integer, ≥ 0; required)
  - `fingerprint` (string, pattern ^[a-f0-9]{64}$; required)

Errors: `400`, `401`, `403`, `404`, `409`, `500` return the standard error envelope.

#### Example request

```bash
curl "https://lyricwinter.com/api/v1/studio/projects/$PROJECT_ID/mastering-profile" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

### Export a project's sections

`POST /studio/projects/{projectId}/exports`

Scope: `studio:write` · Retries: send an `Idempotency-Key` header · Operation ID: `createStudioProjectExport`

Creates a parent job with one section export per selected active section, in project order. Send `schema_version: 1`, `format`, and `pin: "current"` with an `Idempotency-Key` header. Optional `sections` selects 1-100 unique section UUIDs; omitting it selects all active sections, up to 100. The selection and saved document, cast, and mastering version plan are captured together and remain fixed. Audio takes are selected when each child compiles, not atomically at enqueue. Returns `202` for a new job or `200` for a database replay; an HTTP replay may retain the original `202`. Dispatch is asynchronous, without a fixed completion deadline. This does not generate speech or automatically retry failed paid generation. Poll the parent and download child files separately; `archive` is always null.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string, uuid | Yes |  |

#### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | string, 8–128 chars, pattern ^[\x21-\x7E]+$ | Yes | Key for one intended project export. Retry the same request with the same key; reuse for a different request returns 409. |

#### Request body (application/json, required)

- `schema_version` (1; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `pin` ("current"; required): Capture saved document, speaker registry, and mastering versions at enqueue. This does not capture an atomic queue-time media revision.
- `sections` (array of string, 1–100 items, unique; optional): Active section IDs belonging to this project. Returned children follow project order, not request order. Omit to select all active sections; the resulting selection must contain one to 100 sections.

#### Response 200

The existing parent was returned by database idempotency replay; this does not imply completion.

Fields inside `data`:

- `schema_version` (1; required)
- `id` (string, uuid; required): Parent project export job ID.
- `project_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `status` (string, one of `queued`, `running`, `completed`, `partial_failed`, `failed`; required): queued when all children are queued; running while any child is active otherwise. Once all children are terminal or unavailable: completed if all succeeded, partial_failed if only some succeeded, or failed if none succeeded. Child cancellation, supersession, and unavailability count as failure, not successful completion.
- `percent` (integer, 0–100; required): Floor of the mean child progress. Each terminal or unavailable child counts as 100, including failed, cancelled, or superseded children. Measures finished work, not success rate.
- `created_at` (string, date-time; required)
- `sections` (array of object, 1–100 items; required): Immutable selection and authority version plan in captured project order, with available child states or per-section unavailability errors.
  - `section_id` (string, uuid; required)
  - `title` (string, max 500 chars; required): Section title captured for this parent.
  - `export_id` (string, uuid; required): Captured child ID. Child status, manifest, and cancellation endpoints are usable only while the child remains accessible.
  - `authority` (object; required): Immutable saved versions captured at enqueue, retained even if the child is moved or deleted.
    - `document_version` (integer, ≥ 1; required)
    - `speaker_registry_version` (integer, ≥ 1; required)
    - `mastering_version` (integer, ≥ 1; required)
  - `export` (object | null; required): Current ordinary child export payload, or null when the child is unavailable after transfer or deletion.
    - `schema_version` (1; required)
    - `id` (string, uuid; required)
    - `project_id` (string, uuid; required)
    - `section_id` (string, uuid; required)
    - `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
    - `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
    - `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
    - `percent` (integer, 0–100; required)
    - `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
    - `authority` (object; required)
      - `document_version` (integer, ≥ 1; required)
      - `speaker_registry_version` (integer, ≥ 1; required)
      - `mastering_version` (integer, ≥ 1; required)
      - `is_current` (boolean; required)
    - `created_at` (string, date-time; required)
    - `started_at` (string | null, date-time; required)
    - `completed_at` (string | null, date-time; required)
    - `error` (object | null; required)
      - `code` (string; required)
      - `message` (string; required)
    - `artifact` (object | null; required)
      - `asset_id` (string, uuid; required)
      - `filename` (string, 1–255 chars; required)
      - `content_type` (string, min 1 chars; required)
      - `size_bytes` (integer, ≥ 1; required)
      - `download_url` (string, uri; required)
      - `download_url_expires_at` (string, date-time; required)
      - `artifact_expires_at` (string, date-time; required)
  - `error` (object | null; required): Per-section availability error, or null when the child is available. Unavailable children report STUDIO_PROJECT_EXPORT_SECTION_UNAVAILABLE and count as aggregate failure.
    - `code` (string, min 1 chars; required)
    - `message` (string; required)
- `archive` (any | null; required): No combined archive or ZIP is produced. Download child artifacts individually.

#### Response 202

New durable project export work accepted, or its original accepted HTTP response replayed. Poll for current state.

Fields inside `data`:

- `schema_version` (1; required)
- `id` (string, uuid; required): Parent project export job ID.
- `project_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `status` (string, one of `queued`, `running`, `completed`, `partial_failed`, `failed`; required): queued when all children are queued; running while any child is active otherwise. Once all children are terminal or unavailable: completed if all succeeded, partial_failed if only some succeeded, or failed if none succeeded. Child cancellation, supersession, and unavailability count as failure, not successful completion.
- `percent` (integer, 0–100; required): Floor of the mean child progress. Each terminal or unavailable child counts as 100, including failed, cancelled, or superseded children. Measures finished work, not success rate.
- `created_at` (string, date-time; required)
- `sections` (array of object, 1–100 items; required): Immutable selection and authority version plan in captured project order, with available child states or per-section unavailability errors.
  - `section_id` (string, uuid; required)
  - `title` (string, max 500 chars; required): Section title captured for this parent.
  - `export_id` (string, uuid; required): Captured child ID. Child status, manifest, and cancellation endpoints are usable only while the child remains accessible.
  - `authority` (object; required): Immutable saved versions captured at enqueue, retained even if the child is moved or deleted.
    - `document_version` (integer, ≥ 1; required)
    - `speaker_registry_version` (integer, ≥ 1; required)
    - `mastering_version` (integer, ≥ 1; required)
  - `export` (object | null; required): Current ordinary child export payload, or null when the child is unavailable after transfer or deletion.
    - `schema_version` (1; required)
    - `id` (string, uuid; required)
    - `project_id` (string, uuid; required)
    - `section_id` (string, uuid; required)
    - `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
    - `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
    - `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
    - `percent` (integer, 0–100; required)
    - `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
    - `authority` (object; required)
      - `document_version` (integer, ≥ 1; required)
      - `speaker_registry_version` (integer, ≥ 1; required)
      - `mastering_version` (integer, ≥ 1; required)
      - `is_current` (boolean; required)
    - `created_at` (string, date-time; required)
    - `started_at` (string | null, date-time; required)
    - `completed_at` (string | null, date-time; required)
    - `error` (object | null; required)
      - `code` (string; required)
      - `message` (string; required)
    - `artifact` (object | null; required)
      - `asset_id` (string, uuid; required)
      - `filename` (string, 1–255 chars; required)
      - `content_type` (string, min 1 chars; required)
      - `size_bytes` (integer, ≥ 1; required)
      - `download_url` (string, uri; required)
      - `download_url_expires_at` (string, date-time; required)
      - `artifact_expires_at` (string, date-time; required)
  - `error` (object | null; required): Per-section availability error, or null when the child is available. Unavailable children report STUDIO_PROJECT_EXPORT_SECTION_UNAVAILABLE and count as aggregate failure.
    - `code` (string, min 1 chars; required)
    - `message` (string; required)
- `archive` (any | null; required): No combined archive or ZIP is produced. Download child artifacts individually.

Errors: `400`, `401`, `403`, `404`, `409`, `500`, `503` return the standard error envelope.

#### Example request

```bash
curl -X POST "https://lyricwinter.com/api/v1/studio/projects/$PROJECT_ID/exports" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "schema_version": 1,
  "format": "mp3",
  "pin": "current"
}'
```

### List project export jobs

`GET /studio/projects/{projectId}/exports`

Scope: `studio:read` · Operation ID: `listStudioProjectExports`

Lists parent jobs newest first, including their child exports. Optional `format` filters the list. `cursor` is an integer offset starting at 0; `limit` is 1-10 and defaults to 1. Pass the returned string `next_cursor` as the next offset; null means the end. Listing does not start exports or regenerate audio.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string, uuid | Yes |  |

#### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `format` | string, one of `mp3`, `wav`, `m4b`, `epub`, `srt` | No |  |
| `cursor` | integer, ≥ 0, default 0 | No |  |
| `limit` | integer, 1–10, default 1 | No |  |

#### Response 200

A page of project export jobs and child statuses.

Fields inside `data`:

- `schema_version` (1; required)
- `exports` (array of object, max 10 items; required)
  - `schema_version` (1; required)
  - `id` (string, uuid; required): Parent project export job ID.
  - `project_id` (string, uuid; required)
  - `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
  - `status` (string, one of `queued`, `running`, `completed`, `partial_failed`, `failed`; required): queued when all children are queued; running while any child is active otherwise. Once all children are terminal or unavailable: completed if all succeeded, partial_failed if only some succeeded, or failed if none succeeded. Child cancellation, supersession, and unavailability count as failure, not successful completion.
  - `percent` (integer, 0–100; required): Floor of the mean child progress. Each terminal or unavailable child counts as 100, including failed, cancelled, or superseded children. Measures finished work, not success rate.
  - `created_at` (string, date-time; required)
  - `sections` (array of object, 1–100 items; required): Immutable selection and authority version plan in captured project order, with available child states or per-section unavailability errors.
    - `section_id` (string, uuid; required)
    - `title` (string, max 500 chars; required): Section title captured for this parent.
    - `export_id` (string, uuid; required): Captured child ID. Child status, manifest, and cancellation endpoints are usable only while the child remains accessible.
    - `authority` (object; required): Immutable saved versions captured at enqueue, retained even if the child is moved or deleted.
      - `document_version` (integer, ≥ 1; required)
      - `speaker_registry_version` (integer, ≥ 1; required)
      - `mastering_version` (integer, ≥ 1; required)
    - `export` (object | null; required): Current ordinary child export payload, or null when the child is unavailable after transfer or deletion.
      - `schema_version` (1; required)
      - `id` (string, uuid; required)
      - `project_id` (string, uuid; required)
      - `section_id` (string, uuid; required)
      - `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
      - `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
      - `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
      - `percent` (integer, 0–100; required)
      - `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
      - `authority` (object; required)
        - `document_version` (integer, ≥ 1; required)
        - `speaker_registry_version` (integer, ≥ 1; required)
        - `mastering_version` (integer, ≥ 1; required)
        - `is_current` (boolean; required)
      - `created_at` (string, date-time; required)
      - `started_at` (string | null, date-time; required)
      - `completed_at` (string | null, date-time; required)
      - `error` (object | null; required)
        - `code` (string; required)
        - `message` (string; required)
      - `artifact` (object | null; required)
        - `asset_id` (string, uuid; required)
        - `filename` (string, 1–255 chars; required)
        - `content_type` (string, min 1 chars; required)
        - `size_bytes` (integer, ≥ 1; required)
        - `download_url` (string, uri; required)
        - `download_url_expires_at` (string, date-time; required)
        - `artifact_expires_at` (string, date-time; required)
    - `error` (object | null; required): Per-section availability error, or null when the child is available. Unavailable children report STUDIO_PROJECT_EXPORT_SECTION_UNAVAILABLE and count as aggregate failure.
      - `code` (string, min 1 chars; required)
      - `message` (string; required)
  - `archive` (any | null; required): No combined archive or ZIP is produced. Download child artifacts individually.
- `next_cursor` (string | null, min 1 chars; required): Next integer offset encoded as a string, or null at the end. Pass it as cursor with the same format filter.

Errors: `400`, `401`, `403`, `404`, `500` return the standard error envelope.

#### Example request

```bash
curl "https://lyricwinter.com/api/v1/studio/projects/$PROJECT_ID/exports" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

### Poll a project export job

`GET /studio/projects/{projectId}/exports/{exportId}`

Scope: `studio:read` · Operation ID: `getStudioProjectExport`

Returns the parent job and ordered `sections`, each with `section_id`, captured `title`, child `export_id`, captured `authority` versions, nullable `export`, and nullable `error`. If a child is moved to another project or deleted, `export` is null and `error.code` is `STUDIO_PROJECT_EXPORT_SECTION_UNAVAILABLE`; the captured plan remains. Poll while `queued` or `running`. `completed`, `partial_failed`, and `failed` are terminal. Unavailable children count as failures; `percent` counts them and terminal failures as finished work, so 100 does not mean success. Download each available completed child's `export.artifact.download_url`; use its child ID for `/studio/exports/{exportId}/manifest` (including optional `schema_version=2` word timings) or `/cancel`. Transfers and cleanup are not blocked, and original child endpoints are not guaranteed to remain accessible. The parent ID is not a child ID. There is no combined archive or automatic re-export after edits.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string, uuid | Yes |  |
| `exportId` | string, uuid | Yes | The parent project export ID, not a child section export ID. |

#### Response 200

Current project export parent and child states.

Fields inside `data`:

- `schema_version` (1; required)
- `id` (string, uuid; required): Parent project export job ID.
- `project_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `status` (string, one of `queued`, `running`, `completed`, `partial_failed`, `failed`; required): queued when all children are queued; running while any child is active otherwise. Once all children are terminal or unavailable: completed if all succeeded, partial_failed if only some succeeded, or failed if none succeeded. Child cancellation, supersession, and unavailability count as failure, not successful completion.
- `percent` (integer, 0–100; required): Floor of the mean child progress. Each terminal or unavailable child counts as 100, including failed, cancelled, or superseded children. Measures finished work, not success rate.
- `created_at` (string, date-time; required)
- `sections` (array of object, 1–100 items; required): Immutable selection and authority version plan in captured project order, with available child states or per-section unavailability errors.
  - `section_id` (string, uuid; required)
  - `title` (string, max 500 chars; required): Section title captured for this parent.
  - `export_id` (string, uuid; required): Captured child ID. Child status, manifest, and cancellation endpoints are usable only while the child remains accessible.
  - `authority` (object; required): Immutable saved versions captured at enqueue, retained even if the child is moved or deleted.
    - `document_version` (integer, ≥ 1; required)
    - `speaker_registry_version` (integer, ≥ 1; required)
    - `mastering_version` (integer, ≥ 1; required)
  - `export` (object | null; required): Current ordinary child export payload, or null when the child is unavailable after transfer or deletion.
    - `schema_version` (1; required)
    - `id` (string, uuid; required)
    - `project_id` (string, uuid; required)
    - `section_id` (string, uuid; required)
    - `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
    - `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
    - `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
    - `percent` (integer, 0–100; required)
    - `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
    - `authority` (object; required)
      - `document_version` (integer, ≥ 1; required)
      - `speaker_registry_version` (integer, ≥ 1; required)
      - `mastering_version` (integer, ≥ 1; required)
      - `is_current` (boolean; required)
    - `created_at` (string, date-time; required)
    - `started_at` (string | null, date-time; required)
    - `completed_at` (string | null, date-time; required)
    - `error` (object | null; required)
      - `code` (string; required)
      - `message` (string; required)
    - `artifact` (object | null; required)
      - `asset_id` (string, uuid; required)
      - `filename` (string, 1–255 chars; required)
      - `content_type` (string, min 1 chars; required)
      - `size_bytes` (integer, ≥ 1; required)
      - `download_url` (string, uri; required)
      - `download_url_expires_at` (string, date-time; required)
      - `artifact_expires_at` (string, date-time; required)
  - `error` (object | null; required): Per-section availability error, or null when the child is available. Unavailable children report STUDIO_PROJECT_EXPORT_SECTION_UNAVAILABLE and count as aggregate failure.
    - `code` (string, min 1 chars; required)
    - `message` (string; required)
- `archive` (any | null; required): No combined archive or ZIP is produced. Download child artifacts individually.

Errors: `400`, `401`, `403`, `404`, `500` return the standard error envelope.

#### Example request

```bash
curl "https://lyricwinter.com/api/v1/studio/projects/$PROJECT_ID/exports/$EXPORT_ID" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

### Compare section export versions

`GET /studio/projects/{projectId}/export-freshness`

Scope: `studio:read` · Operation ID: `getStudioProjectExportFreshness`

Returns active sections in project order, their saved document, speaker registry, and mastering versions, and their latest export for `format` (default `mp3`). Deleted sections are omitted; at most 100 active sections are supported. `basis` is `document_cast_mastering_versions`. Without an export, `latest_export` and `matches_current_authority` are null. A true match is only a version comparison: it does not guarantee latest audio takes, successful completion, complete media, or a valid downloadable artifact. Inspect status and artifact separately. This read does not export or generate anything.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string, uuid | Yes |  |

#### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `format` | string, default "mp3", one of `mp3`, `wav`, `m4b`, `epub`, `srt` | No |  |

#### Response 200

Version comparisons for the project's active sections.

Fields inside `data`:

- `schema_version` (1; required)
- `project_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `basis` ("document_cast_mastering_versions"; required): Saved version comparison only; not take freshness, artifact validity, or successful completion.
- `sections` (array of object, max 100 items; required): Active sections in project order; deleted sections are omitted. Projects exceeding 100 active sections return 400.
  - `section_id` (string, uuid; required)
  - `title` (string, max 500 chars; required)
  - `document_version` (integer, ≥ 1; required)
  - `speaker_registry_version` (integer, ≥ 1; required)
  - `mastering_version` (integer, ≥ 1; required)
  - `latest_export` (object | null; required): Latest section export for the requested format, regardless of status; null if none exists.
    - `schema_version` (1; required)
    - `id` (string, uuid; required)
    - `project_id` (string, uuid; required)
    - `section_id` (string, uuid; required)
    - `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
    - `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
    - `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
    - `percent` (integer, 0–100; required)
    - `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
    - `authority` (object; required)
      - `document_version` (integer, ≥ 1; required)
      - `speaker_registry_version` (integer, ≥ 1; required)
      - `mastering_version` (integer, ≥ 1; required)
      - `is_current` (boolean; required)
    - `created_at` (string, date-time; required)
    - `started_at` (string | null, date-time; required)
    - `completed_at` (string | null, date-time; required)
    - `error` (object | null; required)
      - `code` (string; required)
      - `message` (string; required)
    - `artifact` (object | null; required)
      - `asset_id` (string, uuid; required)
      - `filename` (string, 1–255 chars; required)
      - `content_type` (string, min 1 chars; required)
      - `size_bytes` (integer, ≥ 1; required)
      - `download_url` (string, uri; required)
      - `download_url_expires_at` (string, date-time; required)
      - `artifact_expires_at` (string, date-time; required)
  - `matches_current_authority` (boolean | null; required): Whether the latest export's document, cast, and mastering versions match. Null without an export. true does not guarantee latest takes, completion, timeline completeness, or a valid artifact.

Errors: `400`, `401`, `403`, `404`, `500` return the standard error envelope.

#### Example request

```bash
curl "https://lyricwinter.com/api/v1/studio/projects/$PROJECT_ID/export-freshness" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

### List exports

`GET /studio/exports`

Scope: `studio:read` · Operation ID: `listStudioExports`

Lists the account's exports, newest first. Completed exports include a download URL that is valid for twelve hours; the file itself is kept for thirty days.

#### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `section_id` | string, uuid | No |  |
| `format` | string, one of `mp3`, `wav`, `m4b`, `epub`, `srt` | No |  |
| `status` | string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded` | No |  |
| `cursor` | integer, ≥ 0, default 0 | No |  |
| `limit` | integer, 1–100, default 25 | No |  |

#### Response 200

One export page.

Fields inside `data`:

- `schema_version` (1; required)
- `exports` (array of object; required)
  - `schema_version` (1; required)
  - `id` (string, uuid; required)
  - `project_id` (string, uuid; required)
  - `section_id` (string, uuid; required)
  - `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
  - `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
  - `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
  - `percent` (integer, 0–100; required)
  - `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
  - `authority` (object; required)
    - `document_version` (integer, ≥ 1; required)
    - `speaker_registry_version` (integer, ≥ 1; required)
    - `mastering_version` (integer, ≥ 1; required)
    - `is_current` (boolean; required)
  - `created_at` (string, date-time; required)
  - `started_at` (string | null, date-time; required)
  - `completed_at` (string | null, date-time; required)
  - `error` (object | null; required)
    - `code` (string; required)
    - `message` (string; required)
  - `artifact` (object | null; required)
    - `asset_id` (string, uuid; required)
    - `filename` (string, 1–255 chars; required)
    - `content_type` (string, min 1 chars; required)
    - `size_bytes` (integer, ≥ 1; required)
    - `download_url` (string, uri; required)
    - `download_url_expires_at` (string, date-time; required)
    - `artifact_expires_at` (string, date-time; required)
- `next_cursor` (string | null, min 1 chars; required)

Errors: `400`, `401`, `403`, `404`, `409`, `500`, `503` return the standard error envelope.

#### Example request

```bash
curl "https://lyricwinter.com/api/v1/studio/exports" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

### Create an export

`POST /studio/exports`

Scope: `studio:write` · Retries: send an `Idempotency-Key` header · Operation ID: `createStudioExport`

Renders one section into `mp3`, `wav`, `m4b`, synchronized `epub`, or `srt`, pinned to the document, speaker registry, and mastering versions you send. Returns `202` for new work or `200` when an identical, unexpired file is reused. Requires an `Idempotency-Key` header.

#### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | string, 1–255 chars | Yes | Opaque caller key. The same key and request replay safely; the same key with a different request conflicts. |

#### Request body (application/json, required)

- `schema_version` (1; required)
- `section_id` (string, uuid; required)
- `document_version` (integer, ≥ 1; required)
- `speaker_registry_version` (integer, ≥ 1; required)
- `mastering_version` (integer, ≥ 1; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)

#### Response 200

An unexpired identical artifact was reused.

Fields inside `data`:

- `schema_version` (1; required)
- `id` (string, uuid; required)
- `project_id` (string, uuid; required)
- `section_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
- `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
- `percent` (integer, 0–100; required)
- `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
- `authority` (object; required)
  - `document_version` (integer, ≥ 1; required)
  - `speaker_registry_version` (integer, ≥ 1; required)
  - `mastering_version` (integer, ≥ 1; required)
  - `is_current` (boolean; required)
- `created_at` (string, date-time; required)
- `started_at` (string | null, date-time; required)
- `completed_at` (string | null, date-time; required)
- `error` (object | null; required)
  - `code` (string; required)
  - `message` (string; required)
- `artifact` (object | null; required)
  - `asset_id` (string, uuid; required)
  - `filename` (string, 1–255 chars; required)
  - `content_type` (string, min 1 chars; required)
  - `size_bytes` (integer, ≥ 1; required)
  - `download_url` (string, uri; required)
  - `download_url_expires_at` (string, date-time; required)
  - `artifact_expires_at` (string, date-time; required)

#### Response 202

New durable export work accepted.

Fields inside `data`:

- `schema_version` (1; required)
- `id` (string, uuid; required)
- `project_id` (string, uuid; required)
- `section_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
- `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
- `percent` (integer, 0–100; required)
- `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
- `authority` (object; required)
  - `document_version` (integer, ≥ 1; required)
  - `speaker_registry_version` (integer, ≥ 1; required)
  - `mastering_version` (integer, ≥ 1; required)
  - `is_current` (boolean; required)
- `created_at` (string, date-time; required)
- `started_at` (string | null, date-time; required)
- `completed_at` (string | null, date-time; required)
- `error` (object | null; required)
  - `code` (string; required)
  - `message` (string; required)
- `artifact` (object | null; required)
  - `asset_id` (string, uuid; required)
  - `filename` (string, 1–255 chars; required)
  - `content_type` (string, min 1 chars; required)
  - `size_bytes` (integer, ≥ 1; required)
  - `download_url` (string, uri; required)
  - `download_url_expires_at` (string, date-time; required)
  - `artifact_expires_at` (string, date-time; required)

Errors: `400`, `401`, `403`, `404`, `409`, `500`, `502`, `503` return the standard error envelope.

#### Example request

```bash
curl -X POST "https://lyricwinter.com/api/v1/studio/exports" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "schema_version": 1,
  "section_id": "11111111-1111-4111-8111-111111111111",
  "document_version": 7,
  "speaker_registry_version": 3,
  "mastering_version": 4,
  "format": "mp3"
}'
```

### Get an export

`GET /studio/exports/{exportId}`

Scope: `studio:read` · Operation ID: `getStudioExport`

Returns an export's status, phase, percent complete, and its completed, unexpired downloadable `artifact`. Historical files remain tied to their original export. `authority.is_current` compares document, cast, and mastering versions only, not the latest audio rendition. For timings matching this file, fetch `/studio/exports/{exportId}/manifest`.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `exportId` | string, uuid | Yes |  |

#### Response 200

Current durable export state.

Fields inside `data`:

- `schema_version` (1; required)
- `id` (string, uuid; required)
- `project_id` (string, uuid; required)
- `section_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
- `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
- `percent` (integer, 0–100; required)
- `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
- `authority` (object; required)
  - `document_version` (integer, ≥ 1; required)
  - `speaker_registry_version` (integer, ≥ 1; required)
  - `mastering_version` (integer, ≥ 1; required)
  - `is_current` (boolean; required)
- `created_at` (string, date-time; required)
- `started_at` (string | null, date-time; required)
- `completed_at` (string | null, date-time; required)
- `error` (object | null; required)
  - `code` (string; required)
  - `message` (string; required)
- `artifact` (object | null; required)
  - `asset_id` (string, uuid; required)
  - `filename` (string, 1–255 chars; required)
  - `content_type` (string, min 1 chars; required)
  - `size_bytes` (integer, ≥ 1; required)
  - `download_url` (string, uri; required)
  - `download_url_expires_at` (string, date-time; required)
  - `artifact_expires_at` (string, date-time; required)

Errors: `400`, `401`, `403`, `404`, `409`, `500`, `503` return the standard error envelope.

#### Example request

```bash
curl "https://lyricwinter.com/api/v1/studio/exports/$EXPORT_ID" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

### Get an export's immutable timeline

`GET /studio/exports/{exportId}/manifest`

Scope: `studio:read` · Operation ID: `getStudioExportManifest`

Returns the exact pinned manifest identity (`id`, content `hash`, and `schema_version`), total duration, completeness, and block timings used by this export. The response's `timing_basis` is `media_and_intra_block_silence_excluding_inter_block_spacing`: speech and narration block durations sum their contiguous playback asset and separately assembled silence units, but exclude inter-block spacing units. An asset unit can share a block's `start_ms` yet have a shorter `duration_ms` when a trailing pause follows it; do not normalize either duration. Join block-level records by stable `block_id` and word sidecars by `unit_id`, not by start time or `block_index`. `block_index` is zero-based in the captured document's full block order. Optional `schema_version=2` adds section-relative provider word timing sidecars for the pinned immutable assets, not today's retakes; missing alignment is explicitly unavailable. Default V1 is unchanged. Returns `409` before a manifest is pinned. This read does not compile or generate media.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `exportId` | string, uuid | Yes |  |

#### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `schema_version` | integer, default 1, one of `1`, `2` | No |  |

#### Response 200

The export's pinned block timeline and content-addressed manifest identity.

Fields inside `data`:

- One of:
  - **schema_version: 1, timing_basis: "media_and_intra_block_silence_excluding_inter_block_spacing"**
    - `schema_version` (1; required)
    - `export_id` (string, uuid; required)
    - `project_id` (string, uuid; required)
    - `section_id` (string, uuid; required)
    - `manifest` (object; required)
      - `id` (string, uuid; required)
      - `hash` (string, pattern ^[a-f0-9]{64}$; required): Content hash of the exact immutable render manifest used by the export.
      - `schema_version` (string, one of `studio-render-manifest-1`, `studio-render-manifest-2`; required)
    - `source_authority` (object; required)
      - `document_version` (integer, ≥ 1; required)
      - `speaker_registry_version` (integer, ≥ 1; required)
      - `mastering_version` (integer, ≥ 1; required)
    - `duration_ms` (integer, ≥ 0; required)
    - `completeness` (string, one of `partial`, `complete`; required)
    - `timing_basis` ("media_and_intra_block_silence_excluding_inter_block_spacing"; required)
    - `blocks` (array of object; required)
      - `block_id` (string, uuid; required)
      - `block_index` (integer, ≥ 0; required): Zero-based position in the export's captured document block order, including non-speech blocks.
      - `media_kind` (string, one of `speech`, `narration`, `sfx`; required)
      - `start_ms` (integer, ≥ 0; required)
      - `duration_ms` (integer, ≥ 1; required): Block span including internal authored silence but excluding inter-block spacing; SFX spans its overlay.
  - **schema_version: 2, timing_basis: "media_and_intra_block_silence_excluding_inter_block_spacing"**: Opt-in export-bound timeline with word timing sidecars from the exact source assets in its immutable stored manifest, never current retakes.
    - `schema_version` (2; required)
    - `export_id` (string, uuid; required)
    - `project_id` (string, uuid; required)
    - `section_id` (string, uuid; required)
    - `manifest` (object; required)
      - `id` (string, uuid; required)
      - `hash` (string, pattern ^[a-f0-9]{64}$; required): Content hash of the exact immutable render manifest used by the export.
      - `schema_version` (string, one of `studio-render-manifest-1`, `studio-render-manifest-2`; required)
    - `source_authority` (object; required)
      - `document_version` (integer, ≥ 1; required)
      - `speaker_registry_version` (integer, ≥ 1; required)
      - `mastering_version` (integer, ≥ 1; required)
    - `duration_ms` (integer, ≥ 0; required)
    - `completeness` (string, one of `partial`, `complete`; required)
    - `timing_basis` ("media_and_intra_block_silence_excluding_inter_block_spacing"; required)
    - `blocks` (array of object; required)
      - `block_id` (string, uuid; required)
      - `block_index` (integer, ≥ 0; required): Zero-based position in the export's captured document block order, including non-speech blocks.
      - `media_kind` (string, one of `speech`, `narration`, `sfx`; required)
      - `start_ms` (integer, ≥ 0; required)
      - `duration_ms` (integer, ≥ 1; required): Block span including internal authored silence but excluding inter-block spacing; SFX spans its overlay.
    - `unit_word_timings` (array of object, max 60000 items; required)
      - One of:
        - **word_timing: "provider"**
          - `unit_id` (string, uuid; required)
          - `block_id` (string, uuid; required)
          - `asset_id` (string, uuid; required)
          - `word_timing` ("provider"; required)
          - `words` (array of object, 1–10000 items; required)
            - `text` (string, 1–4096 chars; required)
            - `start_ms` (integer, ≥ 0; required)
            - `end_ms` (integer, ≥ 0; required)
        - **word_timing: "unavailable"**
          - `unit_id` (string, uuid; required)
          - `block_id` (string, uuid; required)
          - `asset_id` (string, uuid; required)
          - `word_timing` ("unavailable"; required)

Errors: `400`, `401`, `403`, `404`, `409`, `500` return the standard error envelope.

#### Example request

```bash
curl "https://lyricwinter.com/api/v1/studio/exports/$EXPORT_ID/manifest" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

### Cancel an export

`POST /studio/exports/{exportId}/cancel`

Scope: `studio:write` · Operation ID: `cancelStudioExport`

Cancels a queued export immediately or asks a running one to stop. Files already produced for other requests are not deleted.

#### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `exportId` | string, uuid | Yes |  |

#### Response 200

Current cancelled or canceling export state.

Fields inside `data`:

- `schema_version` (1; required)
- `id` (string, uuid; required)
- `project_id` (string, uuid; required)
- `section_id` (string, uuid; required)
- `format` (string, one of `mp3`, `wav`, `m4b`, `epub`, `srt`; required)
- `status` (string, one of `queued`, `running`, `retry_wait`, `canceling`, `completed`, `failed`, `cancelled`, `superseded`; required)
- `phase` (string, one of `queued`, `compiling`, `claiming_artifact`, `downloading`, `mixing`, `encoding`, `packaging`, `uploading`, `complete`, `failed`, `cancelled`; required)
- `percent` (integer, 0–100; required)
- `cache_result` (string, one of `miss`, `reused`, `coalesced`; required)
- `authority` (object; required)
  - `document_version` (integer, ≥ 1; required)
  - `speaker_registry_version` (integer, ≥ 1; required)
  - `mastering_version` (integer, ≥ 1; required)
  - `is_current` (boolean; required)
- `created_at` (string, date-time; required)
- `started_at` (string | null, date-time; required)
- `completed_at` (string | null, date-time; required)
- `error` (object | null; required)
  - `code` (string; required)
  - `message` (string; required)
- `artifact` (object | null; required)
  - `asset_id` (string, uuid; required)
  - `filename` (string, 1–255 chars; required)
  - `content_type` (string, min 1 chars; required)
  - `size_bytes` (integer, ≥ 1; required)
  - `download_url` (string, uri; required)
  - `download_url_expires_at` (string, date-time; required)
  - `artifact_expires_at` (string, date-time; required)

Errors: `400`, `401`, `403`, `404`, `409`, `500` return the standard error envelope.

#### Example request

```bash
curl -X POST "https://lyricwinter.com/api/v1/studio/exports/$EXPORT_ID/cancel" \
  -H "Authorization: Bearer $LYRICWINTER_API_KEY"
```

