انتقل إلى المقال
Aniq-UI

Learnioمرجع واجهة API

مرجع واجهة API

كل مسار تقدّمه واجهة API في Learnio، ومن يحق له استدعاؤه، وكيف يعمل تسجيل الدخول والصلاحيات والأخطاء والتقسيم إلى صفحات.

لحزمة الحزمة الكاملة

العنوان الأساسي وصيغة الاستجابة

يُقدَّم كل مسار تحت البادئة /api. محليًا، العنوان الأساسي هو http://localhost:8000/api. وعلى الخادم، هو عنوان واجهة API الخاصة بك متبوعًا بـ /api، وهي القيمة نفسها التي تقرؤها الواجهتان الأماميتان من NEXT_PUBLIC_API_BASE_URL (متغيرات البيئة).

تخدم واجهة API جمهورين لا يتشاركان رمزًا أبدًا. يستخدم الطلاب المسارات تحت /api/users/<area> و/api/shop، المذكورة في أقسام الطلاب أدناه. وتستخدم لوحة الإدارة كل المسارات الأخرى، بما فيها /api/users نفسه و/api/users/<username>، اللذان يديران حسابات الطلاب.

أجسام الطلبات بصيغة JSON، باستثناء رفع الملفات. وتأتي كل إجابة في الغلاف نفسه:

الغلاف
{
  "success": true,
  "data": { },
  "message": ""
}

يحمل data النتيجة. وmessage جملة قصيرة تملؤها بعض عمليات الكتابة، مترجمة إلى لغة الطلب، وتكون فارغة في غير ذلك. لا يحتاج فحص السلامة إلى رمز، ويُظهر الغلاف:

الطرفية
curl http://localhost:8000/api/health
الاستجابة
{"success":true,"data":{"status":"ok"},"message":""}

يجيب بـ 503 ما دام الوصول إلى قاعدة البيانات متعذرًا أو كانت خالية من الجداول، لذا يمكن لموازن الأحمال استخدامه كفحص للجاهزية.

الأخطاء

يُجاب الطلب الفاشل برمز حالة HTTP المناسب وبالغلاف نفسه، مع success: false وdata: null، ومع المشكلات لكل حقل عند التحقق، مفهرسةً باسم الحقل (والحقل داخل كائن متداخل بمساره المنقّط):

الطرفية
curl -X POST http://localhost:8000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"not-an-email","password":"x"}'
الاستجابة (400)
{
  "success": false,
  "data": null,
  "message": "Enter a valid email address (example@domain.com).",
  "errors": {
    "email": ["Enter a valid email address (example@domain.com)."]
  }
}
الحالةمتى
400فشل حقل في التحقق، أو قيمة استعلام غير صالحة، أو يحتوي الجسم على حقل لا يقبله المسار. تُرفض الحقول غير المعروفة، ولا تُتجاهل.
401الرمز مفقود، أو منتهي الصلاحية، أو يخص الجمهور الآخر. وكذلك تسجيل الدخول الفاشل، سواء لم يكن للبريد حساب أو كانت كلمة المرور خاطئة.
403أدوار المسؤول لا تمنح صلاحية المسار، أو حاول حساب مدرّس الوصول إلى ما هو خارج دوراته.
404لا يوجد سجل كهذا.
409تتعارض عملية الكتابة مع سجل موجود، مثل بريد إلكتروني أو slug مستخدم بالفعل.
429محاولات كثيرة جدًا من عنوان واحد على مسار تسجيل دخول أو إنشاء حساب أو كلمة مرور. ترويسة Retry-After تحدد عدد الثواني التي يجب انتظارها.
500فشل غير متوقع. تبقى الرسالة عامة وتذهب التفاصيل إلى سجل واجهة API.

تجيب عمليات الكتابة الناجحة بـ 201 مع POST وبـ 200 مع الطرق الأخرى.

التقسيم إلى صفحات والترتيب

تأتي القوائم بشكلين، واحد لكل جمهور. تجيب مسارات الطلاب بالشكل الذي يقرؤه موقع الطلاب؛ وتجيب مسارات الإدارة بالشكل الذي تقرؤه لوحة الإدارة.

قوائم الطلاب والقوائم العامةقوائم الإدارة
الصفحةpage، بدءًا من 1page، بدءًا من 1
حجم الصفحةpage_count (الدورات، والمدونة، والتسجيلات، والتقييمات) أو per_page (المدرّسون). حجم صفحة الدورات افتراضيًا هو الإعداد courses_per_page، والتسجيلات 100.page_count، وهو 15 افتراضيًا (10 للمسؤولين). وتستخدم الطلبات limit.
الترتيبللدورات فقط: sort_by وsort_dir (asc أو desc)sort وorder (asc أو desc). وتستخدم الطلبات sort_by وsort_order.
الترتيب الافتراضيالدورات حسب الأحدث تحديثًا أولًا، والمدونة حسب الأحدث نشرًا أولًاالأحدث تحديثًا أولًا، ويُفصل في التساوي بواسطة id. وتحتفظ الفئات والمدرّسون بترتيبهم المنسَّق.
الإجابةdata، وcurrent_page، وlast_page، وper_page، وtotal، وfrom، وto، إضافة إلى روابط الصفحاتdata, page, limit, total, totalPages

تضم الصفحة 100 صف على الأكثر: حجم الصفحة الأكبر يُقرأ 100، والحجم المفقود أو غير المقروء يعود إلى القيمة الافتراضية للقائمة. وينطبق الأمر نفسه على page، التي تعود إلى 1.

لا يقبل sort إلا الأعمدة التي تسمح بها كل قائمة. ويعود المفتاح غير المعروف إلى الترتيب الافتراضي بدلًا من الفشل، فتظل الإشارة المرجعية القديمة تعمل.

