Fields are never removed or redefined within v1; we only add. Clients must ignore fields they do not recognise. Policy →
GET /v1/decode
stableIdentityDecode a vehicle (identity only)
Resolve a VIN (or config_key / YMMT) to its canonical identity — config + engine — with no group joins. The lightest lookup.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| year | query | integer | no | Model year.e.g. 2019 |
| make | query | string | no | Make (case-insensitive).e.g. Honda |
| model | query | string | no | Model (case-insensitive).e.g. CR-V |
| trim | query | string | no | Optional trim filter to narrow YMMT matches.e.g. EX |
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
Pass exactly one identifier mode: a vin, a config_key, or year + make + model (with an optional trim). A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Vehicle identity.
- object: "decode"
- config: VehicleConfig
- 400 — No usable identifier was provided. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 409 — More than one config matched a YMMT lookup — retry with a config_key from `matches` (or add &trim=). (error, message, matches)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/decode?config_key=2019_honda_cr_v_ex_l15be'GET /v1/configs
stableIdentityList candidate configs for a YMMT
Every enriched config that fits a year/make/model[/trim], always as a list. Turns the 409 disambiguation into a first-class lookup — pick a config_key and switch to exact access.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| year | query | integer | no | Model year.e.g. 2019 |
| make | query | string | no | Make (case-insensitive).e.g. Honda |
| model | query | string | no | Model (case-insensitive).e.g. CR-V |
| trim | query | string | no | Optional trim filter to narrow YMMT matches.e.g. EX |
// Responses
200 Candidate configs.
- object: "config_list"
- year: integer
- make: string
- model: string
- trim: string | null
- count: integer
- configs: ConfigCandidate[]
- 400 — Missing YMMT. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No config matches that YMMT. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/configs?year=2019&make=Honda&model=CR-V'GET /v1/catalog
stableIdentityThe enriched catalog
Every config we hold that is complete (50% fill or more), as the same rows `/v1/configs` returns. No VINs. `?limit=` caps the list (default 2000).
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer | no | Maximum rows (1–5000).e.g. 50 |
// Responses
200 The catalog.
- object: "config_catalog"
- count: integer
- configs: ConfigCandidate[]
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v1/catalog?limit=50' \
-H 'Authorization: Bearer otp_live_4f2a9c…'GET /v1/vehicle
stableSpecificationsFull vehicle payload (field-selectable)
Everything we hold on one vehicle: identity, layer-tagged specs (served + excluded), OEM tires, service intervals, priced parts with labor per service, and (VIN lookups only, `service_history:read` keys only) sanitized service history. Use `?include=` to return only the groups you need — omit it for every group your key may see. `/v1/labor` returns labor alone, without the parts and price joins.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| year | query | integer | no | Model year.e.g. 2019 |
| make | query | string | no | Make (case-insensitive).e.g. Honda |
| model | query | string | no | Model (case-insensitive).e.g. CR-V |
| trim | query | string | no | Optional trim filter to narrow YMMT matches.e.g. EX |
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| include | query | "specs" | "fluids" | "tires" | "intervals" | "maintenance" | "services" | "parts" | "history"[] | no | Comma-separated groups to return (omit for every group your key may see; empty for identity only). Aliases resolve: specs·fluids·attributes·chassis→specs, tires·wheels, intervals·maintenance·schedule, services·parts·labor, history. `history` needs the `service_history:read` scope: requesting it without that scope returns 403.e.g. fluids,tires |
Pass exactly one identifier mode: a vin, a config_key, or year + make + model (with an optional trim). A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 The vehicle payload.
- object: "vehicle"
- config: VehicleConfig
- specs: SpecFieldV1[]
- excluded: ExcludedField[]
- tires: TiresV1
- intervals: Interval[]
- services: ServiceEntryV1[]
- history: object | null
- meta: MetaV1
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — No usable identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks maintenance:read, or asked for include=history without service_history:read. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 409 — More than one config matched a YMMT lookup — retry with a config_key from `matches` (or add &trim=). (error, message, matches)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/vehicle?config_key=2019_honda_cr_v_ex_l15be'GET /v1/specs
stableSpecificationsThe layer-tagged spec sheet
Every populated spec field (fluids + attributes + chassis service points), each tagged with its data layer, confidence and source domain — plus the `excluded[]` list of B-licensed / X-flagged fields the gate withheld.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Spec sheet.
- object: "specs"
- config: VehicleConfig
- specs: SpecFieldV1[]
- excluded: ExcludedField[]
- meta: MetaV1
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/specs?config_key=2019_honda_cr_v_ex_l15be'GET /v1/fluids
stableFluids & CapacitiesFluids & capacities
The flagship depth slice: engine oil viscosity + capacity, coolant, transmission, brake, power-steering, and differential / transfer-case fluid types and capacities — layer-tagged.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Fluid specs.
- object: "fluids"
- config: VehicleConfig
- specs: SpecFieldV1[]
- meta: MetaV1
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/fluids?config_key=2019_honda_cr_v_ex_l15be'GET /v1/maintenance-schedule
stableMaintenanceOEM service intervals
OEM maintenance intervals by miles and months, each with confidence and a mechanic-verified flag.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Intervals.
- object: "maintenance_schedule"
- config: VehicleConfig
- intervals: Interval[]
- meta: MetaV1
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/maintenance-schedule?config_key=2019_honda_cr_v_ex_l15be'GET /v1/parts
stablePartsParts, prices & labor per service
OEM part numbers matched to the config and grouped per service — role, position, quantity and fitment confidence — each with a reference price and its as-of date, alongside the labor answer for that service.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| service | query | string | no | Optional service-slug filter: a snake_case slug from the vehicle's services[].service (e.g. brake_pad_replacement). On /v1/parts an unknown slug returns 404 unknown_service listing the valid slugs.e.g. brake_pad_replacement |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Parts + labor per service.
- object: "parts"
- config: VehicleConfig
- services: ServiceEntryV1[]
- meta: MetaV1
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier, or `service` names a slug this vehicle doesn't have (`unknown_service`; the valid slugs are in `available`). (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/parts?config_key=2019_honda_cr_v_ex_l15be'GET /v1/tires
stableTiresOEM tire & wheel package
Full OEM fitment: every tire option, with the top-level sizes and recommended pressures taken from the OEM-standard option, plus run-flat / staggered flags. (Battery CCA is in `/v1/specs`.)
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Tire package.
- object: "tires"
- config: VehicleConfig
- tires: TiresV1
- meta: MetaV1
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v1/tires?config_key=2019_honda_cr_v_ex_l15be'GET /v1/labor
stableLaborLabor per service
Labor for every service that applies to the vehicle, without the parts and price joins. `source` says how each answer was made: `empirical` (measured from completed jobs), `model_estimate` (our tier model), `service_default` (the service's default time, when nothing better resolves) or `unresolved`. `empirical` carries the measured hours, p25–p75 and sample size when the config has them. Requires the `labor:read` scope.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| year | query | integer | no | Model year.e.g. 2019 |
| make | query | string | no | Make (case-insensitive).e.g. Honda |
| model | query | string | no | Model (case-insensitive).e.g. CR-V |
| trim | query | string | no | Optional trim filter to narrow YMMT matches.e.g. EX |
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| service | query | string | no | Optional service-slug filter: a snake_case slug from the vehicle's services[].service (e.g. brake_pad_replacement). On /v1/parts an unknown slug returns 404 unknown_service listing the valid slugs.e.g. brake_pad_replacement |
Pass exactly one identifier mode: a vin, a config_key, or year + make + model (with an optional trim). A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Labor.
- object: "labor"
- config: VehicleConfig
- tier: string | null
- services: object[]
- meta: MetaV1
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — No usable identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier, or `service` names a slug this vehicle doesn't have (`unknown_service`; the valid slugs are in `available`). (error, message, available)
- 409 — More than one config matched a YMMT lookup — retry with a config_key from `matches` (or add &trim=). (error, message, matches)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v1/labor?config_key=2019_honda_cr_v_ex_l15be' \
-H 'Authorization: Bearer otp_live_4f2a9c…'GET /v1/service-history
stableService HistorySanitized service history (by VIN)
Per-VIN records: completed shop visits, owner-reported maintenance, and accepted document extractions. **Sanitized by contract** — no PII, costs, shop identity or free-text notes. `confidence` is a 0–1 number where one exists (document extractions); `confidence_label` carries the qualitative label (`verified`, `self_reported`…). Requires the `service_history:read` scope.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
// Responses
200 Service history.
- object: "service_history"
- vin: string
- records: object[]
- meta: object
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — Missing VIN. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — Unknown VIN. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v1/service-history?vin=5J6RW2H82KL000007' \
-H 'Authorization: Bearer otp_live_4f2a9c…'GET /v1/enrich
stableEnrichmentPoll enrichment status
Free status poll for a VIN or config_key.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Status.
- object: string
- status: "complete" | "enriching" | "failed" | "incomplete" | "queued"
- config_key: string | null
- last_enriched_at: string | null
- fill_rate: number | null
- 304 — Not modified: the `If-None-Match` ETag still matches. No body, and not counted against the monthly quota.
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — Unknown. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v1/enrich?config_key=2019_honda_cr_v_ex_l15be' \
-H 'Authorization: Bearer otp_live_4f2a9c…'POST /v1/enrich
stableEnrichmentEnrich a VIN on demand
POST a VIN we haven't seen (or whose data is stale) and the full enrichment pipeline runs. Fresh cache hits → 200 (free). A scheduled run → 202; poll `GET /v1/enrich?vin=…` until `complete`. Requires the `enrich:write` scope. Runs scheduled through `/v0/enrich` and `/v1/enrich` share one daily cap.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | body | string | yes | —e.g. 5J6RW2H82KL000007 |
// Responses
200 Cache hit (enriched in the last 180 days; free) or already in flight.
- object: string
- status: "complete" | "enriching" | "failed" | "incomplete" | "queued"
- config_key: string | null
- last_enriched_at: string | null
- fill_rate: number | null
202 Enrichment scheduled. Uses one enrich credit (or metered overage), refunded if the run can't be scheduled.
- object: "enrichment"
- status: string
- vin: string
- run_id: string | null
- credits_remaining: integer
- poll: object
- 400 — No VIN (`missing_param`), a VIN that isn't 17 characters (`invalid_vin`), or one that couldn't be decoded (`vin_decode_failed`). No credit is used. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 402 — No credit to spend (self-serve keys): out of enrich credits with metered overage off (`no_enrich_credits`, with a `topup_url`), or the monthly enrich spend cap reached (`spend_cap_reached`). (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 422 — Decoded but unsupported. No credit is used. (error, message, available)
- 429 — The per-minute rate limit (`rate_limited`), or the daily safety cap of 500 scheduled runs per key, counted across `/v0/enrich` and `/v1/enrich` (`daily_cap`; the reserved credit is refunded). Cache hits stay free. (error, message, available)
- 500 — The vehicle row couldn't be created. No credit is used. (error, message, available)
// Example
Writes need your own key with the enrich:write scope; the sandbox is read-only.
curl -X POST 'https://vinspeclookup.com/api/v1/enrich' \
-H 'Authorization: Bearer otp_live_4f2a9c…' \
-H 'Content-Type: application/json' \
-d '{"vin":"5J6RW2H82KL000007"}'Shape may change with notice on the changelog. Any version gets at least 90 days' notice before retirement. Policy →
GET /v0/vehicle
previewSpecificationsFull vehicle payload (v0, legacy)
Legacy. The original flagship — the whole vehicle payload in one response (history only for `service_history:read` keys). Unchanged and still supported; new integrations use `/v1/vehicle`, whose shapes differ (see Versions).
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| year | query | integer | no | Model year.e.g. 2019 |
| make | query | string | no | Make (case-insensitive).e.g. Honda |
| model | query | string | no | Model (case-insensitive).e.g. CR-V |
| trim | query | string | no | Optional trim filter to narrow YMMT matches.e.g. EX |
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
Pass exactly one identifier mode: a vin, a config_key, or year + make + model (with an optional trim). A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 The vehicle payload.
- object: "vehicle"
- config: VehicleConfig
- specs: SpecField[]
- excluded: ExcludedField[]
- tires: Tires
- intervals: Interval[]
- services: ServiceEntry[]
- history: object | null
- meta: Meta
- 400 — No usable identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 409 — More than one config matched a YMMT lookup — retry with a config_key from `matches` (or add &trim=). (error, message, matches)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v0/vehicle?config_key=2019_honda_cr_v_ex_l15be' \
-H 'Authorization: Bearer otp_live_4f2a9c…'GET /v0/maintenance
previewFluids & CapacitiesMaintenance specs (v0, legacy, strict gate)
Legacy. Layer-gated maintenance specs. Unlike `/v1/specs`, a field is only served when it has an evidence trail with a servable layer; everything else is listed in `excluded[]`.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Maintenance specs.
- object: "maintenance_specs"
- config: ConfigBrief
- fields: SpecField[]
- excluded: ExcludedField[]
- meta: Meta
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v0/maintenance?config_key=2019_honda_cr_v_ex_l15be'GET /v0/labor
previewLaborLabor times & estimates (v0, legacy)
Legacy; new integrations use `/v1/labor`. `estimates[]` covers every applicable service, each labelled with its method (`estimate_source`: `empirical` or `model_estimate`) and a confidence score. In v0, `model_estimate` also covers the service's default time when nothing better resolves; `/v1/labor` labels that `service_default`. `services[]` carries hours measured from completed repair jobs (sample size, p25–p75) once a config has them. Licensed book-time blends are never served.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| service | query | string | no | Optional service-slug filter: a snake_case slug from the vehicle's services[].service (e.g. brake_pad_replacement). On /v1/parts an unknown slug returns 404 unknown_service listing the valid slugs.e.g. brake_pad_replacement |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Labor.
- object: "empirical_labor"
- config_key: string | null
- services: object[]
- estimates: object[]
- tier: string | null
- note: string
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No enriched vehicle matches that identifier. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Runs against the free, keyless sandbox — no signup, rate-limited per IP.
curl 'https://vinspeclookup.com/api/sample/v0/labor?config_key=2019_honda_cr_v_ex_l15be'GET /v0/vehicle-image
previewMediaVehicle exterior render
The cached exterior render for a config. Cache-only: a config without a cached render returns 404 `no_image`, and no live fetch is made. Requires the `media:read` scope.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| year | query | integer | no | Model year.e.g. 2019 |
| make | query | string | no | Make (case-insensitive).e.g. Honda |
| model | query | string | no | Model (case-insensitive).e.g. CR-V |
| trim | query | string | no | Optional trim filter to narrow YMMT matches.e.g. EX |
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
Pass exactly one identifier mode: a vin, a config_key, or year + make + model (with an optional trim). A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Vehicle image.
- object: "vehicle_image"
- config: ConfigBrief
- image: object | null
- meta: Meta
- 400 — No usable identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — No vehicle or image. (error, message, available)
- 409 — More than one config matched a YMMT lookup — retry with a config_key from `matches` (or add &trim=). (error, message, matches)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v0/vehicle-image?config_key=2019_honda_cr_v_ex_l15be' \
-H 'Authorization: Bearer otp_live_4f2a9c…'GET /v0/service-history
previewService HistorySanitized service history (by VIN, v0, legacy)
Legacy; new integrations use `/v1/service-history`. Carfax-style per-VIN records: completed shop visits, owner-reported maintenance, and accepted document extractions. **Sanitized by contract** — no PII, costs, shop identity or free-text notes. Requires the `service_history:read` scope.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
// Responses
200 Service history.
- object: "service_history"
- vin: string
- records: object[]
- meta: object
- 400 — Missing VIN. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — Unknown VIN. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v0/service-history?vin=5J6RW2H82KL000007' \
-H 'Authorization: Bearer otp_live_4f2a9c…'GET /v0/enrich
previewEnrichmentPoll enrichment status (v0, legacy)
Free status poll for a VIN or config_key.
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | query | string | no | 17-char VIN of a vehicle we've seen. The only mode that adds the service-history section.e.g. 5J6RW2H82KL000007 |
| config_key | query | string | no | Canonical vehicle-config key — exact and unambiguous. 409 responses hand these back.e.g. 2019_honda_cr_v_ex_l15be |
Pass exactly one identifier mode: a vin, a config_key. A year/make/model lookup that matches several configs returns 409 with the candidate config_keys.
// Responses
200 Status.
- object: string
- status: "complete" | "enriching" | "failed" | "incomplete"
- config_key: string | null
- enrichment_status: string | null
- last_enriched_at: integer | null
- fill_rate: number | null
- 400 — Missing identifier. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 404 — Unknown. (error, message, available)
- 429 — Per-key per-minute rate limit exceeded. (error, message, available)
// Example
Authenticated call through the API gateway with your own key.
curl 'https://vinspeclookup.com/api/v0/enrich?config_key=2019_honda_cr_v_ex_l15be' \
-H 'Authorization: Bearer otp_live_4f2a9c…'POST /v0/enrich
previewEnrichmentEnrich a VIN on demand (v0, legacy)
POST a VIN we haven't seen (or whose data is stale) and the full enrichment pipeline runs. Fresh cache hits → 200 (free). A scheduled run → 202; poll `GET /v0/enrich?vin=…` until `complete`. Requires the `enrich:write` scope (granted separately).
// Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vin | body | string | yes | —e.g. 5J6RW2H82KL000007 |
// Responses
200 Cache hit (enriched in the last 180 days; free) or already in flight.
- object: string
- status: "complete" | "enriching" | "failed" | "incomplete"
- config_key: string | null
- enrichment_status: string | null
- last_enriched_at: integer | null
- fill_rate: number | null
202 Enrichment scheduled. Uses one enrich credit (or metered overage), refunded if the run can't be scheduled.
- object: "enrichment"
- status: string
- vin: string
- run_id: string | null
- credits_remaining: integer
- poll: object
- 400 — No VIN (`missing_param`), a VIN that isn't 17 characters (`invalid_vin`), or one that couldn't be decoded (`vin_decode_failed`). No credit is used. (error, message, available)
- 401 — Missing, invalid, or revoked key. (error, message, available)
- 402 — No credit to spend (self-serve keys): out of enrich credits with metered overage off (`no_enrich_credits`, with a `topup_url`), or the monthly enrich spend cap reached (`spend_cap_reached`). (error, message, available)
- 403 — The key lacks the required scope. (error, message, available)
- 422 — Decoded but unsupported. No credit is used. (error, message, available)
- 429 — The per-minute rate limit (`rate_limited`), or the daily safety cap of 500 scheduled runs per key, counted across `/v0/enrich` and `/v1/enrich` (`daily_cap`; the reserved credit is refunded). Cache hits stay free. (error, message, available)
- 500 — The vehicle row couldn't be created. No credit is used. (error, message, available)
// Example
Writes need your own key with the enrich:write scope; the sandbox is read-only.
curl -X POST 'https://vinspeclookup.com/api/v0/enrich' \
-H 'Authorization: Bearer otp_live_4f2a9c…' \
-H 'Content-Type: application/json' \
-d '{"vin":"5J6RW2H82KL000007"}'Authentication
Send your API key on every authenticated request, either as a Bearer token in the Authorization header or in an x-api-key header. Keys look like otp_live_…, are shown once when issued and stored hashed; each key carries scopes (for example maintenance:read, labor:read, media:read, service_history:read, enrich:write) and a per-minute rate limit. A missing or invalid key returns 401; a key without the endpoint's scope returns 403; over the limit returns 429.
curl 'https://vinspeclookup.com/api/v1/fluids?config_key=2019_honda_cr_v_ex_l15be' \
-H 'Authorization: Bearer otp_live_4f2a9c…'
# or
curl 'https://vinspeclookup.com/api/v1/fluids?config_key=2019_honda_cr_v_ex_l15be' \
-H 'x-api-key: otp_live_4f2a9c…'The sandbox at https://vinspeclookup.com/api/sample needs no key at all: it mirrors every documented read endpoint, is rate-limited per IP address, and blocks writes. Keys for the authenticated API are issued through the request-access form; plans and limits are on the pricing page.
Versioning
The version is the first path segment. /v1 endpoints are stable: we will not remove fields or change their meaning within v1; we may add fields, and clients must ignore fields they do not recognise. /v0 endpoints are preview: their shape may change with notice on the changelog, and we do not recommend depending on them for anything you cannot adjust quickly. When we retire a version, we announce it at least 90 days ahead and keep it running for that period.
stable and preview pills on each endpoint above follow this rule. The full policy is in the Terms of Service.
How to read provenance
Each field carries a layer (the kind of source, below) and, where one is recorded, a confidence between 0 and 1 and the source_domain it was taken from. A value stored without an evidence trail is still served, tagged C, with source_domain set to null: treat it as unverified. Part prices also carry as_of, the date the price was last confirmed, so you can tell a fresh price from an old one.
| Layer | Meaning | Served |
|---|---|---|
| A | OEM or official: owner's manuals, manufacturer data | Yes |
| B | Licensed third-party database (public NHTSA data is the exception and is served) | No |
| C | Web-derived: our own research. Stored values without an evidence trail are also served as C | Yes |
| D | Empirical: measured from completed repair jobs | Yes |
| E | Human-verified: confirmed by a mechanic or a director | Yes |
| X | Flagged: an anomaly, or confidence below 0.4 | No |
The gate is visible, never silent. Every response restates the rule in meta.gate and meta.layer_formula, and the vehicle, spec-sheet and maintenance responses list each value held back as B or X in an excluded array, with the layer that blocked it.
Read confidence as a ranking signal, not a probability. It is assigned when the vehicle is enriched; below 0.4 a value becomes X and is not served. Where a decision matters (a fluid specification, a part fitment), check it against the manufacturer's service information.