Skip to content

Legacy Suno Operation Reference

Legacy Suno overview · Task model

/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.

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-hawk
chirp-hawk-wild
chirp-goose
chirp-auk-turbo
chirp-v4
chirp-auk
chirp-bluejay
chirp-crow
chirp-fenix

Ordinary 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.

Custom music generation and the four legacy derivative dispatch modes.

FieldTypeRequiredLimit and behavior
promptstringYesMaximum 5,000 characters; an empty string remains valid
titlestringYesMaximum 80 characters; an empty string remains valid
tagsstringYesMaximum 1,000 characters; an empty string remains valid
mvstringNoAccepted model request; ordinary generation defaults to chirp-goose, while Vox defaults to chirp-hawk, unless opted in
use_requested_modelbooleanNoWhen true, preserve the supported mv; Vox accepts all three V6 models and the chirp-crow / chirp-fenix aliases
taskstringNoextend, upload_extend, cover, or vox
continue_clip_idstringConditionalRequired by extend and upload_extend; when task is omitted, this field infers extend
continue_atnumberNoNon-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_idstringConditionalRequired by cover; when task is omitted, this field infers cover
persona_idstringConditionalRequired 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.

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.

Terminal window
export REQUEST_KEY="$(uuidgen)"
Terminal window
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"
}'
  • Custom generation: POST /api/v1/suno/songs with mode: "custom".
  • Voice generation: POST /api/v1/suno/songs with mode: "vox", the owned Voice as voiceId.
  • For new customer-owned audio, use mode: "upload-extend" or mode: "upload-cover" and send the source URL in audio.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 poll GET /api/v1/tasks/{taskId}.

Simple prompt-to-song generation.

FieldTypeRequiredLimit and behavior
gpt_description_promptstringYesMaximum 3,000 characters; an empty string remains valid
make_instrumentalbooleanYesMust be a JSON boolean
mvstringNoUses the legacy model-selection rule
use_requested_modelbooleanNoSet 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.

Terminal window
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.

FieldTypeRequiredLimit and behavior
promptstringYesMaximum 200 characters; an empty string remains valid
lyrics_modelstringNoValidated 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.

Terminal window
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.

FieldTypeRequiredBehavior
midstringYesSource 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.

Terminal window
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.

QueryTypeBehavior
idscomma-separated stringMatch compatibility resource-row IDs
midscomma-separated stringMatch clip IDs
takeinteger stringValid range 1–50; effective maximum 30; default 20
skipnon-negative integer stringApplied 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.

Terminal window
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 to mid or omnapiTaskId first.
  • Recent listing: use GET /api/v1/tasks?providerCode=suno, then read the task resources. The modern clip batch endpoint requires explicit clip IDs.

Suno can acknowledge a generation quickly and leave its clips non-terminal for much longer. Treat these resource statuses as follows:

Clip statusMeaningClient action
submittedAccepted by Suno; usually changes in about 3–5 secondsKeep polling; do not resubmit
queuedWaiting for Suno capacity; usually changes in about 5–10 secondsKeep polling; do not resubmit
streamingMedia is being produced; commonly lasts at least 15 secondsKeep polling; partial URLs are not a terminal guarantee
completeTerminal successPersist the clip and media URLs
errorTerminal Suno failureRead 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.

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.

Terminal window
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.

Success is HTTP 200 with an OmnAPI credit-account view plus familiar aliases:

FieldMeaning
creditsLeft, leftCreditsExact available OmnAPI credit balance
currentUsageTotal used OmnAPI credits
totalPurchasedTotal purchased credits
totalRefundedTotal refunded credits
tierCurrent account tier
apiKeyIdCurrent OmnAPI API-key ID
apikeyEmpty compatibility field; the credential secret is never echoed
openidEmpty compatibility field; internal customer IDs are not exposed
packagesEmpty compatibility array; package rows are not recreated
expiredAtnull compatibility field
usage0 compatibility alias
requestMeta{ "type": "profile" } compatibility alias
updatedAtCredit-account update time

The compatibility API never echoes the API-key secret.

Terminal window
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.

Import a remote audio URL into Suno.

FieldTypeRequiredBehavior
urlstringYesPublicly reachable audio URL
typestringYesfile_upload or audio_recording
extensionTypestringYesmp3 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.

Terminal window
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.

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.

Terminal window
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.

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.

Terminal window
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:

Terminal window
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.