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

# API errors

> Status codes, stable error codes, and how to decode all four envelope shapes.

This page is the API-reference view of failures. For a task-oriented guide, see [Error handling](https://docs.everabyte.com/errors/overview.md).

## Decoding algorithm

```text theme={null}
1. Parse the body defensively; it may not be JSON (for example a proxy failure).
2. If `code` exists, branch on `code`. It is stable.
3. Otherwise use `status` (or `statusCode` for framework errors).
4. Fall back to `message` for logging only, never for logic.
5. Treat 5xx messages as sanitized and non-actionable.
```

## Status codes

| Status | Meaning | Retry |
| - | - | - |
| `200` | Success. Some operations embed failure in `data.status` | No |
| `206` | Partial content, used by range downloads | No |
| `400` | Validation or request error | No |
| `401` | Missing, malformed, revoked, or expired credentials | No |
| `402` | Billing or capacity prevents the operation | No |
| `403` | Authorization, scope, surface, or quota denial | No |
| `404` | Resource not found, or not visible to this key | No |
| `410` | Trash window elapsed; resource is gone | No |
| `413` | Payload too large for the plan or trial | No |
| `429` | Rate limited | Yes, with backoff |
| `500` | Unexpected server error | Yes, bounded |
| `503` | Temporarily unavailable | Yes, bounded |

## Stable error codes

These come from middleware and guards, and are safe to branch on.

| Code | Status | Meaning | Fix |
| - | - | - | - |
| `API_COMPANY_ONLY` | 403 | Key belongs to an individual account | Use a company workspace |
| `API_KEY_SURFACE_DENIED` | 403 | Route family is not available to API keys | Use a documented storage route |
| `API_BUCKET_SCOPE_DENIED` | 403 | Key is restricted to other buckets | Use an allowed bucket or unrestricted key |
| `API_KEY_RATE_LIMITED` | 429 | Request rate exceeded | Back off and retry |
| `SUBSCRIPTION_REQUIRED` | 402 | Billing lapsed or subscription inactive | Restore billing |
| `TRIAL_API_LIMIT_REACHED` | 403 | Trial call quota exhausted | Upgrade, or wait for reset |
| `DEVICE_BLOCKED` | 403 | Device is not authorized for this key | Re-enroll the device |
| `MCP_SCOPE_REQUIRED` | 403 | MCP call without the `mcp` scope | Add the scope |
| `MCP_TRIAL_LOCKED` | 403 | MCP attempted on a trial account | Upgrade |

## Codes you should not require

Some internal errors define codes that are not guaranteed to reach clients. In particular, trial upload-limit violations are detected internally, but the upload controller's error path does not always forward the code.

Practical rule:

> [!TIP]
>
> Branch on `code` when present. Always have a status-based fallback. Never fail because a `code` is missing.

## Authorization failure triage

| Response | Likely cause |
| - | - |
| `401` | Wrong header names, whitespace in the secret, revoked key, expired key |
| `403` with `API_COMPANY_ONLY` | Individual account |
| `403` with `API_KEY_SURFACE_DENIED` | Not a storage route |
| `403` with `API_BUCKET_SCOPE_DENIED` | Bucket restriction |
| `403` with no code | Missing scope; check the required pair |
| `404` | Resource does not exist, or is not visible to this key |
| `402` | Billing state or storage capacity |

A `404` on a resource you believe exists is often a visibility problem, not a deletion. Verify the bucket and the key's restriction before assuming data loss.

## Nested-status operations

These return HTTP `200` with the real outcome inside the body:

| Operation | Inspect |
| - | - |
| `POST /files/{fileId}/restore` | `data.status` |
| `POST /files/{fileId}/versions/{versionId}/restore` | `data.status` |
| `DELETE /files/{fileId}/versions/{versionId}` | `data.status` |
| `POST /folders/restore-from-trash/{folderId}` | `message` and `data` |

Example of a nested failure:

```json theme={null}
{
  "status": 200,
  "message": "Restore operation completed with errors",
  "data": {
    "status": 400,
    "message": "Cannot restore the current version"
  }
}
```

Do not treat the outer `200` as success.

## Rate limit responses

`429` responses use `API_KEY_RATE_LIMITED`. No `Retry-After` header is documented.

Use exponential backoff with jitter:

```text theme={null}
base 1s, multiplier 2, cap 30s, full jitter, max 5 attempts
```

Do not retry `401`, `402`, or `403`.

## Error handling example

```typescript theme={null}
type ApiError = {
  status: number;
  message: string;
  code?: string;
};

function normalize(payload: unknown, httpStatus: number): ApiError {
  const body = (payload ?? {}) as Record<string, unknown>;
  return {
    status: httpStatus,
    message: typeof body.message === "string" ? body.message : "Unknown error",
    code: typeof body.code === "string" ? body.code : undefined,
  };
}

function shouldRetry(error: ApiError): boolean {
  if (error.status === 429) return true;
  if (error.status >= 500) return true;
  return false;
}
```

## Related

> **[Error handling](https://docs.everabyte.com/errors/overview.md)**
>
> Task-oriented guide with retry patterns.

> **[Error codes](https://docs.everabyte.com/errors/error-codes.md)**
>
> Full code reference.

> **[Troubleshooting](https://docs.everabyte.com/errors/troubleshooting.md)**
>
> Symptom-to-cause table.

> **[Conventions](https://docs.everabyte.com/api-reference/conventions.md)**
>
> Envelope shapes.


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