Quickstart

Generate AI music
programmatically.

The Lacuna Music API ships with a typed TypeScript SDK, a CLI, and an MCP server. Five steps below take you from no account to a finished, hosted audio file.

1

Get an API key

Music API access requires the Pro plan or above. From your dashboard, create a key — it's shown once at creation; copy it into a secrets manager immediately. Keys begin with lyr_live_.

2

Install the SDK

The official SDK is lacuna-sdk — typed TypeScript client on Node 18+. Prefer the command line? Install lacuna-toolkit instead.

npm install lacuna-sdk
# or
pnpm add lacuna-sdk
# or
yarn add lacuna-sdk
3

Make your first request

Create a task. Credits are deducted up-front at the selected model's rate and refunded automatically if the upstream provider fails. The response is a complete task object; use its id to poll.

import Lacuna from 'lacuna-sdk'

const lacuna = new Lacuna({ apiKey: process.env.LACUNA_API_KEY })

const task = await lacuna.music.generations.create({
  style: 'lofi hip hop, mellow piano, 70 bpm',
  title: 'Late Night Study',
  instrumental: true,
})

console.log(task.id, task.status) // 'cm123abc...' 'pending'
4

Wait for completion

Tasks run asynchronously. waitFor polls until the task reaches a terminal state. For production traffic, prefer webhooks — see step 5.

const finished = await lacuna.music.generations.waitFor(task.id, {
  pollInterval: 5_000, // poll every 5s
  timeout: 600_000,    // up to 10 minutes
})

if (finished.status === 'ready') {
  for (const track of finished.tracks) {
    console.log(track.audio_url, track.duration, track.lyrics)
  }
}
5

Verify webhooks

optional

Subscribe to job.completed and job.failed events and verify their HMAC-SHA256 signatures. The SDK ships a verifier with replay protection.

// Next.js (App Router) — app/api/webhooks/lacuna/route.ts
import { Webhooks } from 'lacuna-sdk/webhooks'

export async function POST(request: Request) {
  const body = await request.text()
  const event = Webhooks.constructEvent(
    body,
    request.headers.get('x-lacuna-signature'),
    process.env.LACUNA_WEBHOOK_SECRET!,
  )

  if (Webhooks.isJobCompleted(event)) {
    // event.data.tracks is fully typed
  }

  return new Response(null, { status: 200 })
}

Errors & rate limits

Every error response carries an OpenAI-style envelope — { error: { type, code, message, param } }. The SDK exposes typed subclasses (RateLimitError, InsufficientCreditsError, …) so your handlers can be precise.

CodeHTTPMeaning
invalid_json400Request body is not valid JSON.
invalid_param400Request body failed validation, including unknown fields. Inspect `error.param`.
missing_lyrics400Lyrics are required unless `instrumental` is true.
invalid_api_key401API key is missing or malformed.
key_expired / key_revoked401The key is expired or has been revoked. Create or rotate a key in the dashboard.
tier_insufficient403Music API requires Pro or above. Downgrades invalidate keys without revoking them.
insufficient_credits402Top up or upgrade your plan.
rpm_exceeded42960 requests/minute per key. Honour the `Retry-After` header.
concurrent_limit_exceeded429Too many in-flight tasks. Wait for one to finish.
resource_not_found404The generation ID does not exist or does not belong to this account.
model_unavailable503Selected model is temporarily unavailable. Honour `Retry-After` or choose another model.
provider_error500Upstream failure. Credits are refunded automatically.

429 and retryable 503 responses include a Retry-After header (seconds). The SDK retries safe read requests with jittered exponential backoff. Creation requests are not automatically retried because the API does not yet support idempotency keys.