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

# Responses and errors

All responses are JSON. Two envelopes are in use, so check which one an endpoint returns before you parse it.

## Standard envelope

Domain endpoints such as containers, manifests, edge ingestion, notifications, and admin return `success` with either `data` or `error`:

**`Success`**

```json Success
{
  "success": true,
  "data": {
    "containerId": "665f1c2e9b1e4a0012ab34cd",
    "containerNumber": "MSCU1234566",
    "isNewContainer": true,
    "status": "IDENTIFIED"
  }
}
```

**`Error`**

```json Error
{
  "success": false,
  "error": {
    "code": "CONTAINER_NOT_FOUND",
    "message": "Container not found"
  }
}
```

Use `error.code` for program logic. The `message` is for people and may change.

## Legacy auth envelope

Endpoints under `/v1/user/auth/*`, and the authentication and role checks in front of every JWT-protected endpoint, return the older `status` envelope:

```json
{
  "status": "error",
  "message": "Unauthorized: Authentication required",
  "data": {}
}
```

Successful auth calls return `"status": "success"` with the payload in `data`.

## Status codes

| Code          | Meaning                                                                                                                     |
| ------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `200` / `201` | Success                                                                                                                     |
| `400`         | Validation failed, for example a missing field, a malformed ID, or an invalid container number                              |
| `401`         | Missing, invalid, or expired JWT, or a missing or wrong edge API key                                                        |
| `403`         | Authenticated but not allowed: wrong role, not the resource owner, or a cookie-authenticated write from an untrusted origin |
| `404`         | Resource or route not found                                                                                                 |
| `409`         | Conflict, for example a container number already in use                                                                     |
| `429`         | Rate limit exceeded; see [Authentication](/authentication#rate-limits)                                                      |
| `500`         | Unexpected server error; details are never included in the response                                                         |

## Common error codes

| Code                                  | Returned when                                                      |
| ------------------------------------- | ------------------------------------------------------------------ |
| `VALIDATION_ERROR`                    | A required field is missing or malformed                           |
| `INVALID_INPUT`                       | A value has the wrong type                                         |
| `INVALID_ID`                          | A path ID is not a valid record ID                                 |
| `INVALID_CONTAINER_NUMBER`            | A container number fails ISO 6346 format or check-digit validation |
| `CONTAINER_NOT_FOUND`                 | No container matches the ID or number                              |
| `FORBIDDEN`                           | The caller cannot access the resource                              |
| `MISSING_API_KEY` / `INVALID_API_KEY` | Edge authentication failed                                         |
| `TOO_MANY_REQUESTS`                   | A rate limit was exceeded                                          |
| `NOT_FOUND`                           | No route matches the method and path                               |
| `INTERNAL_ERROR`                      | An unexpected server error occurred                                |

## Pagination

Page-based list endpoints such as `GET /v1/containers` accept `page` (starting at 1) and `limit` query parameters and return a `pagination` object next to the items. A few admin listings use cursors instead; see each endpoint in the [API reference](/api-reference).

```json
{
  "success": true,
  "data": {
    "containers": [],
    "pagination": { "page": 1, "limit": 20, "total": 0, "pages": 0 }
  }
}
```

`GET /v1/containers` defaults to 20 items per page and caps `limit` at 100.