مفاهيم الـ API
كيف تنطبق الصلاحيات والفروع على طلبات الـ API، والصفحات والتصفية، والتواريخ والتوقيت، واللغات، والأخطاء، وحدود الطلبات، وإعادة المحاولة، والإصدارات.
القواعد التي يتبعها كل طلب إلى واجهة مهنارو. اقرأ البدء مع واجهة API أولاً إن لم ترسل طلباً بعد.
المصادقة والصلاحيات
- المفتاح أو الرمز شخص. رمز الدخول هو من دخل؛ ومفتاح API يعمل باسم الشخص المختار في يعمل باسم عند إنشائه. كل طلب يُفحص كأن هذا الشخص فعله على الشاشات: أولاً ترخيص الشركة (هل الوحدة مشمولة، وهل الترخيص فعّال)، ثم صلاحية دوره (مثل
employees.view)، ثم نطاقه (الفروع أو الأقسام أو الموظفون الذين أُعطي الدور عليهم). - المفتاح يضيّق صلاحيات صاحبه فقط ولا يوسّعها أبداً: الصلاحيات (قراءة = GET، كتابة = POST، تحديث = PUT وPATCH، حذف = DELETE)، وعناوين IP المسموحة، وتاريخ تنتهي في. المفاتيح لا تنشئ مفاتيح أخرى ولا تدير الـ webhooks؛ هذا يحتاج رمز دخول شخص.
- صلاحية كل طلب مذكورة في مرجع الـ API. الطلب بلا صلاحية مذكورة مفتوح لأي مستخدم نشط في الشركة، ويعرض عندها ما يخصه فقط (إجازاتي، كشوف راتبي) أو ما يحق له رؤيته.
- كلمة المرور المؤقتة أو المنتهية تمنع كل شيء ما عدا
GET /api/v1/app/meوPUT /api/v1/app/me/passwordوDELETE /api/v1/app/token؛ أي طلب آخر يرد بـ403و"code": "password_change_required". - طلبات المنصة (
/api/v1/platform/…و/mcp/platform) لفريق مهنارو فقط وتحتاج مفتاح مدير منصة. مفاتيح الشركات ورموزها لا تعمل عليها، ومفاتيح المنصة لا تعمل على طلبات الشركات.
الفروع والعزل
قد يكون للشركة عدة فروع، وكل فرع مساحة عمل منفصلة. كل طلب /api/v1/app/companies/{company}/… يقرأ ويكتب في فرع واحد:
- الفرع المحدد لهذا الطلب، بالمعامل
branchأو الترويسةX-Branch(رقم فرع، أوallلكل الفروع التي يحق لك العمل فيها)؛ - وإلا آخر فرع انتقل إليه الشخص (
PUT /api/v1/app/companies/{company}/branchمع{"branch": 77}أو{"branch": "all"}، وGETعلى نفس المسار لقراءته)؛ - وإلا فرع الشخص نفسه.
الفرع الذي لا يستطيع الشخص العمل فيه يرد بـ 403 و"code": "branch_forbidden". سجلات الفروع الأخرى لا تُرجع: رقم من فرع آخر يرد بـ 404، أو 422 مع رسالة تذكر فرعه عندما ترسله في حقل نموذج. والبيانات لا تنتقل أبداً من شركة إلى أخرى.
في الطلب الأول من البدء أعطت قائمة الموظفين total: 8 في فرع المقر - بغداد، وtotal: 10 مع X-Branch: all.
الصفحات والتصفية والترتيب
- الصفحات: القوائم مقسمة إلى صفحات. اطلب صفحة بـ
?page=2. كثير من القوائم تقبلper_page(عادة حتى 100)، والباقي بحجم صفحة ثابت. - معلومات الصفحة في
meta:current_page(أوpageفي بعض القوائم)، وlast_page، وtotal. استمر في الطلب حتى تساويcurrent_pageقيمةlast_page. - التصفية بمعاملات الاستعلام، مذكورة لكل طلب في المرجع. الأسماء الشائعة:
searchأوq(نص حر)، وstatus، وemployeeأوemployee_id، وbranch_id، وtype، والتاريخانfromوto. - الترتيب ثابت لكل قائمة ومذكور في وصف الطلب (مثلاً الموظفون حسب الرقم الوظيفي، والإجازات حسب تاريخ البداية، ومسيرات الرواتب الأحدث أولاً). لا يوجد معامل
sortعام.
"meta": {"current_page": 1, "last_page": 4, "total": 8}
التواريخ والأوقات والتوقيت
- التواريخ بالشكل
YYYY-MM-DD("hire_date": "2026-03-01")، والأشهرYYYY-MM(GET …/payroll/2026-10). - الأوقات بساعة الشركة، أي المنطقة الزمنية المحددة للشركة (Asia/Baghdad ما لم تختر شركتك غيرها؛ وهي في
timezoneلكل فرع). البصمة في 08:00 ببغداد تظهر08:00في الرد، مهما كان توقيت خادمك. - التاريخ مع الوقت في الردود بصيغة ISO 8601 مع فرق التوقيت، مثل
2026-11-02T22:40:00+03:00. - عندما ترسل تاريخاً مع وقت، أضف فرق التوقيت (
2026-11-02T08:00:00+03:00) ومهنارو يحوّله إلى ساعة الشركة. بدونه يُقرأ على أنه بساعة الشركة.
اللغات
- الرسائل والأخطاء بالإنجليزية. أرسل
Accept-Language: arللعربية. - الأسماء المدخلة بلغتين ترجع باللغتين:
"name": {"en": "Ali Hassan", "ar": "علي حسن"}. وعند الإنشاء أو التعديل أرسلها بنفس الشكل{"en": "…", "ar": "…"}.
نفس الطلب الخاطئ بالعربية:
{"message": "اختر قيمة من القائمة.", "errors": {"status": ["اختر قيمة من القائمة."]}}
الأخطاء
الأخطاء دائماً JSON فيها message. كثير منها يضيف code يستطيع برنامجك التصرف بناءً عليه، وأخطاء التحقق تضيف errors، قائمة رسائل لكل حقل:
{
"message": "The selected status is invalid. (and 1 more error)",
"errors": {
"status": ["The selected status is invalid."],
"from": ["The from field must be a valid date."]
}
}
| الرمز | المعنى |
|---|---|
200، 201 |
تم (201 عند إنشاء شيء) |
401 |
غير مسجّل: لا رمز، أو رمز خاطئ أو منتهٍ أو ملغى (invalid_api_key للمفاتيح) |
403 |
مسجّل لكن غير مسموح: الصلاحية، أو الترخيص، أو الفرع (branch_forbidden)، أو قيود المفتاح (forbidden)، أو password_change_required |
404 |
غير موجود، أو ليس مما يحق لك رؤيته |
409 |
السجل ليس جاهزاً لهذا بعد (مثل PDF وثيقة قبل أن يوقّع الجميع) |
422 |
البيانات غير صحيحة؛ انظر errors. بعض حالات الرفض تضيف code |
426 |
update_required: لتطبيق مهنارو للجوال فقط، عندما يكون إصداره قديماً |
429 |
طلبات كثيرة؛ انتظر الثواني المذكورة في Retry-After |
500 |
خطأ من جهتنا. حاول لاحقاً، وأخبر الدعم إن استمر |
رموز قد تراها:
| الرمز | متى |
|---|---|
invalid_api_key |
مفتاح API خاطئ أو منتهٍ أو ملغى (401) |
forbidden |
شركة المفتاح أو طريقته أو عنوان IP لا يسمح بالطلب (403) |
branch_forbidden |
الفرع المطلوب ليس من الفروع التي يحق لك العمل فيها (403) |
password_change_required |
يجب على الشخص تغيير كلمة مروره أولاً (403) |
two_factor_required |
الدخول يحتاج رمز الخطوة الثانية: أرسل code (422) |
update_required |
تطبيق الجوال قديم؛ وupdate في الرد يقول أين يُحدَّث (426) |
live_location_required |
رُفضت بصمة دخول أو خروج لأن الشركة تطلب من هذا الموظف مشاركة موقعه المباشر من تطبيق مهنارو (422، والرسالة في errors.) |
كل حالات رفض البصمة ترد بـ 422 والرسالة في errors.clock مع code مثل device_pending أو device_blocked أو mock_location أو wifi_required أو held_for_review أو live_location_required.
حدود الطلبات
| ماذا | الحد |
|---|---|
طلبات الشركة (/) |
60 طلباً في الدقيقة |
| الدخول وكلمة المرور والتحقق بخطوتين | 10 في الدقيقة |
| طلبات المنصة | 120 في الدقيقة |
| MCP: خادم الشركة / خادم المنصة | 60 / 120 في الدقيقة |
بعض الطلبات لها حد أشد خاص بها، ويظهر في المرجع. الحدود تُحسب لكل شخص مسجّل. كل رد يحمل X-RateLimit-Limit وX-RateLimit-Remaining، وبعد تجاوز الحد يأتي 429 مع Retry-After (بالثواني).
إعادة المحاولة وتكرار الطلب
- لا تدعم الواجهة ترويسة
Idempotency-Key. تكرارGETوPUTوPATCHوDELETEآمن: تنفيذها مرتين يترك نفس النتيجة. أماPOSTالذي انتهت مهلته فقد يكون نجح: تحقق أولاً (مثلاً اعرض الإجازات) قبل إعادة إرساله، وإلا قد يُنشأ مرتين. - مع
429انتظرRetry-After؛ ومع500أو502أو503أعد المحاولة بانتظار متزايد (1، 2، 4 … ثوانٍ). - تسليمات الـ webhooks تحمل نفس
X-Mihnaro-Deliveryفي كل إعادة محاولة وإعادة إرسال: احفظه وتجاوز ما عالجته سابقاً (الـ Webhooks).
الإصدارات
- الإصدار في العنوان:
/api/v1. داخلv1نضيف فقط: طلبات جديدة، وحقول جديدة في الردود، ومعاملات اختيارية جديدة. اكتب برنامجك بحيث يتجاهل الحقول التي لا يعرفها. - أي تغيير يكسر البرامج الموجودة (حذف حقل أو تغيير اسمه أو معناه) يذهب إلى إصدار جديد،
/api/v2، ويبقىv1يعمل. - مرجع الـ API وملف OpenAPI مولَّدان من الكود الحي، فهما مطابقان للخادم دائماً.
آخر تحديث: