Documentation

API reference.

Decode VINs, pull official US safety data and look up plates. JSON over HTTPS, one API key, and an MCP server for AI agents.

BASE URLhttps://vehicles-api.com/api/v1

Overview

Every endpoint lives under https://vehicles-api.com/api/v1, accepts JSON (POST) or a query string (GET) and answers with the same envelope:

Success
{
  "status": "success",
  "source": "nhtsa",
  "data": { … }
}
Error
{
  "status": "error",
  "error": {
    "code": "invalid_vin",
    "message": "VIN must be 17 characters…"
  }
}
Coverage: VIN decode works worldwide (fullest for US-market vehicles). Recalls, complaints and NCAP ratings come from NHTSA and cover vehicles sold in the US, matched by make + model + year — wherever the vehicle was built. A US-market vehicle with no recalls returns HTTP 200 and an empty list. A VIN NHTSA can't match to a US-market make/model/year returns HTTP 422 coverage_us_only on /vin/recalls, /vin/complaints and /vin/safety-ratings (not billed), while /vin/report still returns 200 with the decoded specs and an empty safety block marked coverage: "us_only". No VIN? GET /recalls?make=&model=&year= lists the US-market campaigns for that model.

Authentication

Send your API key in the X-API-Key header on every request. Authorization: Bearer <key> works too, and the legacy ?api_key= query parameter is still accepted for backwards compatibility.

Header
X-API-Key: YOUR_API_KEY

Create, rename and revoke keys from the dashboard. Keep keys server-side — never ship them in browser or mobile code.

Errors

Errors use standard HTTP status codes plus a stable machine-readable error.code. Only 2xx responses count toward your quota — an error is never billed.

HTTPerror.codeMeaningCounts toward quota
401invalid_api_keyMissing, invalid, revoked or expired API key.No
403no_active_planThe account has no active trial or subscription.No
404not_foundNo record for that input (e.g. unknown Dutch plate).No
422invalid_vin · invalid_plate · invalid_vehicleMalformed or missing input — VINs are 17 characters without I, O or Q; /v1/recalls needs make, model and year.No
422coverage_us_onlyValid VIN, but NHTSA has no US-market match for it, so recalls, complaints and NCAP ratings don't apply. Returned by the three /v1/vin safety GETs; /v1/vin/report still answers 200.No
429rate_limit_exceeded · quota_exceededPer-minute rate limit or monthly quota reached. Back off and retry.No
502upstream_unavailableThe government data source is temporarily down. Retry with backoff.No

Rate limits & quotas

Each plan has a monthly request quota and a per-minute rate limit. Responses include X-RateLimit-Limit and X-RateLimit-Remaining; a 429 carries Retry-After. During the 7-day free trial the quota is 50 requests.

PlanRequests / monthRequests / minutePrice
Starter50,000100$49/mo
Pro250,000500$199/mo
POST /v1/vin/decode

Decode

Year, make, model, trim, engine, transmission and assembly plant for any 17-character VIN.

Parameters — JSON body

NameTypeDescription
vin
required
string 17 characters · letters I, O and Q are never used
Example: 1HGCM82633A004352
curl -X POST https://vehicles-api.com/api/v1/vin/decode \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"vin":"1HGCM82633A004352"}'
const res = await fetch("https://vehicles-api.com/api/v1/vin/decode", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"vin":"1HGCM82633A004352"}),
});
const json = await res.json();
import requests

res = requests.post(
    "https://vehicles-api.com/api/v1/vin/decode",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"vin":"1HGCM82633A004352"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "nhtsa",
    "data": {
        "vin": "1HGCM82633A004352",
        "valid": true,
        "year": 2003,
        "make": "HONDA",
        "model": "Accord",
        "trim": "EX-V6",
        "body": "Coupe",
        "doors": 2,
        "vehicle_type": "PASSENGER CAR",
        "engine": {
            "cylinders": 6,
            "displacement_l": 3,
            "configuration": "V-Shaped",
            "model": "J30A4",
            "hp": 240,
            "fuel": "Gasoline"
        },
        "drive": null,
        "transmission": {
            "style": "Automatic",
            "speeds": 5
        },
        "plant": {
            "country": "UNITED STATES (USA)",
            "city": "MARYSVILLE",
            "state": "OHIO"
        },
        "manufacturer": "AMERICAN HONDA MOTOR CO., INC."
    }
}
POST /v1/vin/report Best value

