التوثيق

تتعرّف واجهة VisionPlate البرمجية (REST) على لوحات المركبات العراقية في صور المركبات. للاطلاع على المخطط الكامل والتفاعلي، راجع مرجع الواجهة البرمجية (بالإنجليزية).

البدء

أنشئ حسابًا واشترِ رصيدًا ثم أنشئ مفتاح API من حسابك. يحتاج كل طلب إلى المفتاح في الترويسة X-Api-Key. تبدو المفاتيح بهذا الشكل vp_live_… وتُعرض مرة واحدة فقط عند إنشائها، لذا احفظ مفتاحك بأمان واستخدمه من جهة الخادم فقط وليس في شيفرة المتصفح. أرسل الصورة بصيغة multipart/form-data.

cURL
curl -X POST https://your-domain/api/v1/recognize \
  -H "X-Api-Key: vp_live_your_key" \
  -F "image=@car.jpg"

التعرّف على لوحة

يستقبل POST /api/v1/recognize حقل ملف واحدًا باسم image (JPEG أو PNG أو WebP أو BMP). أضف ?includeCrop=true لتحصل أيضًا على صورة اللوحة المقتطعة بصيغة PNG مرمّزة بـ base64. إذا لم يُعثر على لوحة، ينجح الطلب مع "detected": false ويستهلك رصيدًا واحدًا.

200 OK
{
  "success": true,
  "data": {
    "id": "0199a0c4-6f1e-7c2b-9d3a-5b8f1e2d4c6a",
    "detected": true,
    "plateNumber": "12 A 34567",
    "province": "baghdad",
    "provinceCode": 1,
    "vehicleType": "private",
    "vehicleCode": 1,
    "plateType": "New",
    "boundingBox": { "x": 412, "y": 530, "width": 220, "height": 64 },
    "fileName": "car.jpg",
    "processingMs": 84.3,
    "createdAtUtc": "2026-09-30T10:15:00Z",
    "croppedPlatePng": null,
    "timings": {
      "uploadMs": 412.5, "validationMs": 1.2, "queueMs": 0.1,
      "localizationMs": 61.8, "recognitionMs": 22.4, "serverMs": 503.9
    }
  },
  "error": null,
  "meta": null
}

حقول الاستجابة

الحقل الوصف
id المعرّف الفريد لهذه العملية في سجلك.
detected تكون false إذا لم يُعثر على لوحة في الصورة.
plateNumber نص اللوحة المقروء.
province / provinceCode اسم المحافظة ورمزها الرقمي، عند إمكانية قراءتهما.
vehicleType / vehicleCode فئة المركبة (مثل: خصوصي، عمومي، حمل) ورمزها الرقمي.
plateType تصميم اللوحة: Kurdistan (old) أو Nineties أو Germany أو New.
boundingBox موقع اللوحة في الصورة الأصلية بالبكسل.
processingMs زمن معالجة هذه الصورة.
croppedPlatePng صورة اللوحة بصيغة PNG مرمّزة بـ base64، تُرجع فقط مع includeCrop=true.
timings توزيع الوقت بالملّي ثانية: الرفع، والفحص، والانتظار، وتحديد اللوحة وقراءتها، والإجمالي على الخادم. يُرسل أيضًا في الترويسة القياسية Server-Timing.

التعرّف المجمّع

يقبل POST /api/v1/recognize/batch حتى 10 ملفات، كلٌّ منها في حقل باسم images. لكل عنصر في الاستجابة مؤشر success خاص به. الملفات التي لا تجتاز التحقق تُرجع خطأً لذلك العنصر فقط ولا تستهلك رصيدًا.

cURL
curl -X POST https://your-domain/api/v1/recognize/batch \
  -H "X-Api-Key: vp_live_your_key" \
  -F "images=@car1.jpg" \
  -F "images=@car2.jpg"

السجل

يُرجع GET /api/v1/recognitions عمليات التعرّف السابقة لمفتاحك، الأحدث أولًا. يمكنك التصفية بـ plate (تطابق جزئي)، وfrom وto (بتوقيت UTC وبصيغة ISO-8601)، والتنقل بين الصفحات بـ page وpageSize (بحد أقصى 100). تُرجع معلومات الصفحات في meta. ولجلب عنصر واحد استخدم GET /api/v1/recognitions/{id}.

cURL
curl "https://your-domain/api/v1/recognitions?page=1&pageSize=20&plate=12345" \
  -H "X-Api-Key: vp_live_your_key"

الاستهلاك والحدود

تُدفع الطلبات من الرصيد المسبق الدفع لحسابك: كل صورة يتم التعرّف عليها تستهلك رصيدًا واحدًا، وتتشارك جميع مفاتيحك الرصيد نفسه. اشترِ باقات الرصيد من حسابك. يعرض GET /api/v1/usage رصيدك واستهلاك هذا المفتاح خلال الشهر، وتتضمن استجابات التعرّف الترويسة X-Credits-Remaining. ولكل مفتاح أيضًا حدٌّ لعدد الطلبات في الدقيقة (429 rate_limited مع الترويسة Retry-After). وعند نفاد الرصيد تحصل على 402 insufficient_credits.

الأخطاء

تستخدم جميع الأخطاء البنية نفسها. اعتمد على الحقل code في شيفرتك؛ أما الرسالة فهي موجّهة للقارئ وقد تتغير.

{
  "success": false,
  "data": null,
  "error": { "code": "insufficient_credits", "message": "Not enough credits for this request..." },
  "meta": null
}
الحالة الرمز المعنى
400 missing_image لم يُرسل ملف في الحقل المتوقع.
400 invalid_image الملف ليس صورة صالحة.
400 unsupported_format استخدم JPEG أو PNG أو WebP أو BMP.
400 image_too_large حجم الملف أو عدد البكسلات يتجاوز الحد.
400 batch_too_large عدد الملفات يتجاوز حد الدفعة.
401 unauthorized مفتاح API مفقود أو غير معروف أو ملغى.
404 not_found المورد غير موجود أو لا يخصّك.
429 rate_limited تم تجاوز الحد في الدقيقة؛ راجع Retry-After.
402 insufficient_credits نفد الرصيد؛ اشترِ باقة.
500 server_error خطأ غير متوقع. يمكن إعادة المحاولة بأمان.

أمثلة برمجية

C#
using var http = new HttpClient { BaseAddress = new Uri("https://your-domain/") };
http.DefaultRequestHeaders.Add("X-Api-Key", "vp_live_your_key");

using var form = new MultipartFormDataContent();
var file = new ByteArrayContent(await File.ReadAllBytesAsync("car.jpg"));
file.Headers.ContentType = new("image/jpeg");
form.Add(file, "image", "car.jpg");

var response = await http.PostAsync("api/v1/recognize", form);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
JavaScript (من جهة الخادم / Node)
const form = new FormData();
form.append("image", fileInput.files[0]);

const res = await fetch("https://your-domain/api/v1/recognize", {
  method: "POST",
  headers: { "X-Api-Key": "vp_live_your_key" },
  body: form,
});
const { success, data, error } = await res.json();
console.log(success ? data.plateNumber : error.message);