Retrieve a job

November 14, 2026

Table of contents

  1. Request Headers
  2. Responses
  3. Model
  4. Examples
  5. Try It

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

  • jobid is URL-encoded in the path (it contains : and @), for example j1114201530412583907m-u1234-email%3Aexample%40example.com-task%3Aso_3f9c2a7d81e64b05a9d2c4e7.so_b6e14d0c9a7f4382be51f0a3-bot%3Aacemusic.
Request Headers
Authorization: Bearer {API token}
Responses
  • 200 OK

    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 200 too: check status, and for a failed job code and error.

  • 400 Bad Request

    {
      "error": "Path parameter jobid (not-a-job) is not a valid ACE Music job id",
      "code": 400
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "useapi.net ⁝ Unauthorized",
      "code": 401
    }
    
  • 403 Forbidden

    The job belongs to another useapi.net user.

    {
      "error": "Not your job",
      "code": 403
    }
    
  • 404 Not Found

    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
    }
    
  • 410 Gone

    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.