Full report

Specs, open recalls, complaint count and crash ratings in a single call.

Parameters — JSON body

NameTypeDescription
vin
required
string 17 characters · letters I, O and Q are never used
Example: 1HGCM82633A004352
curl -X POST https://vehicles-api.com/api/v1/vin/report \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"vin":"1HGCM82633A004352"}'
const res = await fetch("https://vehicles-api.com/api/v1/vin/report", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"vin":"1HGCM82633A004352"}),
});
const json = await res.json();
import requests

res = requests.post(
    "https://vehicles-api.com/api/v1/vin/report",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"vin":"1HGCM82633A004352"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "nhtsa",
    "data": {
        "vin": "1HGCM82633A004352",
        "valid": true,
        "year": 2003,
        "make": "HONDA",
        "model": "Accord",
        "trim": "EX-V6",
        "body": "Coupe",
        "doors": 2,
        "vehicle_type": "PASSENGER CAR",
        "engine": {
            "cylinders": 6,
            "displacement_l": 3,
            "fuel": "Gasoline"
        },
        "plant": {
            "country": "UNITED STATES (USA)",
            "city": "MARYSVILLE",
            "state": "OHIO"
        },
        "manufacturer": "AMERICAN HONDA MOTOR CO., INC.",
        "coverage": "us",
        "recalls_count": 24,
        "recalls": [
            {
                "campaign": "19V182000",
                "component": "AIR BAGS:FRONTAL:DRIVER SIDE:INFLATOR MODULE",
                "received": "2019-03-06",
                "summary": "Replacement driver air bag inflator may explode.",
                "consequence": "Sharp metal fragments may strike occupants.",
                "remedy": "Dealers will replace the inflator, free of charge."
            }
        ],
        "complaints_count": 2013,
        "safety_ratings": {
            "match": "partial",
            "vehicle_description": "2003 Honda Accord 2-DR.",
            "overall": null,
            "front": {
                "driver": 5,
                "passenger": 5
            },
            "side": {
                "driver": 5,
                "passenger": 5
            },
            "rollover": 4
        }
    }
}
POST /v1/vin/validate Instant

Validate

Format and ISO 3779 check-digit validation, computed locally (no upstream call).

Parameters — JSON body

NameTypeDescription
vin
required
string 17 characters · the 9th character is the check digit
Example: 1HGCM82633A004352
curl -X POST https://vehicles-api.com/api/v1/vin/validate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"vin":"1HGCM82633A004352"}'
const res = await fetch("https://vehicles-api.com/api/v1/vin/validate", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"vin":"1HGCM82633A004352"}),
});
const json = await res.json();
import requests

res = requests.post(
    "https://vehicles-api.com/api/v1/vin/validate",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"vin":"1HGCM82633A004352"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "local",
    "data": {
        "vin": "1HGCM82633A004352",
        "valid": true,
        "check_digit": "3"
    }
}
GET /v1/vin/recalls US market

Recalls

Official NHTSA recall campaigns for the decoded year / make / model.

Parameters — query string

NameTypeDescription
vin
required
string Matched by make + model + year: any vehicle sold in the US, wherever it was built
Example: 1HGCM82633A004352
curl "https://vehicles-api.com/api/v1/vin/recalls?vin=1HGCM82633A004352" \
  -H "X-API-Key: YOUR_API_KEY"
