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

# Errors

> Every error code, what it means and whether to retry.

A request that is refused answers `application/problem+json` with a stable `code`, a `title`, a human `detail`, `retryable` and `request_id` (also the `X-Request-Id` header). `x-should-retry` mirrors `retryable`, and `Retry-After` gives the wait when there is one. A run that starts and then fails is not an HTTP error: the run object answers `200` with `status: "failed"` and an `error` with one of the run codes below.

## Request errors

| Code | HTTP | Meaning | Retry |
| - | - | - | - |
| `INVALID_JSON` | 400 | Invalid JSON | No: change the request first |
| `INVALID_REQUEST` | 400 | Invalid request | No: change the request first |
| `INVALID_HEADER` | 400 | Invalid header | No: change the request first |
| `INVALID_INPUT` | 400 | Invalid input | No: change the request first |
| `UNAUTHENTICATED` | 401 | Authentication required | No: change the request first |
| `API_KEY_REVOKED` | 401 | API key revoked | No: change the request first |
| `API_KEY_EXPIRED` | 401 | API key expired | No: change the request first |
| `SPEND_LIMIT_REACHED` | 402 | Spend limit reached | No: change the request first |
| `INSUFFICIENT_BALANCE` | 402 | Insufficient balance | No: change the request first |
| `PERMISSION_DENIED` | 403 | Permission denied | No: change the request first |
| `ORG_SUSPENDED` | 403 | Organization suspended | No: change the request first |
| `PROVIDER_DISABLED_BY_ORG` | 403 | Provider turned off | No: change the request first |
| `MODEL_DISABLED_BY_ORG` | 403 | Model turned off | No: change the request first |
| `NOT_FOUND` | 404 | Not found | No: change the request first |
| `PROVIDER_NOT_FOUND` | 404 | Provider not found | No: change the request first |
| `MODEL_NOT_FOUND` | 404 | Model not found | No: change the request first |
| `RUN_NOT_FOUND` | 404 | Run not found | No: change the request first |
| `FILE_NOT_FOUND` | 404 | File not found | No: change the request first |
| `METHOD_NOT_ALLOWED` | 405 | Method not allowed | No: change the request first |
| `IDEMPOTENCY_IN_PROGRESS` | 409 | Request in progress | Yes, with the same `Idempotency-Key` |
| `MODEL_RETIRED` | 410 | Model retired | No: change the request first |
| `PAYLOAD_TOO_LARGE` | 413 | Payload too large | No: change the request first |
| `UNSUPPORTED_MEDIA_TYPE` | 415 | Unsupported media type | No: change the request first |
| `IDEMPOTENCY_KEY_REUSED` | 422 | Idempotency key reused | No: change the request first |
| `PRICE_UNAVAILABLE` | 422 | Price unavailable | No: change the request first |
| `MODEL_NOT_AVAILABLE` | 422 | Model not available | No: change the request first |
| `INPUT_URL_UNREACHABLE` | 422 | Input URL unreachable | No: change the request first |
| `RATE_LIMITED` | 429 | Too many requests | Yes, after `Retry-After` |
| `CONCURRENCY_LIMITED` | 429 | Too many runs in progress | Yes, after `Retry-After` |
| `QUEUE_FULL` | 429 | Queue full | Yes, after `Retry-After` |
| `INTERNAL_ERROR` | 500 | Internal error | Yes, with the same `Idempotency-Key` |
| `BILLING_UNAVAILABLE` | 503 | Billing unavailable | Yes, with the same `Idempotency-Key` |
| `SCHEMA_UNAVAILABLE` | 503 | Schema unavailable | Yes, after `Retry-After` |
| `PROVIDER_PAUSED` | 503 | Provider paused | Yes, after `Retry-After` |
| `MODEL_PAUSED` | 503 | Model paused | Yes, after `Retry-After` |
| `SERVICE_UNAVAILABLE` | 503 | Service unavailable | Yes, with the same `Idempotency-Key` |

## Run errors

