Car Image API

Clienți · Instrumente pentru dealeri, importuri și VIN

Cum transformați un VIN sau o listă de stoc într-o fotografie pentru fiecare vehicul din software-ul pentru dealeri

Cum ajung instrumentele pentru dealeri și importuri de la un VIN sau de la o linie din fișa de stoc la o imagine de studio pe fiecare înregistrare: decodare VIN gratuită, resolve, id-uri stabile și URL-uri semnate.

Problema: înregistrarea are un VIN cu luni înainte de a avea o fotografie

O înregistrare de stoc într-un CRM, un ERP sau un sistem de gestiune pentru dealeri (DMS) începe ca un VIN, un număr de stoc și un preț. Fotografia vine când vine fotograful din parcare, iar pentru unele mașini nu vine niciodată: o unitate în tranzit, o mașină preluată în schimb aflată încă în recondiționare, un import al cărui nume de model nu corespunde cu nimic din fluxul de imagini al DMS-ului, o mașină din anii 1990 pentru care nimeni nu a licențiat o fotografie de presă. Fiecare ecran care afișează acea înregistrare – lista vânzătorului, evaluarea cumpărătorului, oferta pentru client – arată în schimb un substituent gri.

Instrumentele pentru dealeri și de import care folosesc API-ul completează acel substituent din ce conține deja înregistrarea. Dacă are un VIN, imaginea se află la o singură decodare gratuită distanță. Dacă are doar un rând într-o listă de stoc, rezolvarea din text liber ajunge acolo. În ambele cazuri, înregistrarea ajunge să conțină un id de vehicul stabil, iar fiecare ecran randează aceeași mașină în același mod.

Cum arată o integrare pentru dealeri

  • Decodare la preluare. VIN-ul este decodat o singură dată, la crearea înregistrării, iar id-ul vehiculului din catalog este stocat lângă el. Nimic din aval nu mai scrie marca sau modelul.
  • O vedere pentru listă, una pentru detalii. Un side drept, într-un cadru lat, pentru listele de stoc; front-3-4 pentru pagina de detalii și oferta de preț.
  • Ani îndepărtați. Stocul de import și cel rulat ajung până în anii 1990 și se randează la fel ca noutățile: catalogul acoperă perioada din 1990 până la anul-model curent, inclusiv modelele pentru piața internă japoneză.
  • URL-uri semnate în aplicație. CRM-ul rulează în browser, așa că încarcă URL-uri semnate fără cheie, generate de server, până la cincizeci per apel, reînnoite pentru înregistrările care rămân active mai mult de o săptămână.

Pasul 1: decodați VIN-ul, gratuit

GET /api/v1/vin/{vin} nu costă nimic și necesită doar o cheie API. Returnează anul, marca, modelul, versiunea de echipare, tipul de caroserie, motorul decodate și orice alt atribut cunoscut de datele vPIC ale NHTSA, iar, atunci când catalogul conține vehiculul, un obiect vehicle cu id-ul său stabil și un image_path gata pregătit. Funcționează și VIN-urile parțiale: cel puțin cinci caractere, * pentru fiecare poziție necunoscută, plus un indiciu opțional year.

Decodare
curl -s -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  "https://carimage.dev/api/v1/vin/1HGCM82633A004352"
200 OK (prescurtat)
{
  "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…"
}

Pasul 1b: când aveți doar un rând dintr-o listă de stoc

Stocul de import vine adesea sub formă de foaie de calcul: un an, o marcă, un nume de model scris în ce variantă a folosit casa de licitații, un cod de grad sau de echipare. POST /api/v1/images/resolve este gratuit și determinist: extrage din expresie cuvintele pentru an, culoare și vedere, caută în catalog cu ce rămâne și returnează parametri exacți, împreună cu un nivel de încredere pe baza căruia puteți acționa.

Identificarea unui rând din fișa de stoc
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"}'
200 OK (prescurtat)
{
  "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…"
}

Vehiculul este corect (Toyota Voxy 2019), dar nivelul de încredere este low, deoarece „ZS” este o versiune pe care catalogul nu o cunoaște, iar potrivirea a trebuit să o ocolească. Într-un import în lot, considerați high drept rezolvat și trimiteți medium și low spre verificare umană, împreună cu lista candidates. Când foaia are deja anul și marca în coloane separate, trimiteți-le în câmpurile year și make și lăsați doar modelul în query; potrivirea devine mult mai precisă. O frază fără cuvinte despre vehicule returnează 400, iar o marcă fără model corespunzător returnează 404, cu anii disponibili pentru marca respectivă, ca să puteți cere modelul.

Pasul 2: păstrați id-ul vehiculului în înregistrare

Indiferent de calea prin care ați ajuns aici, stocați vehicle.id (sau params.vehicle_id) în înregistrarea de stoc, ca o coloană simplă de tip string. Este determinist și permanent: același vehicul are același id la fiecare implementare și după fiecare lansare a catalogului, deci poate fi folosit în siguranță ca cheie străină. De atunci încolo, fiecare cerere de imagine este vehicle=veh_…, care nu poate fi scris greșit, iar o marcă redenumită de un producător sau reclasificată de o sursă nu va strica niciodată un URL stocat.

Pasul 3: o vedere pentru listă, una pentru pagina de detalii

