> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.cail.health/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.cail.health/_mcp/server.

# Error envelope

When a request fails, the CAIL Health API returns a non-2xx HTTP status and a JSON body describing the failure. Most errors share a common shape. A few categories of failure return a reduced shape, so a client should branch on the HTTP status code and read `message`, both of which are always available.

## Standard error

The majority of errors use this shape:

```json
{
  "statusCode": 404,
  "message": "Provider not found",
  "error": "Not Found",
  "meta": {
    "requestId": "4a3b2c1d-5e6f-4890-9abc-def0fedcba98",
    "timestamp": "2026-05-15T10:30:45.000Z"
  }
}
```

| Field            | Type                       | Notes                                                                          |
| ---------------- | -------------------------- | ------------------------------------------------------------------------------ |
| `statusCode`     | integer                    | The HTTP status code, mirrored into the body.                                  |
| `message`        | string or array of strings | A human-readable description of the failure. See [Message](#message).          |
| `error`          | string                     | A short label for the status class, for example `Not Found` or `Unauthorized`. |
| `meta.requestId` | string                     | An opaque request identifier, for support traceability.                        |
| `meta.timestamp` | string                     | The time the response was produced, in ISO 8601 UTC.                           |

## Message

`message` is always present, and is either a single string or an array of strings.

For most failures it is a single human-readable string. For a request that fails field validation, it is an array with one entry per validation problem:

```json
{
  "statusCode": 400,
  "message": [
    "latitude must not be less than -90",
    "latitude must not be greater than 90"
  ],
  "error": "Bad Request",
  "meta": {
    "requestId": "5e6f7a8b-9c0d-4123-a4b5-c6d7e8f9a0b1",
    "timestamp": "2026-05-15T10:30:45.000Z"
  }
}
```

Always handle `message` as either type.

## Error code

Some failures add a `code` field: a short, machine-readable label for the specific failure. When present, `code` is the most precise signal to branch on.

```json
{
  "statusCode": 409,
  "message": "Idempotency key reused with a different body.",
  "code": "conflict",
  "meta": {
    "requestId": "7e6f5d4c-3b2a-4190-bf8e-7d6c5b4a3f2e",
    "timestamp": "2026-05-15T10:30:45.000Z"
  }
}
```

`code` is not present on every error, and `error` may be absent when `code` is present. Treat both as optional.

## Reduced shapes

Two categories of failure return fewer fields.

Pathway execution errors return only `message` and `code`, with no `statusCode` or `meta`. Read the HTTP status from the response itself:

```json
{
  "message": "Pathway execution not found.",
  "code": "ExecutionNotFound"
}
```

An unexpected server error returns only `statusCode` and `message`:

```json
{
  "statusCode": 500,
  "message": "Internal server error"
}
```

## What to rely on

Field availability varies across these shapes, so build clients on the parts that do not vary:

* **The HTTP status code** of the response is always present and authoritative. Branch on it first.
* **`message`** is always present. Handle it as a string or an array of strings.
* **`code`**, **`error`**, and **`meta`** are best-effort. Use them when present, but never require them.

## Support traceability

When `meta.requestId` is present, it uniquely identifies the request. Log it, and include it in any support request so the team can locate the request and its server-side context.