Skip to content
Live catalog

Vehicle history (VHR)

Statuses, errors and webhooks

How it works

01Authentication

Send x-api-key on every request. Source ids and formats come from your own catalog and VIN check; access and prices are applied by the API.

02Check, then choose one source

POST /checks returns price, available_formats and a preview for every source. POST /reports takes one source_id, one language and one or more formats, for one price per report. If availability_confirmed is false, read availability_notice first.

03Files, not an inline history

JSON, HTML and PDF come as links on our CDN; some sources keep photos or a ready HTML page at their original address. Treat every report link as an access key.

04Long requests

HTTP waits up to 10 seconds. HTTP 202 means the work goes on: poll status_url every 1 to 2 seconds until the status is final. Never repeat a pending purchase.

05Failure and recovery

A source error is not the same as no data. A report is charged only when every selected file is ready. If the files fail, POST /reports/{id}/retry reuses the saved data, with no second charge.

06Webhooks

For real VINs add a public HTTPS webhook_url and a webhook_secret (16 to 256 characters). The API answers 202 and posts the result when it is ready, signed in X-VHR-Signature with X-VHR-Timestamp.

Statuses

An answer is final when its status is final; until then follow status_url.

Check

running
Still working. Poll status_url.
completedFinal
Done. Every source answered, or the files are ready.
partialFinal
Done, but some sources returned an error.
failedFinal
Stopped with an error. Nothing is charged.

Report

running
Still working. Poll status_url.
preparing
The source data is saved; the files are being made.
rendering
The PDF is being rendered.
completedFinal
Done. Every source answered, or the files are ready.
not_foundFinal
The source has no record for this VIN. Nothing is charged.
failedFinal
Stopped with an error. Nothing is charged.

Each source in a check

available
Records found: the source can be ordered (no status field).
pending
This source is still answering.
not_found
The source has no record for this VIN. Nothing is charged.
error
This source could not answer now. It is not the same as no data.
not_checked
Not checked by this request. It does not mean there is no data.

Errors

Errors come back as JSON with error_code and message. Nothing is charged for an error.

401Missing or invalid x-api-key.
402Not enough report balance for this report.
403This report type is not enabled for your key.
409The same report for this VIN is already being prepared.
422Invalid body, for example a VIN, a format or a language, or a changed price.
429Too many requests. Wait a moment and try again.
503Reports are paused for a moment.

Webhooks

Add webhook_url and webhook_secret to a check or a report for a real VIN: the API answers 202 at once and posts the result when it is ready. Check the signature before you trust it.

  • X-VHR-Signature is sha256= followed by the HMAC-SHA256 of the X-VHR-Timestamp value, a dot and the raw body.
  • Refuse old timestamps (for example older than 5 minutes) and repeated X-VHR-Event-Id values.
  • Sample VINs answer at once and never call a webhook.
import crypto from 'node:crypto'
 
// raw: the request body exactly as received (a Buffer or string)
export const verify = (raw, headers, secret) => {
const stamp = headers['x-vhr-timestamp']
const sent = String(headers['x-vhr-signature'] || '').replace('sha256=', '')
const age = Math.abs(Date.now() / 1000 - Number(stamp))
if (!stamp || !Number.isFinite(age) || age > 300) return false
const mac = crypto.createHmac('sha256', secret).update(`${stamp}.${raw}`).digest('hex')
return sent.length === mac.length && crypto.timingSafeEqual(Buffer.from(sent), Buffer.from(mac))
}
© 2025. AuctionsAPI operates independently and is not affiliated with Copart, IAAI or Encar.