คู่มือการสร้างที่เขียนจากพฤติกรรมของ API ตามเอกสาร โดยไม่ได้ระบุชื่อลูกค้ารายใด เผยแพร่เมื่อ
ปัญหา: การขายเริ่มขึ้นก่อนที่รูปถ่ายจะพร้อม
แคตตาล็อกการประมูลจะเผยแพร่ทันทีที่รถฝากขายเข้ามาครบ โดยมี VIN หมายเลขล็อต และวันประมูลของรถแต่ละคัน ส่วนภาพถ่ายจะมาเมื่อรถถึงลานจอดและช่างภาพไปถึงรถ ซึ่งสำหรับรถบางส่วนในการประมูลนั้นเกิดขึ้นหลังจากเปิดให้เสนอราคาแล้ว ระหว่างนั้นแต่ละล็อตจึงเป็นเพียงกล่องสีเทาข้างข้อความหนึ่งบรรทัด
ภาพเรนเดอร์จากแค็ตตาล็อกช่วยเติมช่องภาพด้วยรุ่นปีที่ถูกต้อง แต่การประมูลก็เป็นที่ที่ภาพเรนเดอร์ต้องไม่ถูกเข้าใจว่าเป็นรถคันจริงเด็ดขาด ผู้ประมูลประเมินราคาจากสภาพรถ และภาพเรนเดอร์ไม่ได้แสดงสภาพใดๆ เลย เพราะภาพนั้นไม่ได้แสดงถึงยานพาหนะคันใดคันหนึ่งที่มีอยู่จริง ทุกอย่างด้านล่างนี้มาจากการยึดถือทั้งสองข้อนี้ไปพร้อมกัน
การผสานรวมมีลักษณะอย่างไร
- ภาพเรนเดอร์หนึ่งภาพต่อหนึ่งล็อตจาก VIN แสดงเฉพาะจนกว่ารูปถ่ายจริงของล็อตจะมาถึง
- ตัวเลือกรถจากแคตตาล็อก สำหรับล็อตที่ถอดรหัส VIN ไม่ได้
- ป้ายกำกับบนรูปภาพ: "ภาพเรนเดอร์จากแค็ตตาล็อก ไม่ใช่รถในล็อตนี้"
- หนึ่ง URL ต่อหนึ่งล็อต สร้างเพียงครั้งเดียว ภายใต้
Idempotency-Keyและใช้งานได้ตลอดช่วงการขาย
ขั้นตอนที่ 1: จาก VIN ของล็อตสู่ id ของรถ
GET /api/v1/vin/{vin} ใช้งานได้ฟรี เมื่อแค็ตตาล็อกมีข้อมูลยานพาหนะนั้น ผลลัพธ์จะมี data.vehicle.id ซึ่งเป็น 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'ขั้นตอนที่ 2: ไม่มี VIN ที่ถอดรหัสได้ใช่ไหม เลือกรถจากแค็ตตาล็อก
บางล็อตมาโดยไม่มี VIN ที่ถอดรหัสได้ เช่น รถที่ผลิตสำหรับตลาดอื่น VIN ที่แหล่งข้อมูลพิมพ์ผิด หรือใบฝากขายที่มีเพียงปี ยี่ห้อ และรุ่น โดยไม่มีข้อมูลอื่น ให้เพิ่มดรอปดาวน์สามรายการในแบบฟอร์มฝากขาย โดยดึงข้อมูลจาก GET /api/v1/vehicles ซึ่งใช้ได้ฟรีและเป็นสาธารณะ: ?year= แสดงรายการยี่ห้อที่มีรุ่นในปีนั้น และ ?year=&makeId= แสดงรายการรุ่นของยี่ห้อนั้น แต่ละรุ่นพร้อม vehicle id ของรุ่นปีนั้น
# 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 ดังนั้นดรอปดาวน์จึงทำงานแบบออฟไลน์กับรายการเดียวกันได้ด้วย ไม่ว่าจะใช้วิธีใด ล็อตจะได้ id ชนิดเดียวกับ VIN ที่ถอดรหัสแล้ว และไม่มีขั้นตอนใดถัดไปที่ต้องสะกดชื่อรถเอง
เมื่อได้รับเอกสารรายการรถฝากขายทั้งชุดในคราวเดียว POST /api/v1/vehicles/check จะอ่านได้สูงสุด 2,000 รายการต่อการเรียกหนึ่งครั้ง โดยแต่ละรายการสะกดตามที่เขียนในเอกสารและใช้หมายเลขล็อตเป็น ref แล้วตอบกลับทุกรายการ: รายการที่ตรงกันพร้อม id ที่ควรจัดเก็บ รายการแนะนำ รายการที่ไม่พบ หรือแถวที่ไม่ถูกต้อง โดยไม่มีการเรนเดอร์และไม่มีการเรียกเก็บเงิน ดูรายละเอียดได้ในเอกสาร vehicles
ขั้นตอนที่ 3: ระบุให้ชัดว่าภาพเรนเดอร์เป็นภาพเรนเดอร์
ใส่ป้ายกำกับไว้บนภาพโดยตรงตรงจุดที่สายตาผู้ประมูลมองไป และใส่ในข้อความ 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>ขั้นตอนที่ 4: หนึ่ง URL ต่อหนึ่งล็อต สร้างเพียงครั้งเดียว
สร้าง URL ของล็อตตอนรับเข้าระบบด้วย POST /api/v1/image-urls และ Idempotency-Key ที่สร้างจากการประมูลและล็อต โดยใช้ตัวอักษร ตัวเลข ., _, : และ - URL จะนับภาพเป็นภาพรถยนต์ของเดือนเมื่อสร้างขึ้น ดังนั้นหากไม่มีคีย์ การรับเข้าที่ลองใหม่จะสร้าง URL ที่สองขึ้นมา เมื่อมีคีย์:
- หากใช้คีย์เดียวกันกับ body เดียวกันภายใน 24 ชั่วโมง ระบบจะส่งการตอบกลับครั้งแรกซ้ำ รวมถึง URL เดิม พร้อม
Idempotent-Replayed: trueและไม่มีการเรียกเก็บเงินครั้งที่สอง - คีย์เดียวกันที่มี body ต่างกันจะได้
422และการลองใหม่ที่แซงหน้าคำขอแรกจะได้409พร้อมRetry-Afterดังนั้นให้กำหนดทุกอย่างใน body ให้ตายตัว รวมถึงอายุการใช้งาน ตั้งแต่ตอนสร้างล็อต และจัดเก็บไว้คู่กับล็อตนั้น - จัดเก็บ URL ไว้กับล็อตด้วย: คีย์ช่วยป้องกันปัญหาจากการลองซ้ำ และ 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ขั้นตอนที่ 5: กำหนดอายุของ 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 100, Pro 2,500 และ Business 10,000 ส่วน Enterprise สามารถเจรจาได้ ภาพที่ถูกนับแล้วในเดือนนี้จะให้บริการได้เสมอ และชุดคำขอที่จะเกินโควตาจะถูกปฏิเสธทั้งชุดก่อนที่จะมีการนับใดๆ โดยคำตอบจะระบุแพ็กเกจและโควตาไว้ เลือกแพ็กเกจให้เหมาะกับจำนวนล็อตที่คุณลงประกาศในหนึ่งเดือน เรื่องราวของมาร์เก็ตเพลส อธิบายวิธีกำหนดจังหวะการนำเข้าจำนวนมากภายใต้ขีดจำกัดอัตราคำขอและการเรนเดอร์
คำถามที่พบบ่อย
- ยังคงแสดงภาพเรนเดอร์ไว้ได้หรือไม่ เมื่อมีภาพถ่ายของล็อตแล้ว
- ให้แทนที่ ภาพเรนเดอร์เป็นเพียงภาพแทนของรุ่นปีนั้น และผู้ประมูลไม่ควรต้องสงสัยว่าภาพใดคือรถที่กำลังขายอยู่ หากหน้าใดยังเก็บภาพไว้เพื่ออ้างอิง ต้องแสดงป้ายกำกับไปด้วย
- URL จะเป็นอย่างไรหลังการขาย
- URL จะหมดอายุเมื่อสิ้นสุดอายุการใช้งาน หรือเมื่อ URL แบบต่ออายุได้ถึงสิ้นสุดช่วงการต่ออายุ จากนั้นจะตอบกลับด้วย 403 ถึงตอนนั้นล็อตก็จะมีภาพถ่ายของตัวเองหรือมีผลการประมูลแล้ว และหน้าเก็บถาวรของการประมูลควรแสดงภาพถ่ายจริง การเพิกถอนคีย์ที่ใช้สร้าง URL จะทำให้ URL ทั้งหมดใช้งานไม่ได้ในทันที
- การลองใหม่ได้รับการตอบกลับเป็น 422 เพราะอะไร
- มีการส่ง Idempotency-Key เดิมมาอีกครั้งพร้อม body ที่ต่างไป สาเหตุที่พบบ่อยคืออายุของ URL ถูกคำนวณใหม่จากเวลาปัจจุบันในขณะที่ลองใหม่ ให้กำหนดอายุให้ตายตัวตั้งแต่ตอนสร้างล็อตและจัดเก็บไว้ แล้วการลองใหม่จะส่ง body เดิมและได้รับคำตอบแรกซ้ำกลับมา
- ภาพเรนเดอร์แสดงสีของรถในล็อตได้หรือไม่
- ได้ color รับได้ทั้งชื่อสีที่กำหนดไว้ล่วงหน้าหรือค่า hex ภาพจึงตรงกับสีในเอกสารฝากขายได้โดยไม่มีค่าใช้จ่ายเพิ่ม แต่ภาพยังคงเป็นรุ่นรถในสีนั้น ไม่ใช่รถคันที่นำมาประมูล จึงยังต้องมีป้ายกำกับ
- การประมูล 400 ล็อตมีค่าใช้จ่ายเท่าใด
- นับเป็นภาพรถยนต์ 400 ภาพของเดือน: ภาพรถยนต์ 1 ภาพต่อล็อตเมื่อสร้าง URL ของล็อตนั้น และการสร้างซ้ำจะไม่นับเพิ่มอีก การโหลดทุกครั้งภายในอายุของ URL ไม่มีค่าใช้จ่าย แพ็กเกจรวมภาพรถยนต์ต่อเดือน ได้แก่ Free 100 ภาพ, Pro 2,500 ภาพ และ Business 10,000 ภาพ และล็อตที่ใช้รถ สี และมุมมองเดียวกันจะนับเพียงครั้งเดียว