ترتَّب قائمة الدورات العامة حسب id أو price أو discount_percentage أو rating أو duration أو level أو language أو created_at أو updated_at، وتُرشَّح حسب title وcategory_id وinstructor_id وtype (live أو recorded).

اللغة

أرسل لغة القارئ في ترويسة Accept-Language. تتحدث واجهة API اللغات المسرودة في back-end/src/i18n/locales.ts، وهي en وar كما تُشحن. تقرأ الوسم الأول، فيكون ar-SA عربية، والطلب الذي لا يحدد لغة مدعومة يُجاب بلغة الإعداد default_locale. لا يوجد معامل استعلام للغة.

  • تُترجم رسائل الخطأ وmessage الخاصة بعمليات الكتابة الناجحة.
  • النص المخزّن باللغتين، مثل عناوين الدورات وأوصافها، يُعاد بالشكل { "en": "...", "ar": "..." } ويختار العميل أحدهما.
  • تجيب بعض مسارات الطلاب باللغة المطلوبة فقط: قائمة التسجيلات، ومحتوى الدورة، والبحث.
  • يأخذ الدفع اللغة من جسم الطلب (locale، إحدى اللغات المدعومة)، فيطابق الإيصال الصفحة التي اشترى منها الطالب.

المصادقة

يسجّل الطلاب والمسؤولون الدخول عبر نقاط نهاية مختلفة، ومقابل جداول مختلفة، ويحصلون على رموز لا تقبلها إلا مساراتهم الخاصة.

الجمهورتسجيل الدخولالرمز في الإجابةمقبول على
الطالبPOST /api/users/auth/logindata.token، مع data.userمسارات الطلاب
لوحة الإدارةPOST /api/auth/logindata.access_token، مع data.admin (الأدوار والصلاحيات)مسارات الإدارة
  • كلاهما رمز JWT موقّع بـ JWT_SECRET. أرسلهما بالشكل Authorization: Bearer <token>.
  • يدوم الرمز طوال JWT_EXPIRATION، و7d افتراضيًا (متغيرات البيئة). ويعيد تسجيل دخول المسؤول القيمة نفسها في expires_in.
  • لا توجد نقطة نهاية للتجديد. عندما تنتهي صلاحية الرمز، يجيب الطلب التالي بـ 401 ويسجّل العميل الدخول من جديد.
  • تسجيل الخروج (POST /api/users/auth/logout) يطلب من العميل فقط التخلص من رمزه. لا يُلغى أي شيء على الخادم، لذا يبقى الرمز صالحًا حتى تنتهي صلاحيته.
  • يُرفض رمز الطالب على مسارات الإدارة، ورمز المسؤول على مسارات الطلاب، رغم أن كليهما يستخدم المفتاح السري نفسه.
  • يُجاب تسجيل الدخول الفاشل بالرمز 401 وبرسالة واحدة، سواء لم يكن للبريد حساب أو كانت كلمة المرور خاطئة، فلا يمكن استخدام النموذج لمعرفة من يملك حسابًا.
  • تقبل مسارات تسجيل الدخول وإنشاء الحساب وكلمة المرور 10 محاولات في الدقيقة من عنوان واحد، تُحسب لكل مسار على حدة. وبعدها تُجيب بالرمز 429 مع ترويسة Retry-After. يُحفظ العدّ في ذاكرة واجهة API، فيبدأ من جديد عند إعادة التشغيل ويُحسب منفصلًا في كل نسخة.
  1. سجّل الدخول بحساب المدير العام التجريبي

    الطرفية
    curl -X POST http://localhost:8000/api/auth/login \
      -H "Content-Type: application/json" \
      -d '{"email":"admin@learnio.com","password":"Admin@123"}'
    الاستجابة
    {
      "success": true,
      "data": {
        "access_token": "eyJhbGciOiJIUzI1NiIs...",
        "token_type": "Bearer",
        "expires_in": "7d",
        "admin": {
          "id": 1,
          "email": "admin@learnio.com",
          "instructor_id": null,
          "roles": [{ "id": 1, "name": "Super Admin", "guard_name": "web" }],
          "permissions": ["admins.view", "admins.create", "..."]
        }
      },
      "message": "Signed in successfully."
    }
  2. استدعِ مسارًا محميًا بالرمز

    الطرفية
    curl "http://localhost:8000/api/courses?page=1&page_count=5" \
      -H "Authorization: Bearer <access_token>"

    النتيجة المتوقعة: أول خمس دورات، بشكل قائمة الإدارة.

  3. سجّل الدخول بحساب الطالب التجريبي

    تحتوي البيانات النموذجية أيضًا على طالب، demo@learnio.com بكلمة المرور Demo@123:

    الطرفية
    curl -X POST http://localhost:8000/api/users/auth/login \
      -H "Content-Type: application/json" \
      -d '{"email":"demo@learnio.com","password":"Demo@123"}'

    ثم مرّر data.token بالطريقة نفسها، على سبيل المثال إلى GET /api/users/enrollments.

غيّر كلمات المرور التجريبية

تستخدم حسابات البيانات النموذجية كلمات مرور منشورة: Admin@123 للمدير العام، وadmin123 لبقية الطاقم، وDemo@123 للطالب التجريبي. غيّرها، أو ابدأ بجداول فارغة، قبل إطلاق الموقع.

الصلاحيات

يتحقق كل مسار إداري من الرمز أولًا، ثم من الصلاحية التي يحددها. تُسمّى الصلاحيات بالشكل <module>.<action>، ويملك المسؤول كل صلاحيات كل دور لديه. وحيث يحدد المسار عدة صلاحيات، تكفي أي واحدة منها. في جداول الإدارة أدناه، يعني اسم الصلاحية في عمود من يحق له استدعاؤه مسؤولًا تمنحه أدواره تلك الصلاحية.

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

