HiAPI
Blog

Tutorial

How to Use lyria-3.5 via the hiapi API: curl, Python, and a Working Request

Sep 15, 2026
How to Use lyria-3.5 via the hiapi API: curl, Python, and a Working Request

lyria-3.5 is hiapi's text-to-music model: send a musical description, lyrics, or both, and get back a finished audio track — with optional title, tempo guidance, and duration control. This guide walks through the full input schema, a request that returns a real track, and the production details you need past a one-off test.

What you need

  • A hiapi API key. Grab one from the dashboard — keys start with sk-.
  • curl or Python's requests. No SDK required; hiapi speaks plain REST.

lyria-3.5 runs on hiapi's unified async task API: you POST a task, get a taskId back immediately, then either poll for the result or receive a callback when the track is ready.

The full input schema

lyria-3.5 accepts more than a bare prompt. Every field is optional except that you must supply at least one of prompt or lyrics:

Field Type Notes
prompt string Genre, instruments, mood, vocals, song structure. Provide prompt or lyrics.
lyrics string One line per phrase. Section tags — [Intro], [Verse], [Chorus], [Bridge], [Outro] — each on their own line, followed by the lyrics. Number repeats as [Verse 1], [Verse 2].
title string Title of the generated song.
bpm string Tempo guidance as a numeric string, e.g. "90".
length integer Requested duration in seconds, 1–240. Guides length; actual duration may vary. Omit to leave unspecified.
seed string Numeric string seed, e.g. "00123". Identical audio is not guaranteed even with the same seed.

Two gotchas worth flagging up front: bpm and seed are strings, not numbers — send "90", not 90, or the API returns a 400 (got number, want string). And the schema is strict: any field not in the table above (duration, style, genre, negative_prompt, etc.) 400s with additional properties '...' not allowed.

Minimal working example

1. Create the task

curl -X POST "https://api.hiapi.ai/v1/tasks" \
  -H "Authorization: Bearer sk-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "lyria-3.5",
    "input": {
      "prompt": "Warm instrumental indie folk, fingerpicked acoustic guitar, soft brushed drums, quiet morning",
      "bpm": "90",
      "length": 30
    }
  }'

A healthy response returns immediately, before the track is actually rendered:

{
  "code": 200,
  "message": "success",
  "data": { "taskId": "tk-hiapi-01M2HCSKAP77MTH1ANKQXE1DT2" }
}

2. Poll for the result

curl "https://api.hiapi.ai/v1/tasks/tk-hiapi-01M2HCSKAP77MTH1ANKQXE1DT2" \
  -H "Authorization: Bearer sk-YOUR_API_KEY"

Wait a few seconds before the first poll, then check every 3–5 seconds. status moves through handling before landing on a terminal state. Here's the actual response for the request above, about 100 seconds later:

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-01M2HCSKAP77MTH1ANKQXE1DT2",
    "model": "lyria-3.5",
    "status": "success",
    "created": 1789437730,
    "completed": 1789437829,
    "output": [
      {
        "type": "audio",
        "url": "https://temp.hiapi.ai/7c6ttvrbpt/01M2HCSKAP77MTH1ANKQXE1DT2-0.m4a",
        "expireAt": 1790042629
      }
    ]
  }
}

Note the output container can vary by request (.m4a here; other music models on hiapi return .mp3) — read output[0].type/URL rather than hardcoding an extension. Download output[0].url promptly: the default temp storage tier expires around 7 days (expireAt is a Unix timestamp). On failure, status is fail and data.error holds { code, message } instead of output.

3. A lyrics-driven request in Python

import time
import requests

API_KEY = "sk-YOUR_API_KEY"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

payload = {
    "model": "lyria-3.5",
    "input": {
        "title": "Carry the Morning",
        "lyrics": (
            "[Verse 1]\n"
            "Light through the window, coffee still warm\n"
            "[Chorus]\n"
            "Carry the morning, carry it slow\n"
        ),
        "bpm": "96",
        "length": 45,
    },
}

create = requests.post("https://api.hiapi.ai/v1/tasks", headers=HEADERS, json=payload)
task_id = create.json()["data"]["taskId"]

status = None
while status not in ("success", "fail"):
    time.sleep(4)
    poll = requests.get(f"https://api.hiapi.ai/v1/tasks/{task_id}", headers=HEADERS).json()
    status = poll["data"]["status"]

if status == "success":
    print(poll["data"]["output"][0]["url"])
else:
    print(poll["data"]["error"])

Swap lyrics for prompt (or send both) depending on whether you want an instrumental or a vocal track.

Production notes

  • Callback instead of polling. Add a top-level callback object: {"url": "https://yourapp.com/hook", "when": "final"}. when only accepts "final" — you get one call when the task reaches a terminal state, not progress updates.
  • Idempotency. The task API doesn't accept a client-supplied idempotency key, so guard retries at the application layer: persist taskId as soon as you receive it, and check task status before firing a duplicate request on retry.
  • Errors. A missing or invalid API key returns HTTP 401 with error_code: "permission_denied". Schema violations return HTTP 400 with error_code: "INVALID_REQUEST" and a message naming the offending field — useful for catching a stray duration or numeric bpm before it reaches production.
  • Storage. Move output[0].url to your own storage right after a successful poll or callback; don't rely on the temp tier past its expireAt.

Related reading

FAQ

Do I need to send both prompt and lyrics? No — the API requires at least one of the two. Send prompt alone for an instrumental track, lyrics alone for a vocal track driven purely by the words, or both together.

What audio format does lyria-3.5 return? It varies by request — check output[0].type and the URL's extension rather than assuming .mp3 or .m4a.

Can I force an exact tempo? bpm is guidance, not a hard constraint, and it must be sent as a string ("90", not 90).

How long can a generated track be? length accepts 1–240 seconds, but it guides the model rather than guaranteeing an exact duration — check the actual runtime of the returned file.

Will the same seed give me the same track twice? No. seed is a numeric string that nudges generation, but hiapi's docs are explicit that identical audio isn't guaranteed.

What happens if I send an unrecognized field, like genre or duration? The schema is strict — you'll get a 400 with additional properties '<field>' not allowed instead of the field being silently ignored.

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