---
title: "Errors"
description: "Every error the CarsXE API returns — what it means, why it happened, and how to fix it. Includes the error envelope, status codes, and retry guidance."
canonical_url: "https://docs.carsxe.com/docs/guides/errors"
markdown_url: "https://docs.carsxe.com/docs/guides/errors.md"
last_updated: "1980-01-01"
---

# Errors
URL: /docs/guides/errors
LLM index: /llms.txt
Description: Every error the CarsXE API returns — what it means, why it happened, and how to fix it. Includes the error envelope, status codes, and retry guidance.

This page is a complete reference for every error the CarsXE API can return. Each entry explains **why the error happened** and **how to fix it**, so you can resolve most issues without contacting support.

You can tell whether a request succeeded from the HTTP status code. Every response body also includes a `success` boolean, so you can check either one.

---

## The error envelope

All errors share the same JSON shape:

<PortableCode value={{
 language: "json",
 code: `{
    "success": false,
    "message": "Missing vin (vehicle identification number)"
  }`
}} />

<Properties>
  <Property name="success" type="boolean">
    Always <code>false</code> for errors. Successful responses return <code>true</code>.
  </Property>
  <Property name="message" type="string">
    A human-readable description of what went wrong. Messages are stable strings — you can match on them — but prefer matching on the HTTP status code where possible.
  </Property>
  <Property name="usage" type="object">
    Present only on <code>429</code> quota errors. Contains <code>current</code>, <code>limit</code>, and <code>remaining</code> so you can see exactly where you stand. See [Rate Limits & Quotas](/docs/guides/rate-limits).
  </Property>
</Properties>

<Note>
  A few legacy v1 routes return a <code>500</code> status for validation problems (for example, a missing
  <code>make</code>/<code>model</code> on the Images API). Always check the <code>success</code> field in addition to
  the status code when working with v1 endpoints. v2 endpoints use precise status codes throughout.
</Note>

---

## Status codes

| Status | Meaning | Safe to retry? |
| --- | --- | --- |
| `200` | Success. | — |
| `202` | Accepted — an async job (e.g. [Recalls Batch](/api-reference/recalls/submit-a-bulk-recalls-batch)) was queued. Poll its status endpoint. | — |
| `400` | Bad request — a parameter is missing or invalid. | No — fix the request first. |
| `401` | Authentication failed — missing, invalid, or inactive API key. | No — fix your key or billing. |
| `403` | Forbidden — your key is blocked or your plan doesn't include this API. | No |
| `404` | Not found — no data exists for this VIN/plate, or an invalid state/country code. | No — same input returns the same result. |
| `405` | Method not allowed — e.g. `GET` sent to a `POST`-only endpoint. | No — change the HTTP method. |
| `429` | Usage quota exceeded. | Not as-is — quota errors persist until you upgrade, enable overage, or the period resets. See [Rate Limits & Quotas](/docs/guides/rate-limits). |
| `500` | Internal server error. | Yes — once, with backoff. If persistent, contact support. |
| `502` | Upstream data provider could not be reached. | Yes — with backoff. |
| `503` | Upstream provider temporarily unavailable. | Yes — with backoff. |
| `504` | Upstream request timed out. | Yes — with backoff. |

---

## Authentication errors