الوحدةالصلاحيات
المسؤولونadmins.view, admins.create, admins.edit, admins.delete, admins.assign_roles
الأدوارroles.view, roles.create, roles.edit, roles.delete, roles.assign_permissions
الإعداداتsettings.view, settings.edit
الطلابstudents.view, students.create, students.update, students.delete, students.restore, students.verify
الفئاتcategories.view, categories.create, categories.edit, categories.delete, categories.restore
الدوراتcourses.view, courses.create, courses.edit, courses.delete, courses.restore
المناهجcurriculum.view, curriculum.create, curriculum.edit, curriculum.delete
المدرّسونinstructors.view, instructors.create, instructors.edit, instructors.delete, instructors.restore
التسجيلاتenrollments.view, enrollments.create, enrollments.edit, enrollments.delete
الطلباتorders.view, orders.create, orders.edit, orders.delete
التقييماتreviews.view, reviews.edit, reviews.delete, reviews.restore
الحصص المباشرةlive_sessions.view, live_sessions.create, live_sessions.edit, live_sessions.delete
الواجباتassignments.view, assignments.create, assignments.edit, assignments.delete
المدونةblog.view, blog.create, blog.edit, blog.delete, blog.restore
المساعد الذكيai_chat.use, ai_chat.view_models

كل صلاحية قراءة تنتهي بـ .view ولا تنتهي بها أي صلاحية أخرى: دور المشاهد (Viewer) التجريبي مبني على هذه القاعدة. الأدوار التي تنشئها البيانات النموذجية:

الدوريمنح
المدير العام (Super Admin)كل شيء
لوحة الإدارةكل شيء باستثناء roles.* وadmins.* وsettings.edit
المدير (Manager)الدورات، والمناهج، والفئات، والمدرّسون، والتسجيلات، والطلبات من دون الحذف، إضافة إلى students.view وreviews.view وreviews.edit
المحرر (Editor)blog.*, reviews.view, reviews.edit, categories.view, courses.view, instructors.view
المشاهد (Viewer)كل صلاحية .view
المدرّسالحصص المباشرة، والواجبات، والمناهج، وcourses.view، وcourses.create، وcourses.edit، وقراءة الطلاب والتسجيلات والتقييمات

يحمل حساب المسؤول المرتبط بمدرّس الحقل instructor_id في إجابة تسجيل الدخول، ويُقيَّد بدوراته الخاصة إضافة إلى صلاحياته: لا تعرض القوائم إلا تلك الدورات وطلابها، وأي عملية كتابة خارجها تجيب بـ 403.

عندما تتغير أدوار مسؤول، تُبلَّغ لوحة الإدارة عبر مقبس /auth (الحدث permissions-updated) لتعيد تحميل GET /api/auth/me. ولا يقبل هذا المقبس إلا رموز المسؤولين.

الكتالوج العام

لا حاجة إلى رمز. هذه هي المسارات التي تستدعيها الصفحات العامة في موقع الطلاب.

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/healthأي شخصفحص الجاهزية
GET/api/users/coursesأي شخصيسرد الدورات العامة المنشورة، مقسّمة إلى صفحات (page_count، والإعداد courses_per_page افتراضيًا)، مع عوامل التصفية والترتيب
GET/api/users/courses/categoriesأي شخصالتصنيفات التي تضم دورة عامة واحدة على الأقل، مع أعدادها
GET/api/users/courses/:slugأي شخصدورة عامة منشورة واحدة مع أقسامها ودروسها. والمسودة تُجاب بالرمز 404. ولا تحمل محتواها وفيديوها إلا دروس المعاينة المجانية.
GET/api/users/courses/:slug/reviewsأي شخصالتقييمات المنشورة للدورة، الأحدث تحديثًا أولًا، مقسّمة إلى صفحات (page_count، و5 افتراضيًا)
GET/api/users/Instructorsأي شخصدليل المدرّسين، مقسّم إلى صفحات (per_page، وهو 8 افتراضيًا)، مع التصفية حسب specialty
GET/api/users/Instructors/:usernameأي شخصمدرّس واحد مع دوراته العامة
GET/api/users/blogأي شخصالمقالات المنشورة، الأحدث أولًا، مقسّمة إلى صفحات (page_count، وهو 9 افتراضيًا)، مع التصفية حسب tag
GET/api/users/blog/tagsأي شخصكل وسم مستخدم، مع عدد المقالات التي تحمله
GET/api/users/blog/:slugأي شخصمقالة منشورة واحدة
GET/api/users/platform/figuresأي شخصأرقام الصفحة الرئيسية: الطلاب، والدورات، والمدرّسون، والدول، ونسبة الرضا
GET/api/categoriesأي شخصقائمة التصنيفات، مقسّمة إلى صفحات، مع search وis_active وparent_id وhas_courses
GET/api/categories/rootsأي شخصالتصنيفات الرئيسية
GET/api/categories/slug/:slugأي شخصتصنيف واحد حسب المعرّف النصي (slug)
GET/api/categories/:idأي شخصتصنيف واحد حسب المعرّف (id)
GET/api/helpers/countriesأي شخصالدول لحقل اختيار، بلغة الطلب
GET/api/shop/payment-methodsأي شخصطرق الدفع التي يجب أن تعرضها صفحة الدفع، وأيها مستضافة

الحرف الكبير I في /api/users/Instructors هو المسار الذي يستدعيه موقع الطلاب؛ والمطابقة لا تميّز بين الأحرف الكبيرة والصغيرة.

تسجيل الطلاب وتسجيل دخولهم

يستخدم موقع الطلاب المسارات تحت /api/users/auth. يسجّل إنشاء الحساب دخول الطالب مباشرة ويرسل إليه رابط تأكيد بالبريد؛ ويظل بإمكان الحساب غير المؤكد التصفح والشراء.

