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). |
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.
Error response body
All error responses share the same JSON structure:
{
"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. |
When handling errors programmatically, branch on the HTTP statusCode rather than parsing the
message, which is meant for humans and may change.