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

# Errors

> How the Matter API communicates errors.

The API uses standard HTTP status codes and returns structured JSON error bodies.

## Error format

Every error response has this shape:

```json theme={null}
{
  "error": {
    "code": "not_found",
    "message": "No item found with ID itm_abc123.",
    "field": null
  }
}
```

| Field     | Type           | Description                                               |
| --------- | -------------- | --------------------------------------------------------- |
| `code`    | string         | Machine-readable error code for programmatic handling.    |
| `message` | string         | Human-readable description of what went wrong.            |
| `field`   | string \| null | The request field that caused the error, when applicable. |

## HTTP status codes

| Status | Meaning               | When you'll see it                                                      |
| ------ | --------------------- | ----------------------------------------------------------------------- |
| `200`  | OK                    | Successful read or update.                                              |
| `201`  | Created               | Successfully created a new resource.                                    |
| `204`  | No Content            | Successful delete.                                                      |
| `400`  | Bad Request           | Invalid request body, missing required field, or malformed parameter.   |
| `401`  | Unauthorized          | Missing or invalid API token.                                           |
| `403`  | Forbidden             | Valid token but insufficient permissions (e.g., no Pro subscription).   |
| `404`  | Not Found             | The requested resource doesn't exist or doesn't belong to your account. |
| `409`  | Conflict              | Resource already exists (e.g., duplicate tag name).                     |
| `422`  | Unprocessable Entity  | Request is well-formed but semantically invalid (e.g., invalid URL).    |
| `429`  | Too Many Requests     | Rate limit exceeded. See [rate limits](/api/rate-limits).               |
| `500`  | Internal Server Error | Something went wrong on our end. Retry with backoff.                    |

## Error codes

| Code               | Status | Description                                            |
| ------------------ | ------ | ------------------------------------------------------ |
| `bad_request`      | 400    | Generic invalid request.                               |
| `validation_error` | 400    | A specific field failed validation. Check `field`.     |
| `unauthorized`     | 401    | Invalid or missing API token.                          |
| `forbidden`        | 403    | Pro subscription required, or resource not accessible. |
| `not_found`        | 404    | Resource not found or not owned by you.                |
| `conflict`         | 409    | Resource already exists.                               |
| `unprocessable`    | 422    | Request is syntactically valid but can't be processed. |
| `rate_limited`     | 429    | Too many requests. Check `Retry-After` header.         |
| `internal_error`   | 500    | Server error. Retry with exponential backoff.          |

## Validation errors

When a specific field is invalid, the `field` property tells you which one:

```json theme={null}
{
  "error": {
    "code": "validation_error",
    "message": "URL must start with http:// or https://.",
    "field": "url"
  }
}
```

## Handling errors

```python theme={null}
response = requests.post(url, headers=headers, json=data)

if response.status_code >= 400:
    error = response.json()["error"]
    if error["code"] == "rate_limited":
        retry_after = int(response.headers["Retry-After"])
        time.sleep(retry_after)
    elif error["code"] == "validation_error":
        print(f"Fix field '{error['field']}': {error['message']}")
    else:
        print(f"Error: {error['message']}")
```
