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

# API Error Codes and Troubleshooting

> Reference for OrbiSearch API error responses, including authentication, validation, rate-limit, and service errors.

The OrbiSearch API uses standard HTTP status codes to indicate whether a request succeeded or failed. Successful requests return `200 OK`. Errors return a JSON body with a `detail` field that describes what went wrong.

## HTTP status codes

| Code  | Status                | When it's returned                                                                                                                           |
| ----- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `200` | OK                    | Request succeeded.                                                                                                                           |
| `400` | Bad Request           | Request body or path parameter is malformed (e.g. empty email list, invalid `job_id` format, more than 100,000 emails in a bulk submission). |
| `401` | Unauthorized          | `X-API-Key` header is missing or contains an invalid key.                                                                                    |
| `403` | Forbidden             | Insufficient credit balance for the requested operation.                                                                                     |
| `404` | Not Found             | The requested `job_id` does not exist or does not belong to your API key.                                                                    |
| `409` | Conflict              | Bulk job results requested before the job has reached `complete`.                                                                            |
| `422` | Unprocessable Entity  | Query, path, or body parameter failed type validation.                                                                                       |
| `429` | Too Many Requests     | Per-second rate limit exceeded, or a per-day quota reached on metered endpoints. The `code` field distinguishes them.                        |
| `500` | Internal Server Error | An unexpected server error occurred. Rare; typically transient.                                                                              |
| `502` | Bad Gateway           | The downstream verification service is temporarily unavailable.                                                                              |
| `503` | Service Unavailable   | A backing analysis engine is temporarily unavailable (e.g. the content spam-check engine).                                                   |

All error responses share the same shape — a `detail` string, plus an optional `code`:

```json theme={null}
{
  "detail": "A human-readable description of what went wrong.",
  "code": "rate_limited"
}
```

The `code` field is a stable, machine-readable identifier. It appears only where it adds a distinction the HTTP status alone doesn't carry — for example, telling a per-second rate limit (`rate_limited`) apart from an exhausted daily quota (`daily_quota_exceeded`), both of which return `429`. When `code` is absent, the status code and `detail` are sufficient; branch on `code` only when you need to react to the specific conditions documented below.

## 400 Bad Request

Returned when the request is structurally valid but semantically rejected. Common causes:

* Empty `emails` array on `POST /v1/bulk`
* More than 100,000 entries in `emails`
* A path-level `job_id` that isn't a valid UUID

```json 400 theme={null}
{
  "detail": "Email list cannot be empty"
}
```

**How to fix:** Inspect the `detail` message — it identifies the offending field. For `job_id` errors, confirm you're passing the UUID returned by `POST /v1/bulk`.

## 401 Unauthorized

Returned when the `X-API-Key` header is missing or contains an invalid key.

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

**How to fix:** Make sure every request includes the `X-API-Key` header with a valid API key. The header name is case-sensitive.

```bash cURL theme={null}
curl --request GET \
  --url "https://api.orbisearch.com/v1/verify?email=jane.doe%40acme.com" \
  --header "X-API-Key: YOUR_API_KEY"
```

## 403 Forbidden — insufficient credits

Returned when your credit balance is too low for the requested operation. Single verifications cost 0.2 credits; bulk submissions are pre-charged for the full deduplicated cost. The error body tells you both your current balance and what was required.

```json 403 theme={null}
{
  "detail": "Insufficient credits. You have 0.15 credits but need 0.2."
}
```

**How to fix:** Top up your balance from the dashboard, then retry. You can check your current balance at any time via [GET /v1/credits](/docs/api-reference/credits).

## 404 Not Found

Returned when a `job_id` doesn't exist, or exists but belongs to a different API key.

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

**How to fix:** Confirm you're using the `job_id` from the original `POST /v1/bulk` response and that you're authenticating with the same API key that created the job.

## 409 Conflict — job not ready

Returned by `GET /v1/bulk/&lcub;job_id&rcub;/results` when the job hasn't finished yet. The `detail` includes the job's current status.

```json 409 theme={null}
{
  "detail": "Job is not completed yet. Current status: in_progress"
}
```

**How to fix:** Poll `GET /v1/bulk/&lcub;job_id&rcub;` until `status` is `complete` (or `partial_complete_retrying` if you want partial results) before fetching results. Partial results can also be fetched directly — see [bulk results](/docs/api-reference/bulk-results) for partial-fetch behaviour.

## 422 Unprocessable Entity — validation errors

