Retrieve a job
November 14, 2026
Table of contents
Fetch a job by its jobid. POST /music and POST /music/stems return one. After an async request, or a sync one that answered 202, poll this endpoint until status is completed or failed.
Songs take 20 seconds to about 2 minutes and a stem split about 1.5 minutes, so polling every 10 seconds is enough. A job still running 30 minutes after it started fails with 504 when it is read. ACE Music may still finish it later, and a later read then shows it completed.
Every read asks ACE Music for the job’s songs, so links are always fresh: each song’s playUrl and the stem track links are read again. playUrl is a direct link to the same MP3 for players, valid until playUrlExpires (about an hour): some browsers (Brave) block the redirect behind audioUrl. Store audioUrl, play playUrl. Stem track links are valid for 24 hours from the read.
After the job ends, nothing of it is kept on our side: the record is rebuilt from the songs ACE Music keeps in the account’s Library. A song deleted since, with DELETE /music/songId or on acemusic.ai, is listed as { songId, taskId, status: "deleted" } with no links, and the job keeps its status from the song still there. A job none of whose songs ACE Music has any more answers 404, and any job answers 410 once it is older than 7 days.
Instead of polling, pass replyUrl (and optionally replyRef) with the POST: when the job completes or fails, the API sends one POST of this same job record, as JSON, to that URL. See Model.
https://api.useapi.net/v1/acemusic/jobs/
jobid
jobidis URL-encoded in the path (it contains:and@), for examplej1114201530412583907m-u1234-email%3Aexample%40example.com-task%3Aso_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot%3Aacemusic.
Request Headers
Authorization: Bearer {API token}
API tokenis required, see Setup useapi.net for details.
Responses
-
A song job (the songs are cut short here, see POST /music for full songs):
{ "jobid": "j1114201530412583907m-u1234-email:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot:acemusic", "type": "music", "status": "completed", "email": "[email protected]", "created": "2026-11-14T20:15:30.412Z", "model": "ace-step-1.5-xl", "modelUsed": "ace-step-1.5-xl", "songs": [ { "songId": "user:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7", "taskId": "so_3f9c2a7d81e64b05a9d2c4e7", "status": "succeeded", "title": "Farmers Market Sunshine", "model": "ace-step-1.5-xl", "duration": 135.02, "audioUrl": "https://acemusic.ai/data/so_3f9c2a7d81e64b05a9d2c4e7.mp3", "playUrl": "https://….r2.cloudflarestorage.com/acemusic-data-prod/users/…/audio/202611/….mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20261114T201722Z&X-Amz-Expires=3599&…", "playUrlExpires": "2026-11-14T21:17:21.000Z", "coverUrl": "https://acemusic.ai/data/so_3f9c2a7d81e64b05a9d2c4e7-cover.jpg?v=1794685678498", "kind": "original", "score": false }, { "songId": "user:[email protected]:so_b6e14d0c9a7f4382be51f0a3", "taskId": "so_b6e14d0c9a7f4382be51f0a3", "status": "succeeded", "title": "Farmers Market Sunshine", "model": "ace-step-1.5-xl", "duration": 135.02, "audioUrl": "https://acemusic.ai/data/so_b6e14d0c9a7f4382be51f0a3.mp3", "playUrl": "https://….r2.cloudflarestorage.com/acemusic-data-prod/users/…/audio/202611/….mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20261114T201723Z&X-Amz-Expires=3599&…", "playUrlExpires": "2026-11-14T21:17:22.000Z", "coverUrl": "https://acemusic.ai/data/so_b6e14d0c9a7f4382be51f0a3-cover.jpg?v=1794685679611", "kind": "original", "score": false } ], "completed": "2026-11-14T20:16:14.205Z" }The same job after its second song was deleted with DELETE /music/
songId:{ "jobid": "j1114201530412583907m-u1234-email:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot:acemusic", "type": "music", "status": "completed", "email": "[email protected]", "created": "2026-11-14T20:15:30.412Z", "model": "ace-step-1.5-xl", "modelUsed": "ace-step-1.5-xl", "songs": [ { "songId": "user:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7", "taskId": "so_3f9c2a7d81e64b05a9d2c4e7", "status": "succeeded", "title": "Farmers Market Sunshine", "audioUrl": "https://acemusic.ai/data/so_3f9c2a7d81e64b05a9d2c4e7.mp3", "playUrl": "https://….r2.cloudflarestorage.com/acemusic-data-prod/users/…/audio/202611/….mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20261114T201722Z&X-Amz-Expires=3599&…", "playUrlExpires": "2026-11-14T21:17:21.000Z" }, { "songId": "user:[email protected]:so_b6e14d0c9a7f4382be51f0a3", "taskId": "so_b6e14d0c9a7f4382be51f0a3", "status": "deleted" } ], "completed": "2026-11-14T20:16:14.205Z" }A stem split:
{ "jobid": "j1114203012775104298s-u1234-email:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7.0-bot:acemusic", "type": "stems", "status": "completed", "email": "[email protected]", "created": "2026-11-14T20:30:12.775Z", "stems": { "mode": "vocals", "songId": "user:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7", "tracks": [ { "type": "vocal", "url": "https://….r2.cloudflarestorage.com/acemusic-data-prod/users/…/stem/202611/…?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=86400&…", "duration": 135.02 }, { "type": "instrumental", "url": "https://….r2.cloudflarestorage.com/acemusic-data-prod/users/…/stem/202611/…?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=86400&…", "duration": 135.02 } ], "expires": "2026-11-15T20:31:40.508Z" }, "completed": "2026-11-14T20:31:39.143Z" }A job that is still running or that failed answers
200too: checkstatus, and for a failed jobcodeanderror. -
{ "error": "Path parameter jobid (not-a-job) is not a valid ACE Music job id", "code": 400 } -
Invalid API token.
{ "error": "useapi.net ⁝ Unauthorized", "code": 401 } -
The job belongs to another useapi.net user.
{ "error": "Not your job", "code": 403 } -
ACE Music has none of the job’s songs any more (deleted and then emptied from the trash on acemusic.ai), or the job’s account was removed.
{ "error": "Job j1114201530412583907m-u1234-email:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot:acemusic not found: ACE Music has none of its songs", "code": 404 }{ "error": "Account [email protected] is not configured: the job cannot be read", "code": 404 } -
The job is older than 7 days. Its songs are still in the account’s Library: read them with GET /music.
{ "error": "Job has expired: jobs can be read for 7 days", "code": 410 }
Model
The job record. POST /music and POST /music/stems return it too, and it is the body of the replyUrl webhook.
{ // TypeScript, all fields are optional
jobid: string // j<time><random><m|s>-u<id>-email:<email>-task:<song>.<song or 0|2>-bot:acemusic
type: 'music' | 'stems'
status: 'processing' | 'completed' | 'failed'
email: string // the ACE Music account the job runs on
created: string // ISO 8601
completed?: string // ISO 8601, when the job completed or failed
model?: string // music: the model you asked for
modelUsed?: string // music: the model that made the songs, see Model switching on POST /music
songs?: Song[] // music: the request's two songs, see Song below. A song deleted since, with
// DELETE /music/{songId} or on acemusic.ai, is only { songId, taskId, status: 'deleted' }
stems?: { // stems
mode: 'vocals' | 'all'
songId: string // the song that was split
songStatus?: 'deleted' // the song was deleted, its stems went with it (the job failed with code 404)
tracks: {
type: string // vocals: vocal, instrumental. all: vocals, backing_vocals, drums, bass, guitar,
// keyboard, strings, synth, woodwinds, fx (the stems ACE Music found)
url: string | null // signed mp3 link, valid 24 hours
duration?: number // seconds
}[]
expires?: string // ISO 8601, when the track links stop working (read the job again for fresh ones)
}
error?: string // status 'failed': why
code?: number // status 'failed': 400 | 422 | 504 | 404 | 596, see GET /jobs/{jobid}
replyUrl?: string
replyRef?: string
}
Song:
{ // TypeScript, all fields are optional
songId: string // user:<id>-<email>-song:so_… use it as a reference, to split, download or delete
taskId: string // ACE Music's own id of the song (so_…)
status: 'planning' | 'scoring' | 'queued' | 'running' | 'succeeded' | 'failed' | 'interrupted'
title: string | null
model: string | null // acemusic-v1 | acemusic-v1.1 | ace-step-1.5-xl, null for an uploaded file
style: string | null // the style the song was made with (ACE Music writes it for a prompt request)
lyrics: string | null // [verse] / [chorus] tagged
instrumental: boolean | null
duration: number | null // seconds
audioUrl: string | null // public mp3 link, https://acemusic.ai/data/<taskId>.mp3, once the song succeeded.
// It never changes: store this one. null for an uploaded file: get its audio with
// GET /music/download
playUrl?: string | null // the same mp3 as a direct link for players, valid until playUrlExpires (about an hour):
// some browsers (Brave) block the redirect behind audioUrl. Store audioUrl, play playUrl.
// For about a minute after the song is made it is audioUrl itself (ACE Music serves the
// file directly then). In job records and GET /music/{songId} only, not in GET /music or
// POST /files. null while the song is not finished, or when the link could not be read
playUrlExpires?: string | null // ISO 8601, when playUrl stops working: read the job or the song again for a fresh one
// an upload (kind 'upload'): no audioUrl; playUrl is its own audio, signed for 24 hours
coverUrl: string | null // cover art (jpg)
pageUrl: string | null // the song's page on acemusic.ai, when ACE Music made one
created: string | null // ISO 8601
finished: string | null // ISO 8601
kind: 'original' | 'cover' | 'mashup' | 'edit' | 'upload'
score: boolean // true when ACE Music already has the song's score (GET /music/score)
error?: { // a failed song
code?: string // ACE Music's code, e.g. ref_no_melody, song_not_made
message?: string
reason?: string
}
refunded?: boolean // ACE Music gave the credits back for a failed song
stems?: { // splits made with POST /music/stems
vocals?: { status?: string, tracks: { type?: string, url: string | null, duration?: number }[] }
all?: { status?: string, tracks: { type?: string, url: string | null, duration?: number }[] }
} // track links are signed (24 hours) on GET /music/{songId}, null elsewhere
upload?: { // an uploaded audio file (POST /files)
seconds?: number // its length, counted against the account's upload minutes
bpm?: number // the tempo ACE Music read
transcription?: string // done once ACE Music has read its lyrics, style and melody
}
}
status | Meaning |
|---|---|
processing | ACE Music is making the songs or the split. Every job starts here. |
completed | Done. A song job is completed when at least one of its two songs succeeded. A song that failed carries its own error, and a song deleted since shows status: "deleted". |
failed | Done without a result. error says why and code is the HTTP status. |
code | Meaning |
|---|---|
400 | ACE Music could not read the melody of a referenced song (ref_no_melody), usually an ACE-Step song with no score yet. Read its score with GET /music/score, then run the request again. The songs show refunded: true: ACE Music gave the credits back. |
404 | The account was removed with DELETE /accounts/email while the job ran, or a stem split’s song was deleted (its stems went with it, stems.songStatus is deleted). |
422 | ACE Music could not make the songs or the split, and error has ACE Music’s reason. A failed song shows refunded: true when ACE Music gave its credits back. |
504 | The job did not finish within 30 minutes. ACE Music may still finish it and has likely charged for it: read the job again later (it shows completed once ACE Music finished it) or look for its songs with GET /music before you run it again. |
596 | The account was signed out while the job ran: ACE Music refused the stored password. ACE Music may still finish the job. Update the password with POST /accounts, then read the job again. |
The replyUrl webhook is one POST with Content-Type: application/json and this record as the body, sent once when the job completes or fails (a 10-second timeout, no retries, redirects are not followed). Use replyRef to match the callback to your own records.
Examples
-
JOBID="j1114201530412583907m-u1234-email:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot:acemusic" curl -H "Authorization: Bearer …" \ "https://api.useapi.net/v1/acemusic/jobs/$(python3 -c "import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1],safe=''))" "$JOBID")" -
const token = "API token"; const jobid = "j1114201530412583907m-u1234-email:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot:acemusic"; const apiUrl = `https://api.useapi.net/v1/acemusic/jobs/${encodeURIComponent(jobid)}`; let job; do { await new Promise(resolve => setTimeout(resolve, 10000)); const response = await fetch(apiUrl, { headers: { "Authorization": `Bearer ${token}` } }); job = await response.json(); console.log(job.status); } while (job.status === "processing"); console.log("job", job); -
import requests, time, urllib.parse token = "API token" jobid = "j1114201530412583907m-u1234-email:[email protected]:so_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot:acemusic" apiUrl = "https://api.useapi.net/v1/acemusic/jobs/" + urllib.parse.quote(jobid, safe="") headers = {"Authorization": f"Bearer {token}"} while True: time.sleep(10) job = requests.get(apiUrl, headers=headers).json() print(job.get("status")) if job.get("status") != "processing": break print(job)
Try It
The songs or stem tracks play above the JSON once the job is completed.