الطريقةالمسارمن يحق له استدعاؤهوظيفته
POST/api/users/auth/registerأي شخصينشئ الحساب (first_name وlast_name وemail وpassword من 8 أحرف أو أكثر، وphone اختياريًا) ويسجّل الدخول. يوضح data.verification_email_sent ما إذا كانت الرسالة قد أُرسلت.
POST/api/users/auth/loginأي شخصيسجّل الدخول بـ email وpassword، ويجيب بـ token وuser
POST/api/users/auth/logoutأي شخصلا شيء يُلغى؛ يتيح للعميل مسح الرمز المميز الخاص به
POST/api/users/auth/resendأي شخصيعيد إرسال رابط التأكيد إلى email
POST/api/users/auth/verify-emailأي شخصيؤكد العنوان باستخدام token من الرابط (صالح لمدة 24 ساعة)
POST/api/users/auth/forgot-passwordأي شخصيرسل رابط إعادة تعيين إلى email (صالح لمدة ساعة واحدة)
POST/api/users/auth/reset-passwordأي شخصيضبط password جديدة باستخدام token من الرابط
GET/api/users/auth/meالطالبالطالب المسجّل دخوله

يُجيب resend وforgot-password بالطريقة نفسها سواء كان للعنوان حساب أم لا، فلا يمكن استخدامهما لمعرفة من المسجّل. وتسجيل الدخول وإنشاء الحساب وresend وforgot-password وreset-password محدودة المعدّل (المصادقة).

تعمل مجموعة ثانية من مسارات الطلاب تحت /api/students/auth على الحسابات نفسها، وتجيب أيضًا بـ token وuser. لا يستخدمها موقع الطلاب؛ فضّل /api/users/auth.

الطريقةالمسارمن يحق له استدعاؤهوظيفته
POST/api/students/auth/registerأي شخصينشئ حساب طالب ويسجّل الدخول، دون رسالة تأكيد
POST/api/students/auth/loginأي شخصيسجّل الدخول
GET/api/students/auth/meالطالبالملف الشخصي للطالب المسجّل دخوله
PATCH/api/students/auth/meالطالبيحدّث الاسم أو البريد الإلكتروني أو الهاتف
PATCH/api/students/auth/me/passwordالطالبيغيّر كلمة المرور
POST/api/students/auth/forgot-passwordأي شخصيرسل رابط إعادة تعيين إلى email، ويُجيب بالطريقة نفسها سواء كان للعنوان حساب أم لا
POST/api/students/auth/reset-passwordأي شخصيضبط كلمة مرور جديدة باستخدام رمز إعادة التعيين

الملف الشخصي للطالب ودوراته وتقدّمه

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

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/users/profileالطالبالطالب المسجّل دخوله
PATCH/api/users/profileالطالبيحدّث first_name أو last_name أو email أو phone
PATCH/api/users/profile/passwordالطالبيغيّر كلمة المرور (الحالية وجديدة من 8 أحرف أو أكثر)
GET/api/users/dashboard/overviewالطالبكل ما تعرضه الشاشة الرئيسية للوحة الطالب، في استدعاء واحد
GET/api/users/dashboard/kpisالطالبالأرقام الرئيسية للطالب
GET/api/users/dashboard/radarالطالبمخطط المهارات، من الإعداد dashboard_radar_metrics
GET/api/users/enrollmentsالطالبدورات الطالب، مقسّمة إلى صفحات (page_count، و100 افتراضيًا)، مع التصفية حسب type وsearch وstatus
GET/api/users/enrollments/courses/:codeالطالبالمحتوى الكامل لدورة يملكها الطالب، مع حالة كل درس والتقدّم
PATCH/api/users/enrollments/courses/:codeالطالبيسجّل آخر درس فُتح (last_accessed_lesson_id)
POST/api/users/enrollments/lessons/:lessonCode/completeالطالبيحدّد الدرس كمكتمل ويحدّث تقدّم الدورة
GET/api/users/enrollments/lessons/:lessonCode/noteالطالبملاحظة الطالب على درس
PUT/api/users/enrollments/lessons/:lessonCode/noteالطالبيحفظ الملاحظة (body)
GET/api/users/searchالطالببحث شامل (q، وlimit لكل نوع): دورات الطالب، والكتالوج، والمدرّسون، وغير ذلك
GET/api/users/courses/:courseId/reviewالطالبتقييم الطالب نفسه للدورة، أو null إذا لم يقيّمها
PUT/api/users/courses/:courseId/reviewالطالبيكتب تقييم الطالب أو يستبدله: rating من 1 إلى 5، وcomment اختياري حتى 2,000 حرف
DELETE/api/users/courses/:courseId/reviewالطالبيسحب تقييم الطالب

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

  • يكون التقييم published فورًا، أو pending إلى أن يعتمده مشرف عندما تكون قيمة الإعداد reviews_require_approval هي true. وتعديل تقييم أخفاه مشرف يعيده إلى pending.
  • التقييم الذي حذفه مشرف يعود بالحالة status: removed ولا يمكن تعديله ولا سحبه (403).
  • كل كتابة تعيد حساب تقييم الدورة وعدد تقييماتها، وكذلك تقييم مدرّسها وعدده.
  • التقييم الجديد، والتعديل الذي ينتظر الموافقة، يُشعِران الطاقم الذي يملك reviews.view.

الاختبارات والواجبات والتقويم

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/users/quizzes?course_id=الطالباختبارات دورة يملكها الطالب
GET/api/users/quizzes/:idالطالباختبار واحد بأسئلته، دون الإجابات
GET/api/users/quizzes/:id/attemptsالطالبمحاولات الطالب السابقة
POST/api/users/quizzes/:id/attemptsالطالبيرسل answers (معرّف السؤال مقابل معرّفات الخيارات المختارة) ويعيد النتيجة
GET/api/users/dashboard/calendarالطالبالحصص ومواعيد تسليم الواجبات بين from وto (تواريخ ISO، 7 أيام افتراضيًا، و92 يومًا كحد أقصى)
POST/api/users/dashboard/calendar/assignments/:id/submitالطالبيسلّم واجبًا (body)
DELETE/api/users/dashboard/calendar/assignments/:id/submitالطالبيسحب تسليمًا

