# Errors

> Error format and common error codes

Source: https://platform.snapany.com/docs/errors

All errors share one JSON shape:

```json
{ "message": "human readable message", "code": "machine_code", "detail": "optional detail" }
```

## Common codes

| HTTP | Code                   | Meaning                                     | Fix                                                                                                               |
| ---- | ---------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| 400  | _(varies)_             | Business failure                            | Handle by the `code` field (extraction codes below) — these calls are **not charged**                             |
| 401  | `invalid_api_key`      | Missing, malformed or deleted key           | Check the `Authorization: Bearer sk_snapany_xxx` header and the key status in [Console → API Keys](https://platform.snapany.com/console/keys) |
| 402  | `insufficient_credits` | Balance too low                             | Top up in the [Console](https://platform.snapany.com/console), or enable auto top-up                                                          |
| 404  | —                      | Resource not found (e.g. an invalid job id) | Check the resource `id` returned by the API                                                                       |
| 422  | —                      | Invalid request parameters                  | The `detail` field says which parameter failed and why                                                            |
| 429  | `rate_limited`         | Over 1200 requests/min                      | Back off and retry after a delay                                                                                  |
| 500  | —                      | Server error                                | Retry later; contact us if it persists                                                                            |

## Extraction error codes

Extraction failures return HTTP `400` with a code from the extraction engine. These are business failures — **no credits are charged**.

The **Transient** column below says whether retrying the same URL can succeed. Codes get added over time, so treat any code you don't recognise as permanent and log it rather than retrying in a loop.

| Code                        | Transient | Common cause                                          | What to do                                                  |
| --------------------------- | --------- | ----------------------------------------------------- | ----------------------------------------------------------- |
| `invalid_url`               |           | Malformed link                                        | Fix the URL format                                          |
| `unsupported_url`           |           | A valid URL, but not a post/video link                | Use the share link of a single post or video                |
| `unsupported_site`          |           | The site is not supported                             | Contact us to request it                                    |
| `invalid_playlist_url`      |           | Not a channel/profile/playlist link                   | Use a public channel, profile or playlist URL               |
| `playlist_not_supported`    |           | A playlist URL was sent to the single-post endpoint   | Use `/extract/playlist`, or pass one post URL               |
| `content_deleted`           |           | The post was deleted or never existed                 | Nothing to extract                                          |
| `user_not_found`            |           | Account deleted, renamed or restricted                | Verify the handle                                           |
| `no_story`                  |           | The account has no active stories                     | Stories expire after 24h                                    |
| `private_content`           |           | Private or follower-only content                      | Not extractable                                             |
| `members_only_content`      |           | Paid or members-only content                          | Not extractable                                             |
| `age_restricted`            |           | The media is age-restricted                           | Not extractable (see note below)                            |
| `region_restricted`         |           | The media is region-restricted                        | Not extractable (see note below)                            |
| `not_premiered`             |           | Scheduled content that has not gone live              | Retry after the publish time                                |
| `live_stream_not_supported` |           | Live streams on this site aren't supported yet        | Retry once archived as a normal video (see note below)      |
| `extract_failed`            | ✅        | Site changes, or the content is currently unreachable | Retry later; if one site keeps failing, contact us          |
| `retryable`                 | ✅        | Transient failure during extraction                   | Retry after a short delay                                   |
| `timeout`                   | ✅        | The extraction took too long                          | Retry after a short delay                                   |
| `unknown`                   | ✅        | Unclassified failure                                  | Retry once; contact us with the request time if it persists |

> `age_restricted`, `region_restricted` and `live_stream_not_supported` only come up on **a small number of sites**. Age- and region-restricted media usually extracts fine, and live streams are supported on many sites — Twitch and TikTok among them. Getting one of these three means we can't reach that kind of media on **that particular site**; it does not mean we don't support age-restricted media, region-restricted media or live streams.

## Transcription request errors

These come back from the submit call (HTTP `400`), before a job is created — nothing is charged.

| Code                       | Common cause                                                          |
| -------------------------- | --------------------------------------------------------------------- |
| `file_too_large`           | Upload over 512 MB, or the file at `file_url` exceeds the limit       |
| `audio_too_long`           | Audio longer than 6 hours                                             |
| `unsupported_audio_format` | Audio format not in the supported list, or the duration can't be read |
| `download_failed`          | We could not fetch `file_url`                                         |

## Transcription failures

A failed job shows `"status": "failed"` with an `error` field when polling, and the reserved credits are refunded automatically.