const res = await fetch("https://vehicles-api.com/api/v1/vin/recalls?vin=1HGCM82633A004352", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const json = await res.json();
import requests

res = requests.get(
    "https://vehicles-api.com/api/v1/vin/recalls",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"vin":"1HGCM82633A004352"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "nhtsa",
    "data": {
        "vin": "1HGCM82633A004352",
        "year": 2003,
        "make": "HONDA",
        "model": "Accord",
        "coverage": "us",
        "count": 24,
        "recalls": [
            {
                "campaign": "19V182000",
                "component": "AIR BAGS:FRONTAL:DRIVER SIDE:INFLATOR MODULE",
                "received": "2019-03-06",
                "summary": "Replacement driver air bag inflator may explode.",
                "consequence": "Sharp metal fragments may strike occupants.",
                "remedy": "Dealers will replace the inflator, free of charge."
            }
        ]
    }
}
GET /v1/recalls No VIN

Recalls by model

US-market NHTSA recall campaigns for a make, model and year — no VIN needed. Zero campaigns is a 200 with an empty list.

Parameters — query string

NameTypeDescription
make
required
string Brand as sold in the US, case-insensitive
Example: BMW
model
required
string US-market model name, as NHTSA lists it
Example: 320i
year
required
string 4-digit model year
Example: 2002
curl "https://vehicles-api.com/api/v1/recalls?make=BMW&model=320i&year=2002" \
  -H "X-API-Key: YOUR_API_KEY"
const res = await fetch("https://vehicles-api.com/api/v1/recalls?make=BMW&model=320i&year=2002", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const json = await res.json();
import requests

res = requests.get(
    "https://vehicles-api.com/api/v1/recalls",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"make":"BMW","model":"320i","year":"2002"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "nhtsa",
    "data": {
        "year": 2002,
        "make": "BMW",
        "model": "320i",
        "coverage": "us",
        "count": 1,
        "recalls": [
            {
                "campaign": "20V018000",
                "component": "AIR BAGS:FRONTAL:PASSENGER SIDE:INFLATOR MODULE",
                "received": "2020-01-15",
                "summary": "BMW is recalling certain 2000-2006 3 Series vehicles equipped with Takata PSAN passenger frontal air bag inflators.",
                "consequence": "An inflator explosion may result in sharp metal fragments striking the driver or other occupants.",
                "remedy": "Dealers will replace the passenger front air bag, free of charge."
            }
        ]
    }
}
GET /v1/vin/complaints US market

Complaints

Owner complaints filed with NHTSA ODI — the 50 most recent, plus the true total.

Parameters — query string

NameTypeDescription
vin
required
string Matched by make + model + year: any vehicle sold in the US, wherever it was built
Example: 1HGCM82633A004352
curl "https://vehicles-api.com/api/v1/vin/complaints?vin=1HGCM82633A004352" \
  -H "X-API-Key: YOUR_API_KEY"
const res = await fetch("https://vehicles-api.com/api/v1/vin/complaints?vin=1HGCM82633A004352", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const json = await res.json();
import requests

res = requests.get(
    "https://vehicles-api.com/api/v1/vin/complaints",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"vin":"1HGCM82633A004352"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "nhtsa",
    "data": {
        "vin": "1HGCM82633A004352",
        "year": 2003,
        "make": "HONDA",
        "model": "Accord",
        "coverage": "us",
        "count": 2013,
        "complaints": [
            {
                "odi_number": "11459899",
                "date": "2022-03-15",
                "crash": false,
                "fire": false,
                "injured": 0,
                "deaths": 0,
                "components": [
                    "AIR BAGS"
                ],
                "summary": "Driver airbag warning light illuminated."
            }
        ]
    }
}
GET /v1/vin/safety-ratings US market

Safety ratings

NHTSA NCAP crash-test stars: frontal, side and rollover.

Parameters — query string

NameTypeDescription
vin
required
string Matched by make + model + year: any vehicle sold in the US, wherever it was built
Example: 1HGCM82633A004352
curl "https://vehicles-api.com/api/v1/vin/safety-ratings?vin=1HGCM82633A004352" \
  -H "X-API-Key: YOUR_API_KEY"
const res = await fetch("https://vehicles-api.com/api/v1/vin/safety-ratings?vin=1HGCM82633A004352", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const json = await res.json();
import requests

res = requests.get(
    "https://vehicles-api.com/api/v1/vin/safety-ratings",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"vin":"1HGCM82633A004352"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "nhtsa",
    "data": {
        "vin": "1HGCM82633A004352",
        "coverage": "us",
        "match": "partial",
        "vehicle_description": "2003 Honda Accord 2-DR.",
        "overall": null,
        "front": {
            "overall": null,
            "driver": 5,
            "passenger": 5
        },
        "side": {
            "overall": null,
            "driver": 5,
            "passenger": 5
        },
        "rollover": 4,
        "nhtsa_vehicle_id": 4736
    }
}
POST /v1/plate/nl NL

Netherlands

Dutch RDW registration record for a kenteken (plate). RDW data never includes the VIN.

Parameters — JSON body

NameTypeDescription
plate
required
string With or without dashes — K-875-HJ works too
Example: K875HJ
curl -X POST https://vehicles-api.com/api/v1/plate/nl \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"plate":"K875HJ"}'
const res = await fetch("https://vehicles-api.com/api/v1/plate/nl", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"plate":"K875HJ"}),
});
const json = await res.json();
import requests

res = requests.post(
    "https://vehicles-api.com/api/v1/plate/nl",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"plate":"K875HJ"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "plate_nl",
    "data": {
        "plate": "K875HJ",
        "vin": null,
        "year": 2021,
        "make": "TOYOTA",
        "model": "AYGO",
        "body": "hatchback",
        "color": "GRIJS",
        "doors": 4,
        "seats": 4,
        "vehicle_type": "Personenauto",
        "engine": {
            "cylinders": 3,
            "displacement_cc": 998,
            "fuel": "Benzine"
        },
        "mass_kg": 815,
        "apk_expires": "2027-01-04",
        "first_registration": "2021-01-04",
        "open_recall": false
    }
}
POST /v1/plate/us Not yet live

United States

Plate + state → VIN → specs, via a plate-to-VIN vendor. Returns upstream_unavailable until a vendor key is configured.

Parameters — JSON body

NameTypeDescription
plate
required
string No spaces
Example: 7ABC123
state
required
string USPS 2-letter code
Example: CA
curl -X POST https://vehicles-api.com/api/v1/plate/us \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"plate":"7ABC123","state":"CA"}'
const res = await fetch("https://vehicles-api.com/api/v1/plate/us", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"plate":"7ABC123","state":"CA"}),
});
const json = await res.json();
import requests

