Car Image API

حالات الاستخدام · تأجير السيارات

صور سيارات لصفحات أساطيل التأجير

اعرضوا كل فئات التأجير بالطريقة نفسها: طراز تمثيلي واحد لكل فئة، وتأطير متطابق باستخدام trim وpadding وfit، ولون طلاء واحد محدد، وعناوين URL تخزّنونها مؤقتًا.

دليل تنفيذ مكتوب وفق سلوك الـ API الموثَّق؛ ولا يذكر اسم أي عميل. نُشر في .

المشكلة: أنت تؤجّر فئة، لا سيارة بعينها

يحجز عميل التأجير فئةً، مثل سيارة مدمجة أو SUV متوسطة الحجم أو ميني فان، ثم ينطلق بأي سيارة من تلك الفئة متاحة في الموقف. ومع ذلك تحتاج صفحة الحجز إلى صورة لكل فئة، والعُرف السائد هو طراز تمثيلي واحد مع عبارة "أو ما يماثلها".

عادةً ما تأتي هذه الصور من أي مكان أمكن العثور عليها فيه: صورة صحفية هنا، وصورة من وكيل هناك، بزوايا مختلفة وخلفيات مختلفة، وسيارات تملأ بطاقاتها بأشكال متفاوتة. والشبكة التي تُجمَع بهذه الطريقة تبدو مُركَّبة من أجزاء متفرقة. أما ما تحتاجه صفحة الأسطول فهو العكس تمامًا: أن تُعرض كل فئة بالطريقة نفسها، بحيث لا يتغير من بطاقة إلى أخرى سوى السيارة.

كيف يبدو التكامل

  • طراز تمثيلي واحد لكل فئة، يُحفظ كمعرّف مركبة من الكتالوج، مع عبارة "أو ما يماثلها" في التسمية، لا في الصورة أبدًا.
  • شكل طلب واحد لكل بطاقة: نفس زاوية العرض والإطار والملاءمة والقص والحشو والطلاء والخلفية والتنسيق.
  • صورتان لكل فئة كحد أقصى: البطاقة في الشبكة والصورة الرئيسية في صفحة الفئة.
  • مخزّنة مؤقتًا، لأن شبكة العرض هي نفسها لكل زائر: ملفات على CDN الخاص بكم، أو عناوين URL موقّعة تُصدَر مرة واحدة ويُعاد استخدامها.

الخطوة 1: اختر طرازًا ممثِّلًا لكل فئة، بواسطة المعرّف

اختاروا الطراز الذي تُباع تحته كل فئة وابحثوا عن سنة طرازه الحالية. GET /api/v1/vehicles?make=&model= مجاني وعام ويسرد كل سنوات الطراز الواحد، ولكل منها معرّف المركبة الثابت الذي ستخزّنونه؛ ويؤدي POST /api/v1/images/resolve الأمر نفسه انطلاقًا من عبارة مثل "2026 toyota rav4".

معرّف سنة طراز واحدة
# one model's years, each with its vehicle id (free, public)
curl -s "https://carimage.dev/api/v1/vehicles?make=toyota&model=rav4" | jq -c '.data.vehicles[] | select(.year == 2026)'
# {"year":2026,"id":"veh_e5w75c93f6cvk"}
fleet.ts
// One representative model per class: its current model year, by catalog id.
// "or similar" lives in the label; the picture never promises the car on the lot.
export const CLASS_IMAGES = {
  compact:        { vehicle: "veh_fy7r2yvwt4p1v", label: "Toyota Corolla or similar" },    // 2026 Toyota Corolla
  "midsize-suv":  { vehicle: "veh_e5w75c93f6cvk", label: "Toyota RAV4 or similar" },       // 2026 Toyota RAV4
  "fullsize-suv": { vehicle: "veh_9mzh9ejqjye43", label: "Chevrolet Tahoe or similar" },   // 2026 Chevrolet Tahoe
  minivan:        { vehicle: "veh_9jck7rrybf35p", label: "Chrysler Pacifica or similar" }, // 2026 Chrysler Pacifica
};

