Car Image API

Müşteriler · İlan siteleri ve araç alışveriş katalogları

Her pazar yeri ilanına stüdyo kalitesinde araç görseli nasıl eklenir

İlan siteleri ve otomobil alışveriş katalogları, katalog ölçeğinde her model yılı için tek bir ana görseli nasıl oluşturuyor: araç kimlikleri, kadraj, istek temposu, önbellekleme ve kod.

Sorun: bir ilanın, satıcı fotoğraf yüklemeden önce bir görsele ihtiyacı var

Bir ilan sitesinin veya otomobil alışveriş kataloğunun kaderi ızgarasına bağlıdır. Her kartın, ilan oluşturulduğu anda bir görsele ihtiyacı vardır; satıcının kendi fotoğrafı ise gelirse sonradan, rastgele bir açıdan, rastgele bir garaj yolunda çekilmiş olarak gelir. Stok fotoğraflarda ise tam tersi bir sorun vardır: lisanslı basın fotoğrafları yalnızca popüler yıllardaki popüler araçlar için, üreticinin seçtiği açı ve arka planla mevcuttur; geri kalanı için hiçbir şey yoktur. 1990 ile güncel model yılı arasını kapsayan bir katalogda on binlerce boşluk vardır.

Bu siteleri geliştiren ekiplerin istediği şey, kelimenin en iyi anlamıyla sıkıcı: her model yılı için tek bir stüdyo görseli, hepsinde aynı açı ve aynı boya, kartın arka planı ne olursa olsun üzerine oturabilmesi için şeffaf ve günde on bin kez sunulabilecek kadar küçük.

Bir katalog entegrasyonu nasıl görünür

Bugün API üzerinde çalışan katalog yapıları, ister ilanlarını ilk kez dolduran bir ilan sitesi, ister karşılaştırma kartlarını oluşturan bir araç alışveriş uygulaması, ister her araç için tek bir ana görsel gösteren bir mobil uygulama olsun, hepsi aynı yapıya sahiptir:

  • Önce toplu doldurma, sonra damla damla. Kataloğu kapsamak için birkaç saatte binlerce render, ardından yeni model yılları ve talepler geldikçe günde birkaç tane.
  • Tek açı, tek boya veya kısa bir palet. Çoğu, gümüş veya beyaz renkte front-3-4 ya da side seçer. Kullanıcının renk seçmesine izin veren bir alışveriş kataloğu, her araç için birkaç hazır renk oluşturur; her biri yeni bir iş akışı değil, yalnızca bir araç görseli daha demektir.
  • Sabit bir kutuda WebP. 512 ile 1024 piksel genişliğinde, tam olarak kartın kullandığı kutu boyutunda teslim edilir; böylece ön yüz görseli asla kırpmak ya da kenarlarına boşluk eklemek zorunda kalmaz.
  • Araç kimliğiyle saklanır. Renderlar ekibin kendi nesne depolama alanına veya CDN'ine yerleşir ya da sayfalar imzalı URL'leri yükler; her iki durumda da anahtar bir marka-model-yıl dizesi değil, kataloğun sabit veh_… kimliğidir.

