Migration
How to migrate from Auto.dev to Cardog
Last updated:
Move from Auto.dev's VIN decode to Cardog's /v2/vin, with a field-by-field map and an adapter you can use while you switch.
Most teams moving from Auto.dev start with VIN decode. You replace GET https://api.auto.dev/vin/{vin} with GET https://api.cardog.app/v2/vin/{vin} and remap about a dozen fields. Year, make, model and trim carry over directly. Body, drive, transmission and plant country come back as entity refs that join to recalls, spec sheets and prices, and engine and plant details sit in the response's attributes map. You also gain Canadian VINs decoded to trim, Transport Canada recalls and batches of 1,000.
This guide is written by Cardog. Every claim about Auto.dev links to Auto.dev's own public documentation, and every claim was checked on 2026-10-26.
The short version
- Create a Cardog API key and send it as
x-api-key. You can also sendAuthorization: Bearer crdg_..., the same header style Auto.dev recommends. - Point your VIN decode at
GET https://api.cardog.app/v2/vin/{vin}and pinCardog-Version: 2026-10-21. - Branch on
validinstead of the HTTP status. When Cardog cannot name a VIN it returns200withvalid: falseand areasonslist, not a404or207. - If you want your existing Auto.dev-shaped code to keep running while you move, use the adapter below.
- Before you switch traffic, compare the two APIs on a sample of your own VINs.
How their fields map to ours
Auto.dev's fields come from the example response and the response structure on its Global VIN Decode page. Cardog's paths come from our response contract for GET /v2/vin/{vin}.
attributes is the decoder's attribute map for the build, keyed by the ids in our spec catalogue (GET /v2/specs/catalog). Each entry is an object, usually { value }, and a measured value can carry a unit. The map is sparse: an entry is there only where the decoder has that fact for the build.
| Auto.dev field | Cardog field | Note |
|---|---|---|
vin | vin | Same. |
vinValid | valid | Not the same thing. Auto.dev's page lists vinValid as a boolean but does not define it. On Cardog, valid means the VIN decodes to a vehicle. A VIN that is not 17 valid characters gets a 400 with code invalid_vin on Cardog. |
wmi | not mapped | It is VIN characters 1 to 3, so you can compute it yourself. |
origin | refs.country | Format change: the plant country as a country ref, such as "country:canada" or "country:united-states-usa", not a display name. null when the decoder does not state a plant country. |
squishVin | nano | Renamed, format change. A ref with a nano: prefix. Auto.dev does not define squishVin, but in its example it is VIN positions 1 to 8, then 10 and 11. Cardog's nano uses the same positions for most makers. Low-volume makers whose WMI ends in 9 get a longer key. Cardog also has a field called squish. That is a different, shorter key, so do not map squishVin to it. |
checkDigit | not mapped | VIN character 9. |
checksum | not mapped | |
type | not mapped | |
make | make | Same (display name). refs.make is the join key. |
model | model | Same (display name). refs.model is the join key. |
trim | trim | Same idea: the catalogue trim decoded from the VIN pattern. Can be null or absent. |
style | not mapped | |
body | refs.bodyStyle | Format change. A ref such as "body-style:pickup", not display text. |
engine | attributes.displacementL, attributes.cylinders, attributes.engineConfiguration, attributes.horsepowerFrom, attributes.engineModel | Not one description string. Separate values on the VIN response where the decoder has them, and with units on the build sheet (sections.engine.* on GET /v2/specs/nano:{code}). |
drive | refs.driveType | Format change. A ref, not display text. Can be null. |
transmission | refs.transmission | Format change. A ref, not display text. Can be null. |
vehicle.vin | vin | Same value. Cardog has no nested vehicle object. |
vehicle.year | year | Moved to the top level. Can be null. |
vehicle.make | make | Moved to the top level. |
vehicle.model | model | Moved to the top level. |
vehicle.manufacturer | attributes.manufacturer | Where the decoder has it. |
ambiguous | not mapped | Cardog returns the catalogue trim decoded from the VIN pattern. |
trims, styles | not mapped | |
yearAmbiguous, years, yearEncoded | not mapped | |
reason, retryable (on a 207) | reasons | Different model. Cardog answers 200 with valid: false and codes from a closed list (for example UNSEEN_BUILD, WMI_UNKNOWN, PATTERN_UNKNOWN). |
| none | refs.make, refs.model, refs.modelYear, refs.fuelType, refs.electrificationLevel, refs.vehicleType, refs.gvwr, refs.series and others | Cardog only. Stable keys that join to recalls, specs, prices and safety. |
| none | doors, numberOfWheels, numberOfAxles, shippingWeight, grossWeight | Cardog only. Optional. Weights are in pounds. |
| none | squish, corgiBuild, authorityTier, links | Cardog only. links gives the paths to the recalls, listings, specs, safety and price for this VIN. |
| none | other attributes.* entries | Cardog only, where the decoder has them: for example transmissionSpeeds, fuelSystem, plantCity, plantCompany, battery fields for EVs and ADAS entries such as adaptiveCruiseControl. |
An adapter for the migration
This function calls Cardog and returns an object in Auto.dev's documented /vin/{vin} shape, for the fields that map. Fields with no mapping are left undefined with a comment. Use it to bridge your migration; it is code you own and run.
type AutoDevVin = {
vin: string;
vinValid?: boolean;
wmi?: string;
origin?: string;
squishVin?: string;
checkDigit?: string;
checksum?: boolean;
type?: string;
make?: string;
model?: string;
trim?: string | null;
style?: string | null;
body?: string;
engine?: string;
drive?: string;
transmission?: string;
vehicle: { vin: string; year?: number; make?: string; model?: string; manufacturer?: string };
ambiguous?: boolean;
yearAmbiguous?: boolean;
};
export async function decodeVinAutoDevShape(vin: string, apiKey: string): Promise<AutoDevVin | null> {
const res = await fetch(`https://api.cardog.app/v2/vin/${encodeURIComponent(vin)}`, {
headers: { "x-api-key": apiKey, "Cardog-Version": "2026-10-21" },
});
if (res.status === 400) throw new Error("INVALID_VIN_FORMAT"); // Auto.dev would also 400
if (!res.ok) throw new Error(`Cardog ${res.status}`);
const c = await res.json();
// Auto.dev answers 404 (or 207) here; Cardog answers 200 with valid:false and c.reasons.
if (!c.valid) return null;
const v = String(c.vin);
return {
vin: v,
vinValid: undefined, // Cardog's `valid` means "decodes"; Auto.dev does not define vinValid
wmi: v.slice(0, 3), // computed from the VIN, not returned by Cardog
origin: undefined, // Cardog returns a ref in c.refs.country, e.g. "country:canada"
squishVin: v.slice(0, 8) + v.slice(9, 11), // matches Auto.dev's example, computed locally
checkDigit: v[8], // computed from the VIN, not returned by Cardog
checksum: undefined, // not mapped
type: undefined, // not mapped
make: c.make ?? undefined,
model: c.model ?? undefined,
trim: c.trim ?? null,
style: undefined, // not mapped
body: undefined, // Cardog returns a ref in c.refs.bodyStyle
engine: undefined, // no description string; parts in c.attributes and on GET /v2/specs/{c.nano}
drive: undefined, // Cardog returns a ref in c.refs.driveType
transmission: undefined, // Cardog returns a ref in c.refs.transmission
vehicle: {
vin: v,
year: c.year ?? undefined,
make: c.make ?? undefined,
model: c.model ?? undefined,
manufacturer: c.attributes?.manufacturer?.value ?? undefined, // where the decoder has it
},
ambiguous: undefined, // not mapped
yearAmbiguous: undefined, // not mapped
};
}If your code reads body, drive or transmission, read the refs (c.refs.bodyStyle, c.refs.driveType, c.refs.transmission) directly. Do not turn them into display strings. The refs are stable keys, and a label you guessed would be a value neither API gave you.
Verify before you switch
- Pick 20 to 50 VINs from your own traffic: your common models, a few EVs, a pickup, anything built outside North America, and a VIN Auto.dev returned
207or404for. - Call both APIs for each VIN and save the raw JSON.
- Compare Auto.dev's
vehicle.year,make,modelandtrimwith Cardog'syear,make,modelandtrim. Note any VIN where one side names the vehicle and the other does not. - For every Cardog
valid: false, readreasons.UNSEEN_BUILDmeans the build code is well formed but has not been decoded yet. You can report it atPOST /v2/feedback, which is also in the response'slinks.feedback. - Run your own downstream tests against the adapter output before moving production traffic.
What Cardog adds
- Transport Canada recalls.
GET /v2/vin/{vin}/recallslists the Transport Canada and NHTSA campaigns for the VIN's model year. Each recall is tagged with its authority ("tc"or"nhtsa"). Auto.dev's Recalls API uses NHTSA data, plus international recalls matched by make and model. Its page does not mention Transport Canada (Vehicle Recalls). - Batch decode.
POST /v2/vin/batchtakes 1 to 1,000 VINs and returns one result per VIN, in request order. One bad VIN fails only its own row, never the whole batch. - No guessing on a miss. When we cannot name a VIN, every identity field and ref is null and
reasonssays why. We do not fill it in from similar vehicles. - Join keys.
refsandnanolink a decode to recalls, spec sheets, market prices and safety data without string matching.linksgives you the paths. - US and Canadian spec sheets.
GET /v2/specs/nano:{code}returns the build's spec sheet with a unit on every number. Pricing and colours are listed separately for each market,USandCA. - Weights and counts.
doors,numberOfAxles,shippingWeight,grossWeightand a GVWR class ref on the decode. - Pinned versions. Send
Cardog-Versionto pin the API version you built against.
FAQ
Do I have to change my auth header?
No. Cardog accepts Authorization: Bearer crdg_... as well as x-api-key.
What happens when Cardog cannot decode a VIN?
You get a 200 with valid: false. The identity fields and refs are null, and reasons is not empty. If the VIN is not 17 valid characters, you get a 400 with code invalid_vin.
Why is body a ref like body-style:pickup?
Refs are stable join keys across our API. Display text can change, but the ref does not.
Where is the engine description?
There is no single string. The parts are in attributes on the decode (displacementL, cylinders, engineConfiguration, horsepowerFrom), where the decoder has them, and with units on the build sheet: take nano from the decode and call GET /v2/specs/{nano}, then read sections.engine.
Can I decode many VINs at once?
Yes. POST /v2/vin/batch takes up to 1,000 VINs.
How is a decode billed?
The identity route is priced at two credits per VIN. Today a single GET /v2/vin/{vin} bills those two credits for any 200 answer, including valid: false, while a batch bills only the rows that come back valid: true. A 400 costs nothing. See /pricing.
Related
- Cardog vs Auto.dev
- Auto.dev alternatives
- Best VIN decoder APIs (2026)
- API docs
- Other migration guides
- Pricing
Sources
Checked on 2026-10-26:
- Auto.dev, Global VIN Decode API: https://docs.auto.dev/v2/products/vin-decode
- Auto.dev, Getting Started: https://docs.auto.dev/v2/getting-started
- Auto.dev, Vehicle Recalls API: https://docs.auto.dev/v2/products/vehicle-recalls
- Auto.dev, documentation index: https://docs.auto.dev/llms.txt
- Auto.dev, Pricing: https://www.auto.dev/pricing
If something here is wrong, tell us and we will fix it.
Was this helpful?