res = requests.post(
    "https://vehicles-api.com/api/v1/plate/us",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"plate":"7ABC123","state":"CA"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "plate_us",
    "data": {
        "plate": "7ABC123",
        "state": "CA",
        "vin": "1HGCM82633A004352",
        "year": 2003,
        "make": "HONDA",
        "model": "Accord",
        "trim": "EX-V6",
        "body": "Coupe",
        "vehicle_type": "PASSENGER CAR"
    }
}
GET /v1/plate/us/states Reference

US states

The US states (USPS codes) covered by plate lookups. Static reference data.

curl "https://vehicles-api.com/api/v1/plate/us/states" \
  -H "X-API-Key: YOUR_API_KEY"
const res = await fetch("https://vehicles-api.com/api/v1/plate/us/states", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const json = await res.json();
import requests

res = requests.get(
    "https://vehicles-api.com/api/v1/plate/us/states",
    headers={"X-API-Key": "YOUR_API_KEY"},
    timeout=15,
)
print(res.json())
Example response · 200
{
    "status": "success",
    "source": "plate_us",
    "data": {
        "states": [
            {
                "code": "AL",
                "name": "Alabama"
            },
            {
                "code": "AK",
                "name": "Alaska"
            },
            {
                "code": "…",
                "name": "51 entries in total"
            }
        ]
    }
}

MCP server

Connect Claude, Cursor, ChatGPT or any Model Context Protocol client to https://vehicles-api.com/mcp (Streamable HTTP). Authenticate with your API key as a Bearer token. initialize and tools/list are free; each tools/call counts as one API request.

Open the MCP setup guide

Tools: decode_vin, vehicle_report, validate_vin, vin_recalls, vehicle_recalls, vin_complaints, vin_safety_ratings, lookup_dutch_plate, plate_us, list_us_plate_states .

Agent credentials

Autonomous agents can obtain a sandbox key without a signup form, using OAuth 2.0 client credentials:

  1. POST https://vehicles-api.com/oauth/register with client_name and contact_email → client_id + client_secret
  2. POST https://vehicles-api.com/oauth/token with grant_type=client_credentials → access_token
  3. Use the token as Authorization: Bearer … on the REST API or the MCP server
Sandbox credentials have a fixed quota of 100 requests, 5 requests/minute, and expire after 7 days. For production traffic, sign up and use a plan key.

Machine-readable discovery: auth.md · oauth-protected-resource · api-catalog · MCP server card · agent skills · llms.txt