Skip to main content
GET
Get Task

Get Task

Retrieve the current status, input, and output of a previously created task. If the task is still in progress, sunor will live-poll the upstream provider and return the latest status.

Request

Path parameters

string
required
The task ID returned from the Create Task endpoint.

Headers

string
required
Your API key.

Response

number
HTTP status code (200 on success).
object
string
The unique task identifier.
string
The model used (e.g., "suno").
string
The task type ("music", "lyrics", "upload", or "concat").
string
Current task status. One of: "pending", "running", "success", "failure", "timeout".
number
Credits charged (or frozen) for this task.
object
The original input parameters submitted with the task.
string | null
The delivery format this task was created with — the value sent on the create request, or null if it was omitted. null means audio_url points at the provider’s own file, whose format is not fixed. See Audio format.
object | null
The task output. null while the task is still processing. Contains model-specific results on completion.
string | null
Human-readable message if the task failed. null otherwise. Prose — do not branch on it. It may be reworded at any time; branch on error_code.
string | null
Stable machine-readable classification of a failed task. null unless status is failure or timeout. One of content_moderation, invalid_task_input, rate_limited, upstream_provider_error — see Error Codes.
boolean | null
false means resending the same request is very unlikely to succeed — change the input, or surface it to a person. true means a later attempt may succeed; see Error Codes for which codes reverse on identical input and which need a wait first. null unless the task failed.
integer | null
Seconds to wait before retrying, when the provider states a concrete wait. null otherwise.
string
ISO 8601 timestamp of task creation.
string | null
ISO 8601 timestamp of task completion. null if not yet completed.

Status values

Audio URL lifetime

audio_url is valid for 7 days after the task completes. After that it returns 404 permanently. If you need the audio for longer, download and store it yourself.
Cover art (image_url, image_large_url) is served by the model provider and is not covered by this window.

Contract

The fields listed on this page are the response contract, and they hold across provider changes: every one of them has been present on every clip we have returned. output.result also carries additional fields from the upstream model provider. Those are passed through as-is. They are not part of the contract, they differ between providers, and they may appear or disappear without notice — build against the documented fields. That last clause is not hypothetical. Some of those fields exist on one provider and not at all on another: routing a request differently makes them vanish from every clip, with no other change on our side and no announcement. Two further things are worth knowing about them:
  • Where such a field lists alternate URLs for the same audio, and the clip’s own audio_url is one we serve, we remove any entry that still points at a provider’s own origin and remove the field entirely when no entry survives. What is left is served from our domain under the same retention as audio_url.
  • For any other clip that field is passed through untouched, provider origins included — a clip we could not store keeps upstream’s list verbatim, because editing a response we are not otherwise the source of would be worse than leaving it alone. Those URLs expire on the provider’s schedule, not ours, and some of them are streams a normal client cannot play. audio_url is the field to use; treat the alternates as informational at best.
If you have built on an undocumented field, treat it as something that can disappear between two consecutive requests.

Audio format

By default audio_url points at the file exactly as the provider produced it. That format is not fixed, and it has changed more than once. As of 2026-09-06 it is MP3, served with a .mp3 extension. Between 2026-08-29 and 2026-09-05 it was Opus in an MP4 container, served with an .m4a extension. It can change for two different reasons, and the second one is ours:
  1. The provider changes what it produces — that is what happened on both dates above.
  2. We route your request to a different provider. We run more than one, they do not all produce the same format, and we will move traffic between them to keep the service up. When that happens the default format changes with it, without notice and without any change on your side.
If your pipeline needs one specific format, pin it. Send audio_format: "mp3" when you create the task and audio_url will point at MP3 — we convert on our side when the source is something else, and skip the conversion when it is already MP3. Leaving the field out keeps today’s behaviour exactly: you get the provider’s own file, in whatever format that is. One case is worth knowing about. If the conversion fails we do not fail the task — you get our copy of the source file instead: our URL, our retention, the source format. A conversion that costs you the recording you paid for would be a bad trade for an optional convenience. The response still echoes back the audio_format you asked for, because that field records the request, not the outcome — so Content-Type remains the only reliable statement of what a file actually is. Every response carries it, and the paragraphs below explain why it is worth reading. Two more things follow, and both are worth building around rather than checking once:
  • Read the format from the response’s Content-Type. Not from the URL’s extension, and not from what the provider was serving the last time you looked. An .m4a extension in particular does not imply AAC.
  • Do not assume every container decodes on every platform. Apple’s CoreAudio — the API every iOS and macOS app sits on — cannot decode Opus in an MP4 container at all. If you target Apple platforms, branch on Content-Type and convert on your side when you receive something it cannot read.

Output format

The output field structure depends on the task type. All outputs share a common wrapper:
string
The task type ("music", "lyrics", "upload", or "concat").
string
Internal processing status: "queued", "processing", "completed", or "failed".
string | null
Processing progress (e.g., "50%", "100%").
string | null
Reason for failure, if any.
array | object | null
The task-specific result. Shape varies by task type (see below).

Output by task type

result is an array of clip objects. Each music generation typically returns one or more clip variations.

Example responses

Task in progress

200

Task completed (music)

200

Task failed

200

Polling strategy

Tasks typically take 30 seconds to 5 minutes to complete, depending on the task type and upstream provider load.
Poll the Get Task endpoint every 5-10 seconds until the status is "success", "failure", or "timeout". Avoid polling more frequently than once per second.

Polling example

Errors