مسارات الحصص المباشرة في التقويم موصوفة في الحصص المباشرة.

رسائل الطلاب وإشعاراتهم

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/users/conversationsالطالبمحادثات الطالب مع مدرّسيه
POST/api/users/conversationsالطالبيفتح المحادثة مع مدرّس course_id، أو يعيدها إن كانت موجودة
GET/api/users/conversations/:id/messagesالطالبالرسائل في محادثة واحدة
POST/api/users/conversations/:id/messagesالطالبيرسل رسالة: body، أو صورة (attachment_url، attachment_name، attachment_type)، أو كليهما
PATCH/api/users/conversations/:id/readالطالبيحدّد المحادثة كمقروءة
PATCH/api/users/conversations/:id/unreadالطالبيحدّدها كغير مقروءة
GET/api/users/notificationsالطالبإشعارات الطالب
PATCH/api/users/notifications/:id/readالطالبيحدّد إشعارًا واحدًا كمقروء
PATCH/api/users/notifications/read-allالطالبيحدّد الكل كمقروء
DELETE/api/users/notifications/:idالطالبيحذف إشعارًا واحدًا

تُدفع الإشعارات الجديدة أيضًا عبر Socket.IO، على مساحة الأسماء /notifications على عنوان واجهة API من دون /api. مرّر الرمز المميز في auth.token أثناء المصافحة واستمع إلى notification:created. يستخدم المسؤولون المقبس نفسه برموزهم الخاصة.

الدفع والمدفوعات

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/shop/payment-methodsأي شخصطرق الدفع methods التي تعرضها صفحة الدفع وأيها hosted
POST/api/shop/checkoutالطالبيشتري course_id، أو ما يصل إلى 50 من course_ids في عملية دفع واحدة، مع payment_method (card أو paypal) وlocale
POST/api/shop/orders/:reference/settleالطالبيُكمل الدفع المستضاف عند عودة المشتري. مطلوب لـ PayPal؛ ولا يفعل شيئًا مع Stripe.
GET/api/shop/ordersالطالبطلبات الطالب
POST/api/webhooks/payments/stripeStripe، موقَّعيُتمّ الطلبات أو يُفشلها أو يستردّها بناءً على أحداث Stripe
POST/api/webhooks/payments/paypalPayPal، موقَّعيُتمّ الطلبات أو يُفشلها أو يستردّها بناءً على أحداث PayPal

عندما تجيب صفحة الدفع بـ redirect_url، وجّه المشتري إليه واعتبر الطلب pending: يُمنح المقعد عندما يؤكد الـ webhook الخاص بمعالج الدفع العملية، لا عند العودة. يتحقق كل webhook من توقيع معالج الدفع ويجيب بـ 401 عند عدم التطابق. تُطبَّق الأحداث مرة واحدة، مهما كرّر معالج الدفع المحاولة.

تمر الدورة المجانية (السعر 0) عبر المسار نفسه ولا تصل إلى أي معالج دفع، فتعمل دون أي مفاتيح دفع. يُكتب الطلب بالحالة paid مع gateway: "free" وredirect_url: null، ويُمنح المقعد فورًا، ويتلقى الطالب رسالة التسجيل دون إيصال. وتُحسب الطلبات المجانية تسجيلات لا مبيعات: فهي مستبعدة من متوسط قيمة الطلب.

إعداد معالجات الدفع واشتراكات الـ webhook الخاصة بها: المدفوعات.

تسجيل دخول المسؤولين وحسابات الطاقم

الطريقةالمسارمن يحق له استدعاؤهوظيفته
POST/api/auth/loginأي شخصيسجّل دخول مسؤول، ويُجيب بـ access_token والأدوار والصلاحيات. محدود المعدّل.
GET/api/auth/meأي مسؤول مسجّل دخولهالمسؤول المسجّل دخوله مع أدواره وصلاحياته
GET/api/adminsadmins.viewقائمة الطاقم، مع التصفية حسب email وname وphone وrole_id
GET/api/admins/statisticsadmins.viewأعداد الطاقم
GET/api/admins/:idadmins.viewمسؤول واحد
POST/api/adminsadmins.createينشئ مسؤولًا
PATCH/api/admins/:idadmins.editيحدّث مسؤولًا
PATCH/api/admins/:id/rolesadmins.assign_rolesيستبدل أدوار المسؤول (role_ids)
DELETE/api/admins/:idadmins.deleteيحذف مسؤولًا
PATCH/api/admins/profileأي مسؤول مسجّل دخولهيحدّث اسم المسؤول المسجّل دخوله وبيانات الاتصال به وصورته
PATCH/api/admins/profile/passwordأي مسؤول مسجّل دخولهيغيّر كلمة مرور المسؤول المسجّل دخوله الخاصة به

عنوان البريد يخص مسؤولًا واحدًا، حتى لو كان محذوفًا: إنشاء مسؤول، أو تغيير بريد إلى عنوان مستخدم، يُجاب بالرمز 409.

الأدوار

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/rolesroles.viewالأدوار، مقسّمة إلى صفحات عند إرسال page، مع التصفية حسب name وguard_name وcreated_from وcreated_to
GET/api/roles/statisticsroles.viewأعداد الأدوار
GET/api/roles/selectroles.viewكل الأدوار، لأداة اختيار
GET/api/roles/permissionsroles.viewكل الصلاحيات، مجمّعة حسب الوحدة
GET/api/roles/:idroles.viewدور واحد بصلاحياته
POST/api/rolesroles.createينشئ دورًا (name)
PUT/api/roles/:idroles.editيعيد تسمية دور
POST/api/roles/:id/permissionsroles.assign_permissionsيستبدل صلاحيات الدور بـ permissions، وهي قائمة أسماء
DELETE/api/roles/:idroles.deleteيحذف دورًا

