Car Image API

Bruksområder · Auksjoner

Bilbilder for auksjonsannonser

Legg ut auksjonsobjekter før bildene kommer, hvert med et studiobilde av sin årsmodell merket som katalogrendering, via signerte URL-er som utløper med auksjonen.

En byggeguide skrevet ut fra API-ets dokumenterte virkemåte; den nevner ingen kunder. Publisert .

Problemet: salget er i gang før bildene er klare

En auksjonskatalog publiseres så snart innleveringene er på plass: et VIN, et objektnummer og en salgsdato for hver bil. Bildene kommer når bilen når fram til tomten og fotografen når fram til bilen, noe som for en del av auksjonen skjer etter at budgivningen har åpnet. Inntil da er hvert av disse objektene en grå boks ved siden av en tekstlinje.

En katalogrendring fyller feltet med riktig årsmodell. En auksjon er også nettopp der en rendring aldri må utgi seg for å være bilen: budgiverne priser tilstanden, og en rendring viser ingen tilstand, fordi den ikke viser noe bestemt fysisk kjøretøy. Alt nedenfor følger av å holde fast ved begge deler samtidig.

Slik ser integrasjonen ut

  • En rendring per objekt ut fra VIN-en, vist bare til objektets egne bilder kommer.
  • En katalogvelger for objektene der VIN-en ikke lar seg dekode.
  • En merknad på bildet: «Katalogbilde, ikke dette objektet».
  • Én URL per auksjonsobjekt, opprettet én gang under en Idempotency-Key, og gyldig så lenge auksjonen varer.

Trinn 1: fra objektets VIN til en kjøretøy-ID

GET /api/v1/vin/{vin} er gratis. Når katalogen har kjøretøyet, inneholder svaret data.vehicle.id, den stabile ID-en som skal lagres på objektet; dekodet utstyrsversjon, karosseri og motor blir værende i objektets tekst. Katalogen spenner fra 1990 til 2027, så de eldre bilene på en auksjon rendres like godt som de nyeste. Forsikringsveiledningen går gjennom en dekoding felt for felt, og VIN-dokumentasjonen dekker delvise VIN-er og feil.

Dekod ved mottak
# the lot's VIN to the vehicle id the lot stores (free); nothing printed means no catalog match
npx @meterapp/car-image vin "$LOT_VIN" --json | jq -r '.data.vehicle.id // empty'

Trinn 2: ingen VIN som kan dekodes? Velg kjøretøyet fra katalogen

Noen objekter kommer uten et VIN som lar seg dekode: et kjøretøy bygd for et annet marked, et VIN som kilden har skrevet feil, et innleveringsskjema med årstall, merke og modell og ingenting annet. Gi innleveringsskjemaet tre nedtrekksmenyer som hentes fra GET /api/v1/vehicles, som er gratis og offentlig: ?year= viser merkene som har en modell det året, og ?year=&makeId= viser modellene til det merket, hver med kjøretøy-id-en for den årsmodellen.

År, så merke, så modell
# every make with a 2006 model year (free, public)
curl -s "https://carimage.dev/api/v1/vehicles?year=2006"
# {"data":{"year":2006,"makes":[…,{"id":476,"name":"DODGE","slug":"dodge"},…]},…}

# that make's 2006 models, each with the id of its 2006 model year
curl -s "https://carimage.dev/api/v1/vehicles?year=2006&makeId=476"
200 OK (forkortet)
{
  "data": {
    "year": 2006,
    "make_id": 476,
    "models": [
      {
        "name": "Caliber",
        "slug": "caliber",
        "vehicle_type": "Passenger Car",
        "id": "veh_294vq81yq0d3y"
      },
      {
        "name": "Charger",
        "slug": "charger",
        "vehicle_type": "Passenger Car",
        "id": "veh_96j8z47jqfd4r"
      },
      "…"
    ]
  }
}

Den samme katalogen er den åpne @meterapp/vehicle-db-pakken, så nedtrekksmenyene kan også kjøre offline mot den identiske listen. Uansett ender auksjonsobjektet opp med samme type ID som en dekodet VIN, og ingenting senere i flyten skriver bilnavnet som fritekst.

