Legacy Suno Operation Reference
Legacy Suno overview · Task model
Shared music response
Section titled “Shared music response”/api/legacy/generate, /api/legacy/generate-gpt, and
/api/legacy/stems return an array. /api/legacy/concatenate and
/api/legacy/upload return one object.
{ "id": "019c...", "mid": "4fd8...", "taskId": "legacy-generation-id", "omnapiTaskId": "019d...", "pollUrl": "/api/v1/tasks/019d...", "url": "https://example.com/song.mp3", "video": "https://example.com/song.mp4", "cover": "https://example.com/cover.jpeg", "title": "Late Train", "tags": "city pop, warm bass", "prompt": "[Verse] ...", "mv": "v6", "duration": 123, "status": "submitted", "type": "generated", "concatBy": null, "syncedAt": "2026-07-15T08:00:01.000Z", "reGenId": null, "createdAt": "2026-07-15T08:00:00.000Z", "updatedAt": "2026-07-15T08:00:01.000Z"}The compatibility shape also contains older fields such as identity, uid,
payload, detail, and notes. Identity fields are empty or redacted; other
compatibility fields may be reconstructed from OmnAPI records. Do not introduce
new dependencies on those fields.
The request and response meanings of mv are intentionally different because
that is the compatibility wire contract. Request mv selects a model when
use_requested_model: true; response mv is only the clip’s exact major model
version (for example v6). It is never copied from the request or inferred
from an OmnAPI model code. When the clip has not reported a major version,
response mv is null.
Request validation
Section titled “Request validation”Legacy JSON DTO failures return HTTP 422. JSON booleans and numbers must use
their real JSON types; strings such as "true" and "42" are not coerced for
the covered generation DTOs. Unknown body properties do not change task
behavior.
The following legacy model values are accepted:
chirp-hawkchirp-hawk-wildchirp-goosechirp-auk-turbochirp-v4chirp-aukchirp-bluejaychirp-crowchirp-fenixOrdinary generation defaults to chirp-goose (v6-mini, 25 credits); Voice/Vox
defaults to chirp-hawk (v6 Pro, 28 credits). Customer discounts still apply.
Set use_requested_model: true to preserve an explicitly supplied supported
mv. This retains the existing legacy selection rule. All three v6 models
support the existing generation operations, subject to the required permission.
With use_requested_model: true, chirp-auk-turbo runs on chirp-goose;
chirp-v4, chirp-auk, chirp-bluejay, chirp-crow, and chirp-fenix run
on chirp-hawk. Hyphen and underscore spellings are accepted. Requested model
names keep their existing customer-specific pricing rules. When the flag is
false or omitted, the established default-selection rule still applies.
Default requests retain the old chirp-auk-turbo pricing identity (or
chirp-fenix for Vox), while execution uses chirp-goose (or chirp-hawk).
Unknown names and models already disabled before V6 return 422 before Task
creation or charging. A free-account model does not mean a free OmnAPI request.
An optional config extension is accepted on write requests:
{ "config": { "priority": 5, "webhookUrl": "https://example.com/webhooks/omnapi", "tags": [ "migration" ], "metadata": { "orderId": "ord_123" } }}On the compatibility surface, priority accepts a number or numeric string,
is rounded, and is clamped to 1–10. tags entries are converted to strings;
an empty webhookUrl is ignored; a non-object metadata becomes an empty
object. Prefer the canonical modern limits: priority 1–10, at most 20 tags of
100 characters each, an object for metadata, and a valid URI for webhookUrl.
Feature-specific modern Suno routes keep these values inside config. Generic
/api/v1/tasks and /api/v1/tasks/sync requests instead put priority,
tags, metadata, and webhookUrl at the request top level.
POST /api/legacy/generate
Section titled “POST /api/legacy/generate”Custom music generation and the four legacy derivative dispatch modes.
| Field | Type | Required | Limit and behavior |
|---|---|---|---|
prompt | string | Yes | Maximum 5,000 characters; an empty string remains valid |
title | string | Yes | Maximum 80 characters; an empty string remains valid |
tags | string | Yes | Maximum 1,000 characters; an empty string remains valid |
mv | string | No | Accepted model request; ordinary generation defaults to chirp-goose, while Vox defaults to chirp-hawk, unless opted in |
use_requested_model | boolean | No | When true, preserve the supported mv; Vox accepts all three V6 models and the chirp-crow / chirp-fenix aliases |
task | string | No | extend, upload_extend, cover, or vox |
continue_clip_id | string | Conditional | Required by extend and upload_extend; when task is omitted, this field infers extend |
continue_at | number | No | Non-negative continue point in seconds; string or negative numbers return 422. Absent/null is omitted for extend and becomes 0 for upload-extend |
cover_clip_id | string | Conditional | Required by cover; when task is omitted, this field infers cover |
persona_id | string | Conditional | Required by vox; when task is omitted, this field infers vox |
Explicit task must agree with the supplied resource field. When task is
omitted, exactly one cover_clip_id, continue_clip_id, or persona_id
selects cover, extend, or Voice music respectively. Combining these intent
fields, or pairing one with a conflicting explicit task, returns 422 before
task creation and credit deduction. upload_extend cannot be distinguished
from a normal extend by continue_clip_id, so it always requires explicit
task: "upload_extend".
Raw Suno clip and Voice IDs do not need a pre-existing OmnAPI resource row.
Resource permission and compatibility checks still apply, and an incompatible
resource can fail with SUNO_RESOURCE_ACCESS_DENIED.
The old DTO could admit a negative continue_at, but OmnAPI will not schedule
one. Normalize stored values to >= 0 before cutover.
Success
Section titled “Success”HTTP 201 with LegacyMusic[]. The call may wait up to 180 seconds for real
clip rows. Extend and upload-extend return their derivative candidates; the
compatibility route also concatenates candidate 0 in the same task and publishes
the full song as resource index 100. The standalone
POST /api/legacy/concatenate remains available for explicit concat
requests and migration compatibility.
For each new logical operation, set and save a fresh REQUEST_KEY once.
Reuse it with the exact same route and body only when recovering that operation.
Use a different saved key when trying a different example or export format.
export REQUEST_KEY="$(uuidgen)"curl -X POST https://api.omnapi.com/api/legacy/generate \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "[Verse]\nNeon rain on the station floor...", "title": "Late Train", "tags": "city pop, warm bass, female vocal", "mv": "chirp-hawk" }'Modern migration
Section titled “Modern migration”- Custom generation:
POST /api/v1/suno/songswithmode: "custom". - Voice generation:
POST /api/v1/suno/songswithmode: "vox", the owned Voice asvoiceId. - For new customer-owned audio, use
mode: "upload-extend"ormode: "upload-cover"and send the source URL inaudio.url. - Move existing-clip Extend and Cover to
POST /api/v1/suno/clips/{clipId}/derive. Modern Extend automatically publishes the concatenated full song in the same task. - Standalone Concatenate has no modern public endpoint. Keep only genuinely independent historical Concat calls on the compatibility API.
- Store the returned modern
taskId, then pollGET /api/v1/tasks/{taskId}.
POST /api/legacy/generate-gpt
Section titled “POST /api/legacy/generate-gpt”Simple prompt-to-song generation.
| Field | Type | Required | Limit and behavior |
|---|---|---|---|
gpt_description_prompt | string | Yes | Maximum 3,000 characters; an empty string remains valid |
make_instrumental | boolean | Yes | Must be a JSON boolean |
mv | string | No | Uses the legacy model-selection rule |
use_requested_model | boolean | No | Set true to preserve the supported mv instead of using chirp-goose |
Success is HTTP 201 with LegacyMusic[]; the real-clip wait budget is 180
seconds.
curl -X POST https://api.omnapi.com/api/legacy/generate-gpt \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{ "gpt_description_prompt": "uplifting synth pop about a red-eye flight", "make_instrumental": false }'Migrate to POST /api/v1/suno/songs with mode: "simple", map
gpt_description_prompt to prompt, and map make_instrumental to
instrumental.
POST /api/legacy/generate/lyric
Section titled “POST /api/legacy/generate/lyric”| Field | Type | Required | Limit and behavior |
|---|---|---|---|
prompt | string | Yes | Maximum 200 characters; an empty string remains valid |
lyrics_model | string | No | Validated for legacy compatibility but intentionally has no model-selection effect |
Success is HTTP 201 with a legacy lyrics object containing id, status,
text, title, createdAt, and optional tags. The route waits up to 30
seconds. A failed or timed-out task returns a structured error; it is not
converted into a successful object with empty lyrics. Its id and createdAt
come from the customer-owned OmnAPI resource row, not the external lyrics ID.
The request fields and response shape are unchanged after the provider lyrics
protocol migration. When style expansion succeeds, tags contains one full
style prompt string; if style expansion fails, tags is simply omitted and the
completed lyrics are still returned.
curl -X POST https://api.omnapi.com/api/legacy/generate/lyric \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{"prompt":"bittersweet indie pop about moving away"}'Migrate to POST /api/v1/suno/lyrics. The compatibility route accepts but
ignores lyrics_model; omit it for the equivalent modern single-candidate
request. The modern lyricsModel option is intended for paired candidates.
The modern API returns a task receipt and supports canonical polling.
POST /api/legacy/concatenate
Section titled “POST /api/legacy/concatenate”| Field | Type | Required | Behavior |
|---|---|---|---|
mid | string | Yes | Source extended clip ID |
The route accepts a raw Suno clip ID and applies resource compatibility checks.
Success is HTTP 201 with one LegacyMusic object. A fresh request may return
before terminal completion, so the returned status can still be submitted.
The legacy object’s taskId remains an empty string; use
the additive omnapiTaskId and pollUrl fields for canonical task tracking.
curl -X POST https://api.omnapi.com/api/legacy/concatenate \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{"mid":"clip_123"}'Concat is not exposed through either the modern resource API or the generic
Task API. Modern
POST /api/v1/suno/clips/{clipId}/derive with action: "extend" performs the
continuation and automatic Concat as one task and one charge; consume the
completed resource with role: "final".
If an old workflow independently concatenates an already-extended historical clip, keep that specific call on this compatibility endpoint until the workflow can be redesigned. Do not create a second Concat after a modern Extend.
GET /api/legacy/songs
Section titled “GET /api/legacy/songs”| Query | Type | Behavior |
|---|---|---|
ids | comma-separated string | Match compatibility resource-row IDs |
mids | comma-separated string | Match clip IDs |
take | integer string | Valid range 1–50; effective maximum 30; default 20 |
skip | non-negative integer string | Applied as the result offset; default 0 |
When both ids and mids are present, they are combined as an intersection.
Results are customer-isolated and sorted newest first. Duplicate clip IDs are
collapsed to the newest resource row. Legacy type is reconstructed from the
creating operation (concatenated, stemed, uploaded, or generated). With
no ID filters, the route returns recent music resources from the OmnAPI data
store; lookup-only rows are not promoted into creation history. While a task is
running, provider feed snapshots refresh the row’s queued/streaming state
and available media URLs; terminal sibling failures retain their own notes
and detail instead of inheriting only a task-level error.
curl "https://api.omnapi.com/api/legacy/songs?mids=clip_123,clip_456&take=20" \ -H "api-key: $OMNAPI_KEY"Success is HTTP 200 with LegacyMusic[].
Modern migration depends on the old query:
mids:GET /api/v1/suno/clips?clipIds=clip_123,clip_456.ids: there is no equivalent because compatibility row IDs are not clip IDs; migrate your stored references tomidoromnapiTaskIdfirst.- Recent listing: use
GET /api/v1/tasks?providerCode=suno, then read the task resources. The modern clip batch endpoint requires explicit clip IDs.
Long-running status synchronization
Section titled “Long-running status synchronization”Suno can acknowledge a generation quickly and leave its clips non-terminal for much longer. Treat these resource statuses as follows:
| Clip status | Meaning | Client action |
|---|---|---|
submitted | Accepted by Suno; usually changes in about 3–5 seconds | Keep polling; do not resubmit |
queued | Waiting for Suno capacity; usually changes in about 5–10 seconds | Keep polling; do not resubmit |
streaming | Media is being produced; commonly lasts at least 15 seconds | Keep polling; partial URLs are not a terminal guarantee |
complete | Terminal success | Persist the clip and media URLs |
error | Terminal Suno failure | Read notes/detail and the OmnAPI task error |
A generation can remain non-terminal for an extended period. Temporary missing results are not proof of failure. Use capped client-side backoff and keep the original task ID; see Task polling.
A compatibility POST may stop waiting before the Provider reaches a terminal
state. This is only a synchronous HTTP wait timeout; it does not cancel or fail
the durable task. Save omnapiTaskId and pollUrl, poll the canonical task,
and use /api/legacy/songs?mids=... when clip IDs are already known. Do not create a
replacement request with a new idempotency key. For application polling, add
jitter and follow the same increasing cadence instead of querying every second
for hours.
If the submission outcome cannot yet be confirmed, keep polling the original
task and contact support with its omnapiTaskId and X-Request-Id. A long
PROCESSING state is not permission to create a replacement request.
GET /api/legacy/songs/lyric-stamp
Section titled “GET /api/legacy/songs/lyric-stamp”Pass either mid (the clip ID) or id (the compatibility resource-row ID).
Any raw Suno mid can be queried. An internal compatibility resource-row id
is resolved only within the current OmnAPI customer, which prevents one
customer from using another customer’s internal ID.
curl "https://api.omnapi.com/api/legacy/songs/lyric-stamp?mid=clip_123" \ -H "api-key: $OMNAPI_KEY"Success is HTTP 200 with the aligned timeline object, including
aligned_lyrics, aligned_words, waveform_data, hoot_cer, and
is_streamed. The wait
budget is 30 seconds. Empty success bodies are not used for failures.
Migrate to GET /api/v1/suno/clips/{clipId}/timeline.
GET /api/legacy/info
Section titled “GET /api/legacy/info”Success is HTTP 200 with an OmnAPI credit-account view plus familiar aliases:
| Field | Meaning |
|---|---|
creditsLeft, leftCredits | Exact available OmnAPI credit balance |
currentUsage | Total used OmnAPI credits |
totalPurchased | Total purchased credits |
totalRefunded | Total refunded credits |
tier | Current account tier |
apiKeyId | Current OmnAPI API-key ID |
apikey | Empty compatibility field; the credential secret is never echoed |
openid | Empty compatibility field; internal customer IDs are not exposed |
packages | Empty compatibility array; package rows are not recreated |
expiredAt | null compatibility field |
usage | 0 compatibility alias |
requestMeta | { "type": "profile" } compatibility alias |
updatedAt | Credit-account update time |
The compatibility API never echoes the API-key secret.
curl https://api.omnapi.com/api/legacy/info \ -H "api-key: $OMNAPI_KEY"There is no exact modern package-object replacement. Use the dashboard for the
current balance, GET /api/v1/usage/export for automated usage reports, and
each task descriptor’s creditsRequired, creditsCharged, and refunded
fields for request-level reconciliation.
POST /api/legacy/upload
Section titled “POST /api/legacy/upload”Import a remote audio URL into Suno.
| Field | Type | Required | Behavior |
|---|---|---|---|
url | string | Yes | Publicly reachable audio URL |
type | string | Yes | file_upload or audio_recording |
extensionType | string | Yes | mp3 or wav |
Success is HTTP 201 with one uploaded LegacyMusic object owned by the
current customer. The route waits up to 30 seconds for the upload task to
complete. Validation failures return 422; a failed or timed-out task returns
the standard compatibility error envelope with task recovery details.
curl -X POST https://api.omnapi.com/api/legacy/upload \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/source.mp3", "type": "file_upload", "extensionType": "mp3" }'There is no standalone Upload operation in the modern public API. Migrate the
business operation as one request: use POST /api/v1/suno/songs with
mode: "upload-extend" or mode: "upload-cover" and place this source URL in
audio.url. The combined operation returns one task receipt for canonical
polling and one model-specific quote: 28 standard credits when model is omitted, or 25 when explicitly selecting
chirp-goose. Customer pricing applies; check the create receipt.
POST /api/legacy/stems
Section titled “POST /api/legacy/stems”Body: { "mid": "clip_123" }. The route accepts a raw Suno clip ID and defers
source existence, completion, and permission checks to the generation service.
Success is HTTP 201 with LegacyMusic[]. The compatibility operation creates
Twelve stems by default and retains the old type: "stemed" spelling. It
waits up to 180 seconds for real music resources. Each
legacy object’s taskId remains an empty string; use its additive
omnapiTaskId and pollUrl fields for canonical task tracking.
curl -X POST https://api.omnapi.com/api/legacy/stems \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{"mid":"clip_123"}'Omitting stem_task (or sending "twelve") creates Twelve stems. Named
extraction accepts the same 98 exact stemName values listed in the modern
Suno Stems guide, using the legacy stem_name key:
{ "mid": "clip_123", "stem_task": "extract", "stem_name": "Lead Vocal"}stem_task: "two" is no longer supported and returns 422. Migrate the
default form to POST /api/v1/suno/clips/{clipId}/export with:
{ "format": "stems", "stemsMode": "twelve"}OmnAPI manages durable delivery for both forms. Twelve is billed at 140 credits and named Extract at 56 credits; storage or delivery recovery does not add a second customer charge.
Reuse the same Idempotency-Key when a transport retry must not create or
charge another task.
POST /api/legacy/generate-wav
Section titled “POST /api/legacy/generate-wav”Body: { "mid": "clip_123" }. The route accepts a raw Suno clip ID and defers
source existence, completion, and permission checks to the generation service.
Delivery is managed by OmnAPI and does not expose its internal processing
stages.
Success is HTTP 201 with a non-null WAV URL:
{ "url": "https://example.com/song.wav"}The wait budget is 45 seconds. A completed task without a WAV URL is a
structured 502 error; the route no longer returns { "url": null } as a
successful export.
A 504 after this wait does not mean that WAV conversion was rejected. It
means OmnAPI already created and charged the export task, but the URL was not
materialized within 45 seconds. The conversion continues asynchronously. Read
the returned taskId/pollUrl until terminal, or replay the exact legacy route,
body, and Idempotency-Key to recover the original task. Do not submit another
export with a new key, and do not fail over this in-flight write to the modern
route.
curl -X POST https://api.omnapi.com/api/legacy/generate-wav \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{"mid":"clip_123"}'Migrate to the modern export endpoint; OmnAPI manages delivery automatically:
curl -X POST https://api.omnapi.com/api/v1/suno/clips/clip_123/export \ -H "x-api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{ "format": "wav" }'WAV export authorizes and settles at 3 standard credits. WAV delivery preserves the requested original clip. Read returned URL and retention fields; see Asset storage.