# Errors

All API errors follow a consistent format.

## Error Format

```json
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description",
    "details": {}
  }
}
```

## HTTP Status Codes

| Status | Code                  | Description                               |
| ------ | --------------------- | ----------------------------------------- |
| 400    | `BAD_REQUEST`         | Malformed request                         |
| 401    | `UNAUTHORIZED`        | Invalid or missing authentication         |
| 403    | `FORBIDDEN`           | Insufficient permissions                  |
| 404    | `NOT_FOUND`           | Resource not found                        |
| 409    | `CONFLICT`            | Resource already exists or state conflict |
| 422    | `VALIDATION_ERROR`    | Invalid request body or parameters        |
| 429    | `RATE_LIMIT_EXCEEDED` | Too many requests                         |
| 500    | `INTERNAL_ERROR`      | Unexpected server error                   |

## Validation Errors

Validation errors include field-level details:

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": {
      "fields": [
        { "field": "name", "message": "Required" },
        { "field": "exchange_account_id", "message": "Invalid UUID format" }
      ]
    }
  }
}
```

## GraphQL Errors

GraphQL responses use the standard `errors` array:

```json
{
  "data": null,
  "errors": [
    {
      "message": "Not authorized",
      "path": ["me"],
      "errorType": "Unauthorized"
    }
  ]
}
```

Many GraphQL operations also return a `success`/`error` envelope:

```json
{
  "data": {
    "create_strategy": {
      "success": false,
      "error": "Exchange account not found",
      "data": null
    }
  }
}
```
