Why two layers of errors?
Soundpiece returns two distinct kinds of error, and they mean different things:- HTTP-level errors (
4xx/5xx) — your request was rejected. The work never started. - Operation-level errors — your request was accepted (you got
200 OKand an operationid), but the operation itself failed during processing. You poll the operation just like any other and findstatus: "failed"with a populatederrorobject.
status.
HTTP errors
The two rules of thumb:4xx— fix your request. Something in what you sent doesn’t work. Retrying with the same body won’t help; you need to change the request.5xx— something unexpected happened on our side. You can retry.PUTendpoints are idempotent onidempotency_key(see Async operations), so retrying with the same key is safe — you won’t double-create work.
Response shape
HTTP errors return a JSON body with adetail field. For most errors it’s a plain string:
422), detail is a list of per-field entries:
| Field | Meaning |
|---|---|
loc | Path to the offending field — e.g. ["body", "lyrics"] for a top-level body field, or ["body", "reference", "url"] for a nested one. |
msg | Human-readable description of the problem. |
type | Stable machine-readable code (e.g. missing, string_too_short, url_parsing). |
Status reference
| Status | When you’ll see it | Recommended handling |
|---|---|---|
400 Bad Request | Malformed JSON or unparseable request body. | Fix the request. |
401 Unauthorized | Missing, invalid, or revoked API key (and, on Enterprise plans with IP allowlisting, a request from a non-allowlisted IP). | Check your Authorization header and source IP. Don’t retry. |
402 Payment Required | Your account doesn’t have enough credits to perform the requested work. See Insufficient credits below for the response shape. | Top up your account, then retry with the same idempotency_key. |
404 Not Found | Only returned when the endpoint URL itself doesn’t exist — e.g. a typo in the path. Entity-not-found (operation id, etc.) is reported as a 422 validation error, not a 404. | Check the URL. |
405 Method Not Allowed | Wrong HTTP verb on a known route (e.g. POST on a PUT-only endpoint). | Use the documented verb. |
410 Gone | The endpoint existed on this API version but has been sunset. The detail field points to the replacement. | Migrate to the replacement endpoint. See versioning. |
422 Unprocessable Entity | Request body validation failed — missing field, wrong type, out-of-range value, invalid URL, or a referenced entity (operation id etc.) wasn’t found. | Read detail to see which field is bad. |
429 Too Many Requests | You’ve hit your account’s request rate limit. | Read the Retry-After header (seconds) and back off. See rate limits. |
5xx | Transient server-side issue. | Retry safely — PUT requests are idempotent if you supply the same idempotency_key. Use exponential backoff. |
Insufficient credits (402)
When you submit a request whose credit cost exceeds your current balance, the call is rejected up-front (no work starts, no charge) with a 402 whose body is:
create.remix_song and create.remix_instrumental charge 3 credits per variation, so n_variations: 3 costs 9). Top up your account and re-submit with the same idempotency_key — the original request was never persisted, so the retry creates the work fresh.
Operation-level failures
When an operation fails, the response looks like this:error.code is a stable machine-readable identifier — safe to branch on. error.message is a human-readable description suitable for surfacing to your end-users.
Not every code applies to every endpoint. The sections below group codes by which endpoints can return them.
Codes returned by all endpoints
| Code | Meaning | Recommended handling |
|---|---|---|
internal_error | Generic failure with no more specific classification available. | Re-submit with the same idempotency_key. If it persists, contact support. |
generation_timeout | The operation took longer than our hard timeout to complete. | Re-submit. Persistent timeouts are worth raising with support. |
quota_exceeded | Your account is out of monthly capacity. | Top up your account or wait for the next billing cycle. |
Codes for endpoints with a source or reference
(applies to adapt.separate_stems, adapt.auto_cut_down, create.remix_song, create.remix_instrumental, and the reference variant of create.new_song / create.new_instrumental)
| Code | Meaning |
|---|---|
source_unreachable | We couldn’t fetch the URL — DNS failure, connection refused, TLS error, 4xx/5xx from the host. |
source_format_unsupported | The file at the URL is not a supported audio format (we accept wav, mp3, flac). |
source_too_short | The fetched audio is too short for this operation (typically under 10 seconds). |
source_too_long | The fetched audio exceeds the maximum length for this operation. |
Codes for generation endpoints
(applies tocreate.new_song, create.new_instrumental, create.new_sample, create.new_fx, create.remix_song, create.remix_instrumental)
| Code | Meaning |
|---|---|
tos_violation | The lyrics, prompt, or reference were rejected by our content policy. |
Why retries don’t risk double-billing
PUT endpoints are idempotent on idempotency_key. The same key always returns the same operation, regardless of how many times you retry. This means:
5xxHTTP responses are safely retryable — retry with the same key and you’ll either get a fresh attempt or the existing successful result.429is retryable — back off usingRetry-After, then send the same key again.4xxother than429indicate a bad request that won’t get better; fix the request before retrying.
idempotency_key is also echoed on every response and webhook payload so you can correlate work against your own records without a separate request-id-to-state map.
Reporting persistent issues
If you receiveinternal_error (operation-level) or 5xx (HTTP-level) that persists across retries, please contact business@soundpiece.co.uk with:
- The endpoint called.
- The operation
idif one was returned. - The
idempotency_keyyou sent. - The approximate timestamp.
- Any
error.code/error.messagefrom the response body.
