Skip to main content

Endpoint

Returns the current status of a job and, once complete, the full results including transcript, transliteration, translation, and download URLs for LRC/SRT files.

Job status values

complete and failed are both terminal — a job never leaves either state on its own, and never moves from failed back to complete. Once you see one of them you can stop polling. The single exception is your own request: calling POST /jobs/{id}/align on a transcript-only job returns it to processing while the timings are produced. Nothing we do server-side will move a job out of complete. failed is only ever returned when the pipeline actually recorded a failure. It is never inferred from how long a job has been running, so a slow job is processing, not failed.

Stage

Alongside status, every response carries a finer-grained stage so you can watch a job advance without inferring progress from elapsed time. A job submitted with align=false goes straight from transcribing to done. awaiting_review appears only for review_stage: "transcript" jobs, and means no machine work is queued — the job will not advance until someone approves it. A job held at the aligned gate reports done instead, because its pipeline work really has finished; use review_approved_at to tell whether a human has signed off.

How long jobs take

Measured end to end on production traffic, a 3-minute track takes roughly 90–130 seconds of processing — about 0.4–0.8× the audio duration. Longer tracks and batches under load take longer.
Do not set a client-side timeout of a few minutes and treat expiry as failure. A job can legitimately stay in processing for up to 15 minutes — the pipeline itself allows 10 minutes for transcription and a further 5 for alignment before it gives up and records a failure.If a job genuinely fails or stalls, the API tells you so by returning failed. You do not need your own timeout to detect it, and adding one will make healthy jobs look broken.
Prefer webhooks over polling. Webhooks only fire on terminal states, so there is no in-flight ambiguity to interpret. If you do poll, every 10–15 seconds is plenty.

Response shapes

Processing

transcript_completed_at is stamped when the transcript is ready, which is before alignment finishes. completed_at means the whole job is done. Use status rather than either timestamp to decide whether a job has finished.

Complete — align=true, word_align=true (default)

words_original and words_transliterated are only present when word_align_requested: true and alignment is complete. Jobs submitted with word_align=false include only lrc_* and srt_* in downloads.

Complete — align=false

When align=false was passed at submission, downloads is omitted from the response.

Failed

error.stage is the pipeline stage that failed — transcription or alignment. A job that failed at alignment still has a usable transcript in results; one that failed at transcription has nothing.

Additional fields

Review fields

Present when review=true was passed at submission:
review_url is null until the job reaches its gate and the token is generated — and permanently null when the job was submitted with review_delivery: "api". review_approved_at is null until someone approves.

The review block

Present only while the job is held, and gone once it is approved. It carries the lyrics the reviewer is being asked to accept, as an array of lines:
This exists because results is only filled once a job is complete, and a held job is not — so without it there is no way to read the lyrics you are being asked to approve. It is what makes it possible to run the review inside your own product: see Running Review In Your Own Product, and POST /jobs/{id}/approve for approving one. The existing results.transcript string is unchanged; this is additive.

second_opinion and alignment

Present on every response. Both are null when the corresponding check did not run — see Quality Signals for the full field reference.
null means the check did not run. An empty suggestions array means it ran and agreed with every line — the opposite signal. Do not collapse the two into a single falsy test.
second_opinion is available as soon as the transcript is, so it is readable while a job is still aligning. alignment is null until alignment completes, and on jobs submitted with align=false.

external_id

Present on all jobs. Contains the value passed at submission, or null if not provided.
Use this to map a job back to a track in your own system without maintaining a separate job_id → track lookup.

end_user

Present when end_user was supplied at submission, absent otherwise.
List rows carry id and external_id only. Either can be used with GET /v1/jobs?end_user_id=.

Audio URL field

Present when the job was submitted via audio_url mode:

studio_url

A link to the lyrcs.ai Studio where the transcript can be edited and reviewed. Requires a lyrcs.ai user account to view. Not intended for end-users — this is an internal review tool for distributors.

Results fields

Top-level quality fields

Examples