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

# Errors

> Understand API error codes and how to handle them in your integration.

## Error Response Format

When an API request fails, the response body contains a `detail` field describing what went wrong:

```json theme={null}
{
  "detail": "Lead not found"
}
```

Rate limit errors use a different format with additional context:

```json theme={null}
{
  "error": "Rate limit exceeded",
  "code": "rate_limit_exceeded",
  "details": {
    "limit": 100,
    "reset": 1706140920
  }
}
```

## HTTP Status Codes

### Success Codes

| Code             | Meaning              | When It's Used                                 |
| ---------------- | -------------------- | ---------------------------------------------- |
| `200 OK`         | Request succeeded    | GET, PATCH, and action endpoints (start/pause) |
| `201 Created`    | Resource created     | POST endpoints that create new resources       |
| `204 No Content` | Deleted successfully | DELETE endpoints                               |

### Client Error Codes

| Code                       | Meaning                  | Common Causes                                                           |
| -------------------------- | ------------------------ | ----------------------------------------------------------------------- |
| `400 Bad Request`          | Malformed request        | Invalid JSON body, missing Content-Type header                          |
| `401 Unauthorized`         | Authentication failed    | Missing, invalid, revoked, or expired API key                           |
| `403 Forbidden`            | Insufficient permissions | API key lacks the required scope (`read`/`write`)                       |
| `404 Not Found`            | Resource doesn't exist   | Wrong ID, resource was deleted, wrong workspace                         |
| `409 Conflict`             | Resource already exists  | Creating a lead with a duplicate email                                  |
| `422 Unprocessable Entity` | Validation failed        | Invalid email format, missing required fields, invalid field values     |
| `429 Too Many Requests`    | Rate limit exceeded      | More than 100 requests per minute — see [Rate Limiting](/rate-limiting) |

### Server Error Codes

| Code                        | Meaning                         | What To Do                     |
| --------------------------- | ------------------------------- | ------------------------------ |
| `500 Internal Server Error` | Something went wrong on our end | Retry with exponential backoff |

## Error Handling Examples

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  def api_request(method, url, headers, json=None, max_retries=3):
      for attempt in range(max_retries):
          response = requests.request(method, url, headers=headers, json=json)

          if response.status_code == 429:
              retry_after = int(response.headers.get("Retry-After", 60))
              time.sleep(retry_after)
              continue

          if response.status_code >= 500:
              time.sleep(2 ** attempt)
              continue

          return response

      return response
  ```

  ```javascript Node.js theme={null}
  async function apiRequest(method, url, headers, body, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
      const response = await fetch(url, {
        method,
        headers: { ...headers, "Content-Type": "application/json" },
        body: body ? JSON.stringify(body) : undefined,
      });

      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
        await new Promise((r) => setTimeout(r, retryAfter * 1000));
        continue;
      }

      if (response.status >= 500) {
        await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
        continue;
      }

      return response;
    }
  }
  ```
</CodeGroup>

## Common Error Scenarios

<AccordionGroup>
  <Accordion title="401 — Invalid or missing API key">
    Make sure you're sending the `X-API-Key` header with a valid key. Keys use the `otr_` prefix.

    ```bash theme={null}
    # Correct
    curl -H "X-API-Key: otr_abc123..." https://api.foxreach.io/api/v1/leads

    # Wrong — missing header
    curl https://api.foxreach.io/api/v1/leads
    ```
  </Accordion>

  <Accordion title="409 — Duplicate lead email">
    Each workspace enforces unique lead emails. If you get a 409, the lead already exists. Use the [List Leads](/api-reference/leads/list-leads) endpoint with `search` to find the existing lead, then update it instead.
  </Accordion>

  <Accordion title="422 — Validation error">
    Check that required fields are present and values match expected formats. For example, `email` must be a valid email address, and `status` must be one of the allowed values.
  </Accordion>

  <Accordion title="429 — Rate limit exceeded">
    You've exceeded 100 requests per minute. Check the `Retry-After` header and wait before retrying. See [Rate Limiting](/rate-limiting) for strategies to avoid hitting limits.
  </Accordion>
</AccordionGroup>