لا تتغير المعرّفات أبدًا، لذا فإن هذه الخريطة هي المكان الوحيد الذي يتأثر بأي تغيير في الأسطول: عندما تنتقل الفئة المتوسطة إلى طراز آخر، أو إلى سنة الطراز التالية، استبدل معرّفًا واحدًا وستتبعه كل بطاقة وصورة رئيسية ورسالة بريد إلكتروني تقرأ من الخريطة.

الخطوة 2: صيغة طلب واحدة لكل الفئات

تُؤطَّر زوايا الكاميرا البالغ عددها 8 بشكل متطابق لكل مركبة في الكتالوج، وهذا ما يجعل الشبكة متناسقة. أما بقية البطاقة فهي مجموعة قليلة من المعاملات تُحدَّد مرة واحدة:

  • view=side للبطاقات: تتجه كل سيارة في الاتجاه نفسه وعلى خط القاعدة نفسه. لكل زاوية من الجانب الأيسر نظير -right (side-right)، بحيث تتجه البطاقات نحو داخل التصميم. وتستخدم صفحة الفئة front-3-4، الزاوية الرئيسية.
  • w=640&h=320&fit=contain: مقاس 640×320 تمامًا لكل فئة، مع ظهور السيارة كاملة. ويؤكد الترويسان X-Image-Width وX-Image-Height في الاستجابة أبعاد اللوحة.
  • trim=1&padding=6: قصّ الصورة حول السيارة قبل ملاءمتها، مع هامش يساوي 6% من ضلعها الأطول، بحيث تملأ Corolla وTahoe بطاقتيهما بالطريقة نفسها بدل أن تطفوا في الإطار المربع الأصلي.
  • يدمج background=f4f4f4 البطاقة في اللون الرمادي الخاص بالشبكة. احذفه للإبقاء على الخلفية الشفافة وإظهار لون البطاقة من خلالها.
  • format=webp للملفات المخزّنة؛ وformat=auto لعناوين URL الموقّعة، إذ يقدّم WebP أو PNG حسب كل متصفح.
بطاقة وصورة رئيسية لفئة واحدة
# the class card: the same box, view, crop, paint and backdrop for every class
curl --fail-with-body -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  "https://carimage.dev/api/v1/images/car?vehicle=veh_e5w75c93f6cvk&view=side&color=white&w=640&h=320&fit=contain&trim=1&padding=6&background=f4f4f4&format=webp" \
  -o midsize-suv-card.webp

# the class page's hero: the three-quarter view, the full width the API delivers
curl --fail-with-body -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  "https://carimage.dev/api/v1/images/car?vehicle=veh_e5w75c93f6cvk&view=front-3-4&color=white&w=1024&format=webp" \
  -o midsize-suv-hero.webp

الخطوة 3: لون طلاء واحد محدد للشبكة كلها

