Notice: GPT Image 2.6 Flare and Sunburst are newly launched with a limited-time 20% off, try it now
HiAPI
Blog

Tutorial

ElevenLabs Music API on HiAPI: Generate Music with curl, Python, and Prompt Recipes

A hands-on tutorial for calling elevenlabs/music-v2.5 through HiAPI, plus copy-paste prompt recipes for style, mood, and duration

Nov 12, 2026 12 min read
封面图:暖炭灰背景上有一条宽大的琥珀色光带斜掠而过,整体简洁克制。
On this page

Why call elevenlabs/music-v2.5 through HiAPI

If you are adding music generation to a product, the fastest path is usually not the cleanest one. Wiring your backend directly to a model provider means you own that provider's account setup, authentication scheme, retry semantics, and request shape. Every new model you adopt adds another set of those decisions, and every experiment leaves another integration branch behind.

Calling elevenlabs/music-v2.5 through HiAPI changes the shape of that work. You get one base URL, one authentication header, and one request convention that stays stable as you move between models. The model identifier (elevenlabs/music-v2.5) is just a string in the request body, so switching between music models or trying a second one for comparison is a one-line change rather than a new SDK import.

Three practical benefits matter for developers choosing an integration approach:

  • One credential surface. Key management, rotation, and environment separation (dev/staging/prod) live in one place instead of multiplying per provider.
  • Portable request patterns. The curl and Python snippets below match the ones you use for other models on HiAPI. Learning the pattern once is enough.
  • Usage in one place. Music generation is billed by output duration, and keeping that alongside your other model usage means cost tracking in a single dashboard rather than scattered invoices.

The trade-off is that you are working through an abstraction layer, so provider-specific quirks are normalized. For a first integration and for most production use cases, that normalization is exactly what you want. When you need to reason about the model's specific behavior, its detail page on the site is the source of truth.

Preparing before your first music request

Confirm four things before writing code, so the first call returns audio instead of a 401 or a validation error.

1. An API key

You need an API key issued from your HiAPI account. Treat it like any other secret: keep it in an environment variable, never in committed source, and use separate keys for local development and production so you can revoke one without breaking the other.

export HIAPI_API_KEY="your_key_here"

2. The base URL and endpoint convention

All model calls go through the same base URL, with the model identified inside the request rather than in the path. Keep a single constant for the base URL in your project so there is exactly one place to change it if your environment differs.

3. A prompt, in plain language

elevenlabs/music-v2.5 takes a text prompt describing the music you want. You do not need musical notation or a MIDI file. A sentence or two naming the genre, instrumentation, mood, and intended duration is enough to start. Later sections give reusable recipes for this.

4. The right expectations for output

Music generation returns audio, not a JSON score. Plan for how you will handle the response payload: writing it to a file during development, and streaming or storing it in production. Decide up front roughly how long you want the clip to be, because duration drives both the request and the billing.

One more thing before the first request: check the current rate limits and prices for elevenlabs/music-v2.5 on the site's pricing panel rather than hardcoding assumptions into your code. Prices and limits change, and your integration should read them as configuration, not as constants embedded in a script.

Making your first call with curl

Start with curl because it removes every layer between you and the HTTP request. If the curl call works, any failure in your application is your application's fault, not the API's.

curl -sS https://api.hiapi.ai/v1/chat/completions \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "elevenlabs/music-v2.5",
    "messages": [
      {
        "role": "user",
        "content": "Instrumental lo-fi hip hop, warm vinyl texture, mellow electric piano, soft brushed drums, 80 BPM, relaxed late-night mood, about 30 seconds."
      }
    ]
  }'

Here is what each part does:

  • -sS keeps progress output quiet but still shows errors. Useful when you are pasting output into a file.
  • The URL is the unified endpoint. Note that the model name does not appear in the path; it appears in the body.
  • Authorization: Bearer $HIAPI_API_KEY reads the key from your environment so it never lands in shell history in plaintext. On Windows, set the variable with set or PowerShell's $env: syntax accordingly.
  • Content-Type: application/json is required; the endpoint does not accept form encoding.
  • model is the exact identifier elevenlabs/music-v2.5. Typos here produce a model-not-found error rather than a generic failure, which is helpful when debugging.
  • messages carries your prompt as the user message content. Keep the prompt in one message; long, structured prompts work better than several fragmented ones.

