Skip to main content
The ColdSend API uses standard HTTP status codes and returns structured error responses.
Always check the HTTP status code first, then parse the detail field for specific error information.

HTTP Status Codes

Status CodeDescription
200 OKRequest succeeded
201 CreatedResource created
204 No ContentSucceeded with no body
400 Bad RequestInvalid request or validation error
401 UnauthorizedMissing or invalid API key
403 ForbiddenInsufficient scopes
404 Not FoundResource doesn’t exist
409 ConflictResource already exists
422 UnprocessableValidation error
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorUnexpected server error
503 Service UnavailableTemporarily unavailable

Error Response Format

All errors return a detail field: Simple error:
{
  "detail": "Error message describing issue"
}
Validation error:
{
  "detail": [
    {
      "loc": ["body", "name"],
      "msg": "ensure this value has at least 8 characters",
      "type": "value_error.any_str.min_length"
    }
  ]
}
Multiple fields:
{
  "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
{
  "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
{
  "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
{
  "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.

Validation Errors

Field Required

Status: 422 Unprocessable Entity (via FastAPI) or 400 Bad Request
{
  "detail": [
    {
      "loc": ["body", "name"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

Value Constraint Violated

{
  "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

{
  "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
{
  "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
{
  "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:
{
  "is_launch_ready": false,
  "missing_requirements": ["leads", "inboxes", "variants"]
}
Fix the missing items and retry. See Campaigns Overview.

Variant Distribution Mismatch

{
  "detail": "Variant distributions must sum to 100%, got 90%"
}
All distribution_percent values must sum to exactly 100.

Sender Account Errors

Email Already Exists

Status: 409 Conflict
{
  "detail": "An email account with this address already exists."
}
Fix: Use a different email address, or delete the existing account first.

Connection Failed

Status: 400 Bad Request
{
  "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 for recommended settings

Inbox In Use

Status: 400 Bad Request
{
  "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
{
  "detail": "Rate limit exceeded. Retry after 60 seconds."
}
Fix: Implement exponential backoff. See 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

Authentication

API keys and security.

Rate Limits

Learn about rate limiting and retry strategies.