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

# Error Codes

> Reference for API error responses and how to handle them.

The ColdSend API uses standard HTTP status codes and returns structured error responses.

<Info>
  Always check the HTTP status code first, then parse the `detail` field for specific error information.
</Info>

## HTTP Status Codes

| Status Code                 | Description                         |
| --------------------------- | ----------------------------------- |
| `200 OK`                    | Request succeeded                   |
| `201 Created`               | Resource created                    |
| `204 No Content`            | Succeeded with no body              |
| `400 Bad Request`           | Invalid request or validation error |
| `401 Unauthorized`          | Missing or invalid API key          |
| `403 Forbidden`             | Insufficient scopes                 |
| `404 Not Found`             | Resource doesn't exist              |
| `409 Conflict`              | Resource already exists             |
| `422 Unprocessable`         | Validation error                    |
| `429 Too Many Requests`     | Rate limit exceeded                 |
| `500 Internal Server Error` | Unexpected server error             |
| `503 Service Unavailable`   | Temporarily unavailable             |

## Error Response Format

All errors return a `detail` field:

**Simple error:**

```json theme={null}
{
  "detail": "Error message describing issue"
}
```

**Validation error:**

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "name"],
      "msg": "ensure this value has at least 8 characters",
      "type": "value_error.any_str.min_length"
    }
  ]
}
```

**Multiple fields:**

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "daily_limit_per_inbox"],
      "msg": "ensure this value is less than or equal to 100",
      "type": "value_error.number.not_le"
    }
  ]
}
```

The `detail` field contains either a simple string or an array of validation failures with `loc` (field path), `msg` (human-readable), and `type` (error category).

## Authentication Errors

### Missing API Key

**Status:** `401 Unauthorized`

```json theme={null}
{
  "detail": "API key required. Include your API key in X-API-Key header."
}
```

Fix: Include `X-API-Key: cs_live_your_key` in every request.

### Invalid or Revoked Key

**Status:** `401 Unauthorized`

```json theme={null}
{
  "detail": "Invalid or revoked API key"
}
```

Fix: Generate a new API key in the dashboard. Revoked keys cannot be restored.

### Insufficient Permissions

**Status:** `403 Forbidden`

```json theme={null}
{
  "detail": "Missing required scopes: campaigns:write",
  "error": "insufficient_scopes",
  "required": ["campaigns:write"],
  "granted": ["sender_accounts:read"]
}
```

Fix: Create a new API key with the required scopes. See [API Key Scopes](/authentication/scopes).

## Validation Errors

### Field Required

**Status:** `422 Unprocessable Entity` (via FastAPI) or `400 Bad Request`

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "name"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

### Value Constraint Violated

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "daily_limit_per_inbox"],
      "msg": "ensure this value is less than or equal to 100",
      "type": "value_error.number.not_le"
    }
  ]
}
```

Common constraints:

* Campaign name: 8-255 characters
* Daily limit per inbox: 1-100
* Variant distribution: must sum to 100%

### Invalid Format

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "email_address"],
      "msg": "value is not a valid email address",
      "type": "value_error.email"
    }
  ]
}
```

## Campaign Errors

### Campaign Not Found

**Status:** `404 Not Found`

```json theme={null}
{
  "detail": "Campaign 550e8400-e29b-41d4-a716-446655440000 not found"
}
```

Check:

* Campaign ID is a valid UUID
* Campaign belongs to your team
* Campaign hasn't been deleted

### Campaign Not Modifiable

**Status:** `400 Bad Request`

```json theme={null}
{
  "detail": "Can only update campaigns in DRAFT status"
}
```

Fix: Pause the campaign first via `POST /api/public/v1/campaigns/{id}/pause`, then make updates.

### Missing Launch Requirements

When you set `launch: true`, the API validates and may return:

```json theme={null}
{
  "is_launch_ready": false,
  "missing_requirements": ["leads", "inboxes", "variants"]
}
```

Fix the missing items and retry. See [Campaigns Overview](/campaigns/overview).

### Variant Distribution Mismatch

```json theme={null}
{
  "detail": "Variant distributions must sum to 100%, got 90%"
}
```

All `distribution_percent` values must sum to exactly 100.

## Sender Account Errors

### Inbox Already Exists

**Status:** `409 Conflict`

```json theme={null}
{
  "detail": "Inbox already exists"
}
```

Fix: Use a different email address, or delete the existing inbox first.

### Connection Failed

**Status:** `400 Bad Request`

```json theme={null}
{
  "detail": "Failed to connect to your email provider. Please verify your credentials and app password settings."
}
```

Fix:

* Verify SMTP/IMAP hostnames and ports match your provider's config
* Check credentials — use app-specific passwords, not main passwords
* See [Provider Configuration](/sender-accounts/providers) for recommended settings

### Inbox In Use

**Status:** `400 Bad Request`

```json theme={null}
{
  "detail": "Inbox is assigned to a campaign and cannot be deleted. Remove from campaigns first."
}
```

Fix: Remove the inbox from all campaigns it's assigned to, then retry deletion.

## Rate Limit Error

**Status:** `429 Too Many Requests`

```json theme={null}
{
  "detail": "Rate limit exceeded. Retry after 60 seconds."
}
```

Fix: Implement exponential backoff. See [Rate Limits](/reference/rate-limits).

## Best Practices

1. **Check status codes** — Differentiate 4xx (client errors, fix the request) from 5xx (server errors, retry with backoff).
2. **Implement retry logic** — Retry on 429 and 5xx with exponential backoff. Don't retry 4xx errors (except 409/422 with fixes).
3. **Log errors** — Include timestamps, request IDs, and context in your logs.
4. **Display user-friendly messages** — Convert technical errors into actionable guidance.
5. **Use separate keys per integration** — Makes debugging scope issues easier.

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" href="/authentication/overview" icon="shield">
    API keys and security.
  </Card>

  <Card title="Rate Limits" href="/reference/rate-limits" icon="gauge">
    Learn about rate limiting and retry strategies.
  </Card>
</CardGroup>