The response body contains the generated audio along with metadata about the request. During development, redirect the output to a file so you can listen to the result immediately:

curl -sS https://api.hiapi.ai/v1/chat/completions \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json -o response.json

Putting the payload in request.json and reading it with -d @request.json is the habit to build early. It makes the request diffable, reviewable, and easy to replay when you change one parameter at a time.

Repeating the call in Python

Once the curl call returns audio, port it to Python. The goal is not just a working script but a function you can call from a job queue, an API handler, or a notebook without copy-paste drift.

import json
import os
import urllib.request

BASE_URL = "https://api.hiapi.ai/v1/chat/completions"
MODEL = "elevenlabs/music-v2.5"

def generate_music(prompt: str, timeout: int = 120) -> dict:
    """Send a music prompt to elevenlabs/music-v2.5 via HiAPI."""
    api_key = os.environ.get("HIAPI_API_KEY")
    if not api_key:
        raise RuntimeError("HIAPI_API_KEY is not set")

    payload = {
        "model": MODEL,
        "messages": [{"role": "user", "content": prompt}],
    }

    request = urllib.request.Request(
        BASE_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        method="POST",
    )

    with urllib.request.urlopen(request, timeout=timeout) as response:
        return json.loads(response.read().decode("utf-8"))

if __name__ == "__main__":
    result = generate_music(
        "Cinematic orchestral swell, strings and low brass, hopeful build, "
        "no percussion, about 20 seconds."
    )
    print(json.dumps(result, indent=2)[:500])

A few decisions worth keeping as the function grows:

  • Standard library first. urllib avoids dependency churn in a tutorial. If your project already uses requests or httpx, the translation is mechanical: pass json=payload, headers=headers, and a timeout.
  • Timeouts are mandatory. Music generation takes longer than a chat completion. Set an explicit timeout and do not rely on the default. Pick a value longer than your expected generation time for the longest clip you plan to request.
  • Read the key at call time, not at import time, so the same module works locally and in a container where the environment is injected at runtime.
  • Return structured data, not a printed string. The caller decides whether to write audio to disk, upload it to object storage, or forward it to a client.

Confirm the Python function and the curl call produce equivalent results for the same prompt before you build anything on top of them. That agreement is your regression baseline.

Prompt recipes for style, mood, and duration

A music prompt works best when it answers three questions in order: what genre and instrumentation, what emotional tone, and how long. Vague prompts produce generic output; overly long prompts dilute the important descriptors. Aim for one dense sentence, or three short clauses.

Use these as copy-paste starting points and edit one dimension at a time.

Style-led recipes

  • Solo piano, felt hammers, close-miked, slow arpeggios in the style of a modern film score.
  • Upbeat synthwave, analog bass, gated reverb drums, arpeggiated lead, 120 BPM.
  • Acoustic folk ensemble, fingerpicked guitar, upright bass, light tambourine, organic room sound.
  • Ambient drone, layered pads, no rhythm section, slowly evolving texture.

Mood-led recipes

  • Warm and nostalgic, like a summer evening, major key, gentle dynamics.
  • Tense and minimal, low pulsing bass, sparse percussion, unresolved harmony.
  • Playful and bright, staccato strings, bouncy rhythm, light-hearted.
  • Melancholic and spacious, reverb-heavy, sparse piano, slow tempo.

Duration-led recipes

Duration belongs in the prompt as an explicit target, and it should be consistent with the arrangement. A 15-second request with a slow build and a long outro will get cut awkwardly.

  • ... about 15 seconds, short intro, no outro, ends cleanly.
  • ... about 30 seconds, one clear section, loopable ending.
  • ... about 60 seconds, intro, main section, and a natural fade.

Combined example

Lo-fi hip hop for focus, dusty vinyl crackle, soft electric piano, brushed drums, 80 BPM, calm and unhurried, about 30 seconds, loopable.