Listele de stoc sunt late și scunde, așa că vederea strict laterală într-un cadru 2:1 este alegerea obișnuită: fiecare unitate este orientată la fel și stă pe aceeași linie de bază. trim=1&padding=6 decupează pe mașină înainte de încadrare, astfel încât un Hilux și un Yaris umplu rândul la fel; fit=contain păstrează pânza exact la 640×320, cu margini transparente. Pagina de detalii folosește front-3-4 la 1024, iar cele două partajează un cache: o vopsea pe care nu ați specificat-o este argintie pe ambele.

Imaginea de listă pentru o înregistrare
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.webp

Pasul 4: afișați-o în CRM prin URL-uri semnate

CRM-ul rulează într-un browser, iar un browser nu trebuie să dețină niciodată cheia API. Când un ecran listează o pagină de stoc, serverul generează câte un URL semnat pentru fiecare înregistrare cu POST /api/v1/image-urls (până la cincizeci per apel; imaginea fiecărui URL se contorizează ca imagine de vehicul a lunii), iar pagina le încarcă la fel ca pe orice imagine. Pentru o înregistrare care rămâne în stoc luni de zile contează două setări:

  • ttl_seconds: 604800 cu renew: true: URL-ul continuă să funcționeze după TTL-ul de șapte zile, iar o reînnoire contorizează imaginea o dată în luna în care are loc și nimic în plus dacă a fost deja contorizată în acea lună. Lunile în care nimeni nu se uită la mașină nu contorizează nimic.
  • Un Idempotency-Key pentru fiecare pagină a sincronizării: o cerere reîncercată redă primul răspuns și nu generează nimic de două ori.

Restricționați cheia de generare la originea CRM-ului din panoul de control, iar un URL care ajunge pe alt site va răspunde cu 403. Revocarea cheii invalidează toate URL-urile generate cu ea. Dacă imaginile de vehicule ale planului pentru luna respectivă s-au epuizat, o reînnoire răspunde cu 402, iar același URL funcționează din nou când limita se resetează sau când treceți la un plan superior. Întregul ciclu de viață este descris în documentația URL-urilor semnate.

Recepția și lista de stoc, cu SDK-ul TypeScript
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 și MCP

npx @meterapp/car-image
# 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, … }) și client.createImageUrls(…), ca mai sus.
  • MCP: decode_vin, resolve_vehicle, get_car_image și create_car_image_urls fac parte din setul de instrumente de bază, astfel încât un asistent care are sistemul de stoc în context poate răspunde la „fotografie pentru stocul 4471” pe baza VIN-ului din înregistrare. Configurarea este descrisă pe pagina MCP; câmpurile și erorile decodorului sunt în documentația VIN.

Întrebări frecvente

Cât costă o fotografie pentru fiecare înregistrare din stoc?
Decodarea VIN este gratuită. Fiecare vehicul, în fiecare vopsea și vedere, reprezintă o imagine de vehicul, contorizată o dată pe lună, indiferent de câte ori este afișată și la orice dimensiune; reverificarea cu If-None-Match este gratuită. Un URL semnat contorizează imaginea la emitere și, cu renew: true, încă o dată în fiecare lună ulterioară în care este deschis. Un grup de dealeri cu câteva mii de unități în stoc afișează câteva mii de imagini de vehicul pe lună, așa că dimensionați planul în funcție de stocul expus.
VIN-ul este decodat, dar vehicle este null. Ce urmează?
Decodorul a recunoscut marca, modelul și anul, dar catalogul nu are nicio intrare pentru acea combinație: o remorcă, unele șasiuri comerciale, o denumire de model pe care sursele nu au înregistrat-o încă. Afișați câmpurile decodate, căutați în catalog cu GET /api/v1/vehicles?q= în caz că ortografia diferă și solicitați vehiculul pe panoul de cereri; POST /api/v1/requests votează o cerere deschisă existentă în loc să o dubleze.
Decodarea VIN acoperă importurile și vehiculele care nu s-au vândut niciodată în SUA?
Decodorul folosește datele vPIC ale NHTSA, așa că un VIN de la un producător care raportează la NHTSA se decodează complet. Un vehicul care nu a fost niciodată certificat pentru SUA se decodează adesea doar la producător și an, fără model, iar unele nu se decodează deloc. Pentru acest stoc, identificați vehiculul pe baza certificatului de înmatriculare: catalogul în sine este global, din 1990, și include modele pentru piața internă japoneză, precum Toyota Voxy.
Randarea arată versiunea de echipare din înregistrare?
Nu. Catalogul se bazează pe marcă, model și an, așa că un coupe EX-V6 și un sedan LX sunt randate ca același Accord din 2003. Păstrați trim și body_class din decodare ca text lângă imagine și nu prezentați niciodată randarea ca fiind exemplarul respectiv.
Poate site-ul dealerului să folosească aceleași URL-uri ca CRM-ul?
Generați-le dintr-o cheie ale cărei origini permise includ site-ul, iar un URL pe care un browser îl încarcă de pe orice alt site răspunde cu 403 origin_not_allowed. Încărcările fără Referer, cum ar fi cele dintr-un client de e-mail, trec. CRM-ul și site-ul pot partaja o cheie și un set de URL-uri sau pot folosi câte o cheie fiecare, astfel încât oricare să poată fi revocată separat.