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

# Error Codes

> Complete reference of the HTTP status codes returned by the Penbox API and how to handle them

The Penbox API uses conventional HTTP status codes to indicate the success or
failure of a request. The same set of codes applies consistently across **all
endpoints** — creating a Case behaves the same way as any other call.

## Success codes

| Code    | Name       | Description                                                                                      |
| ------- | ---------- | ------------------------------------------------------------------------------------------------ |
| **200** | `OK`       | The request succeeded. Returned for reads, updates, **and for creating a Case** (`POST /cases`). |
| **201** | `Created`  | A resource was created successfully (e.g. attachment upload, document intelligence).             |
| **202** | `Accepted` | The request was accepted and will be processed asynchronously (e.g. webhooks / events).          |

## Client error codes (4xx)

| Code    | Name                   | Description                                                                                                                                                                             |
| ------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **400** | `Bad Request`          | The request is invalid: a required field is missing, the JSON is malformed, a UUID or email is invalid, a schema value is incorrect, or a referenced template/owner could not be found. |
| **401** | `Unauthorized`         | Authentication failed: the `Authorization` header is missing, or the token/JWT is invalid or expired.                                                                                   |
| **403** | `Forbidden`            | Authenticated but not allowed: the token does not have access to the requested workspace or resource.                                                                                   |
| **404** | `Not Found`            | The resource does not exist (unknown id for a case, template, workspace, form…) or the endpoint does not exist.                                                                         |
| **409** | `Conflict`             | The request conflicts with the current state of the resource (e.g. a step already started, a duplicate).                                                                                |
| **413** | `Payload Too Large`    | The request body is too large (e.g. a file upload exceeding the size limit).                                                                                                            |
| **422** | `Unprocessable Entity` | The request is well-formed but fails a business validation rule.                                                                                                                        |

## Server error codes (5xx)

| Code    | Name                    | Description                                                    |
| ------- | ----------------------- | -------------------------------------------------------------- |
| **500** | `Internal Server Error` | An unexpected error occurred on our side.                      |
| **502** | `Bad Gateway`           | A backend service is unreachable or returned an error.         |
| **503** | `Service Unavailable`   | The service is temporarily unavailable (infrastructure level). |
| **504** | `Gateway Timeout`       | The request took too long to complete (timeout ≈ 30 s).        |

<Note>
  **`429 Too Many Requests`** is not produced by the application itself, but may be returned by the
  network / gateway layer if rate limiting is in effect.
</Note>

## Error response body

All error responses share the same JSON structure:

```json theme={null}
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "A human-readable description of the error",
  "errors": [
    {
      "message": "validation detail",
      "path": ["field"],
      "type": "..."
    }
  ]
}
```

| Field        | Description                                                                        |
| ------------ | ---------------------------------------------------------------------------------- |
| `statusCode` | The HTTP status code, repeated in the body for convenience.                        |
| `error`      | The official HTTP status name (e.g. `Bad Request`).                                |
| `message`    | A human-readable description of what went wrong.                                   |
| `errors`     | Present only for validation errors (`400`). An array detailing each invalid field. |

<Tip>
  When handling errors programmatically, branch on the HTTP `statusCode` rather than parsing the
  `message`, which is meant for humans and may change.
</Tip>