When the output is not what you expected

Adjust one variable per attempt so you learn what actually changes the result.

  • Too generic: replace mood words with concrete instrumentation and tempo. "Energetic" is weaker than "driving 16th-note bass at 128 BPM."
  • Too busy or cluttered: remove instruments explicitly (no drums, no vocals, sparse arrangement) rather than adding more positive descriptors.
  • Wrong length feel: if the clip stops abruptly, ask for a shorter target with an explicit ending; if it feels rushed, reduce the number of sections requested.
  • Style drift: move genre and instrumentation to the front of the prompt. Early tokens carry more weight.

Keep a small prompt file in your repository with the recipes that worked. That file is more valuable than any single generated clip, because it turns prompt writing into a repeatable engineering artifact.

Common errors and how to fix them

Most first integrations fail in a small number of predictable ways. Run through this checklist before you start guessing.

Authentication failures

A 401 almost always means the header is malformed or the key is missing from the process environment. Check for a stray space after Bearer, a key loaded from the wrong .env file, or a shell where export ran in a different session than the one running the script. Print the key length (not the key) to confirm it is populated.

Model identifier mismatches

A model-not-found or validation error usually means the model string is not an exact match. elevenlabs/music-v2.5 is case-sensitive and contains a slash. If you copied it from a chat window, check for smart quotes or line-wrap artifacts.

Malformed request bodies

If curl works but your Python does not, the difference is almost always serialization. Passing a Python dict directly where a JSON string is expected, double-encoding with json.dumps twice, or forgetting Content-Type: application/json all produce server-side parse errors that look unrelated to the real cause. Log the exact request body your code sends and compare it character by character with the working curl payload.

Timeouts on longer clips

Longer durations take longer to generate. A client-side timeout that is fine for a chat request will cut off a longer music request. Raise the timeout for this endpoint specifically, and add a retry with backoff only for connection-level failures, never blindly for requests that may already have been billed.

Prompt length and content

Extremely long prompts, or prompts containing instructions about the API itself, tend to produce worse music. Keep the prompt about the music. If a prompt that worked yesterday stops working, simplify it to the style/mood/duration skeleton and rebuild.

Treating the response as text

The endpoint returns audio data, not a readable transcript. Writing the raw response body into a .txt file and wondering why it will not play is a common first-day mistake. Save with the correct audio extension and verify the file opens in a player before building further.

When an error is genuinely unclear, reproduce it with the smallest possible curl request. That isolates whether the problem is the API contract or your code.

From test call to repeatable workflow

A successful test call is a starting point, not an integration. Use this checklist to turn it into something a team can rely on.

  • Externalize configuration. Base URL, model identifier, timeout, and default duration target go into config, not scattered string literals. Environment-specific values come from the environment.
  • Centralize the client. One function or thin client class owns the request. No module should build its own HTTP call to the music endpoint, or you will diverge on headers and error handling.
  • Handle errors by category. Distinguish authentication, validation, timeout, and server errors. Retry only the transient ones, with backoff and a cap. Never retry a request whose output may already have been produced and billed.
  • Store audio properly. Write to object storage with deterministic keys, keep the prompt alongside the generated asset, and record the model identifier. Reproducing a result later depends on knowing exactly what was asked.
  • Track duration as a first-class parameter. Since billing follows output duration, make the target duration explicit in your prompt templates and log it per request so cost reporting lines up with usage.
  • Build a prompt library. Keep validated recipes in version control, with a short note on what each one was used for. New team members start from working prompts instead of guessing.
  • Separate sync and async paths. Generation can be slow. For user-facing features, submit a job, persist the request, and let a worker call the model. The HTTP handler should not hold open for the full generation time.
  • Verify with a smoke test. One test that sends a fixed short prompt and asserts a well-formed audio response catches credential and contract drift early.

When you are ready to go deeper on parameters and limits, the elevenlabs/music-v2.5 model page on HiAPI is the place to check current capabilities before you hardcode assumptions.

Related articles

View all articles →

Start building with persistent AI artifacts

Get your API key and call image, video and audio models through one task-based API.

Read the API docs