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
Submit with review=true
Distributor calls POST /transcribe with review: true and a webhook_url.
Transcription and alignment run
lyrcs.ai transcribes and time-aligns the audio. This takes ~90 seconds.
job.awaiting_review fires
A job.awaiting_review webhook delivers a review_url and expires_at timestamp to the distributor’s webhook endpoint.
Distributor routes review_url to artist
The distributor sends the URL to the artist by email or their own platform.
Artist approves
The artist visits the review URL, checks the lyrics in the lyrcs.ai Studio, and clicks Approve.
job.complete fires
After approval, a job.complete webhook delivers the full results including transcript, transliteration, translation, and download URLs.
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
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.
The token is single-use and has an expiry. Once expired, the artist cannot approve. Contact support@lyrcs.ai if a token expires before approval.
Webhook payloads
job.awaiting_review — fires after alignment:
{
"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:
{
"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}:
{
"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 for a full end-to-end walkthrough.