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

> ## Agent Instructions
> Five API is a video generation REST API. Base URL: https://api.fiveapi.ai. Authenticate with the header Authorization: Bearer <API key>; read the key from the FIVEAPI_API_KEY environment variable and never hard-code it.
> Every generation is an asynchronous task: POST /v1/{brand}/{version}/{task} returns a queued task, then poll GET /v1/tasks/{task_id} or receive a signed webhook, and download output.video.url before expires_at (7 days).
> The OpenAPI spec is at https://docs.fiveapi.ai/api-reference/openapi.yaml. An installable agent skill: npx skills add https://docs.fiveapi.ai

# Errors

> The error format, every error code, why a task can fail, and which errors to retry.

Five API reports problems in two places:

* **Request errors** answer the HTTP request itself with a `4xx` or `5xx` status and an error body. Nothing is created and nothing is charged.
* **Task failures** happen after a task was accepted. The task ends with `status: failed`, its `error` explains why, and its credits are released.

## Error format

Every error response has the same body:

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_parameter",
    "message": "duration 20 s at 768p is not available on this model",
    "param": "duration",
    "request_id": "req_01M5KN36P1JPANPMDW0HEWMM07"
  }
}
```

| Field | Description |
| - | - |
| `type` | The category: `invalid_request_error`, `authentication_error`, `billing_error`, `permission_error`, `not_found_error`, `conflict_error`, `rate_limit_error` or `api_error`. |
| `code` | A stable, machine-readable code. **Branch on `code`**, never on `message`. |
| `message` | A human-readable explanation. Its wording may change. |
| `param` | The request field at fault, when there is one. |
| `request_id` | The id of the request, also in the `X-Request-Id` header. Include it when you contact support. |
| `details` | Extra data for some codes, for example `required` and `available` on `insufficient_credits`. |

New codes may be added over time. Handle an unknown code by its `type` and HTTP status.

## Request errors

| HTTP | `code` | Meaning | Retry? |
| - | - | - | - |
| `400` | `invalid_json` | The body is not a JSON object, or `Content-Type` is not `application/json` | No: fix the request |
| `400` | `missing_parameter` | A required field is missing; `param` names it | No |
| `400` | `invalid_parameter` | A field has the wrong type or is out of range, the model does not offer this resolution and duration, or a query parameter is invalid | No |
| `400` | `unsupported_model` | The model exists but is not available | No |
| `400` | `url_not_allowed` | An input URL or `webhook_url` breaks the [URL policy](https://testweb2-docs-openapi.test765.com/concepts/input-files.md#url-policy) | No: fix the URL |
| `400` | `idempotency_key_reused` | The `Idempotency-Key` was already used with a different body | No: use a new key |
| `401` | `invalid_api_key` | No key was sent, or the key is unknown | No |
| `401` | `api_key_revoked` | The key was revoked | No |
| `401` | `api_key_expired` | The key expired | No |
| `402` | `insufficient_credits` | The spendable balance does not cover the estimate; `details` has `required` and `available` | After a top-up |
| `403` | `insufficient_scope` | The key lacks the scope for this endpoint | No |
| `403` | `ip_not_allowed` | The caller's IP address is not on the key's allowlist | No |
| `403` | `account_not_active` | The account has not been approved yet | No |
| `403` | `account_suspended` | The account was suspended | No |
| `404` | `model_not_found` | Unknown model id | No |
| `404` | `task_not_found` | Unknown task, or a task of another account | No |
| `404` | `not_found` | Unknown endpoint | No |
| `409` | `task_already_terminal` | Cancel on a task that already completed or failed | No |
| `409` | `idempotency_in_progress` | The first request with this `Idempotency-Key` is still running | Yes, after a moment, with the same key and body |
| `429` | `rate_limit_exceeded` | Too many requests | Yes, after `Retry-After` |
| `429` | `concurrency_limit_exceeded` | Too many tasks queued or processing | Yes, after `Retry-After` or when a task finishes |
| `429` | `daily_cap_exceeded` | The plan's daily credit cap would be exceeded | Yes, after `Retry-After` |
| `500` | `internal_error` | Unexpected error | Yes, with backoff and the same `Idempotency-Key` |
| `503` | `service_unavailable` | Generation capacity is temporarily unavailable; nothing was charged | Yes, after `Retry-After` and with the same `Idempotency-Key` |

## Task failures

A task that was accepted can still fail. Its `error` tells you why and whether a new attempt can succeed:

```json theme={null}
{
  "id": "task_01J9X8A1B2C3D4E5F6G7H8J9K0",
  "object": "task",
  "status": "failed",
  "error": {
    "code": "generation_failed",
    "message": "the model failed to produce a result",
    "retryable": true
  },
  "credits": { "estimated": 9 },
  "...": "..."
}
```

| `error.code` | `retryable` | Meaning |
| - | - | - |
| `input_fetch_failed` | yes | An input file could not be downloaded or processed. Check that the URL is still valid. |
| `input_invalid` | no | The input was downloaded but cannot be used: format, dimensions or length. |
| `content_moderation_rejected` | no | The request was rejected by the content policy. `reason` may name the category: `ip` (protected intellectual property), `audio_copyright` or `public_figure`. |
| `generation_failed` | yes | The model did not produce a result. |
| `timeout` | yes | The task did not finish in time. |
| `service_unavailable` | yes | Generation capacity became unavailable after the task was accepted. |

Failed tasks are never charged. To try again, create a **new** task (with a new `Idempotency-Key`); a failed task cannot be restarted.

## Retry strategy

Retry only what can succeed:

* **`429` and `503`:** wait `Retry-After` seconds, then retry.
* **`500` and network errors:** retry with exponential backoff.
* **Other `4xx`:** don't retry. Fix the request.

Always retry with the **same `Idempotency-Key`** so a retry can never create a second task. See [Idempotency](https://testweb2-docs-openapi.test765.com/concepts/idempotency.md).

```python Python theme={null}
import time

