Skip to main content
When you upload several files with the single Upload Audio endpoint, each call may land on a different Suno account. That breaks flows that require clips on one account — Inspiration, Create Persona, and similar. Batch Upload Session binds one account at prepare time; every item in that session uploads to the same account.

Workflow

Step 1: POST /suno/v2/audio/upload/session
        → sessionId (account selected synchronously)

Step 2: POST /suno/v2/audio/upload/session/item  (×N, can run in parallel)
        → taskId per file (async)

Step 3: GET /suno/v2/status?taskId={sessionId}
        → aggregated audioIds[]
StepEndpointTypePurpose
1POST /suno/v2/audio/upload/sessionSyncPick account, return sessionId
2POST /suno/v2/audio/upload/session/itemAsync × NUpload one file on bound account
3GET /suno/v2/status?taskId={sessionId}QueryAll clip IDs in data.audioIds
Existing POST /suno/v2/upload is unchanged. Use the session flow only when you need multiple clips on one account.

Step 1 — Create session

Prepare Upload Session — no request body. Response:
{
  "sessionId": "f259907e-32dd-468d-95f9-e3c0baf4f01c"
}
  • Synchronous — returns immediately
  • A random available upload account is selected and stored on the session
  • Session task status is success; result.audioIds starts as []

Step 2 — Upload items (concurrent OK)

Upload Session Item — one call per file.
{
  "sessionId": "f259907e-32dd-468d-95f9-e3c0baf4f01c",
  "audioUrl": "https://example.com/audio.mp3"
}
Response:
{
  "taskId": "833c3d28-7948-42b8-9d4c-4c145bddfbf5"
}
  • Async — poll GET /suno/v2/status?taskId={itemTaskId} for clip details
  • Submit many items with the same sessionId in parallel; all use the same account
  • On each success, the clip ID is appended to the session’s audioIds
  • Credits per item match a normal upload

Step 3 — Poll progress & aggregated IDs

Per-item status

GET /suno/v2/status?taskId={itemTaskId}
Success example:
{
  "taskId": "833c3d28-...",
  "status": "success",
  "data": {
    "id": "e9fe2c0e-189d-4a0a-9f4d-354b1c47b99c",
    "status": "complete",
    "audio_url": "https://cdn1.suno.ai/....mp3",
    "image_url": "https://cdn2.suno.ai/....jpeg",
    "has_vocal": true,
    "display_tags": "indie pop, electronic pop, male vocals"
  }
}

Session aggregate (all clip IDs)

GET /suno/v2/status?taskId={sessionId}
{
  "taskId": "f259907e-...",
  "status": "success",
  "data": {
    "audioIds": [
      "e9fe2c0e-189d-4a0a-9f4d-354b1c47b99c",
      "4595e4da-af12-4c24-a013-9cfd11db7d50"
    ]
  }
}
audioIds grows as each item completes. In-flight uploads are not listed yet.

Same-account guarantee

prepare  →  Random account pick → session.accountId = 500046

item create  →  task.accountId = session.accountId (fixed at creation)

item execute  →  pickAccount(ById, 500046) with row lock — never switches account

vs Custom Model upload session

Custom Model uploadBatch Upload Session
AccountDedicated custom-model accountRandom available upload account
Next stepcustomModelCreate (training)None — audioIds ready to use
Use caseTrain chirp-custom:<uuid>Persona, Inspiration, any same-account workflow
Session status after prepareREADY (waits for create)success (prepare is terminal)

Full example

curl -X POST https://api.mountsea.ai/suno/v2/audio/upload/session \
  -H "Authorization: Bearer your-api-key"
Use returned audioIds directly in Inspiration clip_ids, or for persona / generate tasks that require one account.