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

# Error Handling

> Practical guidance for handling validation, auth, permission, and rate-limit errors in the CaseXchange Public API

## Error handling strategy

Every error response from the CaseXchange Public API uses a consistent envelope. The fastest path to resilient clients is:

1. Branch on HTTP status code.
2. Parse the error envelope (see [Response Format](/api-reference/response-format) for the full specification).
3. Use `error.code` for logic and `error.message` for logs/UI.
4. Retry only when the failure mode is transient.

### Error envelope

All error responses share this shape:

```json theme={null}
{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed"
  },
  "meta": {
    "requestId": "req_f2dbe1d3f6ad4a7bb5b4c9f2",
    "timestamp": "2026-03-31T12:00:00.000Z"
  }
}
```

* **`error.code`** -- a machine-readable string you can switch on.
* **`error.message`** -- a human-readable explanation safe for logs or UI display.
* **`meta.requestId`** -- include this when contacting support for faster triage.

## Authentication errors

### `401 Unauthorized`

Common causes:

* Missing `X-API-Key` header
* Invalid or revoked API key

Client handling:

* Verify the `X-API-Key` value matches the key issued in the CaseXchange dashboard.
* Check whether the key has been revoked or rotated.
* If the key is no longer valid, generate a new key from the dashboard.
* Avoid infinite retry loops on repeated `401`s.

## Authorization errors

### `403 Forbidden`

Common causes:

* API key tier is insufficient for the operation (e.g., a `read_only` key attempting a `POST`)
* Caller's firm does not own the target resource
* Action is not permitted for the current resource state

Client handling:

* Surface a clear permission error to the caller.
* Do not retry automatically.
* Verify the firm context and key tier with `GET /firms/me`.
* If a higher-tier key is required, generate one from the CaseXchange dashboard.

## Validation and state errors

### `400 Bad Request`

Common causes:

* Missing required fields
* Invalid enum values
* Invalid UUIDs or malformed dates
* Invalid case state transition (for example, trying to re-refer a non-terminal referral)
* Malformed multipart uploads or CSV files

Client handling:

* Inspect `error.code` and `error.message` to map field messages into form-level validation.
* Keep raw request payloads in debug logs (without secrets) to speed up support.
* Prefer client-side validation for enums and required fields, but still handle server validation.

### `409 Conflict`

Common causes:

* Duplicate resources (email, firm name, etc.)
* Existing active referral to the same target firm
* Operations that require a non-conflicting system state

Client handling:

* Present a conflict-specific recovery path (use existing resource, change target, or refresh current state).
* Refetch the resource before asking the user to retry.

## Not found

### `404 Not Found`

Common causes:

* Stale IDs cached in the client
* Resource deleted or not visible to the calling firm
* Environment mismatch (ID from QA used in production)

Client handling:

* Confirm the active environment and API base URL.
* Refetch parent lists to refresh stale references.

## Rate limiting

### `429 Too Many Requests`

Common causes:

* Rate limit exceeded for this API key

Client handling:

* Read the `X-RateLimit-Reset` header to determine when the limit resets.
* Do **not** retry immediately -- wait until the reset window.
* Implement exponential backoff with jitter for burst-retry scenarios.
* If you consistently hit limits, consider batching requests or requesting a higher rate-limit tier.

## Server errors

### `5xx Internal Server Error`

If the API returns a 500, 502, or 503, this indicates a server-side issue — not a problem with your request.

Client handling:

* Retry with exponential backoff (start at 1 second, max 30 seconds).
* Include the `meta.requestId` from the error response (if present) when contacting support.
* Do not retry immediately in a tight loop.
* If 5xx errors persist for more than 5 minutes, check for platform status updates or email [help@casexchange.com](mailto:help@casexchange.com) with your `requestId` values.

## Error code reference

| `error.code`               | HTTP Status | Description                                                           |
| -------------------------- | ----------- | --------------------------------------------------------------------- |
| `invalid_api_key`          | 401         | API key is missing, invalid, or revoked                               |
| `insufficient_tier`        | 403         | API key tier does not permit this operation                           |
| `permission_denied`        | 403         | Caller's firm does not own the target resource                        |
| `validation_error`         | 400         | Request body or query parameters failed validation                    |
| `invalid_state_transition` | 400         | The requested status change is not allowed from the current state     |
| `resource_not_found`       | 404         | The referenced resource ID does not exist                             |
| `conflict`                 | 409         | Duplicate or conflicting state (e.g., active referral already exists) |
| `rate_limited`             | 429         | Rate limit exceeded for this API key                                  |
| `internal_error`           | 500         | Unexpected server error                                               |

## Logging recommendations

* Log request method, path, status code, and a scrubbed request payload.
* Log `error.code` and `error.message`.
* Log `meta.requestId` -- this is the fastest way to trace an issue with support.
* Never log unmasked API keys or sensitive payload fields.

## Testing checklist

* Invalid API key (`401`) path
* Insufficient key tier (`403`) path
* Firm ownership restriction (`403`) path
* Validation error (`400`) with field details
* Not found (`404`) with stale UUID
* Conflict (`409`) on duplicate/re-refer edge cases
* Rate limit (`429`) with backoff and retry