Når en hel innleveringsliste kommer på én gang, leser POST /api/v1/vehicles/check opptil 2 000 oppføringer per kall, hver slik listen skriver den og med objektnummeret som ref, og svarer på hver enkelt: et treff med id-en som skal lagres, forslag, ingen treff eller en ugyldig rad. Ingenting genereres og ingenting belastes; vehicles-dokumentasjonen har detaljene.

Trinn 3: merk renderingen som en rendering

Sett merkingen på selve bildet, der budgiverens blikk havner, og i alt-teksten, ikke bare i beskrivelsen under. Tilstand, kilometerstand, skader, utstyr og lakken på bilen hører hjemme i objektteksten og, når de finnes, på fotografiene. Når fotografiene kommer, forsvinner det genererte bildet.

Objektets bilde til fotografiene kommer
<figure class="lot-image">
  <img src="https://carimage.dev/api/v1/delivery/eyJhbGciOi…" width="800" height="450"
       alt="Catalog render of a 2006 Dodge Charger, not a photo of lot 117">
  <span class="lot-image__badge">Catalog render, not this lot</span>
</figure>
<p>Photos of this lot are on their way. Condition, mileage and damage are in the report.</p>

Trinn 4: én URL per objekt, generert én gang

Opprett objektets URL ved registrering med POST /api/v1/image-urls og en Idempotency-Key laget av auksjonen og objektet, med bokstaver, sifre, ., _, : og -. URL-en teller bildet sitt som et av månedens kjøretøybilder når den opprettes, så uten en nøkkel ville et nytt registreringsforsøk opprette en ekstra URL. Med nøkkel:

  • Samme nøkkel med samme innhold i forespørselen innen 24 timer gir det første svaret på nytt, inkludert samme URL, med Idempotent-Replayed: true og uten ny belastning.
  • Samme nøkkel med en annen body gir 422, og et nytt forsøk som går forbi den første forespørselen, gir 409 med Retry-After. Fastsett derfor alt i body-en, også levetiden, når auksjonsobjektet opprettes, og lagre det sammen med objektet.
  • Lagre også URL-en på objektet: nøkkelen beskytter nye forsøk, og den lagrede URL-en er det sidene leser resten av auksjonen.

En hel katalog som importeres på én gang, kan opprette opptil 50 auksjonsobjekter per kall, med én nøkkel per batch; hver URL i svaret gjengir kjøretøyet og alternativene den ble opprettet for.

URL-en til objekt 117
curl --fail-with-body -X POST https://carimage.dev/api/v1/image-urls \
  -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: sale-2026-10-14:lot-117" \
  -d '{"images":[{"vehicle":"veh_96j8z47jqfd4r","view":"side","width":800,"height":450,"fit":"contain","trim":true,"padding":6,"format":"auto"}],"ttl_seconds":259200}'
# run it again: the same URL comes back with Idempotent-Replayed: true, and nothing more is charged

Trinn 5: tilpass URL-ens levetid til salget

ttl_seconds kan være opptil 604800 (7 dager); en lengre verdi kuttes ned til dette. For et salg som avsluttes innen en uke, setter du den til tiden som gjenstår til avslutningen. Da slutter plassholderen å virke samtidig med budgivningen, og deretter svarer URL-en med 403.

  • Et tidsbestemt salg som varer lenger enn 7 dager: lag URL-en med renew: true, ttl_seconds satt til maksimum og renew_days som dekker salget. En fornyelse teller bildet én gang i måneden den skjer, og ingenting mer hvis det allerede er telt den måneden; uker der ingen åpner objektet, teller ingenting, og fornyelsen stopper ved renews_until.
  • Behold max_uses på 0, som er standard: en ubegrenset URL kan mellomlagres offentlig så lenge den er gyldig, mens en begrenset URL er private, no-store og sender hver innlasting til opprinnelsesserveren.
  • Begrens nøkkelen som lager signerte URL-er til auksjonens domener på dashbordet: Et objektbilde som kopieres til et annet nettsted, får svaret 403.
