Skip to main content

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.

Batch processing lets you submit multiple audio files in a single API call. All jobs process concurrently. A single batch.complete webhook fires when every job is done — regardless of whether individual jobs succeeded or failed.

When to use batch vs individual jobs

Use caseRecommendation
Releasing a multi-track albumBatch — one request, one webhook
Processing a catalog of 100+ songsBatch in groups of 20
Single track with a webhookIndividual job
Real-time single track (need result ASAP)Individual job
Metadata-only for a set of tracksBatch with align=false per job

Submitting a batch

Batches are JSON-only — every job must use audio_url. File uploads are not supported.
POST /api/v1/batch

{
  "webhook_url": "https://api.example.com/webhooks/lyrcs",
  "jobs": [
    { "audio_url": "https://cdn.example.com/track-1.mp3", "language": "Hindi" },
    { "audio_url": "https://cdn.example.com/track-2.mp3", "language": "Tamil" },
    { "audio_url": "https://cdn.example.com/track-3.mp3", "language": "Telugu", "align": false }
  ]
}
  • Minimum 1 job, maximum 20 jobs per request
  • Per-job fields: audio_url (required), language (required), align (optional, default true), review (optional, default false)

Rate limit pre-flight

The rate limit check is performed before any jobs are created. If submitting N jobs would push any window over the limit, the entire batch is rejected with 429 and no jobs are queued.
{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded: minute limit would be exceeded by this batch",
  "code": "RATE_001",
  "retry_after": 60,
  "jobs_requested": 15
}
Check the X-RateLimit-Remaining-* headers on any previous response to know how much headroom you have before submitting a large batch.

Polling GET /batch/[id]

The batch status progresses through:
queued → in_progress → complete (or partial)
Poll every 15–30 seconds. For a 20-job batch, expect 2–3 minutes total. The batch finalizes as soon as the last job finishes — it does not wait the full polling budget.
async function waitForBatch(batchId, apiKey, { intervalMs = 15000, timeoutMs = 600000 } = {}) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const res = await fetch(`https://lyrcs.ai/api/v1/batch/${batchId}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const batch = await res.json();
    if (batch.status === "complete" || batch.status === "partial") return batch;
    await new Promise((r) => setTimeout(r, intervalMs));
  }
  throw new Error("Batch timed out");
}

Handling partial failures

A batch.complete webhook with status: "partial" means at least one job failed. The failed field tells you how many. Individual job entries in jobs[] have their own status field.
// From a batch.complete webhook payload
const failed = payload.jobs.filter((j) => j.status === "failed");

for (const job of failed) {
  console.error(`Job ${job.job_id} (${job.language}) failed — resubmit individually`);
  // Resubmit as an individual job via POST /transcribe
}

const completed = payload.jobs.filter((j) => j.status === "complete");
for (const job of completed) {
  const lrcUrl = job.downloads?.lrc_original;
  if (lrcUrl) {
    // Download and deliver
  }
}
Failed jobs should be resubmitted individually via POST /transcribe. The batch endpoint requires at least 1 job and you may only have 1 to retry.

Metadata-only batch (align=false)

For catalog workflows where you need lyrics text but not LRC files, set align=false per job. Processing is faster (~60s per job) and the batch completes sooner.
{
  "webhook_url": "https://api.example.com/webhooks/lyrcs",
  "jobs": [
    { "audio_url": "https://cdn.example.com/track-1.mp3", "language": "Hindi", "align": false },
    { "audio_url": "https://cdn.example.com/track-2.mp3", "language": "Marathi", "align": false }
  ]
}
Jobs submitted with align=false will not include downloads in the batch.complete payload or in GET /batch/{id} responses.

Processing large catalogs

The rate limit is 1,000 jobs per day. For a catalog larger than 1,000 tracks, spread submissions across multiple days or contact api@lyrcs.ai to discuss higher limits. For 1,000 tracks:
  • 50 batches of 20 jobs each
  • All within the daily limit
  • Each batch submitted when the previous batch.complete fires (or use a queue)