
You need to quickly verify whether a VIN is structurally valid before you spend time (and requests) on decoding, recalls, or quoting. By the end of this guide, you’ll be able to validate a VIN’s ISO 3779 check digit with Vehicle API, extract the check digit value, and integrate robust error handling and caching so your app can reject mistyped VINs early.
What the VIN check digit is and when to validate it
The check digit is the 9th character of a 17-character VIN. It’s calculated from the other 16 characters under ISO 3779 to prevent typos and basic fraud. Validating the check digit before any downstream lookups saves time and quota: if the check fails, the VIN is malformed and should not be decoded or used for quoting, lead intake, or inventory ingestion.
Because the check digit is purely a function of the VIN characters, validation is deterministic and cacheable. Vehicle API computes this locally with no upstream dependency, so it’s fast and consistent across regions.
Endpoint overview
Vehicle API exposes a dedicated endpoint to validate the VIN format and check digit:
- Method and URL: POST https://vehicles-api.com/api/v1/vin/validate
- Headers:
- X-API-Key: YOUR_API_KEY (Authorization: Bearer YOUR_API_KEY is also accepted)
- Content-Type: application/json
- Body: JSON with a single key vin containing a 17-character VIN string
- Computation: ISO 3779 check-digit validation, performed locally; the 9th character is the check digit
- Response envelope: status, source, and data on success; status: error with error.code and error.message on failure
This endpoint focuses only on structure and check digit. It does not decode year, make, model, trim, or safety data. Use it to short-circuit bad inputs before calling VIN decoding or US-market safety resources through Vehicle API.
Copy-and-paste cURL
The following is the official example request and response. You can paste this directly into your terminal and swap in your API key when you’re ready.
cURL
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"}'
JSON
{
"status": "success",
"source": "local",
"data": {
"vin": "1HGCM82633A004352",
"valid": true,
"check_digit": "3"
}
}
JavaScript example
This sample posts a VIN to the validation endpoint, checks the valid boolean, and reads the check_digit string for auditing or UI display. It uses the same endpoint shown above.
async function validateVin(vin) {
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 })
});
const payload = await res.json();
// Handle the uniform response envelope
if (payload.status !== "success") {
const code = payload.error?.code || "unknown_error";
const message = payload.error?.message || "Request failed";
throw new Error(`VIN validate error [${code}]: ${message}`);
}
// Extract fields you actually use
const { vin: echoedVin, valid, check_digit } = payload.data;
// Typical gate: reject invalid VIN early
if (!valid) {
return { ok: false, vin: echoedVin, reason: "check_digit_failed", checkDigit: check_digit || null };
}
// Optionally persist this in your cache keyed by VIN
return { ok: true, vin: echoedVin, checkDigit: check_digit };
}
// Example usage with the documented control VIN:
validateVin("1HGCM82633A004352")
.then(result => console.log(result))
.catch(err => console.error(err));
Understanding the response envelope and fields
All Vehicle API endpoints return a consistent envelope. For this endpoint, on success you will see:
- status: "success"
- source: "local" (validation is computed locally; no external call)
- data:
- vin: Echo of the input VIN string
- valid: Boolean that indicates whether the VIN passes ISO 3779 check-digit validation and basic formatting
- check_digit: String containing the 9th character of the VIN (the expected check digit)
On error, the envelope uses:
- status: "error"
- error.code: A machine-readable error identifier
- error.message: A human-readable description explaining what went wrong
Null fields: This response generally fills all keys for valid inputs. If the VIN is malformed (wrong length or disallowed characters), valid will be false or you may receive an error; check_digit may be null or omitted in error cases depending on input and validation path. Always guard your code for missing or null fields.
When to use the check_digit field
Most applications only need valid to gate subsequent work. However, check_digit is useful when you want to:
- Display the expected check digit in a UI so users can compare against their document or barcode.
- Log the expected digit during lead capture to detect systematic OCR or scanning issues.
- Build automated correction flows: if the 9th character differs from check_digit, prompt for re-entry.
Because the 9th character is the check digit, mismatches indicate either a mistyped VIN or a non-compliant identifier that should be rejected before decode or quoting.
Coverage and scope you should plan around
- VIN validation: Works worldwide for 17-character VINs under ISO 3779. The check is independent of market.
- VIN decoding (year, make, model, trim, engine, transmission, assembly plant): Available through Vehicle API and based on NHTSA vPIC, with fullest coverage for US-market vehicles.
- US safety data (recalls, owner complaints, NCAP crash ratings): US-market only and matched by make + model + year, not strictly the VIN itself. Do not expect international recall or rating coverage.
- Dutch plates: Supported via RDW open data. Dutch plate lookups never include a VIN. Use validation only when you already have a VIN.
- Not a vehicle history report: Vehicle API does not provide title, accident, or ownership history.
Plan to validate early, then branch into VIN decoding or market-specific safety data based on your application and the customer’s region.
Practical integration details
Authentication
Send your key in X-API-Key: YOUR_API_KEY. Authorization: Bearer YOUR_API_KEY is also accepted if your HTTP tooling prefers Authorization headers.
Latency and reliability
Validation is computed locally with no external calls, so it’s low-latency and stable. Use this as a first step in any VIN pipeline (lead forms, ingestion jobs, mobile scan flows) to filter out malformed VINs fast.
Caching strategy
- Cache key: the 17-character VIN string.
- Value: { valid, check_digit } and any timestamp.
- TTL: You can safely use long TTLs (weeks to months). The ISO 3779 computation won’t change for the same VIN.
- Invalid VINs: Also cache negative results (valid: false) to avoid repeated rejects on the same bad input.
Rate limits and monthly quota
All plans include a 7-day free trial. Starter is $19/mo. Exact rate limits and monthly quotas can change by plan and may be updated—refer to the Documentation for current limits. If you anticipate bursts (e.g., nightly ingestion), queue and pace requests, and cache results as described above.
Error handling patterns
- Transport errors (timeouts, 5xx): Retry with backoff. Since computation is idempotent, retries are safe.
- 4xx with status: "error": Do not retry. Inspect error.code and error.message. Correct the request, surface a user-friendly message, or halt the pipeline.
- Input validation errors: Ensure the VIN is exactly 17 characters and uppercase alphanumerics (I, O, Q are not used in VINs). If your scanner/OCR includes spaces or punctuation, strip them before sending.
Security and PII
VINs are identifiers for vehicles, not people. Still, avoid logging full VINs in plaintext if your compliance standards require redaction; you can hash or mask the middle characters and store check_digit separately for debugging.
Workflow: where VIN validation fits
- Dealers and marketplaces: Validate VINs on listing creation or import before decoding and enriching, so you don’t waste quota on malformed identifiers.
- Fleet and insurance: Validate VINs in policy bind flows and telematics enrollments before quoting or binding. Reject invalid entries and prompt for correction.
- AI agents: Before autonomous actions (e.g., scheduling service or ordering parts), confirm the VIN structure so agents don’t chase an invalid identifier.
If the VIN is valid, proceed to VIN decoding for model details, then optionally layer in US-market recalls, complaints, and NCAP ratings based on make, model and year. Remember: Dutch plate lookups from RDW never include a VIN; treat that as a separate input pathway.
Using the MCP server
If you’re building an AI agent or a tool using the Model Context Protocol, Vehicle API is also exposed as an MCP server at MCP. This enables your agent framework to call the same validation and decoding capabilities as tools, with consistent envelopes and fields. The check-digit behavior and fields are identical: status, source, data.vin, data.valid, and data.check_digit.
Testing and QA tips
- Golden VIN: Keep a known-good VIN (like the official example in this article) in your test suite to assert integration health.
- Negative cases: Create inputs with wrong length, illegal characters, or an intentionally flipped 9th character to confirm your error handling and UI prompts.
- Monitoring: Track rates of invalid VINs over time by source (manual entry, scan, import). Spikes may indicate an OCR regression or a source feed issue.
Field-by-field guide for developers
- data.vin: Use as an echo to ensure the response corresponds to the request you sent, especially when processing many VINs asynchronously.
- data.valid: This is your primary gate. If false, stop downstream processing (decode, recall lookup, quoting) and surface a correction path to the user.
- data.check_digit: Display in UIs that accept manual VIN entry to help users correct the 9th character. Log to diagnose OCR or scan issues.
- source: Expect "local" for this endpoint. If you observe changes here in future API versions, consult the docs; it won’t affect the check-digit contract.
- status: Always check this first. Only read data if status === "success".
End-to-end flow example
- Receive a VIN string (manual entry, scan, or import).
- POST to /api/v1/vin/validate with headers and body as shown.
- If status is "success" and data.valid is true:
- Cache { vin, valid: true, check_digit } with a long TTL.
- Continue to VIN decoding for year, make, model, trim, engine, transmission, and assembly plant.
- If the vehicle is US-market, you can optionally attach recalls, owner complaints, and NCAP crash ratings matched by make + model + year.
- If status is "success" and data.valid is false:
- Cache the negative result and prompt for correction; highlight the 9th position.
- If status is "error":
- Inspect error.code and error.message. Fix client issues or surface a user-friendly message without retrying.
Operational considerations
- Idempotency: Repeated validation calls with the same VIN yield the same result; you can safely retry on transient errors.
- Batching: If you ingest large files, parallelize with care to stay within your plan’s rate limits. Cache successful validations to reduce duplicate calls.
- International handling: Validation succeeds or fails based on ISO 3779 regardless of market. Decoding depth is fullest for US-market vehicles; don’t assume trim-level detail for all regions.
- Non-VIN identifiers: Dutch plates from RDW never include VIN; don’t attempt to derive a VIN from plates.
FAQs
Does validation require a network round trip to external sources?
No. The ISO 3779 computation is performed locally by Vehicle API. The response will show source: "local".
What happens if the VIN is not 17 characters?
You will receive status: "error" or a "success" response with valid: false depending on the exact input. Always check status first, then data.valid. Strip whitespace and punctuation before sending.
Can I rely on valid: true to guarantee a successful decode?
valid: true confirms the VIN’s structural integrity and check digit. It does not guarantee that every market-specific detail is available. Decoding coverage is worldwide but fullest for US-market vehicles.
Do Dutch plate lookups return a VIN?
No. Dutch plates come from RDW open data and never include a VIN. Treat plate lookups and VIN validation as separate workflows.
Where can I find current rate limits and quotas?
Plan limits can change. Refer to the Documentation for the latest rate limits and monthly quotas, and cache your validation results to minimize calls.
Start validating VINs in minutes and only process structurally sound identifiers. Sign up for the 7-day free trial and get your API key here: Register. For agent integrations, see the MCP server: MCP. Visit Vehicle API anytime at https://vehicles-api.com for product updates and endpoints.




