# Error Handling

> Understand error responses, HTTP status codes, and how to handle errors in the Lev API.

Source: https://www.lev.com/docs/build/errors

Last updated: March 2026

---
## Error Format

All error responses include a `request_id` for correlation with support and a structured error object:

```json
{
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "error": {
    "status": 404,
    "type": "not_found",
    "message": "Deal with id 999 not found",
    "details": {}
  }
}
```

| Field | Type | Description |
|-------|------|-------------|
| `status` | integer | HTTP status code mirrored in the envelope for convenience |
| `type` | string | Short machine-readable error type (see [Status Codes](#status-codes) below) |
| `message` | string | Human-readable description |
| `details` | object | Additional context; always present but may be empty |
| `prerequisites` | array | *(optional)* Actions required before the request can succeed |
| `upgrade_url` | string | *(optional)* URL to upgrade the account when the error is tier-gated |

The `request_id` matches the value logged in usage tracking, so it can be referenced when contacting support.

## Status Codes

| Code | `type` | Meaning |
|------|--------|---------|
| `200` | — | OK — successful read or update |
| `201` | — | Created — successful resource creation |
| `400` | `bad_request` | Invalid request body, missing required fields, malformed query parameters |
| `401` | `unauthorized` | Missing, invalid, or expired authentication token |
| `403` | `forbidden` | Valid token but insufficient permissions |
| `404` | `not_found` | Resource doesn't exist or isn't accessible to the authenticated user |
| `409` | `conflict` | Idempotency conflict (different request body with same idempotency key) |
| `422` | `validation_error` | Valid JSON but semantically invalid (e.g., invalid enum value) |
| `429` | `rate_limit_exceeded` | Rate limit exceeded |
| `500` | `internal_error` | Unexpected server error |

## Common Errors

### Missing authentication

```json
{
  "request_id": "...",
  "error": {
    "status": 401,
    "type": "unauthorized",
    "message": "Authentication required",
    "details": {}
  }
}
```

### Resource not found

Returns `404` both when a resource doesn't exist and when the authenticated user doesn't have access to it. This prevents information leakage about resource existence.

```json
{
  "request_id": "...",
  "error": {
    "status": 404,
    "type": "not_found",
    "message": "Deal with id 999 not found",
    "details": {}
  }
}
```

### Validation error

```json
{
  "request_id": "...",
  "error": {
    "status": 422,
    "type": "validation_error",
    "message": "Invalid value for field 'loan_type': must be one of [construction, heavy_bridge, light_bridge, permanent, land, predevelopment, tbd]",
    "details": {}
  }
}
```

### Rate limited

```json
{
  "request_id": "...",
  "error": {
    "status": 429,
    "type": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Retry after 30 seconds.",
    "details": {}
  }
}
```