Api

Music Generation API

Create music tracks with POST /api/v1/music, including options, pricing, and errors.

Create a music task

POST /api/v1/music generates an original track from a text prompt. The track renders before the call returns, so the response usually already has status: "success" and the track URL in data.taskUrls; keep the connection open and use a generous client timeout. The returned data.id also works with GET /api/v1/tasks/{taskId} if you prefer one polling flow.

POST https://viewmax.studio/api/v1/music
Authorization: Bearer sk-your-api-key
Content-Type: application/json
Idempotency-Key: lofi-001

Request body

FieldRequiredTypeDescription
promptYesstringNon-empty description of the track
optionsNoobjectGeneration controls

options

FieldTypeDescription
duration_secondsnumberTrack length in seconds: a JSON number from 3 to 300. Default 60
instrumentalbooleantrue for no vocals
stylestringGenre or mood. Changes how prompt is read; see below
titlestringSong title. Changes how prompt is read; see below
lyricsstringLyrics to sing

options.duration and options.music_length_ms are rejected; use duration_seconds.

When style or title is set, the model receives prompt as lyrics. To describe a track, put the whole description in prompt and leave style and title unset. To give a song a style, put the lyrics in prompt and do not also send lyrics.

Cost

Music costs max(60, ceil(duration_seconds)) credits: 60 credits up to 60 seconds, then 1 credit per second (300 seconds cost 300). Omitting duration_seconds renders 60 seconds for 60 credits. Plan allowances do not apply to music on the API. GET /api/v1/models?type=music lists the base price as credits.

Example

curl -X POST https://viewmax.studio/api/v1/music \
  -H "Authorization: Bearer $VIEWMAX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: lofi-001" \
  -d '{
    "prompt": "Warm lo-fi hip-hop with a mellow piano loop",
    "options": { "duration_seconds": 30, "instrumental": true }
  }'

This costs 60 credits.

Successful response

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "5c7e9a1b-3d5f-4b6c-8e0a-2f4b6d8e0a12",
    "userId": "usr_123",
    "mediaType": "music",
    "model": "music_v2",
    "prompt": "Warm lo-fi hip-hop with a mellow piano loop",
    "options": "{\"duration_seconds\":30,\"instrumental\":true}",
    "status": "success",
    "createdAt": "2026-09-29T08:00:00.000Z",
    "updatedAt": "2026-09-29T08:00:42.000Z",
    "deletedAt": null,
    "taskId": "sync:5c7e9a1b-3d5f-4b6c-8e0a-2f4b6d8e0a12",
    "taskInfo": null,
    "taskResult": "{\"output\":[\"https://cdn.example.com/music/track.mp3\"]}",
    "taskUrls": ["https://cdn.example.com/music/track.mp3"],
    "costCredits": 60,
    "scene": "text-to-music",
    "visibility": "user",
    "creditId": "cr_789",
    "waivedCredits": 0,
    "fairUseKey": null
  }
}

The fields are described under Task fields in the Video Generation API. taskUrls is always an array.

Idempotency and refunds

  • Send Idempotency-Key (1–200 visible ASCII characters, no spaces). Repeating a key returns the original task and its costCredits without charging again; the body is not compared. Retry a timed-out request with the same key; use a new key for a deliberate new attempt. Without the header, every POST creates and charges a new task.
  • Credits are deducted when the task is created. If the balance is lower than the cost, the call returns 402 and creates no task. A task that ends failed or canceled is refunded automatically.

Errors

All errors use the error envelope.

HTTPerror.typeExample messageWhat to do
400invalid_requestprompt is requiredSend a non-empty prompt
400invalid_requestoptions.duration_seconds must be a number from 3 to 300Send a JSON number in range
400invalid_requestoptions.duration is not supported; use options.duration_secondsRename the option
400invalid_requestthe generation request uses unsupported settings, with error.task_idThe provider rejected the settings; the task failed and was refunded. Read its taskInfo.errorMessage, adjust, and retry with a new key
400content_rejectedinput content was rejected by safety filtersChange the prompt or lyrics; do not retry unchanged
402insufficient_creditsinsufficient creditsNo task was created. Add credits; do not retry until then
500internal_errorthe generation service is temporarily unavailableWith error.task_id the task failed and was refunded: retry once. If the hint says the outcome is unknown, poll that task instead of retrying
503internal_error—The content-safety check is temporarily unavailable; retry after a short delay

On this page