# ElevenLabs Music (music) > ElevenLabs Music writes a track of the length you ask for, from one text prompt. It is the default model for an instrumental music bed. Status: roasOS API v1.1. Catalog `model-catalog@2026-10-06.v5`, pricing `customer-pricing@2026-11-05.v15`. The endpoint `POST /v1/music/elevenlabs-music` is live. `POST /v1/generations` has no `music` type, so this endpoint is the only path to this model. ## Endpoint POST https://api.roasos.com/v1/music/elevenlabs-music Auth: Authorization: Bearer roasos_sk_… (scope api:write). Idempotency-Key required. quote_only / quote_id / webhook_url as in https://docs.roasos.com/llms.txt. ## Good at Make a music bed that ends with the ad. Set `duration_seconds` to the length of the cut (3 to 600 seconds, whole seconds) and the track runs to that length. A 15-second ad gets a 15-second bed. `instrumental` is true by default, so the track has no vocals. Set it to false when the prompt asks for a voice. The price is $0.60 per started minute of output. The length is always sent, so a request for 15, 30 or 60 seconds costs one minute, and a request for 61 to 120 seconds costs two. When you do not send `duration_seconds`, roasOS sends 120 seconds and charges two minutes. It never lets the model pick a length with no limit. The output reports no duration, so the quote is exact and nothing reconciles. roasOS states no rights position on the music this model generates. Read the terms of the model and of fal before you publish a track. ## Pricing Unit: minute. Pricing key: `elevenlabs-music`. | request | credits | |---|---| | `15s` | 8 | | `30s` | 8 | | `60s` | 8 | | `90s` | 15 | | `120s` | 15 | Credits come from the roasOS pricing table (`MODEL_COSTS`) through the catalog. No other field changes the price. ## Modes - `text-to-music` Provider endpoints: `elevenlabs/music/v2.5`. ## Request fields | field | type | required | default | rule | |---|---|---|---|---| | `duration_seconds` | integer | no | `120` | 3–600 | | `instrumental` | boolean | no | `true` | — | | `prompt` | string | yes | — | ≥ 1 character; ≤ 4,100 characters | | `quote_id` | string | no | — | UUID | | `quote_only` | boolean | no | `false` | — | | `wait_timeout_seconds` | integer | no | `0` | 0–60 | | `webhook_url` | string | no | — | https URL; ≤ 4,096 characters | The schema is strict: a field that is not in this table returns `400 unsupported_option`. Field names are the roasOS role names, one name per role across every family. ## Media The endpoint accepts no media. Every media role below is refused. - Refused: `avatar_id`, `elements`, `product_id`, `product_images`, `references`, `reference_images`, `image_url`, `end_image_url`, `scene_id`, `scene_image`, `video_urls`, `video_url`, `audio_urls`, `audio_url`, `voice_id`. A refused role returns `400 unsupported_option`. - Every URL must be an immutable object on `https://cdn.roasos.com/…` that your workspace owns; any other URL is `400 reference_media_not_workspace_owned`. Upload with `POST /v1/uploads` (direct POST of the bytes to `put_url`, or a `source_url` import), then use the returned CDN URL. ## Prompt Write a short brief: the genre, the mood, the tempo in BPM, the lead instruments and the energy arc. Say what the track is for ("a background bed for a product ad, with room for a voice"), so the mix stays under the speech. Do not write the length in the prompt. `duration_seconds` sets it. Example: "Warm modern lo-fi bed for a skincare ad, 85 BPM, soft keys, light vinyl texture and a brushed kick; a steady groove that leaves room for a voice, a gentle build and a clean ending." ## Not exposed - `composition_plan`: not accepted by this public endpoint. - `seed`: not accepted by this public endpoint. - `output_format`: not accepted by this public endpoint. ## Result Result kind `audio`. Always present: `url`. Present when the run produces it: `timestamps`. ```json { "data": { "id": "gen_…", "kind": "audio", "model": "elevenlabs-music", "status": "completed", "result": {"timestamps":[{}],"url":"https://cdn.roasos.com/workspaces/ws_01/result"} } } ``` Files live on `https://cdn.roasos.com` and are immutable; a result URL can be a media input to the next call. Poll `GET /v1/jobs/{id}/status` → `{ id, status, updated_at }`, then `GET /v1/jobs/{id}/result` (`409 run_not_completed` until the job is `completed`, `failed` or `canceled`). Statuses: `queued → processing → completed | failed | canceled`. ## Example ```bash # 1. quote — nothing is spent curl -X POST https://api.roasos.com/v1/music/elevenlabs-music \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-elevenlabs-music-0001" \ -H "Content-Type: application/json" \ -d '{"quote_only":true,"prompt":"A woman holds the bottle at eye level in a bright kitchen, morning light, static camera."}' # → 200 { "data": { "kind": "quote", "quote_id": "q_7Hk…", "credits": 8, "expires_at": "…", "confirmation": { "model": "elevenlabs-music", "example": "15s" } } } # 2. run — the same body and the same Idempotency-Key, quote_id instead of quote_only curl -X POST https://api.roasos.com/v1/music/elevenlabs-music \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-elevenlabs-music-0001" \ -H "Content-Type: application/json" \ -d '{"quote_id":"q_7Hk…","prompt":"A woman holds the bottle at eye level in a bright kitchen, morning light, static camera."}' # → 201 { "data": { "id": "gen_…", "kind": "audio", "model": "elevenlabs-music", "status": "queued", "credits_reserved": 8, "links": { "status": "/v1/jobs/gen_…/status", "result": "/v1/jobs/gen_…/result" } } } # 3. poll curl https://api.roasos.com/v1/jobs/gen_…/status -H "Authorization: Bearer roasos_sk_live_…" curl https://api.roasos.com/v1/jobs/gen_…/result -H "Authorization: Bearer roasos_sk_live_…" ``` ## Today The endpoint is `POST /v1/music/elevenlabs-music`. It runs fal `elevenlabs/music/v2.5`. It is live. ## See also https://docs.roasos.com/models/music/elevenlabs-music · https://api.roasos.com/v1/catalog/music/elevenlabs-music · elevenlabs/music/v2.5