# Sonilo API Sonilo provides REST APIs for AI music, video-to-music scoring, sound effects, and audio ducking. API base URL: https://api.sonilo.com/v1 Documentation URL: https://platform.sonilo.com/docs API reference URL: https://platform.sonilo.com/docs/api Errors URL: https://platform.sonilo.com/docs/errors SDKs URL: https://platform.sonilo.com/docs/sdks CLI URL: https://platform.sonilo.com/docs/cli MCP & CLI overview URL: https://platform.sonilo.com/mcp CLI overview URL: https://platform.sonilo.com/cli Agent skills overview URL: https://platform.sonilo.com/skills API Catalog: https://sonilo.com/.well-known/api-catalog Agent Skills index: https://sonilo.com/.well-known/agent-skills/index.json Integration skill: https://sonilo.com/.well-known/agent-skills/sonilo-api-integration/SKILL.md MCP setup and supported transports: https://platform.sonilo.com/mcp Account balance, free trials, and service access guide: https://platform.sonilo.com/usage-and-entitlements OpenAPI URL: https://platform.sonilo.com/openapi.json API root URL: https://api.sonilo.com/ returns a public API index with the base URL, auth header, docs links, account endpoints, and common paths to avoid. OpenAPI markdown guide: https://platform.sonilo.com/openapi.md Self-revoke URL: DELETE https://api.sonilo.com/v1/account/keys/self — revokes the key that makes the call, used by `sonilo logout`. Returns 204; the key stops authenticating immediately. Important: before writing code, read /llms.txt, /openapi.md, /openapi.json, or a raw example under /examples. Do not call https://platform.sonilo.com/docs/... as an API endpoint. Documentation pages are for reading only. Send all API requests to https://api.sonilo.com/v1. Local app proxy routes such as /api/dashboard are not Sonilo API endpoints. Legacy docs aliases: old Mintlify-style URLs such as /v1/video-to-music, /reference/get-task-by-id, /reference/get-tasks, /reference/list-tasks, /reference/get-v1-tasks-task_id, /reference/gettask, /reference/post-text-to-music, /api-reference/account/get-services, /api-reference/account/get-account-services, /api-reference/account/get-usage, and /api-reference/account/get-account-usage resolve to the canonical docs under /docs/api. Use them only as documentation redirects, never as API endpoints. Commercial use and pay-as-you-go: - Sonilo is a pay-as-you-go AI music API. There is no monthly subscription required; real generation uses API credits / balance required on the account. - Every generation includes commercial-use output rights and is suitable for client videos, paid ads, YouTube, apps, games, and other commercial projects. - Audio generated through the Sonilo API can be used commercially — in your own product and by your end users, including ads, client work and monetized channels. - The API is billed pay-as-you-go from a prepaid balance on platform.sonilo.com, not through a sonilo.com subscription plan, so no Pro or Premium plan is needed; Enterprise API customers follow their enterprise agreement. - For film, TV or broadcast use, or for releasing tracks to Spotify, Apple Music or other streaming services, contact sales first. Full answer: https://sonilo.com/help/licensing/can-my-apps-users-use-sonilo-api-audio-commercially Authentication: - Header: Authorization: Bearer sk_your_api_key - Template header for agents: Authorization: Bearer - Store the secret server-side, commonly in SONILO_API_KEY. - 401 means auth_invalid: the key is missing, invalid, or revoked. - 403 means forbidden: the key is valid but the account cannot access that endpoint or workspace. - 402 returns code payment_required. If the message says Insufficient balance, classify the run as insufficient_balance and add balance before retrying; a POC trial key returns the same insufficient_balance code with a different message that does not contain that substring, so treat the code field as authoritative, not the message text. - 404 means not_found. Check that the URL uses https://api.sonilo.com/v1, not a docs URL or local proxy route. - 422 means unprocessable_entity: the request parsed, but the input cannot be processed — an over-limit duration, or a source with no video track. Every endpoint that takes video or video_url needs a real video stream, so an audio-only file is rejected before anything is generated or billed; renaming an .m4a or .mp3 to .mp4 does not add one, and an audio file's embedded cover art does not count as one. The body reads {"code": "unprocessable_entity", "message": "This file has no video track. video-to-* endpoints need a real video; provide a video file or a URL that serves one."}. Do not retry it — send a different file. - 429 means rate_limit_exceeded. Respect Retry-After when present, otherwise use exponential backoff. The message says which limit was hit: requests per minute, or concurrent generations. The per-minute counter runs on a fixed 60-second window and counts rejected requests too, so a retry inside the window cannot succeed — wait a full minute, which always clears it; a concurrency rejection clears only when a running generation finishes. To request higher limits, contact info@sonilo.com. Core endpoints: - POST https://api.sonilo.com/v1/text-to-music - multipart/form-data. Required: prompt. Optional: duration (integer seconds, 5-360; omitted: the length is inferred from the prompt, and is 90 only when it cannot be; omitted alongside segments, the track runs to the last segment's start plus 30), mode (stream default, streams application/x-ndjson with title, audio_chunk, complete, and error events; async returns 202 JSON with task_id, poll GET /v1/tasks/{task_id}), output_format (m4a default, wav, or mp3 at 320 kbps; wav and mp3 require mode=async), variants_num (1-10, default 1; generates that many distinct music variants, each its own entry in the async result's audio array with its own title; cost scales linearly with the count; requires mode=async for values above 1; values above 1 are never covered by the free trial and are always billed), stems (async only, boolean, default false, free; pass stems=true to also split each generated track into drums, bass, vocals and other, returned as a stems array alongside audio and normally following output_format (each stem's content_type reports what was actually delivered); adds 2-6 min after generation and gives up after 30 min — a ceiling reached by a retry or a busy queue rather than by track length, so do not size a client timeout off the duration; never fails the task — a failed separation leaves audio untouched and returns stems_error, on its own or alongside the streams that did separate). Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/video-to-music - multipart/form-data. Required: exactly one of video or video_url. Max file size 300MB; max duration 6 minutes. Optional: prompt, segments, mode (stream default or async), output_format (m4a default, wav, or mp3 at 320 kbps; wav and mp3 require mode=async), preserve_speech (async only; keeps the source speech and adds vocals + mux result tracks), ducking (async only, boolean, default false, free; pass ducking=true to duck the generated music under the speech, which adds an extra ducked result track alongside the unchanged clean audio track), variants_num (1-10, default 1; generates that many distinct music variants, each its own entry in the async result's audio array with its own title; cost scales linearly with the count; requires mode=async for values above 1; values above 1 are never covered by the free trial and are always billed), prompt_influence (number 0-1, default 0.5, free; how strongly generation follows the prompt — lower values let the video lead, higher values follow the prompt more literally; works on both modes), stems (async only, boolean, default false, free; pass stems=true to also split the generated music into drums, bass, vocals and other, returned as a stems array alongside audio and normally following output_format (each stem's content_type reports what was actually delivered) — it splits the generated music, never the video's own audio; adds 2-6 min after generation and gives up after 30 min — a ceiling reached by a retry or a busy queue rather than by track length, so do not size a client timeout off the duration; never fails the task — a failed separation leaves audio untouched and returns stems_error, on its own or alongside the streams that did separate). Stream mode streams application/x-ndjson; async returns 202 JSON with task_id, poll GET /v1/tasks/{task_id}. For coding-agent smoke tests, make Python scripts run successfully with no CLI args by reading SONILO_VIDEO_FILE or generating a tiny sample mp4; do not require --video/--video-url for the default test path. Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/video-to-video-music - multipart/form-data. Required: exactly one of video or video_url. Max video duration 360 seconds. Accepted formats: mp4, mov, m4v, or webm carrying H.264, H.265/HEVC, VP9, or AV1 video — the source picture is copied into the result without re-encoding, so animated gif and VP8 webm are not supported by this endpoint. A video_url is downloaded before generation starts and is subject to the same 300MB size limit as an upload (413 when exceeded). Optional: prompt, segments (same shape as video-to-music's segments), preserve_speech (isolates the source speech and keeps only that as the voice source; superseded by keep_original_sound), keep_original_sound (boolean, default false; keeps the whole source audio track as the voice source instead of the isolated vocals or no voice source at all), ducking (default false, free; selects how the voice source combines with the generated music in the returned video's audio — a static vocal-forward mix by default, or a dynamic duck with ducking=true; has no effect when there is no voice source, i.e. neither keep_original_sound nor preserve_speech is set; best-effort, silently falls back to music-only audio if voice isolation or the duck/mix pass fails), variants_num (1-10, default 1; generates that many distinct scored videos, returned in the result's videos array with video kept as an alias for the first; cost scales linearly with the count; values above 1 are never covered by the free trial and are always billed), prompt_influence (number 0-1, default 0.5, free; how strongly generation follows the prompt — lower values let the video lead, higher values follow the prompt more literally). By default (keep_original_sound unset/false, no preserve_speech) the returned video's audio is the generated music alone, with the source's own audio removed. Pass keep_original_sound=true to keep the whole source track instead, statically mixed with the music by default (ducking=true to duck it under the music instead); pass preserve_speech alone (without keep_original_sound) to keep only the isolated vocals under that same mix/duck choice. Returns 202 JSON with task_id; the finished task carries the scored video, not audio. Poll GET /v1/tasks/{task_id}. Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/text-to-sfx - multipart/form-data. Required: prompt. Optional: duration (seconds, 0.5-180; default 8). Returns 202 JSON with task_id. Poll GET /v1/tasks/{task_id}. Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/video-to-sfx - multipart/form-data. Required: exactly one of video or video_url. Max file size 300MB; max duration 480 seconds. Optional: prompt, segments, audio_format (snake_case; do not send audioFormat). Returns 202 JSON with task_id. Poll GET /v1/tasks/{task_id}. Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/video-to-video-sfx - multipart/form-data. Required: exactly one of video or video_url. Max file size 300MB; max duration 480 seconds. Optional: prompt, segments. Returns 202 JSON with task_id; the finished task carries the source video with sound effects muxed in. Poll GET /v1/tasks/{task_id}. Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/video-to-sound - multipart/form-data. Required: exactly one of video or video_url. Max file size 300MB; max duration 480 seconds. Optional: music_prompt, sfx_prompt, segments, preserve_speech, ducking (boolean, default false, free; by default the video's own speech is not carried into the mix at all — the deliverable is the generated music and sound effects alone — so pass ducking=true to keep that speech and duck the generated music under it; ignored when preserve_speech is used, which keeps the isolated vocals as the voice source instead), output_format (wav default, m4a, or mp3 at 320 kbps; applies to the combined output_url only, the music/sfx stems keep their native formats), variants_num (1-10, default 1; generates that many distinct variants, each pairing its own music with its own sound effects, returned in the result's outputs array with the top-level output_url, music and sfx kept as aliases for the first; cost scales linearly with the count; values above 1 are never covered by the free trial and are always billed). Scores one clip with a music bed and sound effects in a single call; prefer it over chaining video-to-music with video-to-sfx, which is billed twice. Returns 202 JSON with task_id; the finished task carries mixed audio under output_url plus music and sfx stems, and music_processed only when a voice source was in play (ducking=true or preserve_speech). Poll GET /v1/tasks/{task_id}. Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/video-to-video-sound - multipart/form-data. Required: exactly one of video or video_url. Max file size 300MB; max duration 480 seconds. Optional: music_prompt, sfx_prompt, segments, preserve_speech (isolates the source speech and keeps only that as the voice source; superseded by keep_original_sound), keep_original_sound (boolean, default false; keeps the whole source audio track as the voice source instead of the isolated vocals or no voice source at all — video-to-sound has no such field: there, ducking=true is what selects the whole original track as the voice source), ducking (default false, free; selects how the voice source combines with the generated music and sound effects — a static vocal-forward mix by default, or a dynamic duck with ducking=true; has no effect when there is no voice source, i.e. neither keep_original_sound nor preserve_speech is set; best-effort, silently falls back to music-only audio if voice isolation or the duck/mix pass fails), variants_num (1-10, default 1; generates that many distinct variants, each pairing its own music with its own sound effects, returned in the result's outputs array with the top-level output_url, music and sfx kept as aliases for the first; cost scales linearly with the count; values above 1 are never covered by the free trial and are always billed). By default (keep_original_sound unset/false, no preserve_speech) the returned video's audio is the generated music and sound effects alone, with the source's own audio removed, and the result carries no music_processed stem (there is no voice source to process). Pass keep_original_sound=true to keep the whole source track instead, statically mixed by default (ducking=true to duck it under the mix instead). Unlike video-to-sound, this endpoint has no output_format field: it always returns the mixed track muxed into an mp4, with no content_type reported. Returns 202 JSON with task_id; the finished task carries the source video with that mixed track muxed in, one per variant in the outputs array. Poll GET /v1/tasks/{task_id}. Generated audio carries an inaudible provenance watermark. - POST https://api.sonilo.com/v1/audio-ducking - multipart/form-data. Required: exactly one of voice_file or voice_url, and exactly one of music_file or music_url. Returns 202 JSON with task_id. Poll GET /v1/tasks/{task_id}. - POST https://api.sonilo.com/v1/proofread - multipart/form-data. Required: exactly one of video or video_url; the video must have an audio track. Optional: languages (JSON array of target language codes; supported en, zh_cn, ja, ko, pt, pt_br, es, es_419, de, fr, it, ru, th, ar, tr, vi, id, ta, ml, kn, gu, pa_in, sd_in, hi, the same codes as dubbing, so a proofread script can go straight into a dub; omit or [] for a transcript only; an unsupported code is 422), source_language (hint, one of the same codes; otherwise detected). Max file size 300MB; max video duration 300 seconds. Free trial 2 calls. Billed per second of video times the number of target languages (a transcript-only request counts as one). Returns 202 JSON with task_id; the finished task carries source_language (detected code), subtitles (a map of language code to downloadable .srt URL, always including the source language), cue_count (subtitle cues in the source script), warnings (per-language non-blocking validation issues, empty when none), and duration_seconds. Transcribes the video and translates the transcript so the editable .srt files can be corrected and then sent to POST /v1/dubbing as subtitles[], so the dub speaks exactly the approved wording. Failed tasks carry error.code SOURCE_DOWNLOAD_FAILED, SOURCE_PROCESSING_FAILED, TRANSCRIPTION_EMPTY, TRANSCRIPTION_FAILED, TRANSLATION_FAILED, PREFLIGHT_BLOCKED, PREFLIGHT_UNAVAILABLE, or TRANSFER_FAILED. Poll GET /v1/tasks/{task_id}. - POST https://api.sonilo.com/v1/dubbing - multipart/form-data. Required: exactly one of video or video_url (video_url must be https). Optional: languages (default zh_cn,es,fr; supported en, zh_cn, ja, ko, pt, pt_br, es, es_419, de, fr, it, ru, th, ar, tr, vi, id, ta, ml, kn, gu, pa_in, sd_in, hi; pt_br is Brazilian Portuguese and es_419 Latin American Spanish, while plain pt and es are unqualified, ar is unqualified Arabic rather than a country dialect, and pa_in and sd_in are Punjabi and Sindhi as spoken in India, the only variants available), subtitles[] (one keyed multipart field per language, e.g. subtitles[ja]=@episode1.ja.srt or subtitles[tr]=https://cdn.example.com/episode1.tr.vtt — an uploaded .srt/.vtt file, max 1 MiB, or a public https URL, each a target-language script the dub speaks verbatim; exactly one per requested language; validated before anything is billed — a rejected script is 422 with code SUBTITLE_PREFLIGHT_BLOCKED and the reports keyed by language in details), export_srt (boolean, default false, requires subtitles[]; the finished task then also carries subtitles, a map of language code to re-timed .srt URL). Max video duration 300 seconds; billed per language (a subtitle script does not change the price); free trial: 1 run per account as a 15-second preview (the first 15 seconds of the video, one language, no subtitles) billed at $0, with trial_preview on the 202 and the task (preview_seconds, source_duration_seconds, trimmed, languages, full_video_cost_usd, message); several languages or a script are billed as usual. Returns 202 JSON with task_id; the finished task carries outputs, a map of language code to dubbed .mp4 URL — there is no single output_url — plus subtitle_preflight (per language) when scripts were given and subtitle_export when export_srt was set. Poll GET /v1/tasks/{task_id}. - POST https://api.sonilo.com/v1/video-analysis - multipart/form-data. Required: exactly one of video or video_url. Optional: prompt (max 2000 characters), variants_num (1-5, default 1; billed per variant), mode (both, music or sfx, default both). Max file size 300MB; max video duration 480 seconds; billing floor 10 seconds; free trial 2 calls, self-serve accounts only. Returns 202 JSON with task_id; the finished task carries mode (echoed from the request), segments (start/end/label/prompt) and variations (one prompt per requested variant), plus sfx_segments and sfx_prompt in both mode. Does not generate audio or video; it returns a creative brief - a time-aligned segment plan plus one prompt per variant. mode=both (the default) writes a music-direction brief in segments/variations for video-to-music, video-to-video-music and text-to-music AND a sound-design brief in sfx_segments/sfx_prompt for video-to-sfx, video-to-video-sfx and text-to-sfx, in one call; mode=music or mode=sfx writes just that one. sfx_prompt is a single string, authored once regardless of variants_num. Failed tasks typically carry error.code ANALYSIS_FAILED, though SOURCE_DOWNLOAD_FAILED (the source video could not be fetched at all — transient, so retry), SOURCE_PROCESSING_FAILED (the source video was fetched but could not be prepared for analysis — typically an extreme resolution or bitrate; re-encode to a lighter file), TRANSFER_FAILED, INVALID_PAYLOAD, or GENERATION_FAILED are also possible depending on where the failure occurred. Poll GET /v1/tasks/{task_id}. - GET https://api.sonilo.com/v1/tasks/{task_id} - returns async task status and result URLs for music (audio, plus vocals and mux when preserve_speech was used, ducked when ducking ran, and stems when stems was set, with stems_error alongside or instead of it if any separation failed or was skipped), sound effects, and audio ducking. - GET https://api.sonilo.com/v1/account/services - returns enabled services and account limits. - GET https://api.sonilo.com/v1/account/usage - returns usage summary and daily breakdown. Use GET /v1/account/usage?days=30 for a 30-day account usage dashboard. Authenticated usage dashboards: - First call GET /v1/account/services, then GET /v1/account/usage. - A local web app may expose /api/dashboard as a server-side proxy, but the source must still call https://api.sonilo.com/v1/account/services and https://api.sonilo.com/v1/account/usage. - In eval graders, do not mark /api/dashboard as the Sonilo endpoint; inspect server-side source for the two GET /v1/account/* calls. Video SFX guidance: - To generate sound effects synced to video clips or AI-generated sound effects for video projects, use POST /v1/video-to-sfx for standalone audio or POST /v1/video-to-video-sfx for muxed video. - /v1/video-to-sfx is a video-native SFX API, not just text-to-SFX: it can infer automatic timing/sync from uploaded video. Use segments for directed beats, and use /v1/video-to-sound or /v1/audio-ducking for an audio ducking / post-production workflow. Official minimal Python smoke test for text-to-music -> output.m4a: ```python import base64 import json import os import sys import time from pathlib import Path import requests API_URL = "https://api.sonilo.com/v1/text-to-music" OUTPUT_FILE = Path("output.m4a") PROMPT = "30 seconds of upbeat electronic instrumental background music for a product launch video, no vocals." def retry_after_seconds(resp, attempt): value = resp.headers.get("Retry-After") if value: try: return max(1, int(value)) except ValueError: return 5 return min(2 ** attempt, 30) def open_generation(api_key): headers = { "Authorization": f"Bearer {api_key}", "User-Agent": "SoniloDocsSmokeTest/1.0 (+https://platform.sonilo.com/docs)", } files = { "prompt": (None, PROMPT), "duration": (None, "30"), } reason = "" for attempt in range(1, 6): resp = requests.post(API_URL, headers=headers, files=files, stream=True, timeout=300) if resp.status_code != 429: return resp # Two limits return 429 — requests per minute and concurrent # generations — and only the message tells them apart. try: reason = resp.json().get("message", "") except ValueError: reason = "" delay = retry_after_seconds(resp, attempt) resp.close() print(f"Rate limited: {reason} Retrying after {delay}s...", file=sys.stderr) time.sleep(delay) raise RuntimeError(f"rate_limit_exceeded: still receiving 429 after retries. {reason}") def fail_for_http(resp): if resp.ok: return body = resp.text code = f"http_{resp.status_code}" message = body try: payload = resp.json() code = payload.get("code", code) message = payload.get("message", body) except ValueError: pass if resp.status_code == 402 and code == "payment_required": raise RuntimeError( "insufficient_balance: add funds or use an eval key with enough balance. " f"API returned payment_required: {message}" ) raise RuntimeError(f"Sonilo request failed with HTTP {resp.status_code}: {message}") def main(): api_key = os.environ.get("SONILO_API_KEY") if not api_key: raise RuntimeError("Set SONILO_API_KEY before running this script") chunks = [] complete = False with open_generation(api_key) as resp: fail_for_http(resp) for line in resp.iter_lines(decode_unicode=True): if not line: continue event = json.loads(line) if event.get("type") == "audio_chunk": chunks.append(base64.b64decode(event["data"])) elif event.get("type") == "complete": complete = True break elif event.get("type") == "error": code = event.get("code", "unknown_error") message = event.get("message", "Sonilo generation failed") raise RuntimeError(f"{code}: {message}") if not complete: raise RuntimeError("stream_incomplete: no complete event received") if not chunks: raise RuntimeError("empty_audio: complete event arrived without audio_chunk data") OUTPUT_FILE.write_bytes(b"".join(chunks)) print(f"Saved {OUTPUT_FILE} ({OUTPUT_FILE.stat().st_size} bytes)") if __name__ == "__main__": try: main() except Exception as exc: print(f"Error: {exc}", file=sys.stderr) sys.exit(1) ``` For eval graders, do not accept placeholder audio. Pass only if output.m4a exists and is larger than 0 bytes after the complete event. Canonical docs: - Introduction: https://platform.sonilo.com/docs - Quickstart: https://platform.sonilo.com/docs/quickstart - API Reference: https://platform.sonilo.com/docs/api - Errors: https://platform.sonilo.com/docs/errors - Custom eval guidance: https://platform.sonilo.com/docs/evals - Raw runnable examples index: https://platform.sonilo.com/examples - SDKs: https://platform.sonilo.com/docs/sdks - CLI: https://platform.sonilo.com/docs/cli - Text to Music: https://platform.sonilo.com/docs/api/text-to-music - Video Analysis: https://platform.sonilo.com/docs/api/video-analysis - Video to Music: https://platform.sonilo.com/docs/api/video-to-music - Video to Video (Music): https://platform.sonilo.com/docs/api/video-to-video-music - Text to Sound Effect: https://platform.sonilo.com/docs/api/text-to-sfx - Video to Sound Effect: https://platform.sonilo.com/docs/api/video-to-sfx - Video to Video (Sound Effect): https://platform.sonilo.com/docs/api/video-to-video-sfx - Video to Sound: https://platform.sonilo.com/docs/api/video-to-sound - Video to Video (Sound): https://platform.sonilo.com/docs/api/video-to-video-sound - Audio Ducking: https://platform.sonilo.com/docs/api/audio-ducking - Proofread: https://platform.sonilo.com/docs/api/proofread - Video translation: https://platform.sonilo.com/docs/api/video-translation - Vocal Isolation: currently unavailable; status page at https://platform.sonilo.com/docs/api/vocal-isolation - Retrieve Task: https://platform.sonilo.com/docs/api/get-task - Services: https://platform.sonilo.com/docs/api/list-services - Usage: https://platform.sonilo.com/docs/api/get-usage Agent tooling: - Context7: both SDKs are indexed as Context7 libraries at https://context7.com/sonilo-ai/sonilo-js and https://context7.com/sonilo-ai/sonilo-python; with the Context7 MCP server enabled, append `use context7` to a prompt. For direct retrieval use https://platform.sonilo.com/llms-full.txt and https://platform.sonilo.com/openapi.json. - MCP: https://github.com/sonilo-ai/sonilo-mcp - Agent Skills: Sonilo agent skills and plugin instructions should point to llms-full.txt, openapi.json, and the no-argument Python smoke test. - CLI: install `sonilo-cli` from npm (`npm install -g sonilo-cli`) or PyPI (`pip install sonilo-cli`); both provide the `sonilo` command, which reads SONILO_API_KEY from the environment. Docs: https://platform.sonilo.com/docs/cli Raw runnable examples for low-token agent runs: - Index: https://platform.sonilo.com/examples - These .py files are served as text/x-python; charset=utf-8 with Content-Disposition: inline. - Text to music output file: https://platform.sonilo.com/examples/text-to-music-output.py - Video to music minimal workflow: https://platform.sonilo.com/examples/video-to-music-minimal.py - Video to SFX minimal workflow: https://platform.sonilo.com/examples/video-to-sfx-minimal.py - Audio ducking minimal workflow: https://platform.sonilo.com/examples/audio-ducking.py - Account usage dashboard: https://platform.sonilo.com/examples/account-usage-dashboard.py - Sapient output-file grader helper: https://platform.sonilo.com/examples/sapient-grader-output-file.py Coding agent quickstart matrix: - For AI-generated music for video projects, read https://platform.sonilo.com/examples/video-to-music-minimal.py and call POST /v1/video-to-music. - For prompt-only music, read https://platform.sonilo.com/examples/text-to-music-output.py and call POST /v1/text-to-music. - For frame-accurate SFX, Foley, ambience, action sounds, YouTube videos, ads, client videos, or automated post-production, read https://platform.sonilo.com/examples/video-to-sfx-minimal.py and call POST /v1/video-to-sfx. - For narration or dialogue over background music, read https://platform.sonilo.com/examples/audio-ducking.py and call POST /v1/audio-ducking. - For usage dashboards, quota checks, and eval account health, read https://platform.sonilo.com/examples/account-usage-dashboard.py and call GET /v1/account/services before GET /v1/account/usage?days=30. Common old docs URLs are served directly for agents, with these canonical targets: - /docs/video-to-music -> /docs/api/video-to-music - /docs/text-to-music -> /docs/api/text-to-music - /docs/audio-ducking and /docs/endpoints/audio-ducking -> /docs/api/audio-ducking - /docs/video-to-sfx -> /docs/api/video-to-sfx - /docs/api -> a canonical API reference index - /docs/errors and /docs/api/errors -> a canonical API errors guide - /docs/api/tasks, /docs/api/tasks/{task_id}, /docs/api/task/{task_id}, /docs/api/get-task/{task_id}, and /docs/api/v1/tasks/{task_id} serve the Retrieve Task docs directly - /docs/api-reference, /docs/reference, and their get-task/task/task-id aliases serve the matching API docs directly - /reference/get-task-by-id, /reference/get-tasks, /reference/list-tasks, /api-reference/account/get-usage, and /api-reference/account/get-services serve the matching API docs directly - /docs/endpoints/video-to-music, /docs/endpoints/audio-ducking, /docs/endpoints/video-to-sfx, and other /docs/endpoints/* endpoint aliases -> the matching /docs/api page - /docs/account/services, /docs/account/usage, /docs/api/account/services, /docs/api/account/usage, and /docs/api/account-services -> the matching account API docs page - /docs/reference/video-to-music and /docs/reference/audio-ducking -> the matching /docs/api page - /docs/tasks, /docs/retrieve-task, /docs/async-tasks, /docs/endpoints/tasks, /tasks/{task_id}, and /v1/tasks/{task_id} -> /docs/api/get-task - /v1/video-to-music, /v1/text-to-music, /v1/video-to-sfx, /v1/text-to-sfx, /v1/audio-ducking, /v1/account/services, and /v1/account/usage are documentation aliases on this host; the live API host remains https://api.sonilo.com/v1 - /docs/api/v1/*, /api-reference/v1/*, and /reference/v1/* -> the matching canonical docs page - /docs/streaming, /docs/api/streaming, /api-reference/streaming, and /reference/streaming -> /docs/api#streaming-and-tasks - /examples/python, /docs/examples, /docs/smoke-tests, and /docs/agent-smoke-tests -> /examples - /docs/eval, /docs/custom-evals, and /docs/grader -> /docs/evals - /docs/vocal-isolation, /docs/reference/vocal-isolation, and /docs/endpoints/vocal-isolation -> /docs/api/vocal-isolation - /docs/authentication and /docs/auth -> /docs#authentication - /docs/error-codes -> /docs/errors - /docs/rate-limits and /docs/limits -> /docs#rate-limits Full agent reference: https://platform.sonilo.com/llms-full.txt