Suno Cloud v1 Migration Guide
This guide is the public contract and migration runbook for existing Suno Cloud
clients. OmnAPI exposes ten compatibility endpoints under the dedicated
/api/legacy namespace. Migrating from Suno Cloud therefore requires
changing the host, credential value, and path prefix.
Compatibility status
Section titled “Compatibility status”All ten covered routes are implemented. Request names, the main success
shapes, real clip IDs, and the live service’s 200/201 success status rules
are preserved. Differences that protect account isolation, use OmnAPI credits,
or reflect the OmnAPI task model are listed in Deliberate differences.
| Method | Compatibility path | Supported purpose | Modern destination |
|---|---|---|---|
POST | /api/legacy/generate | Custom, extend, upload-extend, cover, or Voice music | POST /api/v1/suno/songs for roots/uploads; POST /api/v1/suno/clips/{clipId}/derive for existing-clip Extend/Cover |
POST | /api/legacy/generate-gpt | Simple prompt-to-song generation | POST /api/v1/suno/songs with mode: "simple" |
POST | /api/legacy/generate/lyric | Lyrics generation | POST /api/v1/suno/lyrics |
POST | /api/legacy/concatenate | Concatenate an existing extended clip | No independent modern endpoint; modern Extend includes automatic Concat |
GET | /api/legacy/songs | Compatibility resource lookup and recent results | Clip lookup or task history, depending on the query |
GET | /api/legacy/songs/lyric-stamp | Aligned lyrics timeline | GET /api/v1/suno/clips/{clipId}/timeline |
GET | /api/legacy/info | Compatibility credit-account view | Dashboard and usage export |
POST | /api/legacy/upload | Import a remote MP3 or WAV URL | Combine the source URL with mode: "upload-extend" or mode: "upload-cover" on POST /api/v1/suno/songs |
POST | /api/legacy/stems | Twelve or named stem export | POST /api/v1/suno/clips/{clipId}/export |
POST | /api/legacy/generate-wav | WAV export | POST /api/v1/suno/clips/{clipId}/export with format: "wav" |
Every other Suno Cloud path is outside this compatibility contract. The old
root-level /v1/* routes are not mounted on OmnAPI.
Base URL and authentication
Section titled “Base URL and authentication”https://api.omnapi.comThe canonical compatibility base path is /api/legacy. For example, Suno Cloud
POST /v1/generate becomes OmnAPI
POST /api/legacy/generate. The previously published
/v1/suno-legacy/* namespace and old root paths such as /v1/generate return
404.
Both header names are accepted:
api-key: YOUR_OMNAPI_KEYx-api-key: YOUR_OMNAPI_KEYThe header name can remain unchanged during phase one, but the credential value cannot. Create a new OmnAPI API key in the dashboard; existing Suno Cloud key values are not portable. Grant these scopes as needed:
| Scope | Used by |
|---|---|
task:create | The seven POST endpoints |
task:read | /api/legacy/songs and /api/legacy/songs/lyric-stamp |
usage:read | /api/legacy/info |
All seven write routes accept Idempotency-Key, including the zero-credit lyrics
task. Reuse the same key only when retrying the same logical request with an
unchanged body. Deduplication is scoped to the customer and exact compatibility
route; it does not span a different /api/legacy route, a modern
/api/v1 route, or the old Suno Cloud host.
curl https://api.omnapi.com/api/legacy/info \ -H "api-key: $OMNAPI_KEY"Compatibility responses include:
Deprecation: @1784073600Link: <https://docs.omnapi.com/legacy/suno/>; rel="deprecation"; type="text/html"The Deprecation value is an RFC 9745 Structured Field Date: it marks the
compatibility surface as deprecated from 2026-07-15T00:00:00Z. It is not the
retirement date. If a retirement date is scheduled, the response also carries
a Sunset header; treat that value as authoritative.
ID dictionary
Section titled “ID dictionary”Do not treat every field containing “id” as interchangeable.
| Field | Meaning | Safe use |
|---|---|---|
id | Compatibility resource-row ID in the OmnAPI data store | /api/legacy/songs?ids=... for resources created through OmnAPI |
mid | Real Suno clip ID | Follow-up clip operations and /api/legacy/songs?mids=... |
taskId | Legacy generation-operation identifier when available | Preserve only for old client compatibility; do not use it to poll OmnAPI |
omnapiTaskId | Stable OmnAPI task UUID added to music responses | GET /api/v1/tasks/{omnapiTaskId} |
pollUrl | Ready-to-use canonical task URL | Poll task state and recover after a wait timeout |
Generation endpoints wait for a real music resource. They do not fabricate an
id or mid from a task UUID. When a real clip cannot be acknowledged within
the compatibility wait window, the request returns an error with task recovery
details instead of a placeholder song.
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": "v4.5-all", "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 Suno Cloud 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 v4.5-all). 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-auk-turbochirp-v4chirp-aukchirp-bluejaychirp-crowchirp-fenixBy default, the compatibility API sends ordinary generation to
chirp-auk-turbo, the v4.5-all/full standard lane, and Voice/Vox generation to
chirp-fenix, the compatible v5.5 lane. When
use_requested_model: true is supplied as a JSON boolean, the requested
supported mv is preserved instead. The compatibility API keeps that exact
selection rule. Malformed model values, or a non-boolean opt-in value, return
422. An explicitly selected Vox model must be chirp-crow or chirp-fenix;
pre-v5 combinations return 400 before task creation or charging.
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.
Modern field and response mapping
Section titled “Modern field and response mapping”| Legacy operation or mode | Modern request mapping |
|---|---|
| GPT generation | Suno songs body: mode: "simple"; gpt_description_prompt → prompt; make_instrumental → instrumental; effective legacy model → model |
| Custom generation | Suno songs body: mode: "custom"; legacy prompt → lyrics (or modern prompt); title/tags keep their names; effective legacy model → model |
| Voice generation | Suno songs body: mode: "vox" plus voiceId; copy prompt, title, and tags |
| Extend or cover of an existing clip | POST /api/v1/suno/clips/{clipId}/derive with action: "extend" or action: "cover" |
| Upload-extend | For a customer-owned audio URL, use Suno songs body mode: "upload-extend" with audio.url, plus prompt, title, tags, and continueAt |
| Upload-cover | For a customer-owned audio URL, use Suno songs body mode: "upload-cover" with audio.url, plus prompt, title, and tags |
| Lyrics | Suno lyrics body uses prompt; omit legacy lyrics_model for equivalent single-candidate behavior |
| Managed M4A or MP3 | POST /api/v1/suno/clips/{clipId}/export with format: "m4a" or format: "mp3"; poll the returned Task instead of relying on historical direct media URLs |
| Stems | Path clip ID = mid; stems defaults to Twelve and maps stem_task=extract plus any of the 98 native Suno stem_name values |
| WAV | POST /api/v1/suno/clips/{clipId}/export with format: "wav" |
“Effective legacy model” is chirp-auk-turbo for ordinary generation and
chirp-fenix for Vox unless use_requested_model: true explicitly opts into
the supplied supported mv. Vox opt-in accepts only chirp-crow or
chirp-fenix.
Modern requests preserve the selected supported model directly. The effective
legacy default chirp-auk-turbo costs 25 standard credits; other published
models cost 28. suno/chirp-v3-5 is retired for new requests.
Modern write routes return HTTP 200 with a CreateTaskResponse task receipt;
poll its taskId. The generic sync route returns SyncTaskResponse with HTTP
200 at terminal state or 202 on timeout. Modern clip reads also return the
OmnAPI task/result envelope. They do not return the raw legacy music object.
The compatibility API permits some empty required strings because the live DTO
did; modern simple/custom routes require meaningful generation text. Normalize
empty prompts before phase-two migration.
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-auk-turbo, while Vox defaults to chirp-fenix, unless opted in |
use_requested_model | boolean | No | When true, preserve the supported mv; Vox accepts only chirp-crow or chirp-fenix |
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.
curl -X POST https://api.omnapi.com/api/legacy/generate \ -H "api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: order-123-generate" \ -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-fenix" }'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-auk-turbo |
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: order-124-generate" \ -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: order-125-lyrics" \ -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.
As in suno-cloud, 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: order-126-concat" \ -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 |
The compatibility Worker polls near the observed fast path—approximately 3
seconds for submitted, 5 seconds for queued, and 15 seconds for
streaming—then backs off for old tasks through 30-second, 2-minute, 5-minute,
and 15-minute tiers. The hard observation window is 48 hours from the Provider
acknowledgement, not from the start of an API queue delay. Temporary empty feed
responses or temporarily missing sibling clips are not treated as 404 or
terminal failure before that deadline.
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.
There is one safety-first acknowledgement-loss case. If OmnAPI started the
Suno submission but did not receive a definitive response, the task remains
PROCESSING. An internal
PROVIDER_SUBMISSION_OUTCOME_UNKNOWN diagnostic is retained for support, but
the public Suno and compatibility responses do not present it as a terminal
failure. OmnAPI deliberately does not submit the request again because Suno
may already have created and charged for the clips. Keep polling the original
task and contact support with its omnapiTaskId; support can reconcile a
confirmed Suno clip ID. If no creation can be confirmed, the 48-hour
observation deadline is followed by a 24-hour reconciliation grace before the
final failure/refund safety net (about 72 hours from the submission boundary).
Never switch to a new idempotency key for this task.
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: order-127-upload" \ -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: 25 credits for the default Turbo model or
28 for another published model.
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. As in suno-cloud, 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: order-127-stems" \ -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: order-128-wav" \ -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: order-128-wav-modern" \ -H "Content-Type: application/json" \ -d '{ "format": "wav" }'WAV export authorizes and settles at 3 standard credits. Existing/native output is preferred; eligible remixable clips are rehomed automatically when direct delivery is unavailable—including missing subscription entitlement, an explicit insufficient-balance rejection, or an exhausted WAV allowance—without adding a second customer charge. Replacement accounts require a positive live balance; a definitive insufficient-balance rejection before derivative acceptance safely rotates to another eligible account.
Credits and settlement
Section titled “Credits and settlement”Suno Cloud package deductions are not reproduced. OmnAPI deducts the quoted
credits atomically when a task is created and records settlement in the task
and credit ledger. Eligible failed tasks and cancellations that were safely
completed before submission or explicitly confirmed by the Provider are
refunded. A post-submit 409 means the task remains active and was not
refunded; keep polling it.
Current standard prices are:
| Operation | Standard OmnAPI credits |
|---|---|
Song generation explicitly using chirp-auk-turbo, including Upload + Extend / Cover | 25 |
| Song generation with another published model, including every Vox request | 28 |
| Existing-clip Extend (automatic Concat included) / Cover | 28 |
| WAV managed delivery | 3 |
| Modern verified public Voice creation | 66 |
| Compatibility audio upload | 5 |
| Twelve-stem export | 140 |
| Named stem extract | 56 |
| Compatibility concatenate | 5 |
| Lyrics generation | 0 |
| Lyrics timeline read | 1; 0 for the legacy Suno 55,000 plan |
Legacy-customer Suno pricing is universal across every paid Suno operation,
including generation, Extend/Cover, WAV, Stems, timeline, and Voice—not only
song generation. The legacy Suno 55,000 plan has one explicit exception:
timeline reads cost 0 while its other 10/11 pricing remains unchanged. Variable
actual settlement and refunds reuse the same frozen customer rate. Treat
creditsRequired on the task receipt and
creditsCharged/refunded on the terminal task as authoritative. See
Credits & Billing.
Error and retry contract
Section titled “Error and retry contract”Compatibility errors use the OmnAPI envelope:
{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "title must be a string" }}| HTTP | Typical meaning | Retry guidance |
|---|---|---|
400 | Valid JSON but an unsupported operation combination | Correct the request |
401 | Missing, invalid, disabled, or expired OmnAPI key | Replace or enable the key |
402 | Insufficient OmnAPI credits; no task was created | Add credits, then retry the unchanged request with the same idempotency key |
403 | API-key scope or IP policy rejected the request | Correct the key scope or IP policy |
404 | Referenced target does not exist or lacks current-customer creation provenance | Do not blind-retry or probe other customer resources |
406 | Stems/WAV source exists but is not complete | Wait for the source task to complete, then retry the unchanged request and key |
409 | Key/body mismatch, concurrent request, or a task was already created | Different body: use a new key. No taskId: back off and retry the same key; if it remains unbound for 15 minutes, contact support rather than changing keys. With taskId: poll that task and do not resubmit |
422 | Legacy DTO type, length, enum, or required-field failure | Correct the request |
429 | Request limit reached | Back off using the response headers |
502 | Task completed without the required compatibility resource | Read task details before deciding to retry |
503 | Service capacity is temporarily unavailable before execution | Back off with the same host, route, body, and idempotency key; if the error includes a task ID, poll it instead of resubmitting |
504 | Compatibility wait expired after a task was created | Poll the pollUrl. For a write request, retry only the original host and route with the same key; a same-key replay returns 409 with the original taskId. The timeline GET has no idempotency key and should use its returned task recovery details |
5xx | Service failure | Before task creation, retry with backoff and the same key. If details contain taskId, poll it and never switch keys |
For the seven write routes, an idempotency claim is released when validation,
ownership, or credit checks fail before a task exists. Task creation now binds
COMMITTED + taskId in the same PostgreSQL transaction as the charge, Task,
credit ledger, and durable dispatch row; the same binding rule applies to every
created task, paid or zero-credit. A lost database response, or a later
compatibility wait/mapping 500/502/504, therefore cannot leave a newly
created task unbound or make a same-route retry create a second task.
For a multi-stage legacy operation, a same-key retry returns the latest durable task associated with that request.
An old claim with no visible taskId is still not automatically discarded.
It can be a pre-atomic-binding migration row or a request that stopped before
task creation; support must compare Task, credit ledger, request hash, and logs
before repairing or releasing it. Clients should keep the original key and
contact support after 15 minutes rather than switching keys. This preserves old
customers’ financial history while new writes use the atomic path.
There is no shared idempotency namespace across the compatibility API, the modern API, and the old host. After an uncertain write, poll the returned task details or replay the exact original host, path, key, and body. Never fail over an individual in-flight write between surfaces; move only cohorts whose prior writes are known to be settled or absent.
Deliberate differences
Section titled “Deliberate differences”These differences are part of the public contract and will not be changed to copy unsafe or incompatible legacy behavior.
| Area | Suno Cloud behavior | OmnAPI compatibility behavior |
|---|---|---|
| Credential | Existing Suno Cloud key value | New OmnAPI key value; either header name is accepted |
| Authentication errors | Commonly 403 | 401 for key authentication; 403 only for key scope or IP policy |
| Insufficient balance | Commonly 403 | 402 |
| Billing | Package-based deduction after generation | Atomic create-time deduction with terminal settlement and eligible refund |
| Long-tail status | Frequent legacy feed sync could still leave tasks stale or expire with process-local state | Durable PostgreSQL task state, adaptive polling, 48-hour Provider-acknowledged observation window, and restart/multi-node recovery |
| Submission acknowledgement loss | A process retry could repeat a non-idempotent Suno write | Automatic replay stops at the durable submission boundary; reconcile the original task or wait through the 48-hour observation window plus 24-hour reconciliation grace instead of creating a replacement |
| Resource access | Some follow-up operations accepted unrelated internal resource IDs | Raw Suno IDs are resolved against resource permission rules; OmnAPI data remains customer-isolated |
| History | MySQL song rows and physical IDs | Only OmnAPI task/resource history is queryable |
| Old resources | A known old clip or Voice ID could be routed by legacy runtime state | Raw Suno clip and Voice IDs are accepted without a matching OmnAPI row; resource compatibility checks still apply |
| Query provenance | A clip returned by a lookup could later be reused as a source | Only create/upload and other operations that generate a new owned resource — including generative derive, concatenate, edits/remaster, Voice creation, and stems — establish provenance. Query, timeline, WAV, and other read-only/conversion results do not |
| Model validation | Malformed mv values could be rewritten to fenix | Supported legacy values normalize as documented; malformed values return 422 |
| Model selection | Legacy clients could request several model names | Defaults to v4.5-all/full; use_requested_model: true preserves a supported requested model |
Response mv | Suno clip major_model_version | Same exact major-version value; null when unavailable, with no fallback to the request model |
| Songs pagination | skip could be validated and then ignored | skip is applied so pages do not repeat the same rows |
| Timeline shape | Some responses included both aligned lines and words | Returns both aligned_lyrics and aligned_words |
| Continue position | A negative continue_at could pass the old DTO | Values must be finite and >= 0; normalize legacy data before migration |
| Legacy identity fields | Identity fields could be populated | identity, uid, openid, and comparable compatibility identifiers are empty or redacted |
| Lyrics timeout | Could return running without a public recovery route | Returns an error with canonical task recovery details |
| Timeline failure | Could return HTTP 200 with an empty body | Returns a structured error |
| WAV failure | Could be surfaced as an empty or unavailable URL | A successful response always contains a URL |
/api/legacy/info | Package rows and internal legacy data | OmnAPI credit-account view; package rows and key secrets are not recreated |
| Error body | Nest-era error shape | OmnAPI { success, error } envelope |
Two-phase migration plan
Section titled “Two-phase migration plan”Phase 0 — inventory and data ownership
Section titled “Phase 0 — inventory and data ownership”- Inventory calls to the exact ten covered paths. Route every other path to a product redesign instead of assuming compatibility.
- Record which stored values are resource
id, clipmid, legacytaskId, or business IDs. - Split historical clips from clips that will be created after the cutover. Historical Suno Cloud rows are not copied automatically.
- Identify workflows that use an old clip for extend, upload-extend, cover, concatenate, stems, WAV, or lyric timeline, plus workflows that reuse an old Voice. Keep them on the old service until the corresponding creation provenance is migrated to the correct OmnAPI customer, or arrange a managed migration with support.
- A successful lookup through the compatibility or modern query endpoints is not a provenance backfill. Importing history must create customer-scoped task/resource records with the correct original operation; never grant ownership merely because a client supplied a clip ID.
Phase 1 — host and credential cutover
Section titled “Phase 1 — host and credential cutover”- Create an OmnAPI account, fund credits, and issue a scoped OmnAPI API key.
- Change the base host to
https://api.omnapi.com, replace the key value, and use the exact/api/legacyprefix. The previously published/v1/suno-legacy/*is not supported. Root/v1/*paths are not supported. The oldapi-keyheader name can remain during this phase. - Add a unique
Idempotency-Keyto every write request. - Persist
mid,omnapiTaskId, andpollUrlfrom new responses. Stop usingtaskIdas a canonical poll key. - Send canary traffic for each write operation. Compare HTTP status, array vs object shape, clip count, non-null media URLs, and terminal task settlement.
- During the history transition, route a request according to where its source clip was created: old clips to the old service, OmnAPI clips to OmnAPI.
Phase 2 — modern API migration
Section titled “Phase 2 — modern API migration”- Move simple/custom music to
/api/v1/suno/songs. - Move extend/cover to
/api/v1/suno/clips/{clipId}/derive. - Move timeline and exports to clip resource endpoints.
- Replace
midslookup with/api/v1/suno/clips?clipIds=...; replace recent compatibility history with task listing. - Let modern Extend perform automatic Concat. Keep independent historical Concat calls on the compatibility route until they can be removed.
- Replace
/api/legacy/inforeporting with dashboard balance, usage export, and task settlement fields. - Remove dependencies on compatibility-only fields, then switch the header to
x-api-keyand remove/api/legacycode paths.
Canary, rollback, and acceptance checks
Section titled “Canary, rollback, and acceptance checks”Before raising traffic, verify all of the following:
- Both generated clip
midvalues can be looked up and downloaded. omnapiTaskIdreaches a terminal state and matches the compatibility result.- Required credits and final charged/refunded credits reconcile.
- Retries with the same idempotency key do not create duplicate tasks, including zero-credit lyrics tasks.
idsandmidsare not mixed in application storage.- Historical clip derivatives follow the intended old/new routing rule.
- Error handling covers
401,402,403,404,406,409,422,429,502,503, and504.
Keep rollback configuration-based: retain the old host and key separately, and route only historical or failing cohorts back. Never send an OmnAPI key to the old host or a Suno Cloud key to OmnAPI.