How to Use the VIN Engine Displacement API

By Vehicle API
How to Use the VIN Engine Displacement API

You need the exact engine size for a VIN so your app can quote insurance, match parts, or validate emissions rules. By the end of this guide you’ll be able to decode any 17-character VIN with Vehicle API and reliably read engine.displacement_l (in liters) and engine.cylinders from the response envelope.

What you’ll build and what this endpoint returns

This walkthrough focuses on the VIN Engine Displacement lookup using Vehicle API’s VIN decode endpoint. You’ll:

Illustration: How to Use the VIN Engine Displacement API
  • Start a 7-day free trial and copy your API key.
  • Send the documented curl request against a known control VIN.
  • Parse the official JSON envelope and read engine.displacement_l and engine.cylinders.
  • Handle null fields, caching, quotas, and errors cleanly.

Scope and coverage:

  • VIN decoding works worldwide, with the fullest coverage for US-market vehicles. Some fields that NHTSA does not publish will be null.
  • Safety datasets (recalls, owner complaints, NCAP crash ratings) are US-market only and matched by year + make + model. They’re not part of the displacement lookup itself.
  • Dutch plates are available from RDW open data and never include a VIN.
  • This is not a vehicle history report (no title, accident, or ownership history).

You can browse more in the Documentation and integrate with agents using the MCP server. Every plan includes a 7-day free trial; Starter is $19/mo.

Step 1 — Start your trial and get your API key

Create your account and start the 7-day free trial. After registering, open your dashboard and copy your key.

  • Base URL: https://vehicles-api.com/api/v1
  • Authentication: send X-API-Key: YOUR_API_KEY. Authorization: Bearer YOUR_API_KEY also works, but use only one.

Register here to get your key: Register.

Step 2 — Send the official curl request

The VIN decode endpoint is a POST to /vin/decode with a JSON body containing the VIN. This response envelope includes status, source, and data. The example below uses a known control VIN to demonstrate the structure. It is not your vehicle.

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"}'

Step 3 — Read the official JSON and locate engine.displacement_l

This is the official JSON example for that control VIN. Note the response envelope fields at the top (status, source, data) and the engine object where you will read displacement and cylinder count.

{
    "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"
        },
        "fuel_type": "Gasoline",
        "electrification_level": null,
        "ev_drive_unit": null,
        "battery_kwh": null,
        "charger_level": null,
        "charger_power_kw": null,
        "drive": null,
        "transmission": {
            "style": "Automatic",
            "speeds": 5
        },
        "plant": {
            "country": "UNITED STATES (USA)",
            "city": "MARYSVILLE",
            "state": "OHIO"
        },
        "manufacturer": "AMERICAN HONDA MOTOR CO., INC."
    }
}

Fields you will typically use for engine displacement workflows:

  • status: "success" indicates a successful decode. On errors, status is "error" and an error object is included.
  • source: "nhtsa" indicates the decoding authority for this response.
  • data.vin: the VIN echo.
  • data.valid: whether the VIN structure is valid.
  • data.year, data.make, data.model, data.trim: the key identifiers you may cache alongside engine specs.
  • data.engine.displacement_l: engine displacement in liters (number). This is the primary field for this article.
  • data.engine.cylinders: number of cylinders (integer).

Note: If NHTSA does not publish a field for a given VIN, that key may be null. In the example, several electrification-related fields are null because this control VIN is a gasoline vehicle.

Step 4 — Parse engine.displacement_l and engine.cylinders in code

Python example

This snippet calls the same endpoint you just tested with curl and extracts engine.displacement_l and engine.cylinders from the envelope.

import json
import requests

API_KEY = "YOUR_API_KEY"
URL = "https://vehicles-api.com/api/v1/vin/decode"

payload = {"vin": "1HGCM82633A004352"}
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
# You could alternatively use: "Authorization": f"Bearer {API_KEY}"
}

resp = requests.post(URL, headers=headers, json=payload)
resp.raise_for_status()

body = resp.json()

if body.get("status") != "success":
# Example error envelope: {"status":"error","error":{"code":"...","message":"..."}}
err = body.get("error", {})
raise RuntimeError(f"VIN decode failed: {err.get('code')} {err.get('message')}")

data = body.get("data", {}) or {}
engine = data.get("engine", {}) or {}

displacement_l = engine.get("displacement_l") # float or int (liters); may be null
cylinders = engine.get("cylinders") # int; may be null if not published

print(f"VIN: {data.get('vin')}")
print(f"Year/Make/Model: {data.get('year')} {data.get('make')} {data.get('model')}")
print(f"Engine displacement (L): {displacement_l}")
print(f"Cylinders: {cylinders}")

Implementation notes:

  • Always read the top-level status first. If status is "error", inspect error.code and error.message.
  • Null fields are expected when a publisher does not provide a value. Check for None before arithmetic or display.
  • Units: displacement is in liters. Cylinders is a count.

Production details: envelopes, errors, caching, and quotas

Response envelope: Every response returns one of two shapes.

  • Success: status, source, data. The fields you need (engine.displacement_l, engine.cylinders) live under data.engine.
  • Error: status: "error", plus error.code and error.message. Handle this branch by logging and retrying only if appropriate.

Caching: VIN decode results are effectively static for a given 17-character VIN. Cache the entire data object keyed by VIN. For common VINs in your workflow, you can avoid repeat decodes and save quota by serving from cache.