Bu sayfanın geri kalanı, kodlarıyla birlikte bu iş akışını adım adım anlatıyor. images:read kapsamına sahip bir API anahtarınız ve kataloğunuza uygun büyüklükte bir planınız olduğu varsayılır (SSS'ye bakın).

1. Adım: kataloğu yazımla değil, her zaman id ile listeleyin

Bir katalog oluştururken en sık karşılaşılan sorun render değil, yazımdır. Marka ve model dizelerini başka bir veritabanından üreten bir yapı, isteklerinin çoğunu 404 vehicle_not_found yanıtlarına harcayabilir: ücretsizdir ama her biri boşa giden bir gidiş-dönüş demektir ve ortaya boşluklarla dolu bir ızgara çıkar. Çözüm, neyin mevcut olduğunu kataloğun size söylemesine izin vermektir. GET /api/v1/vehicles ücretsizdir, anahtar gerektirmez ve döndürdüğü her model, dağıtımlar veya katalog sürümleri arasında asla değişmeyen sabit bir araç kimliği (veh_ artı 13 karakter) taşır. Bu kimliği ilanda saklayın ve render işlemini onunla yapın.

Tek bir model yılını tarayın
# every make with a 2024 model year (free, no key)
curl -s "https://carimage.dev/api/v1/vehicles?year=2024"

# every 2024 model of one make, each with the id you will store
curl -s "https://carimage.dev/api/v1/vehicles?year=2024&makeId=584"
200 OK (kısaltılmış)
{
  "data": {
    "year": 2024,
    "make_id": 584,
    "models": [
      {
        "name": "718",
        "slug": "718",
        "vehicle_type": "Passenger Car",
        "id": "veh_b4bf090fyb53k"
      },
      {
        "name": "911",
        "slug": "911",
        "vehicle_type": "Passenger Car",
        "id": "veh_78qtwrgh37bkr"
      }
    ]
  }
}

?make=porsche&model=911 bir modelin tüm yıllarını her yıl için bir id ile listeler; ?q= ise satıcı bir ad yazdığında serbest metin araması yapar. Aynı katalog açık @meterapp/vehicle-db paketi olarak da yayımlanır; böylece açılır menüler ve doğrulama, aynı listeye karşı çevrimdışı çalışabilir. Her iki durumda da bu adımın sonunda elinizde bir id listesi olur ve sonraki hiçbir adımda bir aracın adı bir daha harf harf yazılmaz.

Araçlarını zaten başka bir veritabanının yazımıyla adlandıran ilanlar tek çağrıda eşlenir: POST /api/v1/vehicles/check, bunlardan en fazla 2.000 tanesini bir render'ın okuyacağı şekilde okur. Her birine araç kimliğiyle, katalogda böyle bir araç yoksa en yakın gerçek araçlarla ya da tüm görünümlerde ve renklerde atlanacak bir eşleşmeme sonucuyla yanıt verir. car-image check listings.csv --out checked.csv kimlikleri dosyaya geri yazar. Ücretsizdir ve eksikleri tek tek 404 hatalarıyla keşfetmenin yerini alır.

2. Adım: Her ilan için tek bir istek yapısı

Kartı bir kez belirleyin ve sorgu dizesine kodlayın. Aşağıda vehicle= ifadesinden sonra gelen her şey, tüm katalog için bir kez verdiğiniz bir çerçeveleme kararıdır:

Tek bir ilan görseli
curl --fail-with-body -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  "https://carimage.dev/api/v1/images/car?vehicle=veh_78qtwrgh37bkr&view=front-3-4&color=silver&w=800&h=600&fit=contain&trim=1&padding=8&format=webp" \
  -o veh_78qtwrgh37bkr.webp
  • w=800&h=600&fit=contain, aracın tamamının göründüğü ve etrafında şeffaf dolgu bulunan tam 800×600 boyutunda bir görsel sunar; böylece her kartın tuvali aynı olur. fit=cover ise kutuyu doldurur ve görseli ortadan kırpar.
  • trim=1&padding=8, sığdırmadan önce görseli aracın dış hatlarına göre kırpar ve uzun kenarının %8'i kadar kenar boşluğu bırakır; böylece bir Suburban ile bir Miata, kaynak karede yüzer gibi durmak yerine kutuyu aynı şekilde doldurur.
  • color=silver varsayılandır ve en güvenli nötr seçenektir; 15 hazır ayardan herhangi biri veya herhangi bir hex kodu aynı şekilde, tek araç görseli olarak sayılır.
  • format=webp, kayıpsız alfa kanallı en küçük kodlamadır. Tarayıcı URL'yi doğrudan yüklediğinde (imzalı URL'ler, 4. adım) format=auto, istemciye göre WebP veya PNG'yi belirler.

Yanıt; ETag, X-Image-Source (cache veya generated) ve sunulan katalog aracını belirten X-Vehicle-Id başlıklarını içerir. ETag’i dosyayla birlikte saklayın: daha sonra If-None-Match ile yapılan bir istek 304 yanıtını döndürür ve hiçbir ücret doğurmaz; gece yapılan yeniden senkronizasyonun ücretsiz kalmasını sağlayan da budur.

Adım 3: Toplu geriye dönük doldurmayı limitlere uygun hızda yürütün

Toplu geriye dönük doldurmayı üç sınır belirler ve her biri sessizce başarısız olmak yerine kendini yanıt başlıklarında belli eder:

  • Dakika başına istek. Free ve Pro'da anahtar başına 120, Business'ta 600, Enterprise'da 1.200; buna ek olarak tüm anahtarlar genelinde hesap başına bir limit uygulanır. Kimliği doğrulanmış her yanıt RateLimit-Remaining içerir; bir 429 yanıtı ise Retry-After içerir. Aynı anda dört ila sekiz istek fazlasıyla yeterlidir.
  • Yeni araç görünümleri. Henüz hazırlamadığımız bir araç görünümü için ilk istek, görünümü her renkte gösterilebilecek şekilde hazırlarken biraz zaman alır; sonraki tüm istekler, hangi renkte olursa olsun, önbellekten sunulur. Yeni görünümlerin hazırlanması, hesabın günlük render bütçesindeki payından düşer (Free planda %2, Pro planda %10, Business planda %25, Enterprise planda %50). Bu pay aşıldığında yeni bir render code: account_generation_cap ve reset_at (UTC gece yarısı) ile 429 yanıtı döndürür, hiçbir ücret alınmaz ve önbellekteki görseller sunulmaya devam eder. Büyük bir geriye dönük doldurma tek bir akşamda değil, birkaç akşamda tamamlanır.
  • Aylık araç görselleri. Free 100, Pro 2.500, Business 10.000 görsel içerir; Enterprise görüşmeyle belirlenir. Bu kota aşıldıktan sonra, bu ay henüz sayılmamış bir görsel için yapılan istek 402 (plan_image_limit) yanıtını döndürür ve hiçbir şey sayılmaz; bu ay zaten sayılmış bir görsel her zaman sunulur, böylece canlı bir ızgara asla bozulmaz.

