eroq

API reference · Media

Music generation

Make a song with vocals and instruments, from one sentence or from your own lyrics — async, poll each take.

GETPOST/v1/music/generations3 per started 30 s of song, per take (Music One)

Two ways in. *Simple*: send prompt, the song in one sentence ("a melancholy synth-pop song about leaving a small town") — the songwriter writes the style, the lyrics and a title for you, included in the price. *Custom*: send your own style (language, vocals, genre, tempo, instruments) and lyrics, with section tags on their own lines — [Intro], [Verse], [Pre-Chorus], [Chorus], [Bridge], [Outro]. A style without lyrics gets lyrics written for it. instrumental: true drops the vocals (lyrics are ignored). The 202 answer echoes the title, style and lyrics the song renders from, so you see what the songwriter wrote.

A song takes minutes of GPU, so this endpoint is asynchronous: the call charges, starts one job per take and answers 202 with jobs (one id + poll path per take). Poll GET /v1/music/generations/{id} every few seconds until status is succeeded (the MP3 is in data) or failed. Or subscribe a webhook to music.generation.succeeded / music.generation.failed.

Billing. 3 credits per started 30 seconds of song, per take — on the REQUESTED length, snapped to the engine's grid (30 seconds to 4 minutes, in steps of 30): it is the time the engine reserves, even when a song finds its ending a little earlier (the finished take reports its real seconds). n takes (1 or 2, default 2) are rendered with their own seeds so you can keep the better one. A take that fails, or never finishes within the engine's window, is refunded on its own — the others still deliver.

While the engine is not live on this deployment the call answers 503 model_unavailable before any debit (GET /v1/engines reports models["eroq-music-one"]). Our content policy applies to every word you send AND to what the songwriter writes: nothing involving minors, no real identifiable people without consent — a refused song answers 400 content_blocked and bills nothing (or is refunded when the written lyrics are the problem).

Every finished take lands in your Library (the Music tab) with its recipe, so the studio can remix it later. GET /v1/music/generations/{id} is free to call; job ids expire 24 hours after creation.

Endpoints

Select a verb to load its request, playground and response.

POST/v1/music/generationsshown

Start a song — one sentence (Simple) or style + lyrics (Custom). Answers 202 with one job per take.

promptstring

Simple mode: the song in one sentence, up to 600 characters. The songwriter writes style, lyrics and title. One of prompt, style or lyrics is required.

stylestring

Custom mode: how it sounds — language, vocals, genre, tempo, instruments (comma-separated words work best), up to 600 characters.

lyricsstring

Custom mode: the sung words, with section tags on their own lines ([Verse], [Chorus], [Bridge]…), up to 3,000 characters. Omitted with a style = written for you.

titlestring

The song's title, up to 80 characters. Omitted = the songwriter names it.

instrumentalboolean

No vocals: lyrics are ignored. Default false.

secondsinteger

Requested length, snapped to the grid: 30 to 240 in steps of 30. Billed on this length.

ninteger

Takes, 1 or 2 (default 2) — each its own job, seed and charge.

seedinteger

Reproducible takes: take N renders with seed + N - 1.

modelstring

eroq-music-one (default, the only music engine today).

folder_idstring

Library folder the takes land in — one of yours (GET /v1/folders). Omitted = the Library root; an unknown id answers 404 folder_not_found before anything is billed.

flow_idstring

A flow to run on each take once it lands — one that starts « After a render » of audio (GET /v1/flows). Checked before anything is billed. See Flows.

GET/v1/music/generations/{id}

Poll one take until the MP3 is ready — free.

GET/v1/music/generations

List the workspace's song takes of the last 24 hours, newest first — free. Entries carry the title, never the lyrics: fetch a take by id for its recipe.

curl https://eroq.ai/v1/music/generations \
  -H "Authorization: Bearer $EROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "eroq-music-one",
  "style": "english, female vocals, synth-pop, 104 bpm, warm analog synths, gated drums",
  "lyrics": "[Verse]\nStreetlights fade behind the bus\nThe town I knew is shrinking fast\n\n[Chorus]\nI'\''m leaving, leaving, nothing left to prove\nThe road is long and I'\''m in love with the move",
  "title": "Leaving Light",
  "seconds": 120,
  "n": 2
}'
/v1/music/generations
→ POST /v1/music/generations
Press run — this replays a real exchange from the docs' own data. No key, no request, no charge.

Response

200 · application/json
{
  "id": "4d2a91c0-…",
  "object": "music.generation",
  "status": "processing",
  "created": 1760400000,
  "model": "eroq-music-one",
  "seconds": 120,
  "title": "Leaving Light",
  "style": "english, female vocals, synth-pop, 104 bpm, warm analog synths, gated drums",
  "lyrics": "[Verse]\nStreetlights fade behind the bus\n…",
  "instrumental": false,
  "jobs": [
    { "id": "4d2a91c0-…", "poll": "/v1/music/generations/4d2a91c0-…", "take": 1, "seed": 182736 },
    { "id": "9b07e3f1-…", "poll": "/v1/music/generations/9b07e3f1-…", "take": 2, "seed": 182737 }
  ],
  "usage": { "credits_spent": 24, "credits_remaining": 852 }
}