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

# Error Codes

> HTTP status codes, error response format, and common error scenarios for the SuperDocs API.

# Error Codes

All API errors return a JSON response with a `detail` field:

```json theme={null}
{
  "detail": "Human-readable error message"
}
```

## Status codes

| Code    | Meaning                  | Common causes                                                                                                                                                                          |
| ------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **400** | Bad Request              | Empty message, invalid parameters                                                                                                                                                      |
| **401** | Unauthorized             | Missing or invalid API key, expired token                                                                                                                                              |
| **403** | Forbidden                | Accessing a resource you don't own; wrong agent-takeover code (the `detail` says how many attempts remain)                                                                             |
| **404** | Not Found                | Job, session, template, or attachment doesn't exist; revert target message not in active history; pre-signed upload expired; expired or unknown agent-takeover link                    |
| **409** | Conflict                 | Revert blocked because a chat job is currently running on the same session                                                                                                             |
| **410** | Gone                     | Agent-takeover link permanently disabled after too many incorrect codes. Terminal: the old link can never work again; the agent must send a fresh handoff link                         |
| **413** | Request Entity Too Large | Request body or export payload above the size cap                                                                                                                                      |
| **415** | Unsupported Media Type   | Upload file extension not supported, including a legacy `.doc` upload (convert to `.docx`); use `.pdf`, `.docx`, `.txt`, `.rtf`, `.md`, `.html`, `.htm`                                |
| **422** | Validation Error         | Request body doesn't match expected schema; format value outside the allowed enum; revert target message predates the revert feature                                                   |
| **429** | Too Many Requests        | Monthly operation limit reached, or an endpoint-specific cooldown. Application 429s are JSON and always carry a `Retry-After` header (seconds); see [Rate Limits](/errors/rate-limits) |
| **500** | Internal Server Error    | Unexpected server error                                                                                                                                                                |
| **504** | Gateway Timeout          | AI processing exceeded 30 minutes                                                                                                                                                      |

## Common errors and fixes

### Authentication errors (401)

```json theme={null}
{"detail": "Invalid authorization header format. Expected 'Bearer <api_key>'"}
```

**Fix:** Use `Authorization: Bearer sk_YOUR_KEY` (include the `Bearer ` prefix).

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

**Fix:** Check that your key is correct and hasn't been revoked. Generate a new key from Settings > API Keys.

### Validation errors (400)

```json theme={null}
{"detail": "Message cannot be empty. Please provide a text message."}
```

**Fix:** Include a non-empty `message` in your request body.

### Unsupported file type (415)

```json theme={null}
{"detail": "Unsupported file type: .xyz. Supported types: .pdf, .docx, .txt, .rtf, .md, .html, .htm"}
```

A legacy binary `.doc` upload returns the same `415`:

```json theme={null}
{"detail": "Unsupported file type: .doc. Supported types: .pdf, .docx, .txt, .rtf, .md, .html, .htm"}
```

**Fix:** Upload one of the supported formats — `.pdf`, `.docx`, `.txt`, `.rtf`, `.md`, `.html`, `.htm`. Convert legacy `.doc` files to `.docx` first. RTF is supported as an upload **input** only; it is not an export target. Catch `415` (Unsupported Media Type) separately from `400` when handling upload-validation failures.

### Rate limit (429)

```json theme={null}
{"detail": "Your monthly operation quota (500) is exhausted. Upgrade to Pro for uninterrupted pay-as-you-go overage."}
```

**Fix:** Upgrade your plan at Settings > Billing, or wait for your monthly reset. Honor the `Retry-After` header (seconds until the request can succeed) and branch on the `429` status and the `X-Usage-Limit` / `X-Usage-Used` / `X-Usage-Remaining` headers rather than the `detail` string (the wording may change). Check the `usage` object in chat responses to monitor remaining operations. A plain-text `429` with no `Retry-After` is an infrastructure surge response, not an application error; back off with jitter and retry (see [Rate Limits](/errors/rate-limits)).

### Timeout (504)

Both the synchronous `/v1/chat` and the async `/v1/chat/async` endpoints apply a 30-minute wall-clock cap, but they surface the timeout differently:

**Synchronous `/v1/chat`** returns an HTTP `504` with a plain `detail` string:

```json theme={null}
{"detail": "The AI agent took longer than 30 minutes to process your request. For long edits or multi-step tasks, use chat_async."}
```

**Async `/v1/chat/async`** does not return a `504` on the poll — the job completes and the friendly summary below is persisted as the job's AI response (read it from the job result):

```
⏱️ Your request ran past my 30-minute cap and I had to wrap up. For very large
documents, try splitting the task into multiple smaller turns — e.g. one section
at a time. Your prompt is still in your history above; you can revise it and
re-send.
```