Mottak med TypeScript SDK
import { CarImageClient, type ImageParams } from "@meterapp/car-image-sdk";

const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });

const lotImage = (vehicle: string): ImageParams => ({
  vehicle, view: "side", width: 800, height: 450, fit: "contain", trim: true, padding: 6, format: "auto",
});

// How long the lot's URL lives, decided once from the sale's close.
function lifetime(closesAt: Date) {
  const seconds = secondsUntil(closesAt);
  return seconds <= 604800
    ? { ttlSeconds: Math.max(seconds, 60) } // closes within the week
    : { ttlSeconds: 604800, renew: true, renewDays: Math.min(daysUntil(closesAt), 365) }; // a longer timed sale
}

// At intake, once per lot. The lifetime is stored with the lot, so a retry sends
// the same body and replays the first answer instead of minting a second URL.
lot.imageLifetime ??= lifetime(sale.closesAt);
const { data: [placeholder] } = await client.createImageUrls(lotImage(lot.vehicleId), {
  ...lot.imageLifetime,
  idempotencyKey: `${sale.id}:lot-${lot.number}`,
});
lot.placeholderUrl = placeholder.url; // replaced by the lot's own photos when they arrive

Planlegg etter auksjonens størrelse

Hvert objekt er ett kjøretøybilde, kjøretøyet i sin lakk og visning, med mindre to objekter deler alle tre, og hver plan inkluderer et antall kjøretøybilder i måneden: Free 100, Pro 2 500 og Business 10 000; Enterprise forhandles. Et bilde som allerede er telt denne måneden, vises alltid, og en batch som ville overskride kvoten, avvises i sin helhet før noe telles, med planen og kvoten i svaret. Tilpass planen til objektene du legger ut i løpet av en måned. Markedsplasshistorien handler om å fordele en stor import innenfor grensene for forespørsler og renderinger.

Ofte stilte spørsmål

Kan renderingen bli stående etter at bildene av objektet har kommet?
Erstatt den. Renderingen er en plassholder for årsmodellen, og en budgiver skal aldri måtte lure på hvilket bilde som viser bilen som selges. Hvis en side beholder den som referanse, følger etiketten med.
Hva skjer med URL-en etter auksjonen?
Den utløper når levetiden er over, eller når en fornybar URL når slutten av fornyelsesperioden, og svarer da med 403. Da har objektet egne bilder eller et resultat, og arkivet for auksjonen bør vise bildene. Å tilbakekalle nøkkelen som genererte URL-ene, avslutter dem alle på én gang.
Et nytt forsøk fikk svaret 422. Hvorfor?
Den samme Idempotency-Key kom tilbake med en annen body. Den vanlige årsaken er en levetid som beregnes på nytt ut fra klokken i det øyeblikket forsøket gjentas. Fastsett levetiden når objektet opprettes, og lagre den, så sender det nye forsøket samme body og spiller av det første svaret på nytt.
Kan renderingen vise lakken på auksjonsobjektet?
Ja: color tar imot alle de forhåndsdefinerte navnene eller en hex-kode, så bildet kan matche lakken på innleveringsskjemaet uten ekstra kostnad. Det er fortsatt modellen i den lakken, ikke selve objektet, så merkingen blir stående.
Hva koster et salg med 400 objekter?
400 kjøretøybilder av månedens kvote: 1 kjøretøybilde per auksjonsobjekt når URL-en opprettes, og en ny opprettelse etter et nytt forsøk teller ikke på nytt. Hver innlasting innenfor URL-ens levetid er gratis. Planene inkluderer Free 100, Pro 2 500 og Business 10 000 kjøretøybilder i måneden, og objekter som deler kjøretøy, lakk og visning, telles én gang.

Les videre

Kundehistorie · BilmarkedsplasserSlik får du et studiobilde av bilen på hver eneste markedsplassannonseEn annonse trenger et bilde før selgeren laster opp et. Markedsplasser fyller en hel katalog med én vinkel og én lakkfarge, og beholder deretter samme forespørselsformat for hver ny årsmodell.