Het probleem: het record heeft al maanden een VIN voordat er een foto is
Een voorraadrecord in een CRM, een ERP of een dealermanagementsysteem begint als een VIN, een voorraadnummer en een prijs. De foto komt pas als de fotograaf langskomt, en voor sommige voorraad komt die er nooit: een auto die nog onderweg is, een inruilauto die nog wordt opgeknapt, een import waarvan de modelnaam met niets in de beeldfeed van het DMS overeenkomt, een auto uit de jaren 90 waarvan niemand ooit een persfoto in licentie heeft genomen. Elk scherm dat dat record toont, de lijst van de verkoper, de taxatie van de inkoper, de offerte voor de klant, toont in plaats daarvan een grijze placeholder.
De dealer- en importtools op de API vullen die placeholder met wat het record al bevat. Heeft het een VIN, dan is de afbeelding slechts één gratis decodering verwijderd. Staat er alleen een regel op een voorraadlijst, dan komt resolve met vrije tekst er ook. Hoe dan ook bevat het record uiteindelijk een stabiel voertuig-id, en toont elk scherm dezelfde auto op dezelfde manier.
Hoe een integratie voor dealers eruitziet
- Decoderen bij intake. Het VIN wordt één keer gedecodeerd, bij het aanmaken van het record, en het voertuig-id uit de catalogus wordt ernaast opgeslagen. Niets verderop in de keten spelt een merk of model uit.
- Eén aanzicht voor de lijst, één voor de detailpagina. Een recht
side-aanzicht in een breed kader voor voorraadlijsten;front-3-4voor de detailpagina en de offerte. - Ver terug in de tijd. Import- en occasionvoorraad gaat terug tot de jaren negentig en wordt net zo gerenderd als de nieuwe binnenkomers: de catalogus loopt van 1990 tot het huidige modeljaar, inclusief modellen voor de Japanse thuismarkt.
- Ondertekende URL's in de app. Het CRM draait in een browser, dus laadt het ondertekende URL's zonder sleutel die de server aanmaakt, tot vijftig per aanroep, en vernieuwt die voor records die langer dan een week bestaan.
Stap 1: de VIN decoderen, gratis
GET /api/v1/vin/{vin} kost niets en vereist alleen een API-key. Het geeft het gedecodeerde jaar, merk, model, uitvoering, carrosserietype, motor en elk ander attribuut terug dat de vPIC-gegevens van NHTSA kennen, en, als de catalogus het voertuig bevat, een vehicle-object met het stabiele id en een kant-en-klaar image_path. Gedeeltelijke VIN's werken ook: minimaal vijf tekens, * voor elke onbekende positie, plus een optionele year-hint.
curl -s -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
"https://carimage.dev/api/v1/vin/1HGCM82633A004352"{
"data": {
"vin": "1HGCM82633A004352",
"valid": true,
"year": 2003,
"make": "Honda",
"model": "Accord",
"trim": "EX-V6",
"body_class": "Coupe",
"vehicle": {
"id": "veh_3qfyk22gfhsx3",
"make": "Honda",
"model": "Accord",
"year": 2003,
"image_path": "/api/v1/images/car?vehicle=veh_3qfyk22gfhsx3"
}
},
"request_id": "req_01j9x…"
}trim en body_class als tekst bij het record en toon ze naast de afbeelding, in plaats van te beweren dat de afbeelding ze weergeeft. Een VIN met een fout in het controlecijfer wordt nog steeds gedecodeerd, met valid: false en de fout vermeld, zodat een verkeerd getypte voorraadlijst geen doodlopende weg is.Stap 1b: als u alleen een regel op een voorraadlijst hebt
Importvoorraad komt vaak binnen als spreadsheet: een bouwjaar, een merk, een modelnaam in de spelling die het veilinghuis toevallig gebruikte, een grade- of uitvoeringscode. POST /api/v1/images/resolve is gratis en deterministisch: het haalt de woorden voor jaar, kleur en aanzicht uit de zin, doorzoekt de catalogus met wat overblijft en geeft exacte parameters terug met een betrouwbaarheidsscore waarop u kunt handelen.
curl -s -X POST https://carimage.dev/api/v1/images/resolve \
-H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "2019 toyota voxy zs side"}'{
"data": {
"params": {
"vehicle_id": "veh_9w0nvw7jphp6r",
"make": "toyota",
"model": "voxy",
"year": 2019,
"view": "side",
"color": "silver"
},
"display": {
"make_name": "TOYOTA",
"model_name": "VOXY"
},
"confidence": "low",
"image_path": "/api/v1/images/car?make=toyota&model=voxy&year=2019&view=side&color=silver"
},
"request_id": "req_01j9x…"
}Het voertuig klopt (de Toyota Voxy uit 2019), maar de betrouwbaarheid is low, omdat "ZS" een uitvoering is die de catalogus niet kent en eromheen moest worden gematcht. Behandel bij een batchimport high als afgerond, en leg medium en low met de lijst candidates voor aan een mens. Staan het bouwjaar en merk al in eigen kolommen in de lijst, stuur ze dan mee als de velden year en make en laat alleen het model in query staan; de match wordt dan veel zuiverder. Een zin zonder voertuigwoorden geeft een 400, en een merk zonder passend model een 404 met de bouwjaren van dat merk, zodat u naar het model kunt vragen.
Stap 2: de voertuig-id bij het record bewaren
Welke route u ook hebt genomen, sla vehicle.id (of params.vehicle_id) op in het voorraadrecord als een gewone tekstkolom. Deze is deterministisch en permanent: hetzelfde voertuig heeft dezelfde id bij elke deploy en na elke catalogusrelease, dus hij is veilig als foreign key. Vanaf dat moment is elk afbeeldingsverzoek vehicle=veh_…, wat niet verkeerd gespeld kan worden, en een merk dat door een fabrikant is hernoemd of door een bron anders is ingedeeld, maakt nooit een opgeslagen URL kapot.
Stap 3: één aanzicht voor de lijst, één voor de detailpagina
Voorraadlijsten zijn breed en laag, dus het rechte zijaanzicht in een 2:1-kader is de gebruikelijke keuze: elk voertuig kijkt dezelfde kant op en staat op dezelfde basislijn. trim=1&padding=6 snijdt bij tot de auto voordat er wordt ingepast, zodat een Hilux en een Yaris de rij op dezelfde manier vullen; fit=contain houdt het canvas precies 640×320 met transparante marges. De detailpagina gebruikt front-3-4 op 1024, en de twee delen een cache: een lakkleur die u niet opgeeft, is op beide zilver.
curl --fail-with-body -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
"https://carimage.dev/api/v1/images/car?vehicle=veh_3qfyk22gfhsx3&view=side&w=640&h=320&fit=contain&trim=1&padding=6&format=webp" \
-o stock-4471.webpStap 4: weergeven in het CRM via ondertekende URL's
Het CRM draait in een browser, en een browser mag nooit de API-sleutel bevatten. Als een scherm een pagina met voorraad toont, maakt de server per record één ondertekende URL aan met POST /api/v1/image-urls (tot vijftig per aanroep; de afbeelding van elke URL telt als voertuigafbeelding van de maand) en laadt de pagina ze als elke andere afbeelding. Twee instellingen zijn belangrijk voor een record dat maandenlang op voorraad blijft:
ttl_seconds: 604800metrenew: true: de URL blijft werken na de TTL van zeven dagen, en een verlenging telt de afbeelding één keer in de maand waarin die plaatsvindt, en niets extra als de afbeelding die maand al was geteld. Maanden waarin niemand de auto bekijkt, tellen niets.- Een
Idempotency-Keyper pagina van de synchronisatie: een herhaald verzoek geeft opnieuw het eerste antwoord terug en maakt niets dubbel aan.
Beperk de sleutel waarmee u URL’s aanmaakt in het dashboard tot de origin van het CRM, dan geeft een URL die op een andere site terechtkomt 403 terug. Als u de sleutel intrekt, worden alle URL’s ongeldig die ermee zijn aangemaakt. Als de voertuigafbeeldingen van het abonnement voor de maand op zijn, geeft een verlenging 402 terug en werkt dezelfde URL weer zodra het tegoed wordt gereset of het abonnement wordt verhoogd. De volledige levenscyclus staat in de documentatie over ondertekende URL’s.
import { CarImageClient } from "@meterapp/car-image-sdk";
const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });
// On intake: VIN in, vehicle id on the record. Free.
const { data: decoded } = await client.decodeVin(stock.vin);
if (decoded.vehicle) {
stock.vehicleId = decoded.vehicle.id; // veh_…, permanent; the record never spells a car again
stock.trim = decoded.trim; // shown next to the image, never claimed by it
}
// When the CRM draws the stock list: one signed URL per record, up to fifty per call.
// The browser loads them; the key never leaves the server.
const { data: urls } = await client.createImageUrls(
page.map((row) => ({
vehicle: row.vehicleId, view: "side",
width: 640, height: 320, fit: "contain", trim: true, padding: 6, format: "auto",
})),
{ ttlSeconds: 604_800, renew: true, renewDays: 365, idempotencyKey: `stock-list:${syncRunId}:${pageIndex}` }
);CLI, SDK en MCP
# decode for free; the output names the vehicle id and a ready-to-run image command
npx @meterapp/car-image vin 1HGCM82633A004352
npx @meterapp/car-image vin 1HGCM82633A004352 --json | jq -r .data.vehicle.id
# a partial VIN from a faded door sticker: at least five characters, * for each unknown position
npx @meterapp/car-image vin "1HGCM826*3A" --year 2003
# the list image for one record
npx @meterapp/car-image get --vehicle veh_3qfyk22gfhsx3 --view side --width 640 --height 320 --fit contain --trim --padding 6 --format webp --out stock-4471.webp- SDK:
client.decodeVin(vin, { year? }),client.resolve(query),client.getImage({ vehicle, … })enclient.createImageUrls(…), zoals hierboven. - MCP:
decode_vin,resolve_vehicle,get_car_imageencreate_car_image_urlszitten in de kerntoolset, zodat een assistent met het voorraadsysteem in zijn context "foto voor voorraadnummer 4471" kan beantwoorden op basis van de VIN in het record. De installatie staat op de MCP-pagina; de velden en foutmeldingen van de decoder staan in de VIN-documentatie.
Veelgestelde vragen
- Wat kost een foto bij elk voertuig in de voorraad?
- Het decoderen van een VIN is gratis. Elk voertuig in elke lak en weergave is één voertuigafbeelding, die één keer per maand wordt geteld, ongeacht hoe vaak en in welk formaat die wordt getoond; opnieuw controleren met If-None-Match is gratis. Een ondertekende URL telt zijn afbeelding bij het aanmaken en, met renew: true, nog één keer in elke volgende maand waarin hij wordt geopend. Een dealergroep met een paar duizend auto's op voorraad toont een paar duizend voertuigafbeeldingen per maand, dus stem het abonnement af op de getoonde voorraad.
- De VIN wordt gedecodeerd, maar vehicle is null. Wat nu?
- De decoder kende merk, model en jaar, maar de catalogus heeft geen vermelding voor die combinatie: een aanhanger, sommige bedrijfswagenchassis, een typenaam die de bronnen nog niet hebben opgenomen. Toon de gedecodeerde velden, doorzoek de catalogus met GET /api/v1/vehicles?q= voor het geval de spelling afwijkt, en vraag het voertuig aan op het aanvraagbord; POST /api/v1/requests stemt op een openstaande aanvraag in plaats van die te dupliceren.
- Dekt VIN-decodering ook importauto's en voertuigen die nooit in de VS zijn verkocht?
- De decoder gebruikt de vPIC-gegevens van NHTSA, dus een VIN van een fabrikant die bij NHTSA registreert, wordt volledig gedecodeerd. Een voertuig dat nooit voor de VS is gecertificeerd, levert vaak alleen een fabrikant en bouwjaar zonder model op, en sommige worden helemaal niet gedecodeerd. Herleid zulke voorraad in plaats daarvan vanuit het kentekenbewijs: de catalogus zelf is wereldwijd, vanaf 1990, en Japanse binnenlandse modellen zoals de Toyota Voxy staan erin.
- Toont de render de uitvoering uit het record?
- Nee. De catalogus is gebaseerd op merk, model en bouwjaar, dus een EX-V6 coupé en een LX sedan worden als dezelfde Accord uit 2003 gerenderd. Bewaar trim en body_class uit de decodering als tekst naast de afbeelding en beschrijf de render nooit als het specifieke exemplaar.
- Kan de dealerwebsite dezelfde URL's gebruiken als het CRM?
- Maak ze aan met een sleutel waarvan de toegestane origins de site bevatten; een URL die een browser vanaf een andere site laadt, geeft dan 403 origin_not_allowed terug. Verzoeken zonder Referer, zoals vanuit een e-mailclient, worden doorgelaten. Het CRM en de website kunnen één sleutel en één set URL's delen, of elk een eigen sleutel gebruiken, zodat elk afzonderlijk kan worden ingetrokken.