> ## Documentation Index
> Fetch the complete documentation index at: https://www.getsoundlink.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Standard error codes and HTTP status mapping for the Public API v1.

All errors follow:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": {
    "code": "invalid_query_parameter",
    "message": "Human-readable summary."
  },
  "meta": { "requestId": "..." }
}
```

Always cite `meta.requestId` when reporting issues to Soundlink.

Using the TypeScript SDK? API errors arrive as `{ data: null, error }` on every method — see [Access the API with TypeScript](/docs/typescript-sdk#errors). Thrown `SoundlinkSdkError` subclasses are only for config, parse, and transport failures.

## Common codes

| HTTP | Code                      | When                                                                  |
| ---- | ------------------------- | --------------------------------------------------------------------- |
| 401  | `invalid_api_key`         | Missing or malformed API key (`x-api-key` or `Authorization: Bearer`) |
| 401  | `api_key_revoked`         | Key revoked                                                           |
| 401  | `api_key_expired`         | Key past `expires_at`                                                 |
| 401  | `mixed_credentials`       | Both `x-api-key` and `Authorization` on the same request              |
| 403  | `insufficient_scope`      | Valid key missing route scope                                         |
| 404  | `not_found`               | Unknown path                                                          |
| 404  | `campaign_not_found`      | Unknown campaign or other org's campaign                              |
| 400  | `invalid_query_parameter` | Bad pagination or sort params                                         |
| 400  | `invalid_date_range`      | `endDate` before `startDate`                                          |
| 400  | `page_size_exceeded`      | `pageSize` above endpoint max                                         |
| 429  | `rate_limit_exceeded`     | Per-key rate limit (honor `Retry-After`)                              |
| 500  | `internal_error`          | Unexpected failure — retry with backoff                               |

## Write endpoint codes

Returned by campaign creation and management routes (`campaigns:write`). See [Creating campaigns](/docs/creating-campaigns) and [Managing campaigns](/docs/managing-campaigns).

| HTTP | Code                             | When                                                                                                      |
| ---- | -------------------------------- | --------------------------------------------------------------------------------------------------------- |
| 400  | `invalid_request`                | Missing/malformed body field, missing `Idempotency-Key`, non-wallet campaign, or a decrease rule violated |
| 400  | `invalid_tier_status`            | Tier update items invalid (missing tiers, sum ≠ 100, none enabled)                                        |
| 402  | `insufficient_credit`            | Wallet balance too low — `details.available` / `details.required`                                         |
| 403  | `wallet_not_enabled`             | Organization not enabled for wallet billing                                                               |
| 409  | `idempotency_key_conflict`       | `Idempotency-Key` reused with a different body, or still processing                                       |
| 409  | `tier_update_cooldown`           | Tier update within 72 hours of the previous one                                                           |
| 422  | `invalid_genre`                  | Genre not in the supported list                                                                           |
| 422  | `invalid_daily_budget`           | `dailyBudget` below \$10/day                                                                              |
| 422  | `invalid_duration_days`          | `durationDays` outside 7–30 and not 60/90                                                                 |
| 422  | `invalid_spotify_url`            | Malformed Spotify URL, or track/playlist does not exist                                                   |
| 422  | `invalid_tier_budget_allocation` | Tier percentages invalid (sum, count, or per-tier minimum)                                                |

## Video import codes

Returned by video import routes (`videos:write`). See [Importing videos](/docs/importing-videos).

| HTTP | Code                             | When                                                               |
| ---- | -------------------------------- | ------------------------------------------------------------------ |
| 400  | `invalid_video_url`              | Not HTTPS, unreachable, not MP4, over 50 MB, or download timed out |
| 403  | `video_import_limit_exceeded`    | Plan video quota or organization storage limit exceeded            |
| 404  | `video_import_session_not_found` | Unknown session or another organization's session                  |
| 429  | `rate_limit_exceeded`            | Stricter per-key limit: 5 imports/hour (honor `Retry-After`)       |

## Pagination limits

* Campaign list: `pageSize` max **100**
* Metrics breakdown list: `pageSize` max **500** (see endpoint docs)