import requests


def create_task(api_key: str, model: str, body: dict, idempotency_key: str, max_attempts: int = 5) -> dict:
    headers = {"Authorization": f"Bearer {api_key}", "Idempotency-Key": idempotency_key}
    for attempt in range(max_attempts):
        try:
            r = requests.post(f"https://api.fiveapi.ai/v1/{model}", json=body, headers=headers, timeout=30)
        except requests.RequestException:
            time.sleep(2 ** attempt)  # network error: back off
            continue
        if r.status_code in (429, 503):
            time.sleep(int(r.headers.get("Retry-After", 2 ** attempt)))
            continue
        if r.status_code >= 500:
            time.sleep(2 ** attempt)
            continue
        if r.status_code >= 400:
            raise RuntimeError(f"{r.status_code} {r.json()['error']['code']}")  # don't retry
        return r.json()
    raise RuntimeError(f"gave up after {max_attempts} attempts")
```

```javascript Node.js theme={null}
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function createTask(apiKey, model, body, idempotencyKey, maxAttempts = 5) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const res = await fetch(`https://api.fiveapi.ai/v1/${model}`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${apiKey}`,
        "Content-Type": "application/json",
        "Idempotency-Key": idempotencyKey,
      },
      body: JSON.stringify(body),
    }).catch(() => null);
    if (!res) { await sleep(1000 * 2 ** attempt); continue; } // network error
    if (res.status === 429 || res.status === 503) {
      await sleep(1000 * Number(res.headers.get("Retry-After") ?? 2 ** attempt));
      continue;
    }
    if (res.status >= 500) { await sleep(1000 * 2 ** attempt); continue; }
    if (!res.ok) throw new Error(`${res.status} ${(await res.json()).error.code}`); // don't retry
    return res.json();
  }
  throw new Error(`gave up after ${maxAttempts} attempts`);
}
```

## Get help with an error

Email [support@fiveapi.ai](mailto:support@fiveapi.ai) with the `request_id` of the failed request, or the task `id` of a failed task, and the time it happened.


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