نسرد هنا كل تغيير على الواجهة البرمجية العامة (/api/v1) وأحداث خطافات الويب، الأحدث أولاً. التغييرات الإضافية تُضاف إلى v1، أما التغييرات الكاسرة فتنتقل إلى /api/v2 مع فترة إيقاف تدريجي.
2026-10-25
-
إعادة محاولة خطافات الويب وإكمال المهام المجمّعة مرة واحدة يوميًا في الخدمة المستضافة: تشغّل الخدمة المستضافة حاليًا مُرسِلها العامل في الخلفية مرة واحدة يوميًا، في الساعة 03:00 بالتوقيت العالمي (UTC). وما زالت المحاولة الأولى لخطاف الويب والدقيقة الأولى من عمل المهمة المجمّعة تُنفَّذان فورًا. أما إعادة المحاولة، وما تبقى من المهام المجمّعة الأطول، والتسليمات المعلّقة بإيقاف مؤقت، والحذف بعد مدة الحفظ، فتُنفَّذ في التشغيل اليومي التالي، وتُعطَّل نقطة الاستقبال التي تفشل 3 أيام عند محاولتها الفاشلة التالية (في الخدمة المستضافة عادةً في التشغيل اليومي التالي). وتُرسَل إعادة المحاولة في أول تشغيل يومي بعد انقضاء تأخيرها، وتمتد المحاولات العشر 8 أيام أو أكثر (بدلًا من نحو 3 أيام و20 ساعة). ولم يتغير جدول الفواصل نفسه، ويحتفظ النشر المستضاف ذاتيًا الذي يشغّل المُرسِل كل دقيقة بالتوقيت الموثّق. انظر متى تنفذ إعادة المحاولة.
-
تغيير كاسر للمفاتيح التي لا تملك
structure.functional.salary: الأجر مخفي في كل قراءة. تعيد الوظائف (payScaleIdوpayGradeIdوpayStepNumberوbaseSalaryوpayPeriod) والأوصاف الوظيفية (payScaleIdوpayGradeIdوsalaryMinوsalaryMax) هذه الحقول الآن بالقيمةnullللمفاتيح التي لا تملكstructure.functional.salary: في القوائم والقراءة المفردة، وفي استجاباتPOSTوPATCHوالأرشفة وإلغائها وPUTبالمعرّف الخارجي، وفي حمولات خطافات الويبposition.*وjob_description.*(ومنها إعادة الإرسال). وتُستبعد حقول الأجر أيضاً منdata.changedFields، ولم يعد يُرسل إلى نقاط الاستقبال تلكposition.updatedأوjob_description.updatedلم يغيّر إلا الأجر (مثل إعادة التسعير عند تعديل مرتبة رواتب). وفي سجل التدقيق (GET /api/v1/audit-events) وaudit.recordedتُستبعد مفاتيح الأجر منmetadata.changesفي صفوف الوظائف والأوصاف الوظيفية، ولا تحمل صفوف سلالم الرواتبmetadata.changes(ولاmetadata.rankللمرتبة)، وتُستبعد معرّفات الأجر ومبالغه المحفوظة في المستوى الأعلى منmetadata(مثلاً عند إنشاء وظيفة أو شاغر) وmetadata.gradeCode. سابقاً كان أي مفتاح يقرأ الوظائف أو الأوصاف الوظيفية يرى أجرها، ولم تكن صلاحية الرواتب مطلوبة إلا لكتابته. ولا يتغيّر شيء للمفاتيح التي تملكstructure.functional.salaryولا لمفاتيح مستوى النشر. أضفstructure.functional.salaryإلى التكامل الذي يحتاج الأجر. -
إعادة ربط معرّف خارجي بعد حذف سجله: ربط معرّف خارجي ما زال يحمله سجل لم يعد موجوداً (مثل وصف وظيفي أو وظيفة أو وحدة تنظيمية أو شخص حُذف من التطبيق) يُزيل الآن الربط القديم ويربط المعرّف بالسجل الجديد، بدلاً من إعادة
409 conflict. ويشمل ذلكexternalRefفيPOSTوPATCH /api/v1/job-descriptions. أما المعرّف الذي يحمله سجل ما زال موجوداً فما زال يعيد409 conflict. -
نسخ المجموعات ومسودات خطة القوى العاملة وتعديل مراتب الرواتب ترسل أحداث الوظائف والأوصاف الوظيفية: نسخ نسخة مجموعة وظيفية إلى صفة أخرى مع أوصافها الوظيفية ووظائفها يرسل الآن
job_description.createdوposition.createdلكل نسخة (أو<resource>.bulk_changedإذا تجاوزت 50)، إلى جانبjob_family.updatedالذي كان يُرسل؛ ولا يُنسخ إلا ما يخص مساحة عملك من أوصاف ووظائف. وتطبيق توصية نقص في الأعداد من خطة القوى العاملة يرسل الآنposition.createdللوظيفة المسودة التي ينشئها. وتعديل مبالغ مرتبة رواتب أو عدد درجاتها يرسل الآنposition.updated(changedFields: ["payStepNumber", "baseSalary"]) لكل وظيفة يعيد تسعيرها وjob_description.updated(changedFields: ["salaryMin", "salaryMax"]) لكل وصف وظيفي يتغيّر نطاقه (أو<resource>.bulk_changedإذا تجاوزت 50)، إلى جانبpay_scale.updated. سابقاً كانت هذه الصفوف تتغيّر دون أي حدث. ولم يعد تعديل مرتبة لا يغيّر الأجر (الاسم أو الرمز أو الترتيب فقط) يحرّكupdatedAtلتلك الوظائف والأوصاف. -
أرشفة وصف وظيفي أو حذفه ترسل
opening.closed: عند أرشفة وصف وظيفي (POST /api/v1/job-descriptions/{id}/archiveأو من التطبيق) أو حذفه من الهيكل التنظيمي، يرسل الآن كل شاغر مفتوح يُغلق بسببهopening.closed(أوopening.bulk_changedواحداً إذا تجاوزت 50)، إلى جانبposition.updatedالذي كان يُرسل لكل وظيفة. سابقاً كانت هذه الشواغر تصبحCLOSEDدون أي حدث. ويُضبط الآنclosedAtأيضاً للشاغر الذي يُغلق بحذف وصف وظيفي. -
GET /api/v1/pingصار في مستند OpenAPI: يسردGET /api/v1/openapi.jsonومرجع الواجهة البرمجية الآنGET /api/v1/ping(أي مفتاح صالح، دون صلاحية) مع استجابته:ok، والتكامل الذي يتبعه المفتاح فيactor(kindبقيمةintegrationأوplatform)، وworkspaceId(nullلمفتاح على مستوى النشر). لم تتغير نقطة النهاية نفسها. -
تغييرات المستخدمين من لوحة إدارة المنصة ترسل أحداث
user.*: عندما يغيّر فريق دعم جديرون دور أحد مستخدمي مساحة عملك من الموظفين، أو يعطّل حسابه أو يعيد تفعيله، أو يزيله من لوحة إدارة المنصة، تتلقى نقاط الاستقبال في مساحة عملك الآنuser.updated(changedFields: ["role"]، أو["status", "disabledAt"]للتعطيل وإعادة التفعيل) أوuser.deleted، كما في التغيير نفسه من إعدادات المستخدمين والأدوار (سابقًا كانaudit.recordedوحده يبلّغ عنها). ويظهر المستخدم المُزال أيضًا في سجل المحذوفات. -
حذف نسخة واحدة من مجموعة وظيفية يحرّك
updatedAtالخاص بها: عندما تحذف مساحة عملك نسخة واحدة من مجموعة وظيفية لها نسخ أخرى (مثلاً نسخة لتكليف واحد)، يتغيّر الآنupdatedAtللنسخ المتبقية، فيتقدّمupdatedAtالخاص بالمجموعة ويلتقطهاupdatedSinceمع حدثjob_family.updated(changedFields: ["instances"]) الذي كان يُرسل أصلاً. سابقاً كانupdatedAtالخاص بالمجموعة قد يرجع إلى الوراء (إلى ختم النسخ المتبقية الأقدم) فيفوت التغييرُupdatedSince. -
قائمة عناوين IP تقرأ عنوان عميل لا يمكن تزويره: صارت قائمة عناوين IP لمفاتيح الواجهة البرمجية وحدود المعدّل وعنوان IP في سجلات التدقيق تستخدم قاعدة واحدة لعنوان العميل. لا يتغيّر شيء في سحابة جديرون (تضبط حافة الاستضافة عنوان العميل). أما النشر الذاتي فيضبط
TRUSTED_PROXY(عدد الوكلاء العكسيين، أو عناوين IP أو نطاقات CIDR الخاصة بهم) فيُقرأ عنوان العميل من يمينX-Forwarded-For، فلم تعد القيمة التي يضعها العميل في هذه الترويسة تتجاوز القائمة. ودونTRUSTED_PROXYلا يثق النشر الذاتي بأي ترويسة تمرير: تتلقى مفاتيح التكامل الذي له قائمة عناوين403 forbidden. راجع قائمة عناوين IP المسموحة. -
أخطاء التعيين ونقل المرحلة لم تعد تكشف نصوصاً داخلية: إذا جرى تعيينان للمرشح نفسه في الوقت نفسه (عبر طلبين له مثلاً)، يعيد
POST /api/v1/applications/{id}/hireالآن للتعيين الذي لم ينجح409 conflictمعdetails.reasonبقيمةconcurrent_hire، بدلاً من422 validation_failedيحمل رسالة من قاعدة البيانات. والإخفاق غير المتوقع أثناء/hireأو/stageأو/rejectيعيد الآن500 internal(يمكن إعادة المحاولة بتأخير متزايد) بدلاً من422 validation_failedمع نص الخطأ الداخلي. أما الأسباب الموثّقة (position_fullوnot_a_candidateوopening_not_openوalready_hiredوalready_rejected) فلم تتغير. -
تغيير كاسر: إنشاء مرشحين ببيانات تواصل يحتاج
recruitment.candidate.contact: أصبحPOST /api/v1/candidatesالذي يرسلemailأوphoneأوnationalIdبقيمة غير فارغة يعيد403 forbidden(details.reasonبقيمةcandidate_contact_requiredوdetails.requiredبقيمة["recruitment.candidate.contact"]) للمفتاح الذي لا يملك صلاحية التواصل، قبل أي فحص للتكرار، فلم يعد409 conflict(معdetails.reasonبقيمةduplicate_person) يكشف لهذا المفتاح وجود شخص بذلك البريد أو رقم الهوية. وفيPOST /api/v1/candidates/bulkيفشل الصف الذي يحمل بيانات تواصل بالطريقة نفسها، وذلك الصف وحده، سواء أنشأ المرشح أم عدّله. وما زال بإمكان المفاتيح التي لا تملك صلاحية التواصل إنشاء مرشحين دون بيانات تواصل (احذف الحقول أو أرسلnull)، وما زالPATCHيتجاهل حقول التواصل دونها. امنح تكاملات الترحيل وأنظمة ERP صلاحية التواصل لاستيراد بيانات التواصل. -
اختيار قطاع فرعي أو إلغاء اختياره يحدّث المجموعات المندرجة تحته: عندما تختار مساحة عملك قطاعات فرعية أو تلغي اختيارها (أثناء التهيئة أو في صفحة الهيكل الوظيفي)، فإن كل مجموعة وظيفية تبقى فيها وتندرج تحت أحد تلك القطاعات الفرعية يتغيّر الآن
updatedAtلنسخها (فيلتقطهاupdatedSince) ويُرسل لهاjob_family.updated(changedFields: ["instances"])، أو حدث واحدjob_family.bulk_changedإذا تجاوز عددها 50، لأنsubSectorsالخاصة بها تغيّرت. سابقاً كانت المجموعات المحذوفة مع قطاع فرعي أُلغي اختياره هي وحدها التي ترسل حدثاً. -
تغيير كاسر: تنزيل السيرة الذاتية وخطاب العرض يحتاج
recruitment.candidate.contact: أصبحGET /api/v1/candidates/{id}/cvوGET /api/v1/offers/{id}/fileيحتاجان صلاحية التواصل أيضاً، لأن السيرة الذاتية تعرض بريد المرشح وهاتفه، وقد يطبع خطاب العرض رقم هويته. والمفتاح الذي يملكrecruitment.viewدونrecruitment.candidate.contactيتلقى الآن403 forbidden(details.reasonبقيمةcandidate_contact_required، وdetails.requiredبقيمة["recruitment.candidate.contact"]) بدلاً من الملف. أضف الصلاحية إلى التكامل لمواصلة التنزيل. ولم يتغيّرhasCvوhasFile، ولا تتأثر المفاتيح على مستوى النشر. -
الطلبات والعروض والمقابلات والشواغر المحذوفة تظهر في سجل المحذوفات: عند حذف شخص في التطبيق (من صفحة الأشخاص، أو حين يحذف المرشح حسابه بنفسه) تُحذف نهائياً طلباته والعروض المقدَّمة عليها ومقابلاته، وحذف شخص مع الحذف المتتابع في محرر البيانات يحذف طلباته ومقابلاته كذلك، وحذف وظيفة بالطريقة نفسها يحذف شواغرها (ولا يمكن حذف وظيفة في شواغرها طلبات من محرر البيانات). وصار كل صف محذوف يترك أثر حذف في
GET /api/v1/deleted(resourceبقيمةapplicationأوofferأوinterviewأوopening) معexternalRefsالتي كانت له، وتُزال روابطه، فإعادة إرسال المعرّف الخارجي نفسه لاحقاً تُنشئ سجلاً جديداً. سابقاً كانت هذه الصفوف تختفي دون أثر حذف وتبقى روابطها. ويُرسل حفظ محرر البيانات الذي يحذف وظيفة حذفاً متتابعاً الحدثopening.bulk_changed(نوع حدث جديد)؛ أعد قراءة الشواغر باستخدامupdatedSinceوسجل المحذوفات. -
يُحجز
Idempotency-Keyغير المكتمل 90 ثانية: المفتاح الذي لم يكتمل طلبه الأول يُحرَّر الآن بعد 90 ثانية من أول استخدام له (كانت 60 ثانية، أي أطول مدة قد يعمل فيها الطلب، فكان يمكن لإعادة محاولة أن تأخذ مفتاح طلب بطيء ما زال يعمل فيُنفَّذ مرتين). وحتى ذلك الحين تعيد إعادة المحاولة بالمفتاح نفسه409 idempotency_conflict. ولم يعد الطلب الذي حُرِّر مفتاحه بهذه الطريقة يكتب فوق الاستجابة التي حفظتها إعادة المحاولة. -
حذف وظيفة يحدّث الموظفين السابقين المرتبطين بها: عند حذف وظيفة (عبر
DELETE /api/v1/positions/{id}أو من التطبيق) تصبحcurrentPositionIdبقيمةnullلدى الموظفين السابقين الذين كانت وظيفتهم، ويتغيّرupdatedAtلهم (فيلتقطهمupdatedSince)، ويُرسل لكل منهمemployee.updated(changedFields: ["currentPositionId"])، أو حدث واحدemployee.bulk_changedإذا تجاوز عددهم 50. سابقاً كان الربط يُمسح دون إشعار. وما زال حذف وظيفة فيها موظفون حاليون مرفوضاً (409 has_people). -
حماية الطلبات المعيَّنة والمرفوضة: تعيد
POST /api/v1/applications/{id}/stageو/rejectو/hireعلى طلب في مرحلةHIREDالقيمة409 conflictمعdetails.reasonبقيمةalready_hired(كان يمكن سابقاً إعادة نقل الطلب المعيَّن أو رفضه). ويعيد/hireعلى طلبREJECTEDالقيمة409 conflict(already_rejected)؛ أعده أولاً إلى مرحلة نشطة عبر/stage. وتعيين طلب معيَّن بالفعل يُبلغ الآنalready_hiredبدلاً منnot_a_candidate. ورفض طلب مرفوض بالفعل ما زال لا يغيّر شيئاً. ويتبع التطبيق القواعد نفسها. -
طلب
PATCHللوصف الوظيفي يحتفظ بنطاق الراتب: لم يعدPATCH /api/v1/job-descriptions/{id}دونpayScaleوpayGradeيمسحsalaryMinوsalaryMaxلوصف وظيفي بلا مرتبة أجر (نطاق حُدّد في محرر البيانات)، ولا يعيد قراءة نطاق وصف له مرتبة. وما زال إرسالpayScaleأوpayGrade(معstructure.functional.salary) يحدد النطاق من المرتبة، وما زالت القيمةpayScale: nullتمسحه. -
التصفح مع
updatedSinceلم يعد يتخطى صفوفاً أو يفشل عند حذف صف: أصبحnextCursorيحمل موضع آخر صف (updatedAtوid؛ وoccurredAtوidفيGET /api/v1/audit-events)، فلم يعد تعديل صف بين طلبَي صفحتين يجعل الصفحة التالية تتخطى صفوفاً، ولم يعد حذف آخر صف يجعل الصفحة التالية تفشل بـ422 validation_failed. وتبقى المؤشرات معتمة، والمؤشرات الصادرة قبل هذا التغيير تعمل كما كانت. والمؤشر المشوَّه ما زال يُعيد422 validation_failed. ولا تغيير على القوائم دونupdatedSince. -
حدث
interview.completedواحد لكل مقابلة: أول بطاقة تقييم من أعضاء اللجنة تجعل المقابلةCOMPLETEDوتُرسلinterview.completedمرة واحدة؛ ويظل بإمكان بقية اللجنة إرسال بطاقاتهم (أو تعديلها)، وكل منها يُرسلinterview.updatedمعchangedFields: ["evaluation"](سابقاً كانت كل بطاقة تُرسلinterview.completedوتبقى الحالةCONFIRMED). وأصبحت كل بطاقة تقييم تُحدّثupdatedAtللمقابلة. ويُعيدPATCH /api/v1/interviews/{id}على مقابلةCOMPLETEDالخطأ409 conflict(interview_closed) لطلب مواعيد جديدة وللإلغاء معاً. -
أرشفة وظيفة لها شاغر مفتوح تتطلب
recruitment.hiring.open: يغلقPOST /api/v1/positions/{id}/archiveالشاغر المفتوح للوظيفة، لذا أصبح يتطلب أيضاًrecruitment.hiring.openعند وجود شاغر مفتوح، كما في التطبيق؛ ودونها يُعاد403 forbidden(معdetails.reasonبقيمةhiring_permission_requiredوdetails.permissionبقيمةrecruitment.hiring.open) ولا يتغيّر شيء. أما الوظيفة التي ليس لها شاغر مفتوح فتُؤرشف بـstructure.org.actوحدها كما كانت. -
التحقق من مساحة العمل عند بث الملفات الخاصة: لا يبث
GET /api/v1/candidates/{id}/cvوGET /api/v1/offers/{id}/fileالملف المخزّن إلا إذا كان تابعاً لمساحة عمل السجل؛ وأي ملف آخر يُعيد404 not_foundكالملف غير الموجود. ولا يقبل محرر البيانات في خلية السيرة الذاتية أو خطاب العرض أو الصورة لشخص إلا رابط http(s) أو قيمة فارغة؛ وأي قيمة أخرى، كمرجع ملف خاص، تُفشل الحفظ بخطأ تحقق. وتُرفق الملفات بالرفع فقط. -
إبلاغ مالكي لوحة الإدارة بالبريد عند التعطيل التلقائي لنقطة استقبال على مستوى النشر: عندما تُعطَّل نقطة استقبال خطاف ويب في لوحة إدارة المنصة بعد فشل متواصل مدة 3 أيام، يتلقى كل مالك في لوحة الإدارة رسالة بريد واحدة تذكر التكامل ونطاق نقطة الاستقبال ومكان إعادة تفعيلها (لوحة إدارة المنصة ← التكاملات). ولا تغيير على نقاط استقبال مساحة العمل (يتلقى مسؤولو مساحة العمل إشعارًا داخل التطبيق).
-
التحقق من أنواع أحداث نقاط الاستقبال على مستوى النشر مقابل الكتالوج: أصبح إنشاء نقطة استقبال لخطافات الويب أو تعديلها في لوحة إدارة المنصة يقبل فقط
*أوaudit.recordedأو نوعًا من كتالوج الأحداث (<resource>.<verb>، مثلemployee.updated)، كما هو الحال في نقاط استقبال مساحات العمل؛ ويُرفض أي نوع آخر بـ422 unknown_event_type(وتسردdetails.invalidالأنواع المرفوضة) ولا يُحفظ شيء. ويظل بإمكان تكامل القراءة على مستوى النشر اختيارaudit.recordedدائمًا. وكما في نقاط استقبال مساحات العمل، تؤدي إزالة أنواع أحداث من نقطة استقبال إلى وسم تسليماتها المعلّقة من تلك الأنواع بـFAILED(scope changed). -
إعادة تسمية مهارة خاصة بمساحة العمل أو حذفها تحدّث المجموعات الوظيفية والأوصاف الوظيفية التي تسردها: عندما تعيد مساحة عملك تسمية إحدى مهاراتها الخاصة (
nameAr/nameEn) أو تحذفها في التطبيق، يتقدّمupdatedAtلكل نسخة مجموعة وظيفية ووصف وظيفي في مساحة عملك يسردها (فيلتقطهupdatedSince)، ويُرسلjob_family.updated(changedFields: ["instances"]) وjob_description.updated(changedFields: ["skills"])، أو<resource>.bulk_changedإذا تجاوز العدد 50. أما تعديل وصف المهارة أو وسمها أو أوصاف مستوياتها فقط فلا يُرسل شيئًا (فهي ليست في كائنات v1). -
مهام الدفعات تتوقف عند تعليق مساحة العمل، والسيرة الذاتية للمرشح تُجلب مرة واحدة: أصبحت مهمة الدفعات الجارية تتوقف بعد الدفعة التي تعالجها عند تعليق مساحة عملها (سابقاً كانت تنتظر المهمة التي لم تبدأ فقط)، ثم تُستأنف من حيث توقفت عندما تعود مساحة العمل نشطة. ويجب أن يكتمل تنزيل
cvUrlفي صف المرشح خلال 20 ثانية إجمالاً (سابقاً كان للبحث عن العنوان وللتنزيل 20 ثانية لكل منهما)، وإلا يفشل الصف بـ422 validation_failed(cv_unreachable). ولم يعد الصف الذي يتكرر بعد تشغيل متقطع ينزّل سيرته مرة أخرى، فلم يعد يرسلcandidate.updatedثانياً ولا يكتب صف تدقيق ثانياً. -
سجل النشاط في لوحة المنصة يسمّي التكامل وراء التغيير عبر الواجهة البرمجية: في سجل النشاط بلوحة إدارة المنصة (عند التصفية على مساحة عمل)، تظهر التغييرات التي تمت بمفتاح API لمساحة العمل الآن بصيغة
تكامل · <اسم التكامل>بدلاً من مستخدم مساحة عمل عام. والصفوف التي يكتبها تكامل على مستوى النشر (لا يوجد منها شيء اليوم، فمفاتيح مستوى النشر للقراءة فقط) تُربط به ولا تتبع أي مساحة عمل (فتظهر في السجل دون تصفية) بصيغةتكامل على مستوى النشر · <الاسم>، ويكونactor.idلها فيaudit.recordedمعرّف التكامل على مستوى النشر. ولم يتغيّر شيء آخر في/api/v1ولا في حمولات خطافات الويب.
2026-10-24
- إصلاحات ما قبل الإطلاق (قبل إتاحة الواجهة البرمجية للعموم): أصبح
validation_failedدائماً422(كان400لقيمة خاطئة فيlimitأوcursorأوupdatedSinceأوsince، أو جسم ليس JSON، أو غيابIdempotency-Key). ويقبلPOST /api/v1/openingsالحقلposting: { ar, en }ويحفظه نصاً لإعلان الوظيفة، فيمكن فتح الوظائف المُنشأة عبر الواجهة البرمجية (ودونه:422 validation_failedمعdetails.reasonبقيمةno_job_description)؛ وفتح وظيفة وصفها الوظيفي مؤرشف يعيد422 validation_failed(معdetails.reasonبقيمةarchived). وإسناد موظف إلى وظيفة في الهيكل التنظيمي يرسلemployee.updated(changedFields: ["currentPositionId"])؛ وضبطstatusلموظف علىFORMER_EMPLOYEEيرسل أيضاًemployee.offboarded؛ والمجموعات المضافة أثناء إعداد مساحة العمل ترسلjob_family.createdفي المرة الأولى. والحفظ الذي لا يغيّر شيئاً (وحدة تنظيمية أو وظيفة) لم يعد يكتب سطر تدقيق ولا يرسل.updated. وحقول الأجر دونstructure.functional.salaryتُرفض بـ403قبل البحث عن سلم الرواتب. خطافات الويب: تُسقط التسليمات المنتظرة (scope changed) حين يفقد التكامل صلاحية أو تتوقف النقطة عن الاشتراك في نوع حدثها؛ وتُبنى إعادة الإرسال بالصلاحيات الحالية وتُرفض (409/403) خارج النطاق، وتتطلب أن تكون النقطة والتكامل نشطين؛ والتدوير الثاني للسر خلال مدة الـ 24 ساعة يعيد409 conflict(معdetails.reasonبقيمةrotation_in_progress). سجل التدقيق وaudit.recorded: تُستبعد حقول التقييم الداخلية منchangesفي صفوف الأوصاف الوظيفية؛ ويبقى منفّذ التكاملtype: "integration"(معid: null) بعد حذف التكامل؛ وتستخدم صفوف المنصةtarget.typeبصيغة snake_case وتشمل تعديلات دليل جديرون (taxonomy.*)؛ وأصبح إظهار سر التوقيع يُسجَّل (settings.integration.secret_revealedوadmin.integration.endpoint_secret_revealed). ومهام الإدراج المجمّع تتوقف بين الدفعات عند إيقاف التكامل، وتُفشل الصفوف المتبقية بـforbiddenعند إزالة صلاحية لازمة، وتعدّ السيرة الذاتية على خادم غير عام خطأ صف422، وتحذف صفوفها المرسلة عندDONE. - التوثيق: صفحات أدلة جديدة (نظرة عامة، والأعراف مع القائمة الكاملة لرموز الأخطاء، والمزامنة مع ERP، والترحيل المجمّع، وخطافات الويب مع التحقق من التوقيع بلغتي Node وPython، وفهرس الأحداث المولّد، وسجل التدقيق لأنظمة SIEM، وصفحة لكل مرحلة من دورة الحياة) ومرجع تفاعلي للواجهة البرمجية معروض من
GET /api/v1/openapi.json. لم يتغير أي سلوك في الواجهة البرمجية. - نقاط استقبال خطافات الويب لتكاملات مساحة العمل: يديرها مسؤول مساحة العمل من الإعدادات ← التكاملات (مع صلاحيات التكامل ومفاتيح API الخاصة به). يجب أن تكون أنواع أحداث نقطة الاستقبال
*أوaudit.recordedأو نوعاً من فهرس الأحداث (<resource>.<verb>، مثلemployee.updated)؛ ولا يمكن اختيارaudit.recordedإلا إذا كان التكامل يملكaudit.view، ولا تشمله*أبداً. ويكتب إرسال حدث اختبار (ping) وإعادة إرسال حدث الآن إجراءَي التدقيقsettings.integration.endpoint_testedوsettings.integration.delivery_redelivered، ويظهران فيGET /api/v1/audit-eventsوفيaudit.recorded. - تكامل القراءة على مستوى النشر: في النشر المخصص، يستطيع مشرف المنصة إنشاء تكامل للقراءة فقط من لوحة تحكم المنصة يقرأ جميع مساحات العمل النشطة. تعمل مفاتيحه على كل نقاط
GETعداGET /api/v1/bulk-jobs/{id}، وتعيد عمليات الكتابة403. يحمل كل كائن يقرؤهworkspaceId، وتقبل القوائم?workspaceId=لحصر النتائج في مساحة عمل واحدة (404لمساحة غير معروفة أو غير نشطة). وتتطلب نقاط الهيكل الوظيفي (/sectorsو/sub-sectorsو/job-families) المعامل?workspaceId=لهذه المفاتيح وتعيد عرض تلك المساحة. لا تُخفى بيانات التواصل عنه. ويعيدGET /api/v1/audit-eventsصفوف كل مساحة عمل نشطة إضافة إلى صفوف المنصة (workspaceId: null). وتستقبل نقاط خطافات الويب الخاصة به الأحداث من كل مساحة عمل نشطة. تحتاج المفاتيح إلى تاريخ انتهاء وإلى قائمة عناوين IP مسموحة على التكامل (422بخلاف ذلك). لا تتغير مفاتيح مساحة العمل، وتتجاهل?workspaceId=. ويُدرج مستند OpenAPI المعاملworkspaceIdفي كلGETويوسم كل عملية بـx-deployment-level. انظر القراءة على مستوى الجهة. - الإدراج المجمّع: تستقبل
POST /api/v1/employees/bulkو/api/v1/candidates/bulkو/api/v1/org-units/bulkو/api/v1/positions/bulkمن 1 إلى 1,000 صف مفتاح كل منها{ system, externalId }(معIdempotency-Keyإلزامي) وتجيب بـ202 { jobId, statusUrl }؛ ويعيدGET /api/v1/bulk-jobs/{id}الحالة والأعداد ونتيجة كل صف (createdأوupdatedأوfailedمع رمز الخطأ)، للتكامل الذي أرسل المهمة فقط. يتبع كل صف قواعد طلبPUTالمفرد بالمعرّف الخارجي نفسها، ويكتب سطر تدقيق وحدث خطاف ويب خاصين به. ويمكن لصفوف المرشحين أن تحملcvUrlبرابطhttps(ملف PDF حتى 5 ميغابايت). مهمتان على الأكثر لكل تكامل في الوقت نفسه (429 too_many_jobs). انظر الإدراج المجمّع. - بث السيرة الذاتية وخطاب العرض يخدم ملفات خاصة: أصبحت السير الذاتية ومستندات الأشخاص وشهادات المؤهلات وخطابات العروض ومرفقات الطلبات تُخزَّن بشكل خاص دون رابط عام. ويواصل
GET /api/v1/candidates/{id}/cvوGET /api/v1/offers/{id}/fileبثها كما هي (الصلاحيات نفسها وcontent-disposition: attachmentنفسه)، وتبقى الملفات المرفوعة قبل التغيير قابلة للبث إلى أن تُنقل. لا تتغير أي حقول في الاستجابات، فالواجهة البرمجية لم تُعِد موقع التخزين قط. - سجل المحذوفات وخطافات الويب يتبعان صلاحيات القراءة للمفتاح: أصبح
GET /api/v1/deletedيسرد فقط الموارد التي يستطيع مفتاحك قراءتها، بالصلاحية نفسها التي يطلبها مسارGETلكل مورد (مثلاً: المفتاح الذي لا يملك إلاstructure.org.viewيرى سجلات حذفorg_unitوpositionفقط). وطلب?resource=لمورد لا يستطيع المفتاح قراءته يعيد403 forbidden. أما نقاط استقبال خطافات الويب فكانت تتلقى الأحداث (ومنها<resource>.deletedو<resource>.bulk_changed) فقط للموارد التي يستطيع تكاملها قراءتها، مع إخفاء بيانات تواصل المرشح دونrecruitment.candidate.contact؛ وترى التكاملات على مستوى المنصة كل الموارد. - المقابلات والمستخدمون والأدوار وسجل التدقيق:
GET/POST /api/v1/interviewsوGET/PATCH /api/v1/interviews/{id}(القراءة:recruitment.view؛ الكتابة:recruitment.act؛ يقترحPATCHمواعيد جديدة ما دامت المقابلةOFFERED، أو يلغيها بالقيمة{ "status": "CANCELLED" })، مع الأحداثinterview.scheduledوinterview.updatedوinterview.cancelledوinterview.completed(وكذلك للمقابلات التي تُجدول أو يُعاد اقتراحها أو يُختار موعدها أو تُلغى أو تُقيَّم في التطبيق)؛ وGET /api/v1/users(حسابات الموظفين، دون كلمات مرور أو رموز أو بيانات التحقق الثنائي) وGET /api/v1/roles(مع مفاتيح صلاحياتها)، وكلاهما للقراءة فقط بالصلاحيةusers.view؛ وGET /api/v1/audit-events(audit.view)، سجل التدقيق لأداة SIEM لديك: الصفوف كما خُزّنت، الأقدم أولاً، وupdatedSinceعلىoccurredAt، وتُخفى قيم تواصل المرشح فيchangesدونrecruitment.candidate.contact. ويُخفىpersonفي المقابلة بالطريقة نفسها. ويحمل المستخدمون والأدوارupdatedAt(فيلتقطupdatedSinceتغييرات الأدوار)، ويرسلونuser.updatedوuser.deletedوrole.createdوrole.updatedوrole.deleted؛ ويُسرد المستخدمون المُزالون والأدوار المحذوفة في سجل المحذوفات. وإلغاء مقابلة ملغاة أصلاً لا يغيّر شيئاً، وإلغاء مقابلة مكتملة يعيد409 conflict(معdetails.reasonبقيمةinterview_closed). - الشواغر والطلبات والعروض:
GET/POST /api/v1/openingsوGET /api/v1/openings/{id}وPOST /api/v1/openings/{id}/close(القراءة:recruitment.view؛ الفتح والإغلاق:recruitment.hiring.openكما في التطبيق)؛ وGET/POST /api/v1/applicationsوGET /api/v1/applications/{id}وPOST /api/v1/applications/{id}/stageوPOST /api/v1/applications/{id}/reject(القراءة:recruitment.view؛ الكتابة:recruitment.act؛ والإضافة تتبع مسار توظيف الشاغر كما في صفحة الوظائف) وPOST /api/v1/applications/{id}/hire(recruitment.hireوrecruitment.candidate.contact)؛ وGET /api/v1/offersوGET /api/v1/offers/{id}وGET /api/v1/offers/{id}/file(recruitment.view، للقراءة فقط، ويُبث الخطاب كملف). الأحداث:opening.createdوopening.openedوopening.closedوopening.archivedوopening.updatedوapplication.createdوapplication.stage_changedوapplication.rejectedوapplication.updatedوapplication.hired؛ ويرسل التعيين أيضاًemployee.created، وتنتقلexternalRefsالخاصة بالمرشح إلى الموظف. كما أصبح فتح التوظيف وإغلاقه من التطبيق يرسلانposition.updated، والوظائف التي تُنشأ من مسار الشواغر ترسلposition.created.
2026-10-22
- الموظفون والمرشحون:
GET/POST /api/v1/employeesوGET/PATCH/DELETE /api/v1/employees/{id}وPOST /api/v1/employees/{id}/archiveوPUT /api/v1/employees/by-external/{system}/{externalId}(القراءة:people.view؛ الكتابة:people.act)، وGET/POST /api/v1/candidatesوGET/PATCH /api/v1/candidates/{id}وGET /api/v1/candidates/{id}/cv(القراءة:recruitment.view؛ الكتابة:recruitment.act)، مع الأحداثemployee.createdوemployee.updatedوemployee.offboardedوemployee.archivedوemployee.deletedوemployee.bulk_changedوcandidate.createdوcandidate.updatedوcandidate.archivedوcandidate.deleted. يُنهيDELETEعلى الموظف خدمته (FORMER_EMPLOYEE)، ولا تحذف الواجهة البرمجية أي شخص. وتُخفى بيانات تواصل المرشح (البريد والجوال ورقم الهوية) في الاستجابات وحمولات خطافات الويب للمفاتيح التي لا تملكrecruitment.candidate.contact. وتُبث السيرة الذاتية كملف للتنزيل، ولا يُعاد موقع تخزينها أبداً. - الأوصاف الوظيفية:
GET/POST /api/v1/job-descriptionsوGET/PATCH /api/v1/job-descriptions/{id}وPOST /api/v1/job-descriptions/{id}/archiveوPOST /api/v1/job-descriptions/{id}/unarchive(القراءة:structure.functional.viewأوrecruitment.view؛ الكتابة:structure.functional.act)، مع الأحداثjob_description.createdوjob_description.updatedوjob_description.archivedوjob_description.unarchivedوjob_description.deletedوjob_description.bulk_changed. يقبلPOSTوPATCHالحقلexternalRefلربط معرّفك؛ ويتركPATCHالحقول ومصفوفات المهارات غير المرسلة كما هي؛ والأوصاف المأخوذة من الدليل الوطني (SSCO) للقراءة فقط (409 ssco_managed)؛ ولا يوجدDELETE. كما أصبحت إزالة القطاعات الفرعية أو المجموعات الوظيفية من التطبيق ترسلjob_description.deletedوposition.updatedلما أُزيل أو أُغلق، وحفظ محرر البيانات يرسل<resource>.bulk_changed. - الهيكل الوظيفي وسلالم الرواتب (للقراءة فقط):
GET /api/v1/sectorsوGET /api/v1/sub-sectorsوGET /api/v1/job-familiesوGET /api/v1/job-families/{jobFamilyId}(structure.functional.view) وGET /api/v1/pay-scalesمع المراتب والدرجات (structure.functional.salary)، مع الأحداثsector.*وsub_sector.*وjob_family.*وpay_scale.*. صفوف الدليل تحملslugثابتاً، والمجموعات الوظيفية تسرد نسخ مساحة عملك (الصفة والقطاعات الفرعية والمهارات). - الوظائف:
GET/POST /api/v1/positionsوGET/PATCH/DELETE /api/v1/positions/{id}وPOST /api/v1/positions/{id}/archiveوPUT /api/v1/positions/by-external/{system}/{externalId}، مع الأحداثposition.createdوposition.updatedوposition.archivedوposition.deletedوposition.bulk_changed. حقول التوظيف للقراءة فقط، وحقول الأجر تتطلبstructure.functional.salary. - الوحدات التنظيمية:
GET/POST /api/v1/org-unitsوGET/PATCH/DELETE /api/v1/org-units/{id}وPUT /api/v1/org-units/by-external/{system}/{externalId}، مع الأحداثorg_unit.createdوorg_unit.updatedوorg_unit.deletedوorg_unit.bulk_changed. حذف وحدة يرسلposition.updatedلكل وظيفة تصبح بلا وحدة. - إطلاق الواجهة البرمجية v1: التكاملات بنطاقات صلاحيات، ومفاتيح الواجهة البرمجية (
Authorization: Bearer jdr_live_…، تظهر مرة واحدة، مع تاريخ انتهاء اختياري)، وقائمة عناوين IP مسموحة اختيارية، و600 طلب في الدقيقة لكل مفتاح (429 rate_limitedمعRetry-After)، وGET /api/v1/ping، وGET /api/v1/openapi.jsonالعام، والترقيم بالمؤشر معupdatedSinceفي كل قائمة، وسجل المحذوفاتGET /api/v1/deleted(تُحفظ آثار الحذف 180 يومًا)، وIdempotency-KeyفيPOST(24 ساعة)، وقائمة رموز الأخطاء المغلقة، وخطافات الويب الموقّعة (Jadiroon-Signature، و10 محاولات بفواصل متزايدة على مدى نحو 3 أيام و20 ساعة حين يعمل مُرسِل إعادة المحاولة كل دقيقة، والتعطيل التلقائي بعد 3 أيام من الفشل، والحفظ 30 يومًا، والحدث الاختياريaudit.recorded). تظهر عمليات الكتابة عبر الواجهة البرمجية في سجل التدقيق باسم تكامل · (الاسم). والسجلات الموجودة قبل الإطلاق تحملupdatedAt= تاريخ الإطلاق، فتعيد أول مزامنة بـupdatedSinceكل شيء.