Skip to main content
API referenceMusic generations

Music Generations

Minimum-discount routing: Prefix the path with a min{N} segment (e.g. /min30/v1/music/generations) to require marketplace seller offers to meet a minimum estimated buyer discount before routing. Buyer-owned providers are not covered. See Minimum-Discount Routing.

Async music and text-to-audio generation via the marketplace. Same flow as video: submit, poll, retrieve.

Submit Job

POST/v1/music/generations

Auth: API key required (Authorization: Bearer ***).

  • modelstringrequired
    Model ID, e.g. venice-ace-step-15; legacy venice-music-gen maps to ACE-Step
  • promptstringrequired
    Prompt or narration text (max 2000 chars)
  • duration_secondsinteger
    Track/audio duration. Optional; omitted values use the model's default duration when known
  • lyrics_promptstring
    Lyrics text (max 5000 chars) for models that support lyrics
  • force_instrumentalboolean
    Generate without vocals when supported
  • voicestring
    Voice selection for TTS-like audio models
  • language_codestring
    Language for lyrics or speech models when supported
  • webhook_urlstring
    Accepted and validated, but not delivered yet — terminal-state callbacks are not enabled in production. Poll instead
  • metadataobject
    Client pass-through metadata

Current Venice-backed examples include venice-ace-step-15, venice-elevenlabs-music, venice-minimax-music-v26, venice-stable-audio-25, venice-elevenlabs-sound-effects-v2, venice-mmaudio-v2-text-to-audio, and Venice audio TTS models. Query /v1/models and /api/markets for the live catalog and active order book.

Response — 202 Accepted (same envelope as video)json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "object": "media.job",
  "kind": "music",
  "status": "queued",
  "created": 1713200000,
  "expires_at": 1713200900,
  "estimated_cost_usdc": "30000",
  "max_cost_usdc": "33000",
  "poll_url": "/v1/music/generations/550e8400-...",
  "cancel_url": "/v1/music/generations/550e8400-...",
  "job_token": "mjt_abc123..."
}
Submit, poll, terminal
  1. SubmitReturns job id + poll_url
  2. Poll2s then back off to 10s
  3. Terminalcompleted, failed, or expired
Music jobs expire after 15 minutes. Poll on the interval the submit response gives you rather than tightly — the job token in that response is what authorizes the poll.

Poll Status

GET/v1/music/generations/:id

Auth: API key OR X-Job-Token header.

Rolling out. The error object below is the shape the API is moving to. Until the rollout completes, a terminal job may instead carry type set to its status ("failed", "canceled") and no retryable field. Write your handler to tolerate both: treat a missing retryable as "safe to retry unless type is invalid_request", and do not assume error is absent on a cancel.

The error object. Present on a terminal job that failed, and absent on one that succeeded or was cleanly canceled. type comes from a closed vocabulary, so it is safe to branch on:

invalid_requestretryable · falseMeans · The request was refused on its merits. It will be refused again — change the request.
provider_errorretryable · trueMeans · The job failed while it was being generated.
provider_unavailableretryable · trueMeans · The job could not be completed in time, or could not be confirmed with any provider.
expiredretryable · trueMeans · The job passed its deadline before it completed.
execution_start_failedretryable · trueMeans · The job could not be started.
unknownretryable · trueMeans · The job failed without a reported reason.

retryable is the field to branch on rather than type: it is false for exactly one value today, and a new type added later will carry the right retryable without your code changing. You are not charged for a job that ends in any of these.

Responsejson
{
  "id": "550e8400-...",
  "object": "media.job",
  "kind": "music",
  "status": "succeeded",
  "results": [
    {
      "artifact_index": 0,
      "url": "$SURPLUS_BASE_URL/media/artifacts/job-id/0",
      "content_type": "audio/mpeg",
      "duration_seconds": 60,
      "bytes": 1200000
    }
  ],
  "usage": {
    "seller_cost_usdc": "30000",
    "buyer_cost_usdc": "30000",
    "settlement_status": "confirmed"
  }
}

Cancel Job

DELETE/v1/music/generations/:id

Same as video.

Errors

400Code · invalid_requestWhen · A malformed parameter, or an image-to-video-only model submitted with no source image
402Code · insufficient_credit / insufficient_balance / insufficient_allowanceWhen · The job's max_cost_usdc is more than you can cover on any rail
402Code · account_frozen / org_frozen / org_closedWhen · The paying account is under review or closed
404Code · model_not_foundWhen · The model is not in the media catalog
404Code · no_sellers_for_modelWhen · No seller can serve this model on this endpoint. This includes a model whose only offers are listed against a host that does not run async music at all — those offers are excluded from routing rather than accepted and failed later, so the refusal arrives before you are charged
503Code · no_healthy_sellersWhen · Sellers exist and can serve the endpoint, but none is currently healthy or able to accept this input. Retryable

A 404 is a statement about supply and will not fix itself on retry; a 503 is transient.

Differences from Video

  • Default expiry: 15 minutes.
  • Poll schedule is faster: 2s initial, 10s cap.
  • Supports lyrics_prompt, force_instrumental, voice, and language_code where the selected Venice model supports them.
  • Seller validation and offer health use /audio/quote so onboarding does not spend provider credits on full generations.
  • results[].url is an authenticated URL on this API, exactly as for video — send Authorization or X-Job-Token and follow redirects. The retention window runs from when the job reached a terminal state (3 hours by default) and stored artifacts are purged within a day regardless, so download promptly.