Errors
Every error the ToneGrid API can return, grouped by HTTP status. Each entry explains the exact message you'll see, what triggered it, and how to fix it. Catalogue is hand-curated from the live codebase — to add an entry, edit errors.php.
Response shape
{
"success": false,
"error": "Human-readable message",
"errors": { "field.path": ["…"] } // 422 only — per-field validation map
}
Plus stock response headers on every error: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-Request-Id. Always log the request id; it's what we look up when you contact support.
search
search_off
No errors matched your search.
4xx Client errors
400
Bad request
Idempotency
Idempotency-Key must be ≤255 chars.
- When
- You sent an
Idempotency-Keyheader longer than 255 chars. - How to fix
- Use a UUIDv4 (36 chars) or a short opaque token. Don't embed full request bodies into the key.
Idempotency
Idempotency-Key was previously used with a different request body.
- When
- You sent the same
Idempotency-Keytwice but the request body hash differs from the first call. - How to fix
- Either reuse the original body exactly, OR mint a new key for the new operation. Keys are scoped to (key, endpoint, body-hash).
401
Unauthorized
Authentication
Authentication token is missing.
- When
- No
Authorizationheader on a route that requires auth. - How to fix
- Send
Authorization: Bearer <token>where the token is either a JWT fromPOST /auth/loginor atgk_API key.
Authentication
Invalid or expired token. Please log in again.
- When
- JWT expired (1h TTL) or signature invalid; or an API key was revoked / deleted / expired.
- How to fix
- For JWT:
POST /auth/refreshusing your refresh-token cookie. For API keys: mint a new one in the admin dashboard.
Authentication
Invalid email or password.
- When
POST /auth/loginwith credentials that don't match (or user soft-deleted).- How to fix
- Verify the email/password. After 5 failed attempts in 60s you'll be rate-limited (429).
402
Payment required
Billing
Payment verification failed.
- When
- The payment provider rejected the transaction (insufficient funds, fraud check, etc.).
- How to fix
- Surface the message to the user; let them retry with a different card. Don't auto-retry — re-run the checkout flow.
403
Forbidden
Authorization
You do not have permission to perform this action.
- When
- Your role / API-key scopes don't include the required permission for this endpoint.
- How to fix
- Generic by design — we don't leak the required role/scope set. Check the endpoint's required scope in the API Reference and rotate to a key that includes it.
Authorization
This workspace is suspended.
- When
- The tenant has
status = suspended. - How to fix
- Contact billing@interspacemusic.com to reinstate.
Authorization
This account has been suspended. Contact support.
- When
- Your user record has
status = suspended(independent of tenant status). - How to fix
- Contact support — usually triggered by repeated abuse signals.
Authorization
Not a descendant of your tenant.
- When
- You called
POST /tenants/clients/:uuid/login-ason a tenant that isn't a child of yours. - How to fix
- Verify the target tenant's
parent_tenant_idmatches your tenant. Cross-parent impersonation is blocked.
404
Not found
Catalog
Release not found.
- When
- No release matches the UUID, OR the release belongs to a different tenant.
- How to fix
- Verify the UUID and that you're using the correct tenant's token. We return 404 (not 403) for cross-tenant reads so existence isn't confirmed.
Catalog
Track not found.
- When
- No track matches the UUID under this release / tenant.
- How to fix
- Same as Release not found — verify UUID + tenant scope.
Catalog
Artist not found.
- When
- No artist matches the UUID under this tenant.
- How to fix
- Verify UUID + tenant scope.
DDEX
DSP '<slug>' not found or inactive.
- When
- The DSP slug in the URL doesn't exist, or its
is_active=0. - How to fix
- List active DSPs via
GET /dsps. Slugs are lowercase, hyphen-separated (egapple-music,youtube-music).
Routing
Endpoint not found.
- When
- The path doesn't match any registered route, OR you hit a privileged route without sufficient scope (we return 404 instead of 403 to hide privileged routes from probes).
- How to fix
- Check the API Reference for the correct path. Trailing slashes matter on a few legacy routes.
Webhooks
Webhook not found.
- When
- No webhook matches the UUID under this tenant.
- How to fix
- List your webhooks via
GET /webhooksfirst.
Finance
Statement not found. / Payee statement not found. / Payout not found. / Period not found.
- When
- No row matches the UUID under your tenant.
- How to fix
- List the relevant collection (eg
GET /finance/statements) and re-fetch using the UUID from the list response.
409
Conflict
Catalog
Only draft or rejected releases can be deleted.
- When
- You tried to
DELETEa release that's already been submitted, approved, or is live. - How to fix
- Use the takedown flow instead:
POST /releases/:uuid/ddex/purge(hard) or update the deal's ValidityPeriod EndDateTime (soft).
Catalog
Only draft or rejected releases can be submitted.
- When
- Release is already in
pending_review,approved, or further. - How to fix
- No action needed if review is already in progress; otherwise check the release status via
GET /releases/:uuid.
Catalog
This release was modified by another user. Please reload and try again.
- When
- Optimistic concurrency check failed — you sent a stale
updated_ator row version. - How to fix
- Re-fetch the release, merge your changes onto the fresh version, then re-submit.
Catalog
Artist slug already taken. / Slug already taken.
- When
- You tried to claim a slug that another artist in your tenant already uses.
- How to fix
- Choose a different slug. Slugs are unique per tenant.
DDEX
Delivery to <DSP> is blocked via per-DSP override (is_blocked=true).
- When
- You called
POST /releases/:uuid/ddex/deliver/:dsp_slugfor a DSP that hasis_blocked=truein your per-DSP overrides. - How to fix
- Either unblock the DSP via
PUT /releases/:uuid/dsps/:dsp_slugwith{"is_blocked": false}, or skip that DSP from the deliver-all flow (it skips blocked DSPs automatically).
Finance
Only draft statements can be approved. / Only draft payee statements can be approved.
- When
- Statement is already
approved,locked, orpaid. - How to fix
- No action needed if status is already past draft.
Finance
Period code already exists.
- When
- You tried to create an accounting period whose
codematches an existing one. - How to fix
- Use a different code (eg
2026-Q3, not2026-Q2if Q2 exists).
Users
You cannot delete your own account.
- When
- A user tried to
DELETE /users/:uuidwith their own UUID. - How to fix
- Have another admin in your tenant perform the deletion, or contact support.
413
Payload too large
Uploads
File exceeds the maximum allowed size of <N> MB.
- When
- Audio / image upload exceeds the per-type cap (audio: 1 GB, image: 50 MB, video: 5 GB).
- How to fix
- For audio: compress to a lossless format (FLAC is half the size of WAV at the same fidelity). For video: use H.264 + AAC at sensible bitrates. We multipart-upload anything >100 MB automatically.
Uploads
Animated artwork must be ≤50 MB.
- When
- Apple Motion / Spotify Canvas upload over 50 MB.
- How to fix
- Compress with ffmpeg:
ffmpeg -i in.mov -c:v libx264 -crf 23 -preset slow out.mp4
Ingestion
Bulk batch limited to 200 releases. Split into multiple requests.
- When
POST /ingestion/bulkwith more than 200 releases in one payload.- How to fix
- Chunk into batches of 200 client-side. Bulk endpoints accept up to 200 per call; for larger catalogs, paginate.
415
Unsupported media type
Uploads
File type '<mime>' is not allowed for <type> uploads.
- When
- Audio upload that isn't WAV/FLAC/AIFF/MP3/AAC, or image upload that isn't JPEG/PNG/TIFF/WebP, etc.
- How to fix
- See accepted formats per asset type in the API Reference. WAV 24-bit / 44.1 kHz / stereo is the safe audio floor.
422
Unprocessable entity
Validation
Validation failed (per-field errors in <code>errors{}</code>)
- When
- One or more fields in your request body failed validation.
- How to fix
- Read
errors— it maps field path → array of human-readable error messages, translated to the user's locale. Surface these directly in your UI.
Auth
Invalid or expired OTP.
- When
POST /auth/verify-otpwith the wrong code or after the 10-min TTL.- How to fix
- Call
POST /auth/resend-otpto mint a fresh one. After 5 wrong attempts you'll be rate-limited.
Auth
Invalid or expired reset token.
- When
- Password-reset link is past its 24-hour TTL, already used, or tampered with.
- How to fix
- Re-trigger
POST /auth/forgot-passwordto mint a new one.
Auth
Current password is incorrect.
- When
PATCH /users/mewith a wrongcurrent_passwordwhile trying to changenew_password.- How to fix
- Have the user re-enter their current password. Don't auto-retry.
Catalog
Please add at least one track before submitting.
- When
POST /releases/:uuid/submiton a release with no tracks attached.- How to fix
- Add tracks via
POST /releases/:uuid/tracksfirst.
Catalog
Please select at least one store before submitting.
- When
- Release has no DSPs attached.
- How to fix
POST /releases/:uuid/dspswith the DSP slugs you want to distribute to.
Catalog
Please set a release date before submitting.
- When
- Release has no
release_date. - How to fix
PATCH /releases/:uuidwith{"release_date": "YYYY-MM-DD"}. Allow at least 7 days lead time for DSPs to ingest.
Catalog
No audio file provided.
- When
POST /tracks/:uuid/audiowith noaudiofile in the multipart body.- How to fix
- Send the file as
audioin amultipart/form-datarequest.
Catalog
Split percentages must sum to 100.
- When
- Royalty split rows for a track don't add up to 100% (within 0.01% tolerance).
- How to fix
- Adjust the percentages client-side before sending. Splits are validated atomically.
Tenants
Unable to resolve tenant. Check your domain configuration.
- When
- Whitelabel domain doesn't map to a tenant (DNS / config mismatch).
- How to fix
- Verify the
X-Tenant-Domainheader or the CNAME for your custom domain.
Webhooks
Webhook subscription limit (25) reached.
- When
- Tenant already has 25 active webhook subscriptions.
- How to fix
- Delete unused webhooks via
DELETE /webhooks/:uuidfirst.
DDEX
No DSPs attached to this release. Add DSPs via POST /releases/:uuid/dsps first.
- When
- You called the deliver / purge / redeliver endpoints on a release with no DSP attachments.
- How to fix
POST /releases/:uuid/dspswith the DSP slugs you want.
Billing
This plan is free — no payment required.
- When
- You tried to charge for a free plan.
- How to fix
- Skip the checkout flow entirely for free plans. The plan flips active immediately.
429
Too many requests
Rate limit
Too many requests. Please slow down.
- When
- You exceeded the per-window rate limit. Auth endpoints: 5/min. Standard endpoints: 120/min. Ingestion bulk: 30/min.
- How to fix
- Honour the
Retry-Afterheader (seconds), then resume. WatchX-RateLimit-Remainingproactively. Don't burst-retry — that just hardens the block.
5xx Server errors
500
Internal server error
Server
Internal server error.
- When
- Unhandled exception on our end. Every 500 is logged with a request id (
X-Request-Idresponse header). - How to fix
- Capture the
X-Request-Idfrom the response and send it to support@interspacemusic.com. Retry once with exponential backoff; sustained 500s are real.
502
Bad gateway
Billing
Payment initialization failed.
- When
- Paystack / Stripe / etc. returned an error during checkout init.
- How to fix
- Surface to the user, let them retry. We log every failed init to
audit_logfor ops investigation.
503
Service unavailable
Status
Service temporarily unavailable.
- When
- Database ping failed (
GET /healthreturns this withchecks.db.ok = false). - How to fix
- Retry with exponential backoff (1s, 2s, 4s, …). Sustained 503 = page /status.