Returned when a query, path, or body parameter fails type validation (e.g. `email` is missing, `timeout` is outside the `3`–`97` range, request body isn't valid JSON).

```json 422 theme={null}
{
  "detail": "Missing required query parameter: email"
}
```

**How to fix:** The `detail` string identifies the offending parameter and the validation rule it violated. Common cases: missing required field, value outside allowed range, wrong type.

## 429 Too Many Requests

Two distinct conditions return `429`. Use the `code` field to tell them apart — they need different handling, and the `Retry-After` header reflects that.

### Per-second rate limit — `code: "rate_limited"`

Returned when you exceed **20 requests per second per API key** across the entire `/v1/*` API.

```json 429 theme={null}
{
  "detail": "Rate limit exceeded. Maximum 20 requests per second per API key. Contact us to discuss higher limits.",
  "code": "rate_limited"
}
```

```
Retry-After: 1
```

**How to fix:** Honour the `Retry-After` value (usually `1`; rises to `5` when you exceed the limit by 3x or more, to break tight retry loops) and back off before retrying. Better still, avoid the `429` entirely: every authenticated response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers describing your current per-key window, so you can self-throttle. For sustained high throughput, use the `POST /v1/bulk` endpoint instead — it's designed for large-volume workloads and isn't subject to the per-second cap. Contact us if you need a higher rate.

### Daily quota — `code: "daily_quota_exceeded"`

Returned by metered free endpoints (such as [POST /v1/content-spam-check](/docs/api-reference/content-spam-check)) when you exhaust the day's allowance. Here `Retry-After` is the number of seconds until the quota resets at UTC midnight — typically thousands of seconds, not `1`.

```json 429 theme={null}
{
  "detail": "You've reached today's limit of 100 checks. Try again tomorrow.",
  "code": "daily_quota_exceeded"
}
```

```
Retry-After: 43200
```

**How to fix:** This is a per-day cap, not a slow-down — retrying immediately won't help. Wait until the quota resets (the `Retry-After` value), or spread your usage across the day. The cap is shared with the corresponding in-dashboard tool.

## 500 Internal Server Error

Returned when an unexpected server-side error occurs. These are rare and typically transient.

**How to fix:** Wait a moment and retry the request. If the error persists, contact OrbiSearch support with the request details and timestamp. Credits deducted before the error are automatically refunded.

## 502 Bad Gateway

Returned when the downstream email verification service is temporarily unavailable.

```json 502 theme={null}
{
  "detail": "Email verification service temporarily unavailable"
}
```

**How to fix:** Retry with exponential backoff. Credits deducted before the error are automatically refunded. If the issue persists for more than a few minutes, check our status page or contact support.

## 503 Service Unavailable — `code: "engine_unavailable"`

Returned when a backing analysis engine is temporarily unavailable — for example, the content spam-check engine behind [POST /v1/content-spam-check](/docs/api-reference/content-spam-check).

```json 503 theme={null}
{
  "detail": "Spam checker temporarily unavailable. Please try again.",
  "code": "engine_unavailable"
}
```

**How to fix:** Retry shortly with a short backoff. These are brief and transient; no credits are involved.

## Common errors and fixes

| Error                                  | Cause                                                          | Fix                                                                         |
| -------------------------------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `API key required in X-API-Key header` | Missing `X-API-Key` header                                     | Add `--header "X-API-Key: YOUR_API_KEY"` to every request                   |
| `Insufficient credits...`              | Balance below required cost                                    | Top up your balance and retry                                               |
| `Email list cannot be empty`           | `POST /v1/bulk` with empty `emails` array                      | Include at least one address                                                |
| `Maximum 100,000 emails per batch`     | Bulk submission too large                                      | Split into multiple jobs of ≤100,000 each                                   |
| `Invalid job ID format`                | `job_id` is not a valid UUID                                   | Use the `job_id` returned by `POST /v1/bulk` verbatim                       |
| `Job not found`                        | `job_id` doesn't exist or belongs to another API key           | Confirm the job ID and authenticate with the original API key               |
| `Job is not completed yet...`          | Fetched results before the job reached `complete`              | Poll job status or accept the partial result set                            |
| `Rate limit exceeded...`               | More than 20 requests per second (`code: rate_limited`)        | Honour `Retry-After`; use `/v1/bulk` for high volume                        |
| `You've reached today's limit...`      | Daily free-tier quota exhausted (`code: daily_quota_exceeded`) | Wait for the `Retry-After` reset; the cap is shared with the dashboard tool |
