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

# Errors and Retries

> Understand Visor API error envelopes, status codes, rate limits, and retry behavior.

Errors use a stable JSON envelope:

```json theme={null}
{
  "error": {
    "type": "validation_error",
    "code": "unknown_query_parameter",
    "message": "Unknown query parameter: bad_filter."
  },
  "_tag": "PublicApiValidationError"
}
```

Use `error.code` for programmatic handling. Use `error.message` for logs and operator-facing diagnostics.

## Status codes

| Status | Type                                 | Retry?     | Meaning                                                                                                                             |
| ------ | ------------------------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `validation_error` or `client_error` | No         | The request shape is invalid, a query parameter is unknown, a value is unsupported, or a CLI compatibility request must be updated. |
| `401`  | `authentication_error`               | No         | The API key is missing or invalid.                                                                                                  |
| `402`  | `billing_error`                      | No         | Billing state, balance, or monthly spend cap blocks the request.                                                                    |
| `403`  | `permission_error`                   | No         | The API key is valid but lacks the required scope.                                                                                  |
| `404`  | `not_found_error`                    | Usually no | A VIN, listing, or dealer detail record was not found.                                                                              |
| `429`  | `rate_limit_error`                   | Yes        | Wait for `Retry-After` when present, then retry.                                                                                    |
| `503`  | `platform_error`                     | Yes        | Retry with bounded exponential backoff.                                                                                             |

## Rate limits

Rate limits are enforced at the API account level. All keys on the same account share the same limits.

Successful responses include rate-limit headers:

```txt theme={null}
X-RateLimit-Tier: tier_1
X-RateLimit-Limit-10s: 20
X-RateLimit-Remaining-10s: 19
X-RateLimit-Limit-60s: 60
X-RateLimit-Remaining-60s: 59
```

Rate-limited responses use HTTP `429` and include `Retry-After` when available:

```txt theme={null}
Retry-After: 10
```

## Retry pattern

Keep retries bounded. Visor endpoints are read-only, but repeated successful requests can still be billable.

```js theme={null}
async function visorFetch(path, { maxAttempts = 3 } = {}) {
  const url = `https://api.visor.vin/v1${path}`;

  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
    const response = await fetch(url, {
      headers: {
        Authorization: `Bearer ${process.env.VISOR_API_KEY}`
      }
    });

    if (response.ok) return response.json();

    const retryAfter = Number(response.headers.get("retry-after") || 0);
    const retryable = response.status === 429 || response.status === 503;
    if (!retryable || attempt === maxAttempts) {
      throw new Error(await response.text());
    }

    const waitMs = retryAfter > 0
      ? retryAfter * 1000
      : Math.min(1000 * 2 ** (attempt - 1), 8000);

    await new Promise((resolve) => setTimeout(resolve, waitMs));
  }
}
```

## Billing and failed requests

Prices are per successful request, not per returned row. Successful zero-result searches are billable.

Validation, authentication, permission, billing, rate-limit, and platform errors are not successful paid responses. Detail `404 not_found_error` responses are not billable.

## Common validation fixes

| Error pattern                                              | Fix                                                                           |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `unknown_query_parameter`                                  | Remove the unsupported parameter or check the API reference for the endpoint. |
| Unsupported `inventory_type`, `keywords`, or `dealer_type` | Use the documented vocabulary or discover values with `/v1/facets`.           |
| `limit` above `100`                                        | Page with `limit=100` and `offset`.                                           |
| `facet_value_limit` above `100`                            | Use `facet_value_limit=100` and narrow with filters.                          |
| `sort=distance` without geography                          | Add `postal_code` or `latitude` and `longitude`.                              |

## CLI compatibility errors

Most CLI releases follow the public API contract. Old-but-compatible releases receive advisory update signals.

If a CLI release is known to send requests the platform cannot safely serve, the API returns `400 client_error` with `code: "unsupported_cli_version"` and targeted update instructions in `update_url` and `update_command`.
