راهنمای پیادهسازی که بر پایهٔ رفتار مستندشدهٔ API نوشته شده است؛ نام هیچ مشتریای در آن نیامده است. منتشرشده در .
مشکل: حراج پیش از آماده شدن عکسها آغاز میشود
کاتالوگ حراج به محض رسیدن خودروهای امانی منتشر میشود: یک VIN، یک شماره لات و یک تاریخ فروش برای هر خودرو. عکسها زمانی میرسند که خودرو به محوطه برسد و عکاس به خودرو، که برای بخشی از حراج پس از شروع مزایده است. تا آن زمان، هر یک از آن لاتها یک کادر خاکستری در کنار یک خط متن است.
رندر کاتالوگ جای خالی را با سال مدل درست پر میکند. اما مزایده دقیقاً همان جایی است که رندر هرگز نباید به جای خود خودرو جا زده شود: خریداران بر اساس وضعیت خودرو قیمت میدهند و رندر هیچ وضعیتی را نشان نمیدهد، زیرا هیچ خودروی فیزیکی مشخصی را به تصویر نمیکشد. هر آنچه در ادامه میآید از در نظر گرفتن همزمان این دو نکته ناشی میشود.
یکپارچهسازی چگونه است
- یک رندر برای هر لات بر اساس VIN آن، که فقط تا رسیدن عکسهای خود لات نمایش داده میشود.
- انتخابگر کاتالوگ برای لاتهایی که VIN آنها رمزگشایی نمیشود.
- برچسبی روی تصویر: «رندر کاتالوگ، نه این لات».
- یک URL برای هر لات، فقط یک بار ساختهشده با یک
Idempotency-Key، و معتبر تا پایان حراج.
گام ۱: از VIN لات تا شناسهٔ خودرو
GET /api/v1/vin/{vin} رایگان است. وقتی خودرو در کاتالوگ موجود باشد، پاسخ شامل data.vehicle.id است، یعنی شناسه پایداری که باید روی لات ذخیره شود؛ تیپ، نوع بدنه و موتورِ رمزگشاییشده در متن لات باقی میمانند. کاتالوگ از 1990 تا 2027 را پوشش میدهد، بنابراین موجودی قدیمیتر یک مزایده هم مانند جدیدترینها رندر میشود. راهنمای بیمه رمزگشایی را فیلد به فیلد شرح میدهد و مستندات VIN به VINهای ناقص و خطاها میپردازد.
# 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'گام ۲: VIN قابل رمزگشایی ندارید؟ خودرو را از کاتالوگ انتخاب کنید
برخی از اقلام حراج بدون VIN قابل رمزگشایی میرسند: خودرویی که برای بازار دیگری ساخته شده، VINای که منبع اشتباه تایپ کرده، یا برگهٔ واگذاریای که فقط سال، برند و مدل دارد و هیچ چیز دیگری ندارد. به فرم واگذاری سه فهرست کشویی بدهید که از GET /api/v1/vehicles تغذیه میشوند؛ این endpoint رایگان و عمومی است: ?year= برندهایی را فهرست میکند که در آن سال مدلی دارند، و ?year=&makeId= مدلهای آن برند را فهرست میکند، هر کدام همراه با شناسهٔ خودروی همان سال مدل.
# 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"{
"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"
},
"…"
]
}
}همین کاتالوگ در قالب بستهٔ متنباز @meterapp/vehicle-db نیز موجود است، بنابراین منوهای کشویی میتوانند بهصورت آفلاین و با همان فهرست کار کنند. در هر دو حالت، لات در نهایت همان نوع شناسهای را نگه میدارد که از رمزگشایی VIN به دست میآید و هیچ بخشی در ادامهٔ کار نام خودرو را تایپ نمیکند.
وقتی یک فهرست کامل محموله یکجا میرسد، POST /api/v1/vehicles/check در هر فراخوانی تا ۲٬۰۰۰ ردیف را میخواند، هر کدام را همانطور که در فهرست نوشته شده و با شمارهٔ لات بهعنوان ref، و به همه پاسخ میدهد: تطابق همراه با شناسهای که باید ذخیره شود، پیشنهادها، عدم تطابق یا ردیف نامعتبر. هیچ چیزی رندر نمیشود و هیچ هزینهای کسر نمیشود؛ جزئیات در مستندات vehicles آمده است.
گام ۳: رندر را بهعنوان رندر برچسب بزنید
برچسب را روی خودِ تصویر بگذارید، همان جایی که چشم پیشنهاددهنده میافتد، و در متن جایگزین (alt)، نه فقط در توضیحات زیر آن. وضعیت، کارکرد، آسیبها، آپشنها و رنگ واقعی خودرو باید در متن لات حراج بیایند و، وقتی عکسها موجود شدند، در خود عکسها. با رسیدن عکسها، رندر کنار میرود.
<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>مرحلهٔ ۴: یک URL برای هر لات، فقط یک بار صادر میشود
URL هر لات را هنگام ثبت با POST /api/v1/image-urls و یک Idempotency-Key بسازید که از شناسهٔ حراج و لات تشکیل شده و شامل حروف، ارقام، .، _، : و - است. URL هنگام ساخت، تصویر خود را بهعنوان یکی از تصاویر خودروی ماه میشمارد، بنابراین بدون کلید، تکرار ثبت یک URL دوم میسازد. با کلید:
- ارسال همان کلید با همان بدنه در طول 24 ساعت، پاسخ اول را با همان URL، همراه با
Idempotent-Replayed: trueو بدون کسر هزینهٔ دوم، دوباره برمیگرداند. - همان کلید با بدنه درخواست متفاوت به
422میانجامد و تلاش مجددی که از درخواست نخست جلو بزند،409همراه باRetry-Afterبرمیگرداند. پس هنگام ایجاد لات، همه چیز را در بدنه درخواست، از جمله مدت اعتبار، ثابت کنید و آن را همراه لات ذخیره کنید. - URL را نیز در رکورد قلم حراج ذخیره کنید: کلید از تلاشهای مجدد محافظت میکند و URL ذخیرهشده همان چیزی است که صفحات در ادامهٔ حراج میخوانند.
کل کاتالوگی که یکجا وارد میشود میتواند در هر فراخوانی برای حداکثر 50 لات حراج URL ایجاد کند، با یک کلید برای هر دسته؛ هر URL در پاسخ، خودرو و گزینههایی را که برایشان ایجاد شده بازتاب میدهد.
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گام ۵: مدت اعتبار URL را با حراج هماهنگ کنید
ttl_seconds حداکثر تا 604800 (7 روز) است؛ مقدار بیشتر به همین حد محدود میشود. برای حراجی که ظرف همین هفته بسته میشود، آن را برابر زمان باقیمانده تا پایان حراج قرار دهید. در این صورت تصویر همزمان با پایان پیشنهاددهی از کار میافتد و پس از آن URL پاسخ 403 میدهد.
- حراج زماندار طولانیتر از 7 روز: با
renew: true،ttl_secondsدر حداکثر مقدار وrenew_daysکه کل مدت حراج را پوشش دهد بسازید. هر تمدید تصویر را یک بار در ماهی که در آن انجام میشود حساب میکند و اگر تصویر در آن ماه قبلاً حساب شده باشد چیزی اضافه نمیشود، هفتههایی که کسی آن قلم حراج را باز نمیکند چیزی حساب نمیشود، و تمدید درrenews_untilمتوقف میشود. max_usesرا روی 0 نگه دارید، که مقدار پیشفرض است: URL نامحدود در تمام طول عمرش بهصورت عمومی قابل کش است، در حالی که URL محدودشدهprivate, no-storeاست و هر بارگذاری را به سرور مبدأ میفرستد.- محدود کردن کلید امضا: در داشبورد کلیدی را که URLهای امضاشده را میسازد به دامنههای حراج خود محدود کنید؛ تصویر خودروی حراجی که در سایت دیگری کپی شود پاسخ
403میدهد.
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متناسب با اندازهٔ حراج برنامهریزی کنید
هر قلم حراج یک تصویر خودرو است، یعنی خودروی آن در رنگ و نمای خودش، مگر اینکه دو قلم در هر سه مورد یکسان باشند، و هر پلن ماهانه شامل تعداد مشخصی تصویر خودرو است: Free ۱۰۰، Pro ۲٬۵۰۰ و Business ۱۰٬۰۰۰؛ Enterprise با مذاکره تعیین میشود. تصویری که این ماه قبلاً حساب شده همیشه ارائه میشود، و دستهای که از سهمیه فراتر برود، پیش از شمارش هر چیزی، بهطور کامل رد میشود و پلن و سهمیه در پاسخ ذکر میشوند. پلن را متناسب با تعداد اقلامی که در یک ماه فهرست میکنید انتخاب کنید. داستان مارکتپلیس نحوه تنظیم سرعت یک واردسازی بزرگ در چارچوب محدودیتهای نرخ و رندر را توضیح میدهد.
پرسشهای متداول
- آیا پس از رسیدن عکسهای لات، رندر میتواند همچنان نمایش داده شود؟
- آن را جایگزین کنید. رندر فقط نمایندهٔ سال مدل است و شرکتکنندهٔ حراج هرگز نباید شک کند کدام تصویر، خودروی در حال فروش است. اگر صفحهای آن را برای مرجع نگه میدارد، برچسب هم باید همراهش بماند.
- بعد از حراج چه بر سر URL میآید؟
- زمانی منقضی میشود که مدت اعتبارش به پایان برسد، یا وقتی یک URL تمدیدشونده به پایان دورهٔ تمدید خود برسد، و از آن پس پاسخ 403 میدهد. تا آن زمان لات عکسهای خودش یا نتیجهای دارد، و بایگانی حراج باید عکسها را نشان دهد. ابطال کلیدی که URLها را صادر کرده، همهٔ آنها را یکجا از کار میاندازد.
- یک تلاش مجدد پاسخ 422 گرفت. چرا؟
- همان Idempotency-Key با بدنهٔ درخواست متفاوتی برگشت. علت معمول، مدت اعتباری است که در لحظهٔ تلاش مجدد از روی ساعت دوباره محاسبه شده است. مدت اعتبار را هنگام ایجاد لات ثابت و ذخیره کنید تا تلاش مجدد همان بدنه را بفرستد و همان پاسخ اول را دوباره دریافت کند.
- آیا رندر میتواند رنگ بدنهٔ لات را نشان دهد؟
- بله: پارامتر color هر یک از نامهای از پیش تعریفشده یا یک کد hex را میپذیرد، پس تصویر میتواند بدون هزینهٔ اضافه با رنگ ذکرشده در برگهٔ امانی مطابقت داشته باشد. با این حال، این همچنان همان مدل با آن رنگ است، نه خودروی حراجی، پس برچسب باقی میماند.
- هزینهٔ یک حراج با ۴۰۰ قلم خودرو چقدر است؟
- ۴۰۰ تصویر خودرو از سهمیهٔ ماه: ۱ تصویر خودرو برای هر لات هنگام ساخت URL آن، و تکرار ساخت دوباره چیزی شمرده نمیشود. هر بارگذاری در طول عمر URL رایگان است. طرحها شامل این تعداد تصویر خودرو در ماه هستند: رایگان ۱۰۰، Pro ۲٬۵۰۰ و Business ۱۰٬۰۰۰؛ و لاتهایی که خودرو، رنگ و نمای یکسانی دارند، یک بار شمرده میشوند.