Enterprise API
Soundverse Enterprise API
Generate licensed music, vocals, stems, and audio insights from your own product. This page covers auth, the request/response contract, and the two ways to call the API — start here before jumping to a capability page.
- What changed
- Authentication
- Two ways to call this API
- Endpoints
- License tiers
- Idempotency-Key
- Errors
- Polling vs. streaming
- Rate limits
- Providing audio/file input
- Account balance
What changed
The Enterprise API moved off the old per-capability, per-version REST surface (POST /v6/generate/music, GET /v5/recognize, etc.) onto a single generic pipeline: every generation — songs, music, vocals, stems, copyright checks — goes through one endpoint, POST /v1/generations, with a tool_id that identifies which capability you want.
If you integrated against the old API, you don’t need to rewrite anything yet: most of the old URLs and field names still work, unchanged, via a compatibility layer that resolves the right tool for you server-side. See Compat Routes for the full list, or jump straight to your capability’s page in the sidebar — each one shows the compat route first, if it has one.
Authentication
Every request (except GET /health) requires a bearer API key in the Authorization header:
Authorization: Bearer sksoundverse_<your_api_key>
Content-Type: application/jsonA missing or malformed header returns 401 {"error": "UNAUTHENTICATED"}; an invalid or revoked key returns 401 {"error": "INVALID_API_KEY"}.
Two ways to call this API
There are two ways to create a generation, and you can mix both across your integration:
- Compat routes — old-style URLs and field names (e.g.
POST /v7/generate/song). The gateway resolves the right tool for you; you never need atool_id. Covers most of the commonly-used capabilities. See Compat Routes. - Native pipeline —
POST /v1/generationswith an explicittool_id. Always available, and the only option for capabilities the compat layer doesn’t cover yet (e.g. audio transcription, sound effects, audio effects, similar-music, MIDI-to-song). Look up the righttool_idon the Tool Catalog page.
Endpoints
POST/v1/generationscreate a generation
GET/v1/generations/{id}fetch one task
GET/v1/generationslist your tasks, cursor-paginated
GET/v1/generations/{id}/streamlive SSE progress
GET/v1/toolslist the tools this account can bill against
GET/v1/account/balanceyour remaining token balance
POST /v1/generations body: tool_id (string, required), license (integer, optional — see below), payload_json (string, a JSON-encoded object of the tool’s own input fields — see each capability page).
It always returns immediately — 201 {"task_id": "...", "status": "queued"} — it never blocks until the generation finishes. From there, poll GET /v1/generations/{id} or open the SSE stream; see Polling vs. streaming below.
License tiers
license is an integer on the request body. Omit it (or send 0) to default to Royalty-Free.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| 0 | LICENSE_UNSPECIFIED | No | — | Not a valid choice — treated as unset. |
| 1 | LICENSE_ROYALTY_FREE | No | — | Default if omitted. |
| 2 | LICENSE_STANDARD | No | — | |
| 3 | LICENSE_DISTRIBUTION | No | — | |
| 4 | LICENSE_SYNC | No | — | |
| 5 | LICENSE_MASTER | No | — |
Pricing is per license tier and varies by capability and version — see the pricing table on each capability’s page, or the consolidated Tool Catalog.
Idempotency-Key
Set an Idempotency-Key header on any create call (native or compat) to make retries safe:
Idempotency-Key: my-client-generated-key-123Up to 200 characters, [A-Za-z0-9_.:-] only. A repeat call with the same key (scoped to your account) returns the original task instead of creating a new one and billing you again — the right thing to set on every create call your client might retry. A missing or malformed key is not an error; the request just proceeds without dedup.
Errors
Two response shapes exist, depending on where the request fails:
Pipeline errors (creating a generation)
{"error": "RateLimited", "message": "...", "retryable": true}| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| 400 | UnknownTool | No | — | Unknown or inactive tool_id / (model, operation) pair. |
| 402 | InsufficientFunds | No | — | Token reservation failed — top up your balance. |
| 422 | ToolNotPriced | No | — | No platform pricing configured for this tool + license. |
| 429 | RateLimited | No | — | Rate limit exceeded. retryable: true. |
Other errors
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| 401 | UNAUTHENTICATED / INVALID_API_KEY | No | — | See Authentication above. |
| 403 | FORBIDDEN | No | — | The task belongs to a different account. |
| 404 | NOT_FOUND | No | — | No task with that id. |
There are no rate-limit response headers (no X-RateLimit-*, no Retry-After) — the 429 body above is the only signal. Back off and retry with the same Idempotency-Key.
Polling vs. streaming
Every generation is created async. Once you have a task id, choose either:
- Poll —
GET /v1/generations/{id}for a point-in-time snapshot (status:queued/processing/completed/failed). - Stream —
GET /v1/generations/{id}/stream, an SSE stream ofprogress/streaming_url/partial_outputevents, ending in aterminalevent. Resume a dropped connection with?after=<seq>from the last event you saw; atimeoutorerrorevent also carries a resume cursor.
Both are backstopped server-side — billing settles even if you never poll or stream to completion.
Rate limits
Limits are enforced per tool and per model, per hour and per day, scoped to your account. There are no response headers exposing remaining quota — a 429 on create is the only signal (see Errors above).
Providing audio/file input
Capabilities that take an audio or MIDI input (extend, remix, singing with a reference, stem separation, copyright check, transcription, audio effects) accept the field in any of three shapes:
{"song": {"url": "https://example.com/track.mp3"}}
// or, as shorthand, a bare string is coerced the same way:
{"song": "https://example.com/track.mp3"}A direct URL or inline base64 is usually the right choice for a server-to-server integration — you don’t need to upload anything to a Soundverse-hosted library first. Each capability page documents the exact field name (song, audio, vocal_reference, etc.) and any size/format limits for that field.
Account balance
GET/v1/account/balance
{
"total_effective": 12500,
"base_effective": 10000,
"extra_tokens": 2500,
"base_expires_at": "2026-08-01T00:00:00Z"
}