Render hataları (502) araç görselini otomatik olarak iade eder, aynı yeni varyant için eşzamanlı istekler tek bir render'ı paylaşır ve basit bir GET güvenle yeniden denenebilir. SDK, Retry-After değerine uyarak 429 ve 503 yanıtlarını sizin için yeniden dener ve 402 yanıtını asla yeniden denemez.

TypeScript SDK ile kaldığı yerden sürdürülebilen geriye dönük doldurma
import { CarImageClient, CarImageError } from "@meterapp/car-image-sdk";

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

// One make, one model year: the ids are what you store and what you render by.
const { data } = await client.vehicles({ year: 2024, makeId: 584 });
const queue = data.models.flatMap((model) => (model.id ? [model.id] : []));

// Four in flight stays well inside 120 requests a minute, and a cold render
// that takes a few seconds never holds up the rest of the batch.
await Promise.all(
  Array.from({ length: 4 }, async () => {
    for (let id = queue.shift(); id; id = queue.shift()) {
      try {
        const image = await client.getImage({
          vehicle: id, view: "front-3-4", color: "silver",
          width: 800, height: 600, fit: "contain", trim: true, padding: 8, format: "webp",
        });
        await store(id, image.bytes, image.etag); // your object store or CDN, keyed by vehicle id
      } catch (error) {
        // 429 and 503 were already retried with Retry-After; a 404 is a vehicle to request, not a failure.
        if (error instanceof CarImageError && error.status === 404) continue;
        throw error;
      }
    }
  })
);

Adım 4: görseli CDN'inizden veya imzalı URL'ler üzerinden sunun

Görseli alışveriş yapan kullanıcının önüne getirmenin iki iyi yolu var ve katalog projeleri ikisini de kullanıyor:

  • Baytları saklayın. Her render'ı kendi nesne depolamanıza veya CDN'inize araç kimliğiyle yazın ve diğer tüm varlıklar gibi sunun. Milyonlarca kez görüntülenen bir ızgara için doğru çözüm budur: her yüklemede bize çağrı yapılmaz ve ücretli plandaki lisans, ürününüzü sunmak için sakladığınız kopyaları kapsar.
  • İmzalı URL'ler oluşturun. POST /api/v1/image-urls çağrı başına en fazla elli görsel alır, her URL'nin görselini oluşturulduğu anda o ayın araç görseli olarak sayar ve tarayıcının doğrudan yüklediği, anahtar içermeyen URL'ler döndürür. ttl_seconds değerini en fazla yedi gün olarak ayarlayın; bundan daha uzun süre yayında kalan ilan sayfaları için renew: true ekleyin (bir yenileme, görseli denk geldiği ayda bir kez sayar; o ay zaten sayılmışsa başka bir şey saymaz). Anahtarı panelde sitenizin origin'leriyle sınırlayın; başka bir yere kopyalanan URL 403 döndürür.

Toplu oluştururken her ilan sayfası için bir Idempotency-Key gönderin: aynı anahtar ve gövdeyle yeniden denenen bir çağrı ilk yanıtı tekrar döndürür ve hiçbir şeyi yeniden saymaz.

listings.json — her seferinde elli tane, 2. adımdaki gibi çerçevelenmiş
{
  "images": [
    {
      "vehicle": "veh_78qtwrgh37bkr",
      "view": "front-3-4",
      "color": "silver",
      "width": 800,
      "height": 600,
      "fit": "contain",
      "trim": true,
      "padding": 8,
      "format": "auto"
    },
    {
      "vehicle": "veh_b4bf090fyb53k",
      "view": "front-3-4",
      "color": "silver",
      "width": 800,
      "height": 600,
      "fit": "contain",
      "trim": true,
      "padding": 8,
      "format": "auto"
    }
  ]
}

Bir araç katalogda yoksa

