الواجهة البرمجية ومفاتيح API

مرجع REST API v1 في مُبَرمِج — المصادقة والصلاحيات ونقاط النهاية والسقوف

الواجهة البرمجية v1 ست وعشرون نقطة نهاية في واحد وعشرين ملف مسارات. سبع عشرة منها تقبل مفتاح API وتفتحها صلاحياته، وثلاث لإدارة المفاتيح لا تقبل إلا جلسة صاحب الحساب في المتصفح، وخمس عامة بلا مصادقة. هذه الصفحة تصف ما يفعله الخادم حرفياً.

English

في هذه الصفحة
مرجع REST API v1 في مُبَرمِج: جدول نقاط النهاية وطريقة مصادقة كل منها
مرجع REST API v1 في مُبَرمِج: جدول نقاط النهاية وطريقة مصادقة كل منها

نظرة عامة

عنوان القاعدة: https://moparmeg-ksa.com. كل المسارات أدناه تبدأ بـ/api/v1، والطلبات والردود JSON.

  • بمفتاح API (Bearer): ثماني عشرة نقطة نهاية، تفتح كلاً منها صلاحيتها — المحادثة المتوافقة مع OpenAI والنماذج وتوليد الكود، والمشاريع وصفحاتها ونسخها ونشرها، ونظام التصميم والشعار، والنطاقات، وبناء مراحل القوالب، وGET /api/v1/me الذي يقبل أي مفتاح صالح.
  • بجلسة المتصفح (كوكي): ثلاث نقاط نهاية — عرض المفاتيح، وإنشاء مفتاح، وإبطال مفتاح.
  • عامة بلا مصادقة: خمس نقاط — قائمة القوالب، وقالب واحد، ومكتبة الأقسام، وقائمة التنزيلات، وتنزيل أداة.