Nullability: If NHTSA does not publish a field for a given vehicle, Vehicle API returns null for that key. In your parser, treat missing or null engine.displacement_l or engine.cylinders as “unknown” and consider fallback UI or logic.

Coverage: VIN decoding works worldwide, with the richest data for US-market vehicles. Safety datasets (recalls, owner complaints, NCAP crash ratings) are US-market only and matched by year, make, and model. Dutch plate lookups come from RDW open data and never include a VIN.

Quotas and rate limits: Each plan has a monthly quota and request rate limits. Check your dashboard and the Documentation for the latest enforcement details. Implement graceful handling for 4xx/5xx HTTP statuses and the error envelope, and enable caching to conserve quota.

Attribution and source: The source field will indicate nhtsa for VIN decoding backed by NHTSA vPIC. Some fields shown in the example (such as electrification properties) are null for gasoline vehicles and may also be null when the publisher has not provided the values.

How to use displacement and cylinder count in your app

Common patterns for engine sizing data:

  • Insurance quoting: rules often depend on displacement (liters) and cylinder count. Use exact comparisons against data.engine.displacement_l and data.engine.cylinders.
  • Parts fitment: filter parts by engine specification. Cache by VIN to avoid repeated decodes during search.
  • Fleet compliance: validate emissions or registration requirements based on liter displacement per VIN.
  • Marketplace listings: normalize engine data to a consistent display, e.g., “3.0L V6,” derived from displacement_l and cylinders plus configuration when available.

Formatting tips:

  • Show displacement with one decimal place when it is an integer in the dataset (e.g., 3 → “3.0L”). For non-integers, preserve provided precision.
  • Only label cylinder count when present. If cylinders is null, omit it from display.
  • Do not infer electrification data from displacement or cylinder count. If the EV fields are null, display accordingly or hide EV-specific UI.

Testing and validation strategy

To avoid misinterpretation in production:

  • Test with the control VIN from this article to verify envelope parsing, null handling, and happy-path logic.
  • Add negative tests: invalid VIN length, malformed JSON, missing authentication header. Assert that your code checks status and branches to error handling.
  • Simulate nulls: run your parser against payloads where engine.displacement_l or engine.cylinders are null and confirm UI/logic fallbacks.
  • Cache validation: decode the same VIN twice and ensure the second call is served from cache in your environment.

Operational guidance for teams

Monitoring and observability:

  • Log status, source, and the presence of data.engine.displacement_l and data.engine.cylinders for each VIN.
  • Record error.code and error.message on failures. Surface a counter for “null displacement” and “null cylinders” to monitor data availability by market.

Resiliency and retries:

  • Do not retry client errors caused by invalid VINs. Validate VIN length (17 chars) before calling the API.
  • If you see transient network errors, limit retries and back off based on your queue design and quotas.

Security and keys:

  • Store YOUR_API_KEY securely using your platform’s secrets management (not in client-side code or public repos).
  • Rotate keys from your dashboard when needed and redeploy your services accordingly.

Using Vehicle API with AI agents

If you are building an agent or tool that needs authoritative VIN decoding with engine displacement, you can integrate Vehicle API via MCP at: MCP. This lets the agent call the same decoding capability you used in curl and Python, and then reason directly over engine.displacement_l and engine.cylinders. Apply the same caching rules: decode once per VIN, store the envelope, and reuse.

Troubleshooting common issues

  • VIN not 17 characters: Validate client-side before calling the API. Shorter or longer VINs will not decode and should be rejected early.
  • Missing fields: If displacement or cylinders is null, check vehicle market coverage and publisher availability. Consider a UX fallback that displays year/make/model without engine sizing.
  • Envelope mismatch: Always parse top-level status first. Do not assume data is present when status is not "success".
  • Quota exhaustion: Since VIN decodes are deterministic, rely on caching to limit calls. Review your monthly usage in the dashboard.

Endpoint reference for this task

Endpoint: POST https://vehicles-api.com/api/v1/vin/decode

  • Headers: X-API-Key: YOUR_API_KEY; Content-Type: application/json. Authorization: Bearer YOUR_API_KEY is also supported (use one auth method).
  • Body: {"vin":"<17-character VIN>"}.
  • Response: JSON envelope with status, source, data on success; status: "error" with error.code and error.message on failure.
  • Fields relevant here: data.engine.displacement_l (liters), data.engine.cylinders (count). Both may be null if not published.

FAQ

Does this endpoint cover all markets?
Yes, VIN decoding works worldwide, with the most complete data for US-market vehicles. If a field is not published by NHTSA for a given VIN, Vehicle API returns null for that key.

Are recalls, complaints, or NCAP ratings included in this decode?
Those datasets are US-market only and matched by year + make + model. They’re separate from the displacement lookup and not part of the decode shown here.

What units are used for displacement, and can it be missing?
engine.displacement_l is in liters. It can be null if the publisher does not provide it for that VIN. Your app should handle null by hiding the value or indicating it is unknown.

Do Dutch plate lookups include a VIN?
No. Dutch plates are sourced from RDW open data and never include a VIN. Use VIN decoding when you have a 17-character VIN; use plate lookups when you have a Dutch registration.

How should I handle errors and rate limits?
On errors, the envelope includes status: "error" with error.code and error.message. Implement backoff where appropriate, and cache decoded VINs to conserve monthly quota. Check the dashboard and the Documentation for current limits.

Start your integration now: create an account, get your key, and ship a working VIN Engine Displacement lookup in minutes. Every plan includes a 7-day free trial: Register.