Your lyrics. Your next song. Try Music 1.5 (beta)

Python quickstart

Text-to-Music Python quickstart

The fastest official path for a coding agent is to install the Python SDK, useSONILO_API_KEY, generate a real 30-second instrumental track with no vocals, save output.mp3, and print its file size.

Billing and credits prerequisite

Real generation requires available balance or credits. If the account has no usable balance, Sonilo returns 402 Payment Required or an insufficient balance error and will not generate placeholder audio. Agents should report that balance is required instead of creating fake files.

1. Install and set the API key

Get an API key

Create a key on the Sonilo Platform API keys page and export it as SONILO_API_KEY. No Platform account yet? Sign up at platform.sonilo.com; it is separate from a sonilo.com app account. The API starts with free trial calls, then bills pay-as-you-go from a prepaid balance.

python -m venv .venv
source .venv/bin/activate
pip install sonilo
export SONILO_API_KEY="sk_your_api_key"

2. Generate and verify output.mp3

from pathlib import Path

from sonilo import Sonilo

OUTPUT = Path("output.mp3")


def is_insufficient_balance_error(exc: Exception) -> bool:
    text = str(exc).lower()
    response = getattr(exc, "response", None)
    status = getattr(exc, "status_code", None) or getattr(response, "status_code", None)
    code = str(getattr(exc, "code", "")).lower()
    return (
        status == 402
        or code == "insufficient_balance"
        or "insufficient balance" in text
        or "payment required" in text
    )


def main() -> None:
    client = Sonilo()  # reads SONILO_API_KEY

    try:
        track = client.text_to_music.generate(
            prompt="30 second instrumental, no vocals, warm cinematic synths, steady beat",
            duration=30,
        )
    except Exception as exc:
        if is_insufficient_balance_error(exc):
            print("Blocked: insufficient balance or credits. Add balance, then rerun.")
            raise SystemExit(2) from exc
        raise

    track.save(OUTPUT)
    size = OUTPUT.stat().st_size
    if size <= 0:
        raise RuntimeError("output.mp3 was empty; do not treat this as a success.")

    print(f"saved {OUTPUT} ({size:,} bytes)")


if __name__ == "__main__":
    main()