الإعدادات المسبقة البالغ عددها 15 هي ألوان طلاء مسمّاة: white, black, gray, silver, blue, red, green, brown, beige, tan, orange, yellow, gold, burgundy, purple. اللون الافتراضي هو silver، ويُقرأ grey على أنه gray. اختر لونًا واحدًا لجميع الفئات لتبدو البطاقات مجموعة متناسقة؛ ويظهر white أعلاه. يحتفظ كل إعداد مسبق بعيّنة طلائه الخاصة بدلًا من لون CSS الذي يحمل الاسم نفسه (red هو #b3151b)، وكل لون طلاء، بما في ذلك رمز hex، هو إعادة تلوين لصورة محايدة واحدة، لذا تبقى تكلفته 1 رصيد.

الخطوة 4: خزّن الملفات أو عناوين URL مؤقتًا

شبكة الفئات متطابقة لكل زائر، لذا ينبغي ألا تكلّف شيئًا يُذكر لكل زيارة. هناك طريقتان لتحقيق ذلك:

  • خزّن الملفات. اجلب كل بطاقة وصورة رئيسية مرة واحدة باستخدام GET /api/v1/images/car وقدّمها من CDN الخاص بك مثل أي أصل آخر؛ تتيح الخطة المدفوعة الاحتفاظ بنسخ على خوادمك الخاصة لخدمة منتجك، وتحتفظ هذه النسخ بترخيصها بعد انتهاء الخطة. احتفظ بـETag لكل ملف: إعادة التحقق الليلية باستخدام If-None-Match تُرجع 304 ولا تكلّف شيئًا. بالنسبة للأسطول أعلاه، يبلغ ذلك 8 أرصدة، لمرة واحدة فقط.
  • أو أصدروا عناوين URL موقّعة مرة واحدة وأعيدوا استخدامها. يقبل POST /api/v1/image-urls ما يصل إلى 50 صورة في كل استدعاء ويُرجع عناوين URL خالية من المفتاح تظل صالحة حتى 7 يومًا. عنوان URL ذو الاستخدامات غير المحدودة قابل للتخزين المؤقت العام خلال مدة صلاحيته، لذا عندما يحمّل كل زائر عنوان URL نفسه، تأتي التحميلات المتكررة من CDN مجانًا. أضيفوا renew: true ليظل عنوان URL المخزَّن صالحًا بعد انتهاء مدته، بتكلفة وحدة رصيد واحدة لكل صورة عن كل أسبوع إضافي يُحمَّل فيه: بحد أقصى 8 وحدات رصيد أسبوعيًا للأسطول المذكور أعلاه.

قيّد المفتاح الذي يُصدر عناوين URL على نطاق الحجز الخاص بك من لوحة التحكم، وعندها سيُرجع أي عنوان URL منسوخ إلى موقع آخر الرمز 403.

عناوين URL الخاصة بالشبكة، مُنشأة مرة واحدة، باستخدام TypeScript SDK
import { CarImageClient, type ImageParams } from "@meterapp/car-image-sdk";
import { CLASS_IMAGES } from "./fleet";

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

// Framed once, for every class.
const card = (vehicle: string): ImageParams => ({
  vehicle, view: "side", color: "white", width: 640, height: 320,
  fit: "contain", trim: true, padding: 6, background: "#f4f4f4", format: "auto",
});
const hero = (vehicle: string): ImageParams => ({ vehicle, view: "front-3-4", color: "white", width: 1024, format: "auto" });

// Every visitor sees the same grid: mint the URLs once and serve the stored ones.
// renew keeps each URL working past its 7-day lifetime, one credit per image
// for each further week in which it is loaded.
const classes = Object.entries(CLASS_IMAGES);
const { data } = await client.createImageUrls(
  classes.flatMap(([, entry]) => [card(entry.vehicle), hero(entry.vehicle)]),
  { ttlSeconds: 604800, renew: true, idempotencyKey: "class-grid-2026-10" }
);
await saveClassImages(
  classes.map(([key], index) => ({ key, card: data[2 * index].url, hero: data[2 * index + 1].url, renewsUntil: data[2 * index].renews_until }))
);

الخطوة 5: تأكيد الحجز

تعرض رسالة التأكيد عبر البريد الإلكتروني الفئة التي حُجزت، وتُفتح الرسائل متى ما وصل إليها المستأجر. أنشئ صورتها كعنوان URL متجدد: ttl_seconds عند الحد الأقصى البالغ 7 يومًا، وrenew: true، وrenew_days تمتد إلى ما بعد تاريخ الإرجاع. الأسابيع التي لا يفتح فيها أحد الرسالة لا تكلّف شيئًا، وبعد انتهاء الإيجار يتوقف العنوان عن التجدد. يجعل Idempotency-Key لكل حجز إعادةَ محاولة الإرسال تعيد العنوان الأول بدلًا من إنشاء عنوان ثانٍ، وتخزين العنوان مع الحجز يتيح لكل إعادة إرسال لاحقة أن تعيد استخدامه. تعمل رسائلنا الخاصة بدورة حياة الحساب بهذه الطريقة؛ وتشرح قصة البريد الإلكتروني الآلية وكود HTML.

URL متجدّد لتأكيد حجز واحد
// The booking confirmation: opened today, again at the counter, maybe never.
const { data: [classImage] } = await client.createImageUrls(card(booking.classVehicle), {
  ttlSeconds: 604800,
  renew: true,
  // A week past the return date, and no renewals after it (365 days at most).
  renewDays: Math.min(daysUntil(booking.returnDate) + 7, 365),
  // A retried send replays the first URL instead of minting a second one.
  idempotencyKey: `booking:${booking.id}:class`,
});
booking.classImageUrl = classImage.url; // later resends reuse it

CLI وSDK وMCP

  • CLI: يكتب npx @meterapp/car-image get --vehicle veh_… --view side --width 640 --height 320 --fit contain --trim --padding 6 --out card.webp بطاقة إلى ملف؛ ويُنشئ car-image url --batch classes.json --renew دفعة من عناوين URL.
  • SDK: client.vehicles({ make, model }) للمعرّفات، وclient.getImage(…) للملفات، وclient.createImageUrls(…) لعناوين URL.
  • MCP: تتيح resolve_vehicle وcreate_car_image_urls للمساعد إعداد بطاقة فئة انطلاقًا من "سيارة SUV متوسطة الحجم، RAV4 أو ما يماثلها". خطوات الإعداد متوفرة في صفحة MCP.

الأسئلة الشائعة

هل يمكن أن تعرض البطاقة السيارة نفسها التي سيستلمها المستأجر؟
لا، ولا ينبغي له أن يحاول. تُؤجَّر الفئة بصيغة “أو ما يماثلها”، والصورة المولَّدة تُظهر شركة مصنّعة وطرازًا وسنة من الكتالوج، لا سيارة موجودة في ساحتك. اعرض طرازًا تمثيليًا واحدًا مع عبارة “أو ما يماثلها” في التسمية. وبمجرد تخصيص سيارة محددة عند المكتب، يمكن فك رموز VIN الخاص بها مجانًا للوصول إلى مركبتها في الكتالوج إن أردت عرض ذلك الطراز بدلًا منه.
لماذا لا تظهر السيارات في الشبكة بمقاييسها الحقيقية؟
لأن trim يقتص كل صورة حول السيارة، ويملأ fit=contain البطاقة بها، فتملأ سيارة مدمجة وسيارة SUV كاملة الحجم بطاقتيهما بالطريقة نفسها. وهذا ما يحافظ على ترتيب الشبكة. عبّروا عن الحجم بالكلمات: اسم الفئة وعدد المقاعد والحقائب.
كم تكلّف شبكة الفئات؟
يكلّف أسطول من 4 فئة، لكلٍّ منها بطاقة وصورة رئيسية، 8 أرصدة. خزّنوا الملفات على CDN الخاصة بكم وتكون هذه هي الفاتورة كاملة، مع إعادة تحقق مجانية عبر ETag. أما إذا قدّمتم عناوين URL موقّعة متجددة بدلاً من ذلك، فلا تتجاوز التكلفة 8 أرصدة أسبوعيًا، وفقط في الأسابيع التي تُفتح فيها الصفحات.
أي لون طلاء ينبغي استخدامه في شبكة الفئات؟
لون مُعدّ مسبقًا واحد لكل الفئات، لتبدو البطاقات مجموعة متناسقة. الألوان المُعدّة مسبقًا وعددها 15 هي white, black, gray, silver, blue, red, green, brown, beige, tan, orange, yellow, gold, burgundy, purple، واللون الافتراضي هو silver؛ ويصلح أي لون hex أيضًا بالسعر نفسه. يحصل المستأجر على اللون الموجود في الساحة، وهو ما لم تَعِد به البطاقة أصلًا.
ماذا لو لم يكن طراز إحدى الفئات موجودًا في الكتالوج؟
المركبة غير الموجودة تُرجع 404 مع اقتراحات: أقرب مركبات الكتالوج، ولكلٍّ منها معرّفها. استخدم إحداها، أو اطلب المركبة على لوحة الطلبات العامة. الكتالوج مفتوح المصدر.

تابعوا القراءة

قصة عميل · أدوات المطورينكيفية تضمين صور السيارات في البريد الإلكتروني بروابط موقّعة لا تتعطل أبدًاتتضمّن رسائل دورة حياة العملاء الخاصة بنا أول صورة مُصيَّرة لكل عميل بالضبط، في صورة عنوان URL موقّع حيّ يجدّد نفسه لمدة عام. إليك طريقة عمل ذلك وكيفية تطبيقه بنفسك.