| Code | Final status | Retryable | Charged | Message |
| - | - | - | - | - |
| `PROVIDER_INVALID_INPUT` | failed | no | only what the provider billed (rare) | The provider rejected this input. Check the fields against the model's schema and try again. |
| `INPUT_URL_UNREACHABLE` | failed | no (fix the URL) | only what the provider billed | An input URL could not be read. Make sure it is public, reachable and points to a supported file. |
| `CONTENT_POLICY_VIOLATION` | failed | no (change the input) | the provider's rule (billed when it did GPU work) | The request was refused by content safety checks. Change the input and try again. |
| `PROVIDER_RATE_LIMITED` | failed | yes, after about a minute | \$0 | The provider is receiving too many requests right now. You were not charged. Try again in a minute. |
| `PROVIDER_UNAVAILABLE` | failed | yes | \$0 | The provider is temporarily unavailable. You were not charged. Try again later. |
| `PROVIDER_TIMEOUT` | failed | yes | only what the provider billed | The provider did not finish in time. Try again, or send a shorter or smaller request. |
| `PROVIDER_ERROR` | failed | yes | only what the provider billed | The provider could not complete this request. |
| `PROVIDER_OUTCOME_UNKNOWN` | failed | no (a new run may repeat paid work) | the provider's billing for this run, else \$0 | We could not confirm the result with the provider. |
| `EMPTY_OUTPUT` | failed | yes | per the provider's receipt | The provider finished but returned no usable output. |
| `OUTPUT_UNAVAILABLE` | failed | yes | \$0 (Magica loss) | The result could not be stored. You were not charged. Try again. |
| `OUTPUT_TOO_LARGE` | failed | no (ask for less) | \$0 (Magica loss) | The result is larger than this model's output limit. You were not charged. Request a smaller output. |
| `QUEUE_TIMEOUT` | failed | yes | \$0 | The run waited too long to start and was stopped. You were not charged. Try again. |
| `QUEUE_UNAVAILABLE` | failed | yes | \$0 | The run could not be started right now. You were not charged. Try again. |
| `RUN_TIMEOUT` | failed | yes | only what the provider billed | The run took longer than this model's time limit. |
| `MODEL_UNAVAILABLE` | failed | no | \$0 | This model is no longer available for this input. You were not charged. |
| `CANCELED` | canceled | no | only what the provider billed before the cancel landed | The run was canceled. |
| `PROVIDER_DISABLED_BY_ORG` | canceled | no | \$0 | Your organization turned off this provider before the run started. You were not charged. |
| `MODEL_DISABLED_BY_ORG` | canceled | no | \$0 | Your organization turned off this model before the run started. You were not charged. |
| `ORG_SUSPENDED` | canceled | no | \$0 (runs already submitted finish and are charged) | Your organization was suspended before the run started. You were not charged. |
| `INTERNAL_ERROR` | failed | yes | \$0 | Something went wrong on our side before the run started. You were not charged. Try again. |

## Retry guidance

1. Retry automatically only on network errors and timeouts (same `Idempotency-Key`) and on the codes below. `retryable` and `x-should-retry` on the answer always win over this table (for example `RATE_LIMITED` is not retryable once the `day` policy is exhausted). Every other code needs a change before the request is sent again.

| Code | HTTP | Retry | Wait |
| - | - | - | - |
| INSUFFICIENT\_BALANCE | 402 | only when the problem says `retryable: true`, with the same `Idempotency-Key` | `Retry-After` (30 s by default) |
| IDEMPOTENCY\_IN\_PROGRESS | 409 | yes, with the same `Idempotency-Key` | `Retry-After` (1 s by default) |
| RATE\_LIMITED | 429 | yes | `Retry-After` |
| CONCURRENCY\_LIMITED | 429 | yes | `Retry-After` (2 s by default) |
| QUEUE\_FULL | 429 | yes | `Retry-After` (2 s by default) |
| INTERNAL\_ERROR | 500 | yes, with the same `Idempotency-Key` | backoff (rule 2) |
| BILLING\_UNAVAILABLE | 503 | yes, with the same `Idempotency-Key` | `Retry-After` (5 s by default) |
| SCHEMA\_UNAVAILABLE | 503 | yes | `Retry-After` (10 s by default) |
| PROVIDER\_PAUSED | 503 | yes | `Retry-After` (60 s by default) |
| MODEL\_PAUSED | 503 | yes | `Retry-After` (60 s by default) |
| SERVICE\_UNAVAILABLE | 503 | yes, with the same `Idempotency-Key` | `Retry-After` (5 s by default) |

2. Backoff: capped exponential with full jitter, `sleep = random(0, min(30 s, 1 s × 2^attempt))`, at most 4 retries and about 2 minutes in total for a create.
3. Retry-After is a floor: wait at least that long (add 0–20 % jitter). Magica never sends more than 60 s.
4. Keys: send a UUIDv4 `Idempotency-Key` on every `POST /v1/runs` and store it with your task before sending. Reuse it for every retry of the same intent, including after a restart; a replay returns the original run with `Idempotent-Replayed: true`, never a second run or charge. Use a new key only to start a new run deliberately. A key is remembered for 3 days, then may start a new run.
5. Unknown outcome of a create (timeout, connection reset): retry with the same key. Never switch to a new key until the first request is known not to have created a run.
6. Failed runs: start at most one new run (new key), and only when `error.retryable` is true. `PROVIDER_OUTCOME_UNKNOWN` is not retryable: check your own results first, because the provider may have done the work.
7. Polling: prefer webhooks. Otherwise use `GET /v1/runs/{id}?wait_seconds=30`, or poll by `Retry-After` on 202 and running responses; without it start at 1 s (search and scrape), 2 s (images), 5 s (video and audio), back off × 1.5 up to 30 s, and stop at a final status. Polling has its own rate-limit policy (`poll`), so it never consumes create quota.
8. Webhooks: verify the signature over the raw body with your org's signing secret (any Standard Webhooks library; during a secret rotation the header carries two signatures and either verifies); answer 2xx fast and do the work afterwards (a delivery that takes over 10 s is re-sent); ignore event types you do not handle (types are added over time); dedupe on `webhook-id` for at least 7 days (every re-send carries the same one); on `truncated: true` read the run with `GET /v1/runs/{id}` (the body left out `output` to stay under receiver limits); ignore a delivery whose run `sequence` is lower than one already applied; download outputs within 24 hours. A webhook is sent right after the run is charged, so it usually carries the final charge (`sequence` 4); when the provider's bill comes later it carries `cost.state: held` (`sequence` 3) and the final charge is on `GET /v1/runs/{id}` (`sequence` 4). No separate billing event is sent.
9. Runs cannot be canceled after submission. Poll the run or wait for its configured terminal webhook.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.