الطلاب

يُشار إلى حسابات الطلاب بقيمة username. حذف أحدها حذف مؤقت يمكن التراجع عنه.

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/usersstudents.viewالطلاب، مع search وemail وphone وcountry_id وusername وfirst_name وlast_name وfrom_date وto_date وverified
GET/api/users/statisticstudents.viewأعداد الطلاب
GET/api/users/:usernamestudents.viewطالب واحد
POST/api/usersstudents.createينشئ طالبًا
PATCH/api/users/:usernamestudents.updateيحدّث طالبًا
PATCH/api/users/:username/change-passwordstudents.updateيضبط كلمة مرور طالب
POST/api/users/:username/resend-verification-emailstudents.updateيرسل رابط التأكيد مجددًا. تكون data.sent بقيمة false وdata.simulated بقيمة true عندما لا يكون هناك مزوّد بريد وذهب الرابط إلى السجل. 409 إذا كان مؤكَّدًا، و429 عندما تلقى العنوان رسائل كثيرة، و503 عندما رفض المزوّد.
POST/api/users/:username/make-verifiedstudents.verifyيحدّد البريد الإلكتروني كمؤكَّد
POST/api/users/:username/make-unverifiedstudents.verifyيحدّد البريد الإلكتروني كغير مؤكَّد
DELETE/api/users/:usernamestudents.deleteينقل الطالب إلى سلة المحذوفات
GET/api/users/deletedstudents.view أو students.delete أو students.restoreالطلاب المحذوفون
GET/api/users/deleted/:usernamestudents.view أو students.delete أو students.restoreطالب محذوف واحد
POST/api/users/deleted/:username/restorestudents.restoreيستعيد طالبًا محذوفًا

المدرّسون

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/instructorsinstructors.viewالمدرّسون، مع search وspecialty وstatus وis_featured
GET/api/instructors/statisticinstructors.viewأعداد المدرّسين
GET/api/instructors/username/:usernameinstructors.viewمدرّس واحد حسب اسم المستخدم
GET/api/instructors/:idinstructors.viewمدرّس واحد
POST/api/instructorsinstructors.createينشئ مدرّسًا
PATCH/api/instructors/:idinstructors.editيحدّث مدرّسًا
DELETE/api/instructors/:idinstructors.deleteينقل مدرّسًا إلى سلة المحذوفات
GET/api/instructors/deletedinstructors.view أو instructors.delete أو instructors.restoreالمدرّسون المحذوفون
POST/api/instructors/deleted/:id/restoreinstructors.restoreيستعيد واحدًا

يراسل حساب المدرّس طلابه عبر هذه المسارات، التي تجيب بـ 403 للمسؤول غير المرتبط بمدرّس:

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/conversationsحساب المدرّسمحادثات المدرّس
GET/api/conversations/with/:userIdحساب المدرّسالدورات المشتركة بين المدرّس وطالب ما، لبدء محادثة منها
POST/api/conversationsحساب المدرّسيفتح محادثة مع user_id، أو يعيدها إن كانت موجودة، اختياريًا حول course_id
GET/api/conversations/:id/messagesحساب المدرّسالرسائل في محادثة واحدة
POST/api/conversations/:id/messagesحساب المدرّسيرسل رسالة
PATCH/api/conversations/:id/readحساب المدرّسيحدّدها كمقروءة
PATCH/api/conversations/:id/unreadحساب المدرّسيحدّدها كغير مقروءة

الفئات

القراءات متاحة للجميع ومدرجة مع الكتالوج العام. أما الكتابة فتحتاج إلى صلاحية:

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/categories/statisticcategories.viewأعداد التصنيفات
POST/api/categoriescategories.createينشئ تصنيفًا
PATCH/api/categories/:idcategories.editيحدّث تصنيفًا
DELETE/api/categories/:idcategories.deleteينقل تصنيفًا إلى سلة المحذوفات
GET/api/categories/deletedcategories.delete أو categories.restoreالتصنيفات المحذوفة
POST/api/categories/deleted/:id/restorecategories.restoreيستعيد واحدًا

الدورات

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/coursescourses.viewالدورات، مع search وcategory_id وinstructor_id وstatus وtype وis_public وis_featured
GET/api/courses/statisticcourses.viewأعداد الدورات
GET/api/courses/slug/:slugcourses.viewدورة واحدة حسب المعرّف النصي (slug)
GET/api/courses/:idcourses.viewدورة واحدة
POST/api/coursescourses.createينشئ دورة
PATCH/api/courses/:idcourses.editيحدّث دورة
DELETE/api/courses/:idcourses.deleteينقل دورة إلى سلة المحذوفات
GET/api/courses/deletedcourses.delete أو courses.restoreالدورات المحذوفة
POST/api/courses/deleted/:id/restorecourses.restoreيستعيد واحدًا

المنهج: الأقسام والدروس والموارد

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/courses/:courseId/sectionscurriculum.viewأقسام دورة
POST/api/courses/:courseId/sectionscurriculum.createيضيف قسمًا
POST/api/courses/:courseId/sections/reordercurriculum.editيضبط ترتيب الأقسام من ids
GET/api/sections/:idcurriculum.viewقسم واحد
PATCH/api/sections/:idcurriculum.editيحدّث قسمًا
DELETE/api/sections/:idcurriculum.deleteيحذف قسمًا
GET/api/sections/:sectionId/lessonscurriculum.viewدروس قسم
POST/api/sections/:sectionId/lessonscurriculum.createيضيف درسًا
POST/api/sections/:sectionId/lessons/reordercurriculum.editيضبط ترتيب الدروس من ids
GET/api/lessons/:idcurriculum.viewدرس واحد
PATCH/api/lessons/:idcurriculum.editيحدّث درسًا
DELETE/api/lessons/:idcurriculum.deleteيحذف درسًا
GET/api/lessons/:lessonId/resourcescurriculum.viewالموارد القابلة للتنزيل في درس
POST/api/lessons/:lessonId/resourcescurriculum.editيرفق موردًا
PATCH/api/lesson-resources/:idcurriculum.editيحدّث موردًا
DELETE/api/lesson-resources/:idcurriculum.editيزيل موردًا

