# Lyria 3.5 (music) > Lyria 3.5 writes a full song from one text prompt. The prompt carries the style, the vocals, the lyrics and the section timestamps. Status: roasOS API v1.1. Catalog `model-catalog@2026-10-06.v5`, pricing `customer-pricing@2026-11-05.v15`. The endpoint `POST /v1/music/lyria-3.5` 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/lyria-3.5 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 song ad from one prompt. Write the genre, tempo, instruments, vocal style and the words to sing; the model writes and performs the song. Songs can be up to a few minutes long. The model sings in English, German, Spanish, French, Hindi, Japanese, Korean and Portuguese. The price is $0.10 per track, flat. There is no duration field, so the quote is exact and nothing reconciles. The endpoint states no fixed output length, so roasOS publishes none: read the length of the file the job returns. There is no separate lyrics field. Put the lyrics in `prompt`. The output can include a `lyrics` string, which is the words the model sang. 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: track. Pricing key: `lyria-3.5`. | request | credits | |---|---| | `per_track` | 2 | Credits come from the roasOS pricing table (`MODEL_COSTS`) through the catalog. No other field changes the price. ## Modes - `text-to-music` Provider endpoints: `google/lyria-3.5`. ## Request fields | field | type | required | default | rule | |---|---|---|---|---| | `image_url` | string | no | — | https URL; ≤ 4,096 characters | | `prompt` | string | yes | — | ≥ 1 character; ≤ 5,000 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 - `image_url` — first frame (or the single source image) | role | items | max size | content types | duration | |---|---|---|---|---| | `image_url` | ≤ 1 | 10 MB | `image/jpeg`, `image/png`, `image/webp` | — | - Refused: `avatar_id`, `elements`, `product_id`, `product_images`, `references`, `reference_images`, `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 the brief, not the adjective. Name the genre, the BPM, the instruments, the vocal style and the hook. To control the length and the structure, write a length ("a 30-second song") or section timestamps: "[0:00-0:10] Intro: soft piano. [0:10-0:25] Verse: 'Morning light on the kitchen floor'. [0:25-0:30] Chorus: 'Rise up and shine today'." Align the timestamps to the cuts of the ad when the song carries the whole soundtrack. `image_url` is mood inspiration, not a first frame: the model reads the feel of the picture, not its contents. ## Not exposed - `negative_prompt`: pinned to `provider-deprecated: fal states negative prompting is not supported`. ## Result Result kind `audio`. Always present: `url`. Present when the run produces it: `timestamps`. ```json { "data": { "id": "gen_…", "kind": "audio", "model": "lyria-3.5", "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/lyria-3.5 \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-lyria-3.5-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": 2, "expires_at": "…", "confirmation": { "model": "lyria-3.5", "example": "per_track" } } } # 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/lyria-3.5 \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-lyria-3.5-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": "lyria-3.5", "status": "queued", "credits_reserved": 2, "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/lyria-3.5`. It is live. ## See also https://docs.roasos.com/models/music/lyria-3.5 · https://api.roasos.com/v1/catalog/music/lyria-3.5 · google/lyria-3.5