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

# Errors

> HTTP status codes and error response shapes returned by the Demomatic API.

## Error response format

Most error responses return a JSON body with an `error` field:

```json theme={null}
{
  "error": "<message>"
}
```

Some endpoints return a plain-text message body instead of JSON. Check the `Content-Type` response header when parsing errors programmatically.

## HTTP status codes

| Status                      | Meaning                                                     |
| --------------------------- | ----------------------------------------------------------- |
| `200 OK`                    | Request succeeded.                                          |
| `400 Bad Request`           | Invalid parameters or missing required fields.              |
| `401 Unauthorized`          | Missing, invalid, or insufficient API key.                  |
| `403 Forbidden`             | Your plan does not include this feature.                    |
| `404 Not Found`             | Resource does not exist or does not belong to your account. |
| `429 Too Many Requests`     | Rate limit exceeded (100 requests per 2-minute window).     |
| `500 Internal Server Error` | Unexpected server error.                                    |

## Common errors

<AccordionGroup>
  <Accordion title="401 — Missing API key">
    The `Authorization` header is absent or does not start with `Bearer `.

    ```json theme={null}
    "Missing API key"
    ```

    Add the header to your request:

    ```bash theme={null}
    curl -H "Authorization: Bearer YOUR_API_KEY" \
      https://api.demomatic.tech/v1/videos
    ```
  </Accordion>

  <Accordion title="401 — Invalid API key">
    The key in the `Authorization` header does not match any active key on your account.

    ```json theme={null}
    "Invalid API key"
    ```

    Verify that the key is copied correctly and has not been deleted. You can manage your keys in **Settings > API Keys**.
  </Accordion>

  <Accordion title="401 — Invalid permissions">
    The key has `read_only` permission but the request uses a write method (`POST`, `PUT`, or `DELETE`).

    ```json theme={null}
    "Invalid permissions"
    ```

    Either switch to a `GET` request or use an `all_access` key.
  </Accordion>

  <Accordion title="403 — Plan does not include API access">
    The account associated with the API key is not on a Starter or Growth plan.

    ```json theme={null}
    "Your plan does not include API access"
    ```

    Upgrade your plan to enable API access.
  </Accordion>

  <Accordion title="404 — Resource not found">
    The requested resource does not exist, or it belongs to a different account.

    ```bash theme={null}
    # Example: video ID that doesn't exist or belongs to another account
    curl -H "Authorization: Bearer YOUR_API_KEY" \
      https://api.demomatic.tech/v1/videos/99999
    # → 404
    ```

    Confirm the ID is correct and that the resource was created under the same account as your API key.
  </Accordion>

  <Accordion title="429 — Rate limit exceeded">
    You have sent more than 100 requests in a 2-minute window from the same IP address.

    ```json theme={null}
    "Too many requests from this IP, please try again later."
    ```

    Wait before retrying. Implement exponential backoff to avoid hitting the limit repeatedly.
  </Accordion>
</AccordionGroup>

## Handling errors in code

<CodeGroup>
  ```javascript Node.js theme={null}
  const response = await fetch('https://api.demomatic.tech/v1/videos', {
    headers: { Authorization: `Bearer ${process.env.DEMOMATIC_API_KEY}` },
  });

  if (!response.ok) {
    const body = await response.text();
    // Parse JSON error if available, otherwise use plain text
    let message;
    try {
      message = JSON.parse(body).error ?? body;
    } catch {
      message = body;
    }
    throw new Error(`Demomatic API error ${response.status}: ${message}`);
  }

  const { data } = await response.json();
  ```

  ```python Python theme={null}
  import os, requests

  response = requests.get(
      "https://api.demomatic.tech/v1/videos",
      headers={"Authorization": f"Bearer {os.environ['DEMOMATIC_API_KEY']}"},
  )

  if not response.ok:
      try:
          message = response.json().get("error", response.text)
      except ValueError:
          message = response.text
      raise Exception(f"Demomatic API error {response.status_code}: {message}")

  data = response.json()["data"]
  ```
</CodeGroup>

<Tip>
  For `429` responses, read the `Retry-After` header if present, or implement exponential backoff starting at 1 second.
</Tip>