الاختبارات والواجبات

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/quizzes?course_id=courses.viewاختبارات دورة (course_id مطلوب)
GET/api/quizzes/:idcourses.viewاختبار واحد بأسئلته وإجاباته
POST/api/quizzescourses.createينشئ اختبارًا
PATCH/api/quizzes/:idcourses.editيحدّث اختبارًا
DELETE/api/quizzes/:idcourses.deleteيحذف اختبارًا
POST/api/quizzes/:id/questionscourses.editيضيف سؤالًا
PATCH/api/quizzes/:id/questions/:questionIdcourses.editيحدّث سؤالًا
DELETE/api/quizzes/:id/questions/:questionIdcourses.editيحذف سؤالًا
GET/api/assignmentsassignments.viewالواجبات، مع search وcourse_id وlesson_id وstatus وfrom وto
GET/api/assignments/:idassignments.viewواجب واحد
GET/api/assignments/:id/submissionsassignments.viewالتسليمات التي تنتظر التصحيح
PATCH/api/assignments/submissions/:submissionId/gradeassignments.editيصحّح تسليمًا
POST/api/assignmentsassignments.createينشئ واجبًا
PATCH/api/assignments/:idassignments.editيحدّث واجبًا
DELETE/api/assignments/:idassignments.deleteيحذف واجبًا

التسجيلات والطلبات

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/enrollmentsenrollments.viewالتسجيلات، مع search وcourse_id وuser_id وstatus وdate_from وdate_to
GET/api/enrollments/statisticenrollments.viewأعداد التسجيلات
GET/api/enrollments/:idenrollments.viewتسجيل واحد
POST/api/enrollmentsenrollments.createيسجّل طالبًا يدويًا
PATCH/api/enrollments/:idenrollments.editيحدّث تسجيلًا
DELETE/api/enrollments/:idenrollments.deleteيزيل تسجيلًا
GET/api/ordersorders.viewالطلبات، مع search وstatus وpayment_method وcourse_id وuser_id وdate_from وdate_to وpage وlimit وsort_by وsort_order
GET/api/orders/revenueorders.viewالإيرادات بين date_from وdate_to. ويستبعد متوسط قيمة الطلب الطلبات المجانية.
GET/api/orders/revenue/seriesorders.viewالإيرادات اليومية لآخر days يومًا (30 افتراضيًا، و365 كحد أقصى)
GET/api/orders/:idorders.viewطلب واحد
POST/api/ordersorders.createيسجّل مقعدًا دُفع ثمنه في مكان آخر
PATCH/api/orders/:idorders.editيحدّث طلبًا
DELETE/api/orders/:idorders.deleteيحذف طلبًا

حالة الطلب status هي pending أو paid أو failed أو refunded. ويذكر gateway معالج الدفع الذي حصّل المبلغ، أو demo للمحاكي المدمج، أو free لدورة لم تكلّف شيئًا.

التقييمات

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/course-reviewsreviews.viewالتقييمات، مع search وcourse_id وuser_id وrating وstatus
GET/api/course-reviews/statisticreviews.viewأعداد التقييمات
GET/api/course-reviews/:idreviews.viewتقييم واحد
PATCH/api/course-reviews/:idreviews.editيراجع تقييمًا: قيمة status هي published أو pending أو hidden
DELETE/api/course-reviews/:idreviews.deleteينقل تقييمًا إلى سلة المحذوفات
GET/api/course-reviews/deletedreviews.delete أو reviews.restoreالتقييمات المحذوفة
POST/api/course-reviews/deleted/:id/restorereviews.restoreيستعيد واحدًا

يكتب الطلاب تقييماتهم عبر مسارات الطالب، وتقرأ صفحة الدورة المنشور منها من الكتالوج العام. كل تغيير إشرافي يعيد حساب تقييم الدورة وتقييم المدرّس.

المدونة

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/blogblog.viewالمقالات بكل حالاتها، مع search وcategory_slug وstatus وtag
GET/api/blog/statisticblog.viewأعداد المقالات
GET/api/blog/slug/:slugblog.viewمقالة واحدة حسب المعرّف النصي (slug)
GET/api/blog/:idblog.viewمقالة واحدة
POST/api/blogblog.createينشئ مقالة
PATCH/api/blog/:idblog.editيحدّث مقالة
DELETE/api/blog/:idblog.deleteينقل مقالة إلى سلة المحذوفات
GET/api/blog/deletedblog.delete أو blog.restoreالمقالات المحذوفة
POST/api/blog/deleted/:id/restoreblog.restoreيستعيد واحدًا

الإعدادات

تُخزَّن إعدادات المنصة كأزواج من المفاتيح والقيم، ويُشار إليها بقيمة key.

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/settingssettings.viewالإعدادات، مع search وcategory وtype
GET/api/settings/:keysettings.viewإعداد واحد
PATCH/api/settings/:keysettings.editيغيّر قيمة إعداد
DELETE/api/settings/:keysettings.editيحذف إعدادًا

تنشئ أداة البذر هذه الإعدادات الستة، ويقرأ كلًّا منها واجهة API أو لوحة الطالب:

