> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lyrcs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Review

> Artist approval flow for jobs submitted with review=true

When a job is submitted with `review=true`, lyrcs.ai holds the results until an artist or rights holder approves them. After alignment completes, a `job.awaiting_review` webhook fires with a `review_url` that the distributor sends to the artist.

## Flow overview

<Steps>
  <Step title="Submit with review=true">
    Distributor calls `POST /transcribe` with `review: true` and a `webhook_url`.
  </Step>

  <Step title="Transcription and alignment run">
    lyrcs.ai transcribes and time-aligns the audio. This takes \~90 seconds.
  </Step>

  <Step title="job.awaiting_review fires">
    A `job.awaiting_review` webhook delivers a `review_url` and `expires_at` timestamp to the distributor's webhook endpoint.
  </Step>

  <Step title="Distributor routes review_url to artist">
    The distributor sends the URL to the artist by email or their own platform.
  </Step>

  <Step title="Artist approves">
    The artist visits the review URL, checks the lyrics in the lyrcs.ai Studio, and clicks Approve.
  </Step>

  <Step title="job.complete fires">
    After approval, a `job.complete` webhook delivers the full results including transcript, transliteration, translation, and download URLs.
  </Step>
</Steps>

## Review URL

The `review_url` has the form:

```
https://lyrcs.ai/review/{job_id}?token={token}
```

It is included in:

* The `job.awaiting_review` webhook payload
* `GET /api/v1/jobs/{id}` response (under `review_url`) once alignment is complete

<Warning>
  `review_url` is `null` until alignment completes and the token is generated. Do not cache or forward a null value — poll `GET /jobs/{id}` until `review_url` is non-null if needed.
</Warning>

The token is single-use and has an expiry. Once expired, the artist cannot approve. Contact [support@lyrcs.ai](mailto:support@lyrcs.ai) if a token expires before approval.

## Webhook payloads

**job.awaiting\_review** — fires after alignment:

```json theme={null}
{
  "event": "job.awaiting_review",
  "job_id": "a1b2c3d4-...",
  "language": "Punjabi",
  "review_url": "https://lyrcs.ai/review/a1b2c3d4-...?token=...",
  "expires_at": "2024-01-02T00:00:00.000Z",
  "studio_url": "https://lyrcs.ai/studio/a1b2c3d4-..."
}
```

**job.complete** — fires after artist approves:

```json theme={null}
{
  "event": "job.complete",
  "job_id": "a1b2c3d4-...",
  "language": "Punjabi",
  "created_at": "2024-01-01T00:00:00.000Z",
  "duration_seconds": 214,
  "studio_url": "https://lyrcs.ai/studio/a1b2c3d4-...",
  "results": {
    "transcript": "...",
    "transliteration": "...",
    "translation": "...",
    "cultural_notes": null,
    "downloads": {
      "lrc_original": "https://lyrcs.ai/api/v1/jobs/a1b2c3d4-.../download/lrc/original",
      "lrc_transliterated": "https://lyrcs.ai/api/v1/jobs/a1b2c3d4-.../download/lrc/transliterated",
      "srt_original": "https://lyrcs.ai/api/v1/jobs/a1b2c3d4-.../download/srt/original",
      "srt_transliterated": "https://lyrcs.ai/api/v1/jobs/a1b2c3d4-.../download/srt/transliterated"
    }
  }
}
```

## review\_required on job response

When a job was submitted with `review=true`, these fields appear on `GET /api/v1/jobs/{id}`:

```json theme={null}
{
  "review_required": true,
  "review_url": "https://lyrcs.ai/review/a1b2c3d4-...?token=...",
  "review_expires_at": "2024-01-02T00:00:00.000Z",
  "review_approved_at": null
}
```

`review_approved_at` is set to an ISO timestamp once the artist approves.

## Known limitations

* The `job.complete` webhook fired after artist approval uses single-attempt delivery — it does not retry on failure, unlike the standard auto-align webhook flow which retries at +1 min, +5 min, +30 min.
* `review_url` is null until alignment completes (typically \~90s after submission).

See the [Review Flow guide](/guides/review-flow) for a full end-to-end walkthrough.