| Message | Status | Why it happened | How to fix it |
| --- | --- | --- | --- |
| `Missing API key` | `401` | The request did not include the `key` parameter. | Pass your API key as the `key` query parameter on every request. See [Authentication](/docs/get-started#authentication). |
| `User with this API key was not found or the API key is disabled` | `401` | The key has a typo, was revoked, or was disabled. | Copy the key again from your [dashboard](https://api.carsxe.com/dashboard). Check for whitespace or truncation. |
| `User with this API key is not active. To activate update your billing on https://api.carsxe.com/dashboard/billing` | `401` | A payment failed or your billing is not in good standing, so API access was suspended. | Update your payment method on the [billing page](https://api.carsxe.com/dashboard/billing). Access resumes immediately after. |
| `This API key has been blocked, please contact support if you believe this is an error.` | `403` | The key was flagged for abuse. | Contact support with your account email. |
| `This API is not available for your current subscription tier. Visit https://api.carsxe.com/pricing to review upgrade options.` | `403` | Your plan does not include this endpoint. | Compare plans on the [pricing page](https://api.carsxe.com/pricing) and upgrade, or remove the call. |

---

## Validation errors

These are returned before any lookup happens, so they don't count against your quota. Fix the request and resend.

| Message | Status | How to fix it |
| --- | --- | --- |
| `Missing vin (vehicle identification number)` | `400` | Pass the `vin` parameter. |
| `Wrong VIN length, must be 17 characters` | `400` | VINs are exactly 17 characters. Strip whitespace; check for `O`/`0` and `I`/`1` transcription mistakes. |
| `Missing vehicle registration number or license plate number` | `400` | Pass the `plate` parameter. |
| `Missing 2 letter state code` | `400` | Pass `state` as a 2-letter code (e.g. `CA`). Required for US plate lookups. |
| `Invalid state or country code.` | `404` | Use ISO-style 2-letter codes. See the supported-country list on the [Plate Decoder page](/api-reference/plate-decoder/license-plate-decoder-v2). |
| `Invalid condition. Available conditions: excellent, clean, average, rough` | `400` | The `condition` parameter on [Market Value v2](/api-reference/market-value/vehicle-market-value-v2) accepts only those four values. |
| `Invalid mileage. Must be a number` | `400` | Pass `mileage` as digits only — no commas or units. |
| `Missing image data` | `400` | VIN OCR and Plate Recognition need an image — pass a URL or base64 string. |
| `Invalid image data format. Must be a valid URL or base64 encoded string.` | `400` | Check the URL is publicly reachable, or that the base64 payload is complete. |
| `Please supply a make and model. Visit http://api.carsxe.com/docs for more information` | `500` | The Images API requires both `make` and `model`. (Legacy route — note the 500 status.) |

The [Recalls Batch](/api-reference/recalls/submit-a-bulk-recalls-batch) endpoints have additional validation rules (VIN count, CSV size and hosting, webhook URLs) — those messages are self-describing and documented on the batch page.

---

## Data not found

A `404` with one of these messages means the request was valid, but no data exists for that vehicle. Retrying the same input returns the same result.

| Message | How to fix it |
| --- | --- |
| `No data found for this VIN` | Verify the VIN is correct. Coverage varies by market and model year. |
| `No data found for this VIN. Try a deep search by setting deepdata=1 in your request` | Retry with `deepdata=1` on the [Specifications API](/api-reference/specifications/vehicle-specifications-vin-decoder) for an extended-source lookup. |
| `Plate searches for this country have been disabled, or No data found for this plate` | Check the plate and region. Some countries are unavailable; see the coverage list on the Plate Decoder page. |
| `No lien or theft data found for this VIN` | No records exist — for many use cases this is the answer you want. |
| `No images found` | Try a less specific query (drop `trim` or `color`). |
| `No plates detected in image` | Use a sharper, better-lit image where the plate is clearly visible. |
| `No valid VIN candidates found in the image` / `No text detected in the image` | Use a higher-resolution image of the VIN plate or windshield etching. |

<Note>
  Not-found results for VIN lookups are cached for about one day. If you believe data should exist, wait before
  retrying rather than hammering the endpoint with the same VIN.
</Note>

---

## Rate limit and quota errors

A `429` means you've used up your plan's included volume for this API:

<PortableCode value={{
 language: "json",
 code: `{
  "success": false,
  "message": "API limit exceeded for market_value (6/2026). Subscription tier: starter. Current usage: 5000, Limit: 5000.",
  "usage": {
    "current": 5000,
    "limit": 5000,
    "remaining": 0
  }
}`
}} />

See [Rate Limits & Quotas](/docs/guides/rate-limits) for how limits work, the exact response shapes, and backoff strategies.

---

## Server and upstream errors

CarsXE aggregates data from multiple providers. When a provider fails or times out, you'll see one of these:

| Message | Status | What it means | What to do |
| --- | --- | --- | --- |
| `Internal server error` | `500` | An unhandled error on our side. | Retry once with backoff. If it persists, contact support with the endpoint, parameters, and timestamp. |
| `Unable to authenticate internal request (code CV-001). Please try again later` | `500` | An internal provider credential issue — not your request. | Retry later. Quote the `CV-001` code to support if it persists. |
| `Unable to authenticate internal request (code CV-002). Please try again later` | `500` | Same as above, for the History API. | Retry later. Quote `CV-002` to support. |
| `Could not fetch data` | `502` | The upstream provider was unreachable or returned an error. | Retry with exponential backoff. |
| `Cannot access the internet at this time` | `503` | The upstream provider is temporarily down. | Retry with backoff. |
| `Request timed out. Please try again.` | `504` | The provider didn't respond in time. | Retry with backoff — these are usually transient. |

---

## Handling errors in code

Check `response.ok` / the status code first, then branch on the category. Retry only `5xx` — a `4xx` (including quota `429`s, which persist until you upgrade or enable overage) needs a fix, not a retry:

<CodeGroup title="Error handling" tag="GET" label="/specs">

```bash
CARSXE_API_KEY="CARSXE_API_KEY"
URL="https://api.carsxe.com/specs?key=${CARSXE_API_KEY}&vin=1HGCM82633A004352"
retries=3

for attempt in $(seq 0 $retries); do
  response=$(curl -s -w "\n%{http_code}" "$URL")
  body=$(echo "$response" | sed '$d')
  status=$(echo "$response" | tail -n 1)

  if [ "$(echo "$body" | jq -r '.success')" = "true" ]; then
    echo "$body"
    exit 0
  fi

  # 4xx: fix the request (or your quota) — retrying won't help
  if [ "$status" -lt 500 ]; then
    echo "CarsXE $status: $(echo "$body" | jq -r '.message')" >&2
    exit 1
  fi

  # 5xx: exponential backoff
  if [ "$attempt" -lt "$retries" ]; then
    sleep $((2 ** attempt))
  fi
done

echo "CarsXE request failed after retries" >&2
exit 1
```

```js
import { CarsXE } from "carsxe-api";

const carsxe = new CarsXE("YOUR_API_KEY");

async function carsxeRequest(vin, { retries = 3 } = {}) {
  for (let attempt = 0; attempt <= retries; attempt++) {
    try {
      return await carsxe.specs({ vin });
    } catch (error) {
      // 4xx: fix the request (or your quota) — retrying won't help
      if (error.statusCode < 500) throw error;

      // 5xx: exponential backoff
      if (attempt < retries) {
        await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
      }
    }
  }
  throw new Error("CarsXE request failed after retries");
}
```

```python
import asyncio
import time
from carsxe_api import CarsXE

carsxe = CarsXE("YOUR_API_KEY")

def carsxe_request(vin: str, retries: int = 3) -> dict:
    for attempt in range(retries + 1):
        try:
            return asyncio.run(carsxe.specs({"vin": vin}))
        except Exception as error:
            # 4xx: fix the request (or your quota) — retrying won't help
            if getattr(error, "status_code", 500) < 500:
                raise

            # 5xx: exponential backoff
            if attempt < retries:
                time.sleep(2 ** attempt)

    raise RuntimeError("CarsXE request failed after retries")
```

```php
<?php
require_once __DIR__ . '/vendor/autoload.php';
use CarsxeDeveloper\Carsxe\Carsxe;

$carsxe = new Carsxe("YOUR_API_KEY");

function carsxeRequest(Carsxe $carsxe, string $vin, int $retries = 3): array
{
    for ($attempt = 0; $attempt <= $retries; $attempt++) {
        try {
            return $carsxe->specs(["vin" => $vin]);
        } catch (Exception $error) {
            // 4xx: fix the request (or your quota) — retrying won't help
            if ($error->getCode() < 500) {
                throw $error;
            }

            // 5xx: exponential backoff
            if ($attempt < $retries) {
                sleep(2 ** $attempt);
            }
        }
    }

    throw new RuntimeException("CarsXE request failed after retries");
}
```

```ruby
require "carsxe"

carsxe = Carsxe::CarsXE.new(api_key: "YOUR_API_KEY")

def carsxe_request(carsxe, vin, retries: 3)
  (0..retries).each do |attempt|
    begin
      return carsxe.specs("vin" => vin)
    rescue => error
      # 4xx: fix the request (or your quota) — retrying won't help
      raise if error.respond_to?(:status_code) && error.status_code < 500

      # 5xx: exponential backoff
      sleep(2**attempt) if attempt < retries
    end
  end

  raise "CarsXE request failed after retries"
end
```

```go
package main

import (
	"fmt"
	"time"
	carsxe "github.com/carsxe/carsxe-go-package"
)

func carsxeRequest(client *carsxe.Client, vin string, retries int) (map[string]any, error) {
	for attempt := 0; attempt <= retries; attempt++ {
		result, err := client.Specs(map[string]string{"vin": vin})
		if err == nil {
			return result, nil
		}

		// 4xx: fix the request (or your quota) — retrying won't help
		if apiErr, ok := err.(*carsxe.APIError); ok && apiErr.StatusCode < 500 {
			return nil, err
		}

		// 5xx: exponential backoff
		if attempt < retries {
			time.Sleep(time.Duration(1<<attempt) * time.Second)
		}
	}

	return nil, fmt.Errorf("CarsXE request failed after retries")
}

func main() {
	client := carsxe.New("YOUR_API_KEY")
	result, err := carsxeRequest(client, "1HGCM82633A004352", 3)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(result)
}
```

```java
import io.github.carsxe.CarsXE;
import io.github.carsxe.CarsXEException;
import java.util.HashMap;
import java.util.Map;

public class CarsxeErrorHandling {
    static Map<String, Object> carsxeRequest(CarsXE carsxe, String vin, int retries) throws Exception {
        for (int attempt = 0; attempt <= retries; attempt++) {
            try {
                Map<String, String> params = new HashMap<>();
                params.put("vin", vin);
                return carsxe.specs(params);
            } catch (CarsXEException e) {
                // 4xx: fix the request (or your quota) — retrying won't help
                if (e.getStatusCode() < 500) throw e;

                // 5xx: exponential backoff
                if (attempt < retries) {
                    Thread.sleep((long) Math.pow(2, attempt) * 1000);
                }
            }
        }
        throw new RuntimeException("CarsXE request failed after retries");
    }

    public static void main(String[] args) throws Exception {
        CarsXE carsxe = new CarsXE("YOUR_API_KEY");
        System.out.println(carsxeRequest(carsxe, "1HGCM82633A004352", 3));
    }
}
```

```swift
import carsxe

let carsxe = CarsXE(apiKey: "YOUR_API_KEY")

func carsxeRequest(vin: String, retries: Int = 3) async throws -> [String: Any] {
    for attempt in 0...retries {
        do {
            return try carsxe.specs(["vin": vin])
        } catch let error as CarsXEError {
            // 4xx: fix the request (or your quota) — retrying won't help
            if error.statusCode < 500 { throw error }

            // 5xx: exponential backoff
            if attempt < retries {
                try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(attempt))) * 1_000_000_000)
            }
        }
    }
    throw CarsXEError(statusCode: -1, message: "CarsXE request failed after retries")
}
```

```csharp
using carsxe;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
    static async Task<Dictionary<string, object>> CarsxeRequest(
        CarsXE carsxe, string vin, int retries = 3)
    {
        for (int attempt = 0; attempt <= retries; attempt++)
        {
            try
            {
                return await carsxe.Specs(new Dictionary<string, string> { { "vin", vin } });
            }
            catch (CarsXEException ex)
            {
                // 4xx: fix the request (or your quota) — retrying won't help
                if (ex.StatusCode < 500) throw;

                // 5xx: exponential backoff
                if (attempt < retries)
                    await Task.Delay((int)Math.Pow(2, attempt) * 1000);
            }
        }
        throw new Exception("CarsXE request failed after retries");
    }

    static async Task Main(string[] args)
    {
        CarsXE carsxe = new CarsXE("YOUR_API_KEY");
        var result = await CarsxeRequest(carsxe, "1HGCM82633A004352");
        Console.WriteLine(result);
    }
}
```

</CodeGroup>

---

## CORS errors

The CarsXE API is meant to be called **from your server**, never from the browser. This protects your API key from being stolen — any key shipped to a browser is public. If you call the API from frontend JavaScript, the browser will block the request with a CORS error.

Route requests through your backend instead, and keep your key in an environment variable.

---

## Still stuck?

If you've checked the tables above and the error doesn't make sense, contact support and include:

- The **endpoint** and **parameters** you sent (redact your API key)
- The **full response body** and **HTTP status code**
- The **timestamp** (with timezone) of the failing request

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