المفتاحالقيمة الأوليةوظيفته
site_nameLearnioاسم المنتج المكتوب في كل رسالة بريد ترسلها واجهة API
default_localeenاللغة المستخدمة عندما لا يحدد الطلب لغة مدعومة. والقيمة التي ليست لغة مدعومة تُرفض بالرمز 400.
support_emailsupport@learnio.comعنوان الرد لكل رسالة بريد، فيصل الرد إلى شخص حقيقي
courses_per_page12حجم صفحة الكتالوج العام عندما لا يحدد الطلب حجمًا (من 1 إلى 100)
reviews_require_approvalfalseعند true، ينتظر تقييم الطالب بالحالة pending حتى ينشره مشرف
dashboard_radar_metricsخريطة JSON من المقياس إلى الدرجةمخطط المهارات في لوحة الطالب

يسري التغيير على الطلب التالي أو الرسالة التالية، دون إعادة تشغيل. وتشغيل أداة البذر مجددًا يضيف الإعداد الناقص لكنه لا يستبدل قيمة محفوظة أبدًا.

رفع الوسائط

الطريقةالمسارمن يحق له استدعاؤهوظيفته
POST/api/helpers/uploadأي مسؤول مسجّل دخوله، أو طالبيرفع ملفًا واحدًا إلى مخزن الوسائط ويجيب بعناوينه

أرسل multipart/form-data مع الملف في file، بحجم يصل إلى 150 ميغابايت، واختياريًا path (المجلد، وهو uploads افتراضيًا)، وfor (إعداد مسبق لحجم الصورة)، وtype (القيمة video لتخطي معالجة الصور). يُعاد تحجيم الصور إلى عدة نسخ؛ أما الفيديو (mp4، webm، mov، m4v) فيُخزَّن كما هو. يحتاج إلى إعدادات المخزن في تخزين الوسائط.

يحتاج المسار إلى رمز مسؤول أو طالب، ويُتحقق منه قبل قراءة الملف. ويجب أن تكون path أحد المجلدات المسرودة في back-end/src/modules/helpers/upload/upload-folders.constants.ts؛ وأي مجلد آخر يُجاب بالرمز 400. يستطيع المسؤول الرفع إلى uploads وadmins/profile وadmins/profiles وusers/profiles وblog وcategories وcourses وinstructors وmessages وai-chat. ولا يستطيع الطالب الرفع إلا إلى messages، للصور التي يرفقها بمحادثة. والشاشة الجديدة التي ترفع إلى مجلد خاص بها تحتاج إلى إضافة ذلك المجلد إلى القائمة.

الطرفية
curl -X POST http://localhost:8000/api/helpers/upload \
  -H "Authorization: Bearer <access_token>" \
  -F "file=@cover.jpg" -F "path=courses"

الإشعارات والبحث والإحصاءات

الطريقةالمسارمن يحق له استدعاؤهوظيفته
GET/api/notificationsأي مسؤول مسجّل دخولهإشعارات المسؤول المسجّل دخوله وعدد غير المقروء منها
PATCH/api/notifications/read-allأي مسؤول مسجّل دخولهيحدّد الكل كمقروء، ويجيب بالقائمة كاملة
PATCH/api/notifications/:id/readأي مسؤول مسجّل دخولهيحدّد إشعارًا واحدًا كمقروء، ويجيب بالقائمة كاملة
DELETE/api/notifications/:idأي مسؤول مسجّل دخولهيحذف إشعارًا واحدًا، ويجيب بالقائمة كاملة
GET/api/searchأي مسؤول مسجّل دخولهبحث شامل (q، وlimit لكل نوع). لا يُبحث إلا في الأنواع التي تسمح بها صلاحيات المسؤول.
GET/api/statistics/trendscourses.viewالأرقام التي تقف خلف كل بطاقة إحصائية، في استدعاء واحد
GET/api/statistics/overviewcourses.viewالنظرة العامة للصفحة الرئيسية في لوحة الإدارة، خلال days، مع limit صفًا لكل قائمة

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

النوعمتىمن يتلقاه
enrollment_createdيُمنح طالب مقعدًا، بالشراء أو بدورة مجانية أو من الطاقمenrollments.view
course_completedيُنهي طالب دورةenrollments.view
course_review_submittedيترك طالب تقييمًا، أو يعدّل تقييمًا ينتظر الموافقةreviews.view
course_publishedتُنشر دورةcourses.view
student_registeredينشئ طالب حسابًاstudents.view

حساب المسؤول المرتبط بمدرّس لا يُشعَر إلا بما يخص دورات ذلك المدرّس، ولا يُشعَر بالحسابات الجديدة. ويُدفع كل إشعار أيضًا عبر مقبس /notifications لحظة حفظه.

الحصص المباشرة

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

مسارات الحصص المباشرة: جدولة الجلسات، ورموز الدخول التي يتلقاها الطلاب والمضيفون لغرفة Jitsi Meet.

الشهادات

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

مسارات الشهادات: كيف يطلب الطالب شهادة لدورة أنهاها، وعنوان التحقق العام.

المساعد الذكي

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

مسارات المساعد الذكي: بث الرد، وقائمة النماذج، وجلسات المحادثة المحفوظة.

سجل محادثات المساعد

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

حفظ محادثات المساعد وعرضها وإعادة تسميتها.

خادم MCP

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

وحدة MCP التي تقدّم بيانات لوحة الإدارة كأدوات للمساعد.

مسارات وضع العرض التجريبي

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

المسارات التي يستخدمها العرض التجريبي العام: مفتاح العرض التجريبي وحسابات الزوار.

بوابات دفع مخصّصة

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

كيف بُنيت طبقة الدفع: واجهتا البوابة والـ webhook، والـ webhook الخاص بالمحاكي، وإضافة معالج دفع.

توقفت عند خطوة؟

ابحث عن الحل قبل أن تبدأ من جديد.

حل المشكلات

تفضيلات ملفات تعريف الارتباط

نستخدم ملفات تعريف الارتباط لتعزيز تجربة التصفح الخاصة بك وتحليل حركة المرور على الموقع وتخصيص المحتوى. بالنقر على "قبول الكل"، فإنك توافق على استخدامنا لملفات تعريف الارتباط للتحليلات والإعلانات المخصصة.