**Fix:** Use the async endpoint (`/v1/chat/async`) for long operations — it streams `intermediate` progress events as the work runs and supports human-in-the-loop approval. Split large requests into smaller turns (one section per turn).

### Request too large (413)

The 413 response covers two distinct cases — caller-too-large and document-too-large for the chosen export format — with a structured JSON detail body so clients can react appropriately.

**Caller payload exceeds the transport limit:**

```json theme={null}
{
  "detail": "Request body too large",
  "error_code": "request_too_large",
  "message_user": "Your request is too large. The current limit is 100 MB.",
  "request_size_mb": 142.3,
  "max_size_mb": 100,
  "suggested_action": "split_request",
  "contact_email": "hello@superdocs.app",
  "support_event_id": "abc1234567890"
}
```

<Note>
  A much smaller \~32 MiB platform limit sits in front of the application. A body over that ceiling is rejected at the gateway with a generic error page (HTML), **not** this structured JSON body — so don't try to parse it as JSON. Keep request bodies well under that limit; for large exports, switch to the upload-then-export pattern below.
</Note>

**Fix:** For exports, switch to the upload-then-export pattern — see [Large documents](/concepts/documents#large-documents). For other endpoints, split the work into smaller requests.

**Export payload exceeds the format-specific cap:**

```json theme={null}
{
  "detail": {
    "error_code": "document_too_large",
    "message_user": "This document is 142.3 MB, which exceeds the 100 MB export limit for the chosen format. Email hello@superdocs.app or use the in-app 'Email me a copy' button — we'll send you the rendered file within 24 hours.",
    "suggested_action": "email_request",
    "contact_email": "hello@superdocs.app",
    "document_size_mb": 142.3,
    "max_size_mb": 100,
    "format": "docx",
    "support_event_id": "abc1234567890"
  }
}
```

**Fix:** Call `POST /v1/documents/export/email-request` instead — the file will be rendered in the background and emailed as a 7-day signed download link. See [Email fallback for very large documents](/concepts/documents#email-fallback-for-very-large-documents).

| Field                                  | Description                                                                      |
| -------------------------------------- | -------------------------------------------------------------------------------- |
| `error_code`                           | `request_too_large` (transport layer) or `document_too_large` (export cap).      |
| `message_user`                         | Human-readable explanation safe to surface in your UI.                           |
| `suggested_action`                     | `split_request` or `email_request`. Use to switch your client between paths.     |
| `request_size_mb` / `document_size_mb` | Observed payload size.                                                           |
| `max_size_mb`                          | Configured cap for the format / endpoint.                                        |
| `format`                               | Export format that triggered the cap (only on `document_too_large`).             |
| `contact_email`                        | Support contact for follow-up.                                                   |
| `support_event_id`                     | Opaque correlation ID. Share with `hello@superdocs.app` when reporting an issue. |

### Validation errors (422)

```json theme={null}
{"detail": [{"type": "literal_error", "loc": ["body", "format"], "msg": "Input should be 'docx', 'pdf', 'html', 'markdown', 'txt' or 'doc'"}]}
```

**Fix:** `format` is now a strict enum on `/v1/documents/export`. Use one of `"docx"`, `"pdf"`, `"html"`, `"markdown"`, `"txt"`. The value `"doc"` is accepted as a legacy alias and will be removed in a future release.

```json theme={null}
{"detail": [{"type": "string_pattern_mismatch", "loc": ["body", "session_id"], "msg": "String should match the expected pattern"}]}
```

**Fix:** `session_id` may contain only letters, digits, and the characters `_`, `-`, and `.`, up to a maximum of 256 characters. Drop spaces, slashes, and other punctuation from the id you choose.

### Not found (404)

```json theme={null}
{"detail": "Job not found"}
```

**Fix:** Jobs are cleaned up 1 hour after completion. Check the job ID and timing. Use `/v1/jobs` to list active jobs.

### Revert conflicts (409)

```json theme={null}
{"detail": "Cannot revert while a chat job is running for this session. Wait for it to complete or cancel it first."}
```

**Fix:** Wait for the in-flight job to finish (poll `/v1/jobs/{job_id}` or watch the SSE stream until you see `final`), or cancel it via `POST /v1/jobs/{job_id}/cancel` before retrying revert.

### Revert target too old (422)

```json theme={null}
{"detail": "This message predates the revertability feature and cannot be reverted. Start a new chat to use revert."}
```

**Fix:** Per-message revert only works for chats started after the feature shipped. Older sessions remain readable but their messages don't carry the marker the rewind needs. Start a new session for full revert support.