Önce arayın: GET /api/v1/vehicles?q= bir modeli adına, önekine veya bulanık eşleşmeyle bulur; POST /api/v1/images/resolve ise serbest metinli bir ifadeyi, buna göre hareket edebileceğiniz bir güven puanıyla birlikte kesin parametrelere dönüştürür. Bundan sonra hâlâ eksik olanların yeri talep panosudur: POST /api/v1/requests talebi oluşturur ya da aynı marka, model ve yıl için açık bir talep varsa yenisini oluşturmak yerine ona oy verir. Kataloğun kendisi açık kaynaktır ve eklemeler tüm müşterilere sunulur.

CLI, SDK ve MCP

Tüm işlem hattı hiç kod yazmadan CLI üzerinden çalışır; API'deki birden fazla katalog da ilk verilerini bu şekilde aldı:

npx @meterapp/car-image
# One file per vehicle id. Re-running skips what exists, so a stopped backfill resumes.
while read -r id; do
  [ -f "cdn/$id.webp" ] || npx @meterapp/car-image get --vehicle "$id" \
      --view front-3-4 --color silver --width 800 --height 600 --fit contain \
      --trim --padding 8 --format webp --out "cdn/$id.webp"
done < vehicle-ids.txt

# Or fifty signed URLs in one call, for a page of listings the browser loads itself.
npx @meterapp/car-image url --batch listings.json --ttl 604800 --renew --json
  • SDK: listelemek için client.vehicles({ year, makeId }), render için client.getImage({ vehicle, … }), imzalı URL grupları için client.createImageUrls(…). Tüm parametreler için görsel belgelerine bakın.
  • MCP: https://carimage.dev/api/mcp adresine bağlı bir asistan aynı kataloğa (search_vehicles, resolve_vehicle) ve aynı görsellere (get_car_image, create_car_image_urls) erişir; bu, bir aracı elle ekleyen bir küratör için doğru seçenektir, binlerce kaydın toplu doldurulması içinse yanlış seçenektir: bunun için CLI'ı ya da SDK'yı kullanın ve asistanı geride kalanlara saklayın. Kurulum bilgileri MCP sayfasında.

Sıkça sorulan sorular

Bir ilanda hangi açı kullanılmalı?
front-3-4 varsayılan ve klasik ana görsel açısıdır; aracın önü sola bakar. Aracın sol tarafına ait her açının bir -right ikizi vardır (front-3-4-right, side-right, rear-3-4-right); böylece bir kart düzenin dışına değil içine bakabilir. Birini seçin ve ona bağlı kalın: değerin büyük kısmı ilanlar arasındaki tutarlılıktan gelir.
20.000 ilanlık bir kataloğun maliyeti nedir?
Her ilan tek boya ve görünümde tek bir araç gösteriyorsa ayda 20.000 araç görseli; her biri herhangi bir boyutta gerektiği sıklıkta teslim edilir. Aynı aracı, boyayı ve görünümü paylaşan ilanlar tek görseldir ve If-None-Match ile yeniden kontrol ücretsizdir. Pro ayda 2.500, Business 10.000 araç görseli içerir; bu nedenle bu büyüklükte bir katalog için Enterprise ya da kalıcı olarak saklayıp kendiniz barındıracağınız tek seferlik bir Image Pack gerekir. Limiti aşan bir toplu doldurma 402 yanıtı verir ve hiçbir şey sayılmaz.
Dosyaları kendi CDN'imizde tutabilir miyiz?
Evet. Ücretli bir plan, plan etkin olduğu sürece render'ları ürününüz içinde kullanmak üzere lisanslar; kendi sunucularınızdaki veya CDN'inizdeki kopyalar da dahildir ve atıf gerekmez. Plan sona erdikten sonraki 30 gün içinde saklanan kopyalar silinir (bir Görsel Paketi'nin görselleri kalıcı olarak saklanabilir). Lisansın izin vermediği şey, bunları bağımsız bir kütüphane, akış veya veri kümesi olarak sunmaktır. Bir sonraki model yılını render eden şey, etkin bir plandır.
Kataloğa yeni bir model yılı eklendiğinde ne olur?
@meterapp/vehicle-db kataloğu kaynaklar yayımladıkça güncellenir ve mevcut kimlikler asla değişmez. Yeni yılı listeleyin, henüz sahip olmadığınız kimlikleri render edin ve gerisine dokunmayın. İstekler bir ETag taşır; If-None-Match ile yapılan tekrar istek 304 yanıtı verir ve ücretsizdir.
Bazı marka ve model dizelerimiz neden 404 döndürüyor?
Çünkü başka bir veritabanının yazımıyla yazılmışlardır. Katalog adları, slug'ları ve birçok donanım rozeti ve kasa tipi varyantını kabul eder, ancak hiç görmediği bir dize 404 vehicle_not_found döndürür (ücretsizdir, ama boşa giden bir istek-yanıt turudur). Kendi dizelerinizi çevirmek yerine kataloğu listeleyip kimliklerini saklayın; geri kalanları arayın veya çözümleyin.