هذا كل ما في v1: ست وعشرون نقطة نهاية. بقية مسارات /api/* في المنصة — ومنها الـWebhooks — تخدم لوحة التحكم والمحرّر، وتُصادَق بجلسة المتصفح، ولا تقبل مفتاح API.

المصادقة

الآليةكيف تُرسلأين تُقبلعند الفشل
مفتاح APIالترويسة Authorization: Bearer mop_…كل ما عمود مصادقته «مفتاح» في جدول نقاط النهاية401 {"error":"Invalid API key","code":"API_KEY_INVALID"}؛ و403 API_KEY_SCOPE_REQUIRED لمفتاح صالح بلا الصلاحية
جلسة المتصفحكوكي access_token (httpOnly) الذي يضعه تسجيل الدخولGET وPOST /api/v1/api-keys، DELETE /api/v1/api-keys/{id}401 {"error":"غير مصرّح"}
بلا مصادقة—GET /api/v1/templates، GET /api/v1/templates/{id}، GET /api/v1/sections، GET /api/v1/downloads، GET /api/v1/downloads/{id}—

مفتاح API

المفتاح mop_ يليه 32 محرفاً من A-Z a-z 0-9 _ -. الخادم يرفض الترويسة المشوّهة قبل أي بحث، ثم يبحث عن بصمة المفتاح. الرد واحد (401 Invalid API key بالرمز API_KEY_INVALID) لكل أسباب الرفض: مفتاح مجهول، أو مُبطَل، أو منتهي الصلاحية، أو حساب محذوف، أو ترويسة مشوّهة — فلا يكشف الرد أيها. تنشئ المفتاح من صفحة مفاتيح API.

المفتاح يعمل بصفة صاحبه دائماً، بلا صلاحيات المدير ولو كان صاحبه مديراً، ويرى المشاريع التي يملكها صاحبه وحدها: مشروع غيره 404 «المشروع غير موجود» ولو كان منشوراً أو كان صاحب المفتاح متعاوناً فيه.

جلسة المتصفح

مسارات /api/v1/api-keys لا تقرأ ترويسة Authorization أصلاً: مفتاح API المرسل إليها يعود بـ401. هذا مقصود — مفتاح يستطيع سكّ مفاتيح يحوّل تسريبة واحدة إلى وصول دائم. هذه المسارات مصممة لصفحة المفاتيح في لوحة التحكم، أي لطلبات من المتصفح نفسه وأنت مسجّل الدخول.

الصلاحيات

تُختار عند سكّ المفتاح (الحقل scopes) ولا تُعدَّل بعده. غيابها عند السكّ يعني الافتراضي: كل الصلاحيات عدا publish وdomains:write. مفتاح بلا الصلاحية المطلوبة يُرفض بـ403:

403
{ "error": "هذا المفتاح لا يحمل صلاحية «…».", "code": "API_KEY_SCOPE_REQUIRED", "scope": "publish" }
الصلاحيةالاسم في صفحة المفاتيحنقاط النهايةفي الافتراضي
ai:chatمحادثة الذكاء الاصطناعي والنماذجPOST /api/v1/chat/completions، GET /api/v1/models، POST /api/v1/aiنعم
projects:readقراءة المشاريع وصفحاتها ونسخهاGET /api/v1/projects، GET /api/v1/projects/{id}، GET /api/v1/projects/{id}/pages، GET /api/v1/projects/{id}/versionsنعم
projects:writeإنشاء المشاريع ورفع ملفاتها وإضافة الصفحات وحفظ النسخPOST /api/v1/projects، PUT /api/v1/projects/{id}، POST /api/v1/projects/{id}/pages، POST /api/v1/projects/{id}/versionsنعم
publishنشر المشاريع وإلغاء نشرهاPOST /api/v1/projects/{id}/publishلا
domains:readفحص توفّر النطاقاتGET /api/v1/domains/availabilityنعم
domains:writeطلب شراء النطاقات ونقلهاPOST /api/v1/domains/ordersلا
designتوليد نظام التصميم والشعارPOST /api/v1/design/system، POST /api/v1/design/logoنعم
templatesبناء مراحل القوالبPOST /api/v1/templates/buildنعم

المفاتيح القديمة (سُكّت قبل الصلاحيات، فصلاحياتها فارغة) تبقى تعمل على POST /api/v1/ai وGET وPOST /api/v1/projects وعلى GET /api/v1/me، وتُرفض بـ403 API_KEY_SCOPE_REQUIRED على غيرها، برسالة تطلب سكّ مفتاح بصلاحيات.

جدول نقاط النهاية

الطريقةالمسارالمصادقةالوصف
GET/api/v1/meمفتاح (أي مفتاح صالح)الحساب والباقة والحصة وصلاحيات المفتاح
POST/api/v1/chat/completionsمفتاح ai:chatمحادثة متوافقة مع OpenAI، مع البثّ والأدوات
GET/api/v1/modelsمفتاح ai:chatقائمة النماذج بصيغة OpenAI
POST/api/v1/aiمفتاح ai:chat (والقديم)توليد ملفات كود من وصف
GET/api/v1/projectsمفتاح projects:read (والقديم)آخر 50 مشروعاً حُدّثت من مشاريعك
POST/api/v1/projectsمفتاح projects:write (والقديم)إنشاء مشروع بفحوص لوحة التحكم نفسها
GET/api/v1/projects/{id}مفتاح projects:readالمشروع كاملاً بملفاته، مع filesDigest (بصمة الملفات)
PUT/api/v1/projects/{id}مفتاح projects:writeحفظ ملفات المشروع من الجهاز (تطبيق «مبرمج إيجنت»): files وexpectedFilesDigest من آخر قراءة؛ بصمة لا تطابق 409، حجم فوق الباقة 413، مكدّس خارج العقد 403 STACK_NOT_IN_PLAN؛ تُحفظ نسخة قبل الكتابة
GET/api/v1/projects/{id}/pagesمفتاح projects:readالصفحات المكتشفة في ملفات المشروع
POST/api/v1/projects/{id}/pagesمفتاح projects:writeإضافة صفحة
GET/api/v1/projects/{id}/versionsمفتاح projects:readقائمة النسخ، أو نسخة واحدة بملفاتها
POST/api/v1/projects/{id}/versionsمفتاح projects:writeحفظ نسخة من الملفات الحالية
POST/api/v1/projects/{id}/publishمفتاح publishنشر المشروع أو إلغاء نشره
POST/api/v1/design/systemمفتاح designنظام تصميم يُحفظ في المشروع (بثّ SSE)
POST/api/v1/design/logoمفتاح designشعار SVG
GET/api/v1/domains/availabilityمفتاح domains:readهل النطاق متاح للتسجيل
POST/api/v1/domains/ordersمفتاح domains:writeطلب شراء نطاق أو نقله
POST/api/v1/templates/buildمفتاح templatesبناء مرحلة من قالب
GET/api/v1/templatesعامةقائمة القوالب الصناعية وفئاتها
GET/api/v1/templates/{id}عامةقالب واحد بمراحله
GET/api/v1/sectionsعامةمكتبة الأقسام وتخطيطاتها
GET/api/v1/downloadsعامةالأدوات المتوفرة للتنزيل فعلاً
GET/api/v1/downloads/{id}عامةتنزيل أداة
GET/api/v1/api-keysجلسة المتصفحمفاتيحك الفعّالة مخفية
POST/api/v1/api-keysجلسة المتصفحسكّ مفتاح جديد (يُعاد كاملاً مرة واحدة)
DELETE/api/v1/api-keys/{id}جلسة المتصفحإبطال مفتاح

GET /api/v1/me

يقبل أي مفتاح صالح، قديماً كان أو بصلاحيات، ويجيب حتى في باقة المجانية ليعرض برنامجك الباقة وسبب منع الذكاء الاصطناعي. لا يُحسب في سقف الساعة للباقة، وله سقف مستقل 120 نداءً في الساعة (429 «كثرة الطلبات — حاول لاحقًا»). لا يعيد البريد الإلكتروني.

200
{
  "data": {
    "id": "…",
    "name": "…",
    "plan": { "id": "…", "tier": "…", "label": "…" },
    "ai": {
      "allowed": true,
      "reason": null,
      "quota": { "used": 0, "limit": 0, "remaining": 0, "resetAt": …, "window": "24h-rolling" }
    },
    "api": { "callsPerHour": 0 },
    "key": { "id": "…", "scopes": ["ai:chat", "projects:read"], "legacy": false }
  }
}

حين لا تشمل الباقة الذكاء الاصطناعي تكون allowed خطأ، وreason نص السبب، وquota تساوي null.

GET /api/v1/projects

يعيد حتى 50 مشروعاً من المشاريع التي تملكها، مرتبة بالأحدث تحديثاً. لا يوجد ترقيم صفحات، وtotal هو عدد العناصر المعادة (50 على الأكثر) لا عدد مشاريعك الكلي. ملفات المشاريع لا تُعاد هنا؛ اطلب المشروع الواحد بـGET /api/v1/projects/{id}.

200
{
  "data": [
    {
      "id": "…",
      "title": "…",
      "slug": "…",
      "status": "…",
      "views": 0,
      "forks": 0,
      "createdAt": "2026-09-01T10:00:00.000Z",
      "updatedAt": "2026-09-10T12:00:00.000Z"
    }
  ],
  "total": 1
}

رموز الحالة: 200، 401، 403 (API_REQUIRES_PAID_PLAN أو API_KEY_SCOPE_REQUIRED)، 429 (سقف الساعة).

GET /api/v1/projects/{id}

يعيد سجل المشروع كما خُزّن، ومنه files، في {"data": {…}}. للمشاريع التي يملكها صاحب المفتاح وحده: المشروع الغائب ومشروع غيره — ولو كان منشوراً أو كنت متعاوناً فيه — كلاهما 404 {"error":"المشروع غير موجود"}.

POST /api/v1/projects

ينشئ مشروعاً باسمك بالدالة نفسها التي تستعملها لوحة التحكم، فيمرّ بفحوصها نفسها: التحقق من الحقول، وفحص الإساءة، وعقد الباقة، وحدّ عدد المشاريع.

الحقلالنوعملاحظات
titleنصمطلوب، حتى 100 محرف
descriptionنصاختياري، حتى 500 محرف
framework"html" | "nextjs" | "react"اختياري (الافتراضي html). nextjs وreact يُنشئان هيكل مشروع جاهزاً، ولا يُسمح بهما إلا في باقة تشمل Next.js
template"blank" | "landing" | "portfolio" | "dashboard" | "form"اختياري لمشروع HTML: ملفات القالب المبدئية (الافتراضي blank)
industryIdنصاختياري؛ معرّف قالب صناعي من GET /api/v1/templates. مع HTML يولّد صفحة القالب كاملة، ومع nextjs أو react يُمرَّر إلى الهيكل

الرابط المختصر slug يُبنى من العنوان: تبقى الحروف بأي لغة (ومنها العربية) والأرقام، ويصير غيرها شرطات، ويُقصّ إلى 60 محرفاً، ثم تُضاف لاحقة عشوائية.

POST /api/v1/projects
{ "title": "My Store", "description": "متجر ملابس", "template": "landing" }

201
{ "data": { "id": "…", "title": "My Store", "slug": "my-store-…", "files": [ … ], … } }

الرد يحمل سجل المشروع كاملاً كما خُزّن. الأخطاء بعد المفتاح والصلاحية وسقف الساعة:

  • 400 برسالة أول خطأ تحقق، مثل «عنوان المشروع طويل جداً» — ومنه جسم ليس JSON أو بلا عنوان. و400 «قالب المجال المحدد غير موجود» لـindustryId مجهول.
  • 403 برسالة السبب إن رفض فحص الإساءة العنوان أو الوصف.
  • 403 STACK_NOT_IN_PLAN: nextjs أو react في باقة لا تشمل Next.js، ومنها المجانية التي تشمل HTML الساكن وحده.
  • 403 PROJECT_QUOTA مع limit وused: بلغت حدّ عدد المشاريع في باقتك.

صفحات المشروع

GET /api/v1/projects/{id}/pages (projects:read) يعيد {"pages": […]}: الصفحات المكتشفة في ملفات المشروع.

POST /api/v1/projects/{id}/pages (projects:write) بجسم {"path": "…", "title": "…"} يولّد ملفات صفحة جديدة ويضيفها إلى ملفات المشروع: صفحة Next.js إن كان في المشروع ملف next.config، وإلا صفحة HTML. يعيد {"added": [أسماء الملفات], "totalFiles": …}. غياب أحد الحقلين أو عنوان فارغ: 400 {"error":"path و title مطلوبان"}. مشروع لا تملكه: 404.

نسخ المشروع

GET /api/v1/projects/{id}/versions (projects:read) يعيد مصفوفة النسخ الأحدث أولاً، لكل نسخة id وlabel وcreatedAt وfileCount وtotalSize دون الملفات. ومع ?versionId=… يعيد نسخة واحدة بملفاتها (id وlabel وcreatedAt وfiles)، أو 404 «النسخة غير موجودة».

POST /api/v1/projects/{id}/versions (projects:write) بجسم اختياري {"label": "…"} يحفظ لقطة من ملفات المشروع الحالية ويعيد 201 بسجل النسخة. السقف 20 حفظاً في الدقيقة (429 «كثرة الطلبات»). للمشروع 50 نسخة على الأكثر: عند بلوغها تُحذف أقدم نسخة لإفساح المكان.

استعادة نسخة سابقة بمفتاح API: غير متاح بعد — الاستعادة تحتاج محرّراً مفتوحاً، فهي في مسار الجلسة وحده.

POST /api/v1/projects/{id}/publish

يحتاج صلاحية publish، وهي خارج الافتراضي. الدالة نفسها التي يستعملها زر النشر في المحرّر، بفحوصها نفسها. راجع النشر.

الحقلالنوعملاحظات
expectedFilesمصفوفة {name, content, language?}مطلوب للنشر: يجب أن يطابق ملفات المشروع الحالية حرفياً، فلا يُنشر إلا ما راجعته. اقرأه من GET /api/v1/projects/{id}
unpublishمنطقيtrue يلغي النشر: الحالة DRAFT والمشروع غير عام

النجاح يعيد سجل المشروع ومعه address: العنوان الذي حصل عليه الموقع، أو null. ويطلق حدث project.published إلى Webhooks المشروع.

  • 400 PUBLISH_REVISION_REQUIRED: expectedFiles غائب أو بشكل غير صالح.
  • 409 PUBLISH_REVISION_CONFLICT: الملفات تغيّرت عمّا أرسلته، قبل النشر أو أثناءه. و409 PUBLISH_ADDRESS_TAKEN: العنوان حُجز للتو، أعد المحاولة.
  • 403: رفض فحص المحتوى، أو PUBLISH_NOT_STATIC حين تحوي الملفات ما لا تنشره باقتك، مع قائمة refusals.
  • 404 لمشروع لا تملكه، و429 بعد 10 عمليات نشر في الدقيقة.

POST /api/v1/ai

يرسل وصفك إلى نموذج الذكاء الاصطناعي ويطلب منه ملفات كود بصيغة JSON. أقصى مدة للطلب 120 ثانية.

الحقلالنوعملاحظات
promptنصمطلوب وغير فارغ؛ غيابه أو كونه غير نص يعيد 400 {"error":"prompt required"}
framework"html" | "nextjs" | "react"اختياري. nextjs يضيف للوصف «(Next.js + Tailwind + Prisma)»، وreact يضيف «(React + Vite + Tailwind)»، وأي قيمة أخرى لا تضيف شيئاً
modelنصاختياري؛ يُمرَّر إلى طبقة النماذج
200
{
  "data": {
    "files": [ … ],
    "raw": "…",
    "model": "…",
    "tokens": …
  }
}
  • files: الملفات بعد المعالجة إن كان رد النموذج JSON فيه files؛ وإلا null.
  • raw: نص رد النموذج كما هو — ارجع إليه حين تكون files فارغة.
  • model وtokens: النموذج الذي أجاب واستهلاكه كما تعيده طبقة النماذج.

ترتيب الفحوص مهم لحصتك: المفتاح (401) ← الصلاحية (403) ← باقة بلا ذكاء اصطناعي (402 AI_PAID_ONLY) ← سقف الساعة (403 أو 429) ← جسم الطلب: ليس JSON (400 {"error":"جسم الطلب ليس JSON","code":"invalid_json"}) أو بلا prompt (400) ← حصة الذكاء الاصطناعي اليومية (429 RATE_LIMITED) ← التوليد (200 أو 500). فالطلب المشوّه أو الذي ينقصه prompt يُرفض قبل أن تُخصم حصة اليوم. فشل التوليد يعيد 500 {"error":"…"} برسالة الخطأ، وتُعاد معه الحصة. للمحادثة والبثّ استعمل POST /api/v1/chat/completions.

POST /api/v1/chat/completions

واجهة متوافقة مع OpenAI Chat Completions، بصلاحية ai:chat؛ المفتاح القديم لا يفتحها. أقصى مدة للطلب 840 ثانية.

الحقلملاحظات
messagesمطلوب. الأدوار system وdeveloper وuser وassistant وtool. المحتوى نص أو أجزاء text وimage_url، والصور بصيغة data:…;base64,… فقط؛ رابط http يُرفض 400 image_url_must_be_data_url
modelاختياري؛ غيابه أو "auto" يعني تفضيل المشرف. الأسماء من GET /api/v1/models
streamtrue يعيد بثّ SSE: أجزاء chat.completion.chunk ثم data: [DONE]
max_tokens أو max_completion_tokensعدد صحيح من 1 إلى 32768
tools، tool_choice، parallel_tool_callsالأدوات مدعومة: tool_choice واحد من none وauto وrequired أو {"type":"function","function":{"name":"…"}}. رسائل tool بـtool_call_id، وtool_calls في رسالة assistant

الرد غير المبثوث chat.completion فيه choices[0].message، ومعه tool_calls وfinish_reason: "tool_calls" حين يستدعي النموذج أداة؛ وفي البثّ تصل دلتات tool_calls. قيم usage تقدير لا عدّ من المزوّد، ويقول ذلك الحقل estimated: true.

ترتيب الفحوص: المفتاح والصلاحية (401/403) ← باقة بلا ذكاء اصطناعي (402 AI_PAID_ONLY) ← سقف الساعة (403/429) ← شكل الطلب (400) ← حصة اليوم (429 RATE_LIMITED) ← النموذج. أخطاء الشكل والمزوّد بصيغة OpenAI: {"error": {"message": "…", "type": "…", "code": "…"}}.

  • 400 invalid_json لجسم ليس JSON، وlegacy_functions_not_supported لـfunctions أو function_call (الصيغة القديمة)، وn_not_supported حين n غير 1، وinvalid_max_tokens.
  • 400 tools_not_supported_for_model: النموذج المختار لا يدعم الأدوات؛ تُعاد الحصة ولا تُسقط الأدوات بصمت.
  • 502 upstream_error ورموز المزوّد الأخرى: فشل مزوّد الذكاء الاصطناعي. إن فشل قبل أن يبدأ النموذج الرد تُعاد الحصة.

GET /api/v1/models

بصلاحية ai:chat، والباقة بلا ذكاء اصطناعي تُرفض 402 قبل سقف الساعة. يعيد قائمة OpenAI من كتالوج النماذج المهيّأة على الخادم:

200
{ "object": "list", "data": [ { "id": "…", "object": "model", "created": 1757940000, "owned_by": "…" } ] }

نظام التصميم والشعار

كلاهما بصلاحية design، والباقة بلا ذكاء اصطناعي تُرفض 402 قبل سقف الساعة، وكلاهما يُخصم من حصة الذكاء الاصطناعي اليومية. الدالتان نفسهما اللتان يستعملهما المحرّر.

POST /api/v1/design/system بجسم {"projectId": "…", "brandName": "…", "industry"?, "mood"?, "primaryColor"?}، وmood واحد من professional وplayful وluxury وminimal وbold وwarm (الافتراضي professional). المشروع يجب أن تملكه (وإلا 404). الرد بثّ SSE بأحداث start ثم thinking وtoken ثم files (الملفات بعد حفظها في المشروع، committed: true) ثم data: [DONE]، أو حدث error. وإن تغيّرت ملفات المشروع أثناء التوليد لا يُحفظ شيء ويصل حدث error.

POST /api/v1/design/logo بجسم {"brandName": "…", "style"?, "projectId"?}؛ غياب brandName: 400 «اسم العلامة مطلوب». يعيد JSON فيه files وcommitted: مع projectId لمشروع تملكه يُحفظ logo.svg في ملفاته (committed: true)، أو 409 MUBARMIJ_PROJECT_REVISION_CONFLICT إن تغيّرت الملفات. شعار غير صالح من النموذج: 502.

النطاقات

GET /api/v1/domains/availability?domain=example.sa (domains:read) يعيد {"data": {"domain": "…", "status": "available" | "taken" | "unknown", "reason": "…"}}. unknown جواب صادق حين تعذّر التحقق، لا «متاح». غياب domain: 400 «النطاق مطلوب». سقف إضافي 20 استعلاماً في الدقيقة.

POST /api/v1/domains/orders (domains:write، خارج الافتراضي) يقدّم طلب شراء نطاق أو نقله — مهمة يصل سعرها بعد مراجعة الفريق، لا شراء فوري. الجسم: domain، وkind (PURCHASE افتراضياً أو TRANSFER_IN)، وyears من 1 إلى 10 (الافتراضي 1)، وcontact وفيه name وemail مطلوبان، وauthCode للنقل، وprojectId اختياري لمشروع تملكه. يعيد 201 {"data": {…}}. باقة لا تشمل النطاق المخصّص: 402 PLAN_CAPABILITY_REQUIRED. خطأ في الحقول: 400 برسالة السبب. سقف إضافي 5 طلبات في الساعة.

GET /api/v1/templates

عامة بلا مصادقة ولا سقف مفتاح. تعيد القوالب الصناعية التي يبني منها المحرّر، وعددها في total.

200
{
  "data": [
    {
      "id": "…",
      "name": "…",
      "nameEn": "…",
      "icon": "…",
      "category": "…",
      "categoryLabel": { "ar": "…", "en": "…" },
      "colorScheme": …,
      "stages": 0,
      "description": "…",
      "descriptionEn": "…"
    }
  ],
  "total": 0,
  "categories": [ { "id": "…", "ar": "…", "en": "…" } ]
}

stages عدد مراحل بناء القالب، لا المراحل نفسها. للقالب الواحد بمراحله كاملة: GET /api/v1/templates/{id} (عامة) يعيد {"data": {…}} ومعه categoryLabel، أو 404 «القالب غير موجود». راجع القوالب.

POST /api/v1/templates/build

بصلاحية templates. يبني مرحلة واحدة من قالب ويعيد ملفاتها دون أن يحفظها في أي مشروع.

الحقلملاحظات
industryIdمطلوب؛ معرّف القالب من GET /api/v1/templates
stageمطلوب، من 1 إلى 5؛ وإلا 400 «stage يجب أن يكون 1-5»
companyName، companyDesc، logoUrl، colorOverrideاختيارية؛ colorOverride بالشكل {"primary"?, "secondary"?}
projectIdاختياري، لمشروع تملكه (وإلا 404): يعرض قسم المنتجات كتالوج متجر ذلك المشروع
200
{
  "files": [
    { "name": "index.html", "content": "…", "language": "html" },
    { "name": "style.css", "content": "…", "language": "css" },
    { "name": "script.js", "content": "…", "language": "javascript" }
  ],
  "progress": …,
  "sectionsAdded": …,
  "nextStageHint": …,
  "storefront": null
}

GET /api/v1/sections

عامة. مكتبة الأقسام التي يُدرجها المحرّر: {"schema": …, "data": [{"id", "label", "hint", "markup"}], "packs": …, "total": …}، وmarkup هو ما يُدرجه المحرّر نفسه للقسم.

التنزيلات

GET /api/v1/downloads (عامة) يعيد {"data": […], "total": …} بالأدوات المتوفرة فعلاً فقط، لكل منها id وplatform وkind وfileName وversion وsha256 وsize وsource وhref. أداة غير متوفرة لا تظهر في القائمة أصلاً.

GET /api/v1/downloads/{id} (عامة) ينزّل الأداة مباشرة أو يحوّل إليها بـ302، مع الترويسة X-Checksum-SHA256 لتتحقق من الملف بعد التنزيل. المعرّف المجهول وغير المتوفر سواء: 404 بالرمز DOWNLOAD_UNAVAILABLE. راجع تطبيق سطح المكتب: التنزيل والتثبيت.

نقاط نهاية إدارة المفاتيح (جلسة المتصفح)

GET /api/v1/api-keys

مفاتيحك الفعّالة (غير المُبطَلة)، الأحدث أولاً. البصمة لا تغادر الخادم أبداً. legacy صحيح للمفتاح القديم، وصلاحياته حينها مصفوفة فارغة.

200
{
  "keys": [
    {
      "id": "…",
      "name": "تطبيق سطح المكتب",
      "maskedKey": "mop_••••••••abcd",
      "createdAt": "…",
      "lastUsedAt": null,
      "expiresAt": null,
      "scopes": ["ai:chat", "projects:read", "projects:write"],
      "legacy": false
    }
  ]
}

POST /api/v1/api-keys

الحقلالنوعملاحظات
nameنصمطلوب، حتى 64 محرفاً بعد قصّ المسافات
expiresInDaysعدد صحيحاختياري، من 1 إلى 365. غيابه = مفتاح بلا انتهاء
scopesمصفوفة نصوصاختيارية. غيابها = الافتراضي (كل الصلاحيات عدا publish وdomains:write). مصفوفة فارغة أو فيها قيمة مجهولة تُرفض 400
201
{
  "key": "mop_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "id": "…",
  "name": "تطبيق سطح المكتب",
  "maskedKey": "mop_••••••••XXXX",
  "createdAt": "…",
  "expiresAt": null,
  "scopes": ["ai:chat", "projects:read"],
  "prefix": "mop_",
  "warning": "انسخه الآن — لن يُعرض مرّةً أخرى."
}

key هو المفتاح الخام، ولا يعود في أي قراءة لاحقة. الأخطاء: 400 «جسم الطلب ليس JSON»، 400 «الاسم مطلوب»، 400 «الاسم يتجاوز 64 محرفاً»، 400 إذا كان expiresInDays خارج 1–365 أو ليس عدداً صحيحاً، 400 إذا كانت scopes فارغة أو فيها صلاحية مجهولة، 409 عند بلوغ 20 مفتاحاً فعّالاً، 401 بلا جلسة. هذا المسار لا يفحص الباقة: الإنشاء متاح لكل حساب.

DELETE /api/v1/api-keys/{id}

يُبطل المفتاح (لا يحذف سجله). 200 {"ok":true}. المفتاح غير الموجود، ومفتاح حساب آخر، والمفتاح المُبطَل من قبل: كلها 404 {"error":"المفتاح غير موجود"} — لا يميّز الرد بينها.

Webhooks (خارج v1، بجلسة المتصفح)

الـWebhooks تُسجَّل لكل مشروع من صفحة إعداداته، وتقبل مساراتها /api/webhooks جلسة صاحب المشروع في المتصفح وحدها، لا مفتاح API. تحتاج باقة تشمل الاستضافة؛ وإلا 402 PLAN_CAPABILITY_REQUIRED.

  • GET /api/webhooks?projectId=…: التسجيلات وقائمة الأحداث. POST /api/webhooks بجسم {"projectId", "url", "events": […]} يعيد 201 ومعه سرّ التوقيع مرة واحدة فقط. 10 تسجيلات على الأكثر للمشروع (409).
  • الأحداث: project.published (ويطلقه النشر بمفتاح API أيضاً)، وorder.created، وform.submitted.
  • كل تسليم طلب POST يحمل الترويسة x-mubarmij-signature: t=…,v1=…، وv1 توقيع HMAC-SHA256 بالسرّ على <t>.<الجسم>. يُقبل عنوان https عام فقط (400 WEBHOOK_URL_REFUSED).
  • إن لم يكن مفتاح تشفير الأسرار مضبوطاً على المنصة يُرفض الإنشاء بـ503 WEBHOOK_SECRETS_UNCONFIGURED، ولا يُحفظ سرّ دون تشفير.

سقوف الاستعمال

عدّادان رئيسيان، كلاهما لحسابك لا لكل مفتاح، ورقماهما من باقتك:

  1. سقف الساعة للواجهة البرمجية: كل نداء مصادَق بمفتاح يُحسب، عدا GET /api/v1/me. السقف في الساعة يساوي حصة الذكاء الاصطناعي اليومية للباقة.
  2. حصة الذكاء الاصطناعي اليومية: لـPOST /api/v1/ai وPOST /api/v1/chat/completions وPOST /api/v1/design/system وPOST /api/v1/design/logo، نافذة 24 ساعة تبدأ من أول طلب، ومشتركة مع طلبات الذكاء الاصطناعي من المحرّر في المتصفح.

وفوقهما سقوف خاصة ببعض نقاط النهاية: GET /api/v1/me 120 في الساعة، وفحص توفّر النطاقات 20 في الدقيقة، وطلبات النطاقات 5 في الساعة، وحفظ النسخ 20 في الدقيقة، والنشر 10 في الدقيقة. هذه السقوف الخاصة تعيد 429 برسالة نصية بلا ترويسات السقف.

الباقةنداءات API في الساعةطلبات الذكاء الاصطناعي في اليوم
المجانية0 (نداءات المفتاح تُرفض بـ403 أو 402، عدا /api/v1/me)0
الأساسية5050
المميزة200200
الاحترافية10001000

تفاصيل الباقات في الفوترة والباقات.

ترويسات السقف

الترويسات تُرسل فقط مع رد 429 الخاص بسقف الساعة، لا مع الردود الناجحة:

الترويسةالمعنى
Retry-Afterثوانٍ حتى تتجدد النافذة (1 على الأقل)
X-RateLimit-Limitسقف الساعة لباقتك
X-RateLimit-Remainingالمتبقي في النافذة
X-RateLimit-Resetوقت تجدد النافذة بثواني Unix
429
Retry-After: 1200
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1757940000

{ "error": "تجاوزتَ سقف باقتك (50 نداءً في الساعة) — أعد المحاولة بعد 1200 ثانية" }

أما نفاد حصة اليوم فيعيد 429 بلا هذه الترويسات، بجسم فيه code وupgradeUrl:

429
{ "error": "وصلت الحد اليومي للطلبات. ترقّى لباقةٍ أعلى لطلبات أكثر.", "code": "RATE_LIMITED", "upgradeUrl": "/billing", "remaining": 0, "limit": 50 }

الأخطاء

الحالةالجسم أو الرمزمتى
400prompt required / رسائل التحقق من الحقول / PUBLISH_REVISION_REQUIRED / رموز OpenAI مثل n_not_supported وtools_not_supported_for_modelحقل مطلوب غائب أو غير صالح
401Invalid API key بالرمز API_KEY_INVALIDنقاط المفتاح: مفتاح غائب أو مشوّه أو مجهول أو مُبطَل أو منتهٍ
401غير مصرّحنقاط إدارة المفاتيح والـWebhooks: لا جلسة متصفح صالحة
402AI_PAID_ONLYباقة بلا ذكاء اصطناعي: في توليد الكود والمحادثة والنماذج والتصميم، قبل سقف الساعة
402PLAN_CAPABILITY_REQUIREDطلب نطاق بباقة لا تشمل النطاق المخصّص، أو Webhooks بباقة لا تشمل الاستضافة
403API_REQUIRES_PAID_PLANنداء بمفتاح من حساب على باقة المجانية
403API_KEY_SCOPE_REQUIRED مع scopeمفتاح لا يحمل صلاحية نقطة النهاية، أو مفتاح قديم خارج نقاطه الثلاث
403PUBLISH_NOT_STATIC أو رسالة فحص المحتوىالنشر مرفوض
403STACK_NOT_IN_PLAN / PROJECT_QUOTA / رسالة فحص الإساءةإنشاء مشروع: إطار لا تشمله الباقة، أو بلوغ حدّ المشاريع، أو محتوى مرفوض
404المشروع غير موجود / المفتاح غير موجود / DOWNLOAD_UNAVAILABLEمشروع لا تملكه أو غائب، مفتاح غير موجود أو ليس لك أو مُبطَل، أداة غير متوفرة
409رسالة الحد الأقصى / PUBLISH_REVISION_CONFLICT / PUBLISH_ADDRESS_TAKEN / MUBARMIJ_PROJECT_REVISION_CONFLICT20 مفتاحاً فعّالاً، أو تغيّرت ملفات المشروع، أو حُجز العنوان
429رسالة سقف الساعة (بلا code) أو RATE_LIMITED أو رسالة سقف خاصسقف الساعة أو حصة اليوم أو سقف نقطة نهاية
500رسالة الخطأفشل التوليد في POST /api/v1/ai (وتُعاد الحصة)
502upstream_error ورموز المزوّدفشل مزوّد الذكاء الاصطناعي في المحادثة، أو شعار غير صالح

مثال curl

ضع مفتاحك في متغير بيئة ولا تكتبه في الأوامر المحفوظة:

export MOPARMEG_API_KEY=mop_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

curl https://moparmeg-ksa.com/api/v1/me -H "Authorization: Bearer $MOPARMEG_API_KEY"

curl https://moparmeg-ksa.com/api/v1/projects -H "Authorization: Bearer $MOPARMEG_API_KEY"

curl -X POST https://moparmeg-ksa.com/api/v1/chat/completions -H "Authorization: Bearer $MOPARMEG_API_KEY" -H "Content-Type: application/json" -d '{"messages":[{"role":"user","content":"اقترح عنواناً لصفحة هبوط لمقهى مختص"}]}'

curl -i https://moparmeg-ksa.com/api/v1/templates

الخيار -i يعرض الترويسات، ومنها Retry-After عند 429. للبدء من الصفر راجع البدء السريع، ولفهم ما يبنيه الذكاء الاصطناعي راجع البناء بالذكاء الاصطناعي.

أسئلة شائعة

هل يقبل مفتاحي مسارات مثل /api/ai/generate أو /api/terminal؟

لا. تلك مسارات لوحة التحكم والمحرّر وتُصادَق بجلسة المتصفح. المفتاح يعمل على نقاط v1 المذكورة أعلاه فقط، بحسب صلاحياته: قراءة المشروع بملفاته (projects:read)، ونشره (publish). أما حذف المشروع واستعادة نسخة سابقة عبر المفتاح: غير متاح بعد.

هل يوجد ترقيم صفحات لقائمة المشاريع؟

غير متاح بعد. القائمة تعيد آخر 50 مشروعاً حُدّثت من مشاريعك، ويُطلب ما بعدها بمعرّفه عبر GET /api/v1/projects/{id} إن عرفته.

هل أستعمل POST /api/v1/ai أم POST /api/v1/chat/completions؟

POST /api/v1/ai يعيد ملفات كود JSON دفعة واحدة، ويبقى يعمل بالمفتاح القديم. POST /api/v1/chat/completions متوافق مع عملاء OpenAI، ويدعم البثّ والأدوات والصور، ويحتاج مفتاحاً بصلاحية ai:chat.

لماذا لا أرى ترويسات X-RateLimit-* في الردود الناجحة؟

لأن الخادم يرسلها مع رد 429 لسقف الساعة وحده. تتبّع استهلاكك في برنامجك، أو اقرأ Retry-After عند الرفض.

هل يمكن إنشاء مفتاح بمفتاح؟

لا. إنشاء المفاتيح وعرضها وإبطالها بجلسة المتصفح وحدها — انظر مفاتيح API.