ปัญหา: ระเบียนมี VIN นานหลายเดือนก่อนจะมีภาพถ่าย
บันทึกสต็อกใน CRM, ERP หรือระบบบริหารจัดการดีลเลอร์เริ่มต้นจากเพียง VIN หมายเลขสต็อก และราคา ภาพถ่ายจะมีก็ต่อเมื่อช่างภาพประจำลานจอดรถมาถ่าย และสำหรับรถบางคันก็ไม่เคยมีเลย ไม่ว่าจะเป็นรถที่อยู่ระหว่างการขนส่ง รถเทิร์นที่ยังปรับสภาพไม่เสร็จ รถนำเข้าที่ชื่อรุ่นไม่ตรงกับรายการใดในฟีดภาพของ DMS หรือรถยุค 1990 ที่ไม่มีใครซื้อสิทธิ์ภาพประชาสัมพันธ์ไว้ ทุกหน้าจอที่แสดงบันทึกนั้น ทั้งรายการของพนักงานขาย ใบประเมินราคาของฝ่ายรับซื้อ และใบเสนอราคาของลูกค้า จึงแสดงภาพตัวยึดตำแหน่งสีเทาแทน
เครื่องมือสำหรับดีลเลอร์และการนำเข้าบน API จะเติมภาพแทนที่นั้นจากข้อมูลที่ระเบียนมีอยู่แล้ว หากมี VIN ภาพก็ห่างไปเพียงการถอดรหัสฟรีหนึ่งครั้ง หากมีเพียงบรรทัดหนึ่งในใบรายการสต็อก การ resolve ด้วยข้อความอิสระก็หาเจอได้ ไม่ว่าทางใด ระเบียนก็จะได้ vehicle id ที่คงที่ และทุกหน้าจอจะเรนเดอร์รถคันเดียวกันในแบบเดียวกัน
การผสานรวมกับระบบของดีลเลอร์มีลักษณะอย่างไร
- ถอดรหัสตั้งแต่ตอนรับข้อมูลเข้า VIN จะถูกถอดรหัสครั้งเดียวเมื่อสร้างเรคคอร์ด และจัดเก็บ vehicle id ของแค็ตตาล็อกไว้คู่กัน ไม่มีขั้นตอนใดหลังจากนั้นต้องสะกดชื่อยี่ห้อหรือรุ่นอีก
- มุมหนึ่งสำหรับหน้ารายการ อีกมุมสำหรับหน้ารายละเอียด ใช้
sideแบบตรงในกรอบกว้างสำหรับรายการสต็อกรถ และใช้front-3-4สำหรับหน้ารายละเอียดและใบเสนอราคา - ครอบคลุมรถหลายปี รถนำเข้าและรถมือสองย้อนไปถึงช่วงทศวรรษ 1990 และเรนเดอร์ได้เหมือนรถที่เพิ่งเข้ามาใหม่ แค็ตตาล็อกครอบคลุมตั้งแต่ปี 1990 จนถึงปีรุ่นปัจจุบัน รวมถึงรุ่นที่จำหน่ายเฉพาะในตลาดญี่ปุ่นด้วย
- Signed URL ภายในแอป CRM ทำงานในเบราว์เซอร์ จึงโหลด signed URL ที่ไม่ต้องใช้คีย์ซึ่งสร้างโดยเซิร์ฟเวอร์ สูงสุดห้าสิบรายการต่อการเรียกหนึ่งครั้ง และต่ออายุสำหรับระเบียนที่อยู่นานกว่าหนึ่งสัปดาห์
ขั้นตอนที่ 1: ถอดรหัส VIN ฟรี
GET /api/v1/vin/{vin} ไม่มีค่าใช้จ่ายและต้องการเพียง API key ระบบจะส่งคืนปี ยี่ห้อ รุ่น รุ่นย่อย ประเภทตัวถัง และเครื่องยนต์ที่ถอดรหัสแล้ว รวมถึงแอตทริบิวต์อื่นๆ ทั้งหมดที่ข้อมูล vPIC ของ NHTSA มี และเมื่อแค็ตตาล็อกมีรถคันนั้น จะส่งคืนออบเจ็กต์ vehicle พร้อม id ที่คงที่และ image_path ที่พร้อมใช้งาน VIN บางส่วนก็ใช้ได้เช่นกัน: อย่างน้อยห้าตัวอักษร ใช้ * แทนแต่ละตำแหน่งที่ไม่ทราบ และระบุ year เป็นคำใบ้เพิ่มเติมได้
curl -s -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
"https://carimage.dev/api/v1/vin/1HGCM82633A004352"{
"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…"
}trim และ body_class เป็นข้อความในเรคคอร์ดและแสดงไว้ข้างรูปภาพ แทนที่จะอ้างว่ารูปภาพแสดงสิ่งเหล่านั้น VIN ที่มีหลักตรวจสอบ (check digit) ผิดพลาดยังคงถอดรหัสได้ โดยมี valid: false และรายการข้อผิดพลาด ดังนั้นใบรายการสต็อกที่พิมพ์ผิดจึงไม่ใช่ทางตันขั้นตอนที่ 1b: เมื่อคุณมีเพียงข้อมูลหนึ่งบรรทัดในใบรายการสต็อก
ข้อมูลรถนำเข้ามักมาในรูปแบบสเปรดชีต ได้แก่ ปี ยี่ห้อ ชื่อรุ่นที่สะกดตามแบบที่บริษัทประมูลใช้ และเกรดหรือรหัสรุ่นย่อย POST /api/v1/images/resolve ใช้งานได้ฟรีและให้ผลลัพธ์เหมือนเดิมทุกครั้ง โดยจะดึงคำที่ระบุปี สี และมุมมองออกจากวลี ค้นหาในแคตตาล็อกด้วยส่วนที่เหลือ แล้วส่งคืนพารามิเตอร์ที่แน่นอนพร้อมค่าความเชื่อมั่นที่คุณนำไปใช้ตัดสินใจได้
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"}'{
"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…"
}รถถูกต้อง (Toyota Voxy ปี 2019) แต่ระดับความเชื่อมั่นเป็น low เพราะ "ZS" เป็นเกรดที่แค็ตตาล็อกไม่รู้จัก จึงต้องจับคู่โดยเลี่ยงส่วนนั้น ในการนำเข้าแบบกลุ่ม ให้ถือว่า high เสร็จเรียบร้อย และส่ง medium กับ low ให้คนตรวจสอบพร้อมรายการ candidates เมื่อชีตมีปีและยี่ห้ออยู่ในคอลัมน์ของตัวเองแล้ว ให้ส่งเป็นฟิลด์ year และ make และใส่เฉพาะรุ่นใน query การจับคู่จะแม่นยำขึ้นมาก วลีที่ไม่มีคำเกี่ยวกับรถจะได้ 400 และยี่ห้อที่ไม่มีรุ่นตรงกันจะได้ 404 ซึ่งแสดงรายการปีของยี่ห้อนั้น เพื่อให้คุณถามหารุ่นได้
ขั้นตอนที่ 2: เก็บ vehicle id ไว้ในเรคคอร์ด
ไม่ว่าคุณจะได้ข้อมูลมาด้วยวิธีใด ให้จัดเก็บ vehicle.id (หรือ params.vehicle_id) ไว้ในเรคคอร์ดสต็อกเป็นคอลัมน์สตริงธรรมดา ค่านี้คงที่แน่นอนและถาวร: รถคันเดียวกันจะมี id เดียวกันในทุกการ deploy และหลังการเผยแพร่แค็ตตาล็อกทุกครั้ง จึงใช้เป็น foreign key ได้อย่างปลอดภัย จากนั้นทุกคำขอภาพจะเป็น vehicle=veh_… ซึ่งสะกดผิดไม่ได้ และแม้ผู้ผลิตจะเปลี่ยนชื่อยี่ห้อหรือแหล่งข้อมูลจะจัดหมวดหมู่ใหม่ URL ที่จัดเก็บไว้ก็จะไม่เสีย
ขั้นตอนที่ 3: มุมมองหนึ่งสำหรับหน้ารายการ อีกมุมมองหนึ่งสำหรับหน้ารายละเอียด
รายการสต็อกมีลักษณะกว้างและเตี้ย มุมมองด้านข้างตรงในกรอบ 2:1 จึงเป็นตัวเลือกปกติ รถทุกคันหันไปทางเดียวกันและตั้งอยู่บนเส้นฐานเดียวกัน trim=1&padding=6 จะครอปให้พอดีกับตัวรถก่อนปรับขนาด ทำให้ Hilux และ Yaris เต็มแถวในลักษณะเดียวกัน ส่วน fit=contain คงขนาดแคนวาสไว้ที่ 640×320 พอดีพร้อมขอบโปร่งใส หน้ารายละเอียดใช้ front-3-4 ที่ 1024 และทั้งสองใช้แคชร่วมกัน สีที่คุณไม่ได้ระบุจะเป็นสีเงินทั้งสองแบบ
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ขั้นตอนที่ 4: แสดงภาพใน CRM ผ่าน signed URL
CRM ทำงานในเบราว์เซอร์ และเบราว์เซอร์ต้องไม่ถือ API key โดยเด็ดขาด เมื่อหน้าจอแสดงรายการสต็อกหนึ่งหน้า เซิร์ฟเวอร์จะสร้าง signed URL หนึ่งรายการต่อหนึ่งระเบียนด้วย POST /api/v1/image-urls (สูงสุดห้าสิบรายการต่อการเรียกหนึ่งครั้ง โดยภาพของแต่ละ URL นับเป็นภาพรถหนึ่งภาพของเดือน) แล้วหน้าเว็บจะโหลดภาพเหล่านั้นเหมือนภาพทั่วไป สำหรับระเบียนที่อยู่ในสต็อกนานหลายเดือน มีการตั้งค่าสำคัญสองอย่าง:
ttl_seconds: 604800พร้อมrenew: true: URL จะยังใช้งานได้หลัง TTL เจ็ดวัน และการต่ออายุจะนับภาพหนึ่งครั้งในเดือนที่เกิดการต่ออายุ และไม่นับเพิ่มหากนับไปแล้วในเดือนนั้น เดือนที่ไม่มีใครดูรถจะไม่นับเลย- ใช้
Idempotency-Keyหนึ่งค่าต่อการซิงก์หนึ่งหน้า คำขอที่ลองใหม่จะได้รับการตอบกลับครั้งแรกซ้ำ และไม่มีการสร้างสิ่งใดซ้ำสองครั้ง
จำกัดคีย์ที่ใช้สร้าง URL ให้ใช้ได้เฉพาะ origin ของ CRM ในแดชบอร์ด แล้ว URL ที่รั่วไหลไปยังเว็บไซต์อื่นจะตอบกลับด้วย 403 การเพิกถอนคีย์จะทำให้ URL ทั้งหมดที่คีย์นั้นสร้างใช้งานไม่ได้ หากภาพรถยนต์ของแพ็กเกจในเดือนนั้นถูกใช้หมดแล้ว การต่ออายุจะตอบกลับด้วย 402 และ URL เดิมจะกลับมาใช้งานได้เมื่อโควตารีเซ็ตหรือเมื่ออัปเกรดแพ็กเกจ ดูวงจรการทำงานทั้งหมดได้ในเอกสาร signed URL
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 และ MCP
# 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, … })และclient.createImageUrls(…)ตามที่แสดงด้านบน - MCP:
decode_vin,resolve_vehicle,get_car_imageและcreate_car_image_urlsอยู่ในชุดเครื่องมือหลัก ผู้ช่วย AI ที่มีข้อมูลระบบสต็อกอยู่ในบริบทจึงตอบคำขอ "รูปของสต็อก 4471" ได้จาก VIN ในระเบียน ดูวิธีตั้งค่าได้ที่หน้า MCP ส่วนฟิลด์และข้อผิดพลาดของตัวถอดรหัสอยู่ในเอกสาร VIN
คำถามที่พบบ่อย
- การมีภาพถ่ายในทุกรายการรถในสต็อกมีค่าใช้จ่ายเท่าไร
- การถอดรหัส VIN ไม่มีค่าใช้จ่าย รถแต่ละคันในแต่ละสีและมุมมองนับเป็นภาพรถหนึ่งภาพ โดยนับหนึ่งครั้งต่อเดือนไม่ว่าจะแสดงบ่อยเพียงใดและในขนาดใด การตรวจสอบซ้ำด้วย If-None-Match ไม่มีค่าใช้จ่าย signed URL จะนับภาพเมื่อสร้างขึ้น และหากใช้ renew: true จะนับอีกหนึ่งครั้งในแต่ละเดือนถัดไปที่มีการเปิด URL นั้น กลุ่มดีลเลอร์ที่มีรถในสต็อกหลายพันคันจะแสดงภาพรถหลายพันภาพต่อเดือน ดังนั้นควรเลือกแพ็กเกจให้เหมาะกับจำนวนรถที่แสดงอยู่
- ถอดรหัส VIN ได้ แต่ vehicle เป็น null แล้วควรทำอย่างไรต่อ
- ตัวถอดรหัสระบุยี่ห้อ รุ่น และปีได้ แต่แค็ตตาล็อกไม่มีรายการสำหรับชุดข้อมูลนั้น เช่น รถพ่วง แชสซีรถเพื่อการพาณิชย์บางรุ่น หรือชื่อรุ่นที่แหล่งข้อมูลยังไม่ได้บันทึก ให้แสดงฟิลด์ที่ถอดรหัสได้ ค้นหาในแค็ตตาล็อกด้วย GET /api/v1/vehicles?q= เผื่อการสะกดต่างกัน และส่งคำขอรถคันนั้นบนบอร์ดคำขอ โดย POST /api/v1/requests จะโหวตให้คำขอที่เปิดอยู่แทนการสร้างคำขอซ้ำ
- การถอดรหัส VIN ครอบคลุมรถนำเข้าและรถที่ไม่เคยจำหน่ายในสหรัฐฯ หรือไม่
- ตัวถอดรหัสใช้ข้อมูล vPIC ของ NHTSA ดังนั้น VIN จากผู้ผลิตที่ยื่นข้อมูลกับ NHTSA จะถอดรหัสได้ครบถ้วน รถที่ไม่เคยได้รับการรับรองสำหรับตลาดสหรัฐฯ มักถอดรหัสได้เพียงผู้ผลิตและปีโดยไม่มีรุ่น และบางคันถอดรหัสไม่ได้เลย สำหรับรถในสต็อกกลุ่มนี้ ให้ระบุรถจากเอกสารจดทะเบียนแทน เพราะแค็ตตาล็อกเองครอบคลุมรถทั่วโลกตั้งแต่ปี 1990 และมีรุ่นสำหรับตลาดในประเทศญี่ปุ่น เช่น Toyota Voxy ด้วย
- ภาพเรนเดอร์แสดงรุ่นย่อย (trim) ตามที่ระบุในเรคคอร์ดหรือไม่
- ไม่ แคตตาล็อกใช้ยี่ห้อ รุ่น และปีเป็นคีย์ ดังนั้น EX-V6 คูเป้และ LX ซีดานจะเรนเดอร์ออกมาเป็น Accord ปี 2003 คันเดียวกัน ให้เก็บ trim และ body_class จากผลการถอดรหัสไว้เป็นข้อความข้างภาพ และอย่าระบุว่าภาพเรนเดอร์คือรถคันนั้นโดยเฉพาะ
- เว็บไซต์ของดีลเลอร์ใช้ URL เดียวกับ CRM ได้หรือไม่
- เมื่อสร้างจากคีย์ที่ระบุเว็บไซต์นั้นไว้ในรายการ origin ที่อนุญาต URL ที่เบราว์เซอร์โหลดจากเว็บไซต์อื่นจะตอบกลับ 403 origin_not_allowed ส่วนการโหลดที่ไม่มี Referer เช่น จากโปรแกรมอีเมล จะผ่านได้ตามปกติ CRM และเว็บไซต์สามารถใช้คีย์และชุด URL ร่วมกันได้ หรือแยกใช้คนละคีย์เพื่อให้เพิกถอนฝั่งใดฝั่งหนึ่งได้โดยไม่กระทบอีกฝั่ง