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

نظرة عامة
عنوان القاعدة: 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: الملفات تغيّرت عمّا أرسلته، قبل النشر أو أثناءه. و409PUBLISH_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 |
stream | true يعيد بثّ 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 عام فقط (400WEBHOOK_URL_REFUSED). - إن لم يكن مفتاح تشفير الأسرار مضبوطاً على المنصة يُرفض الإنشاء بـ503
WEBHOOK_SECRETS_UNCONFIGURED، ولا يُحفظ سرّ دون تشفير.
سقوف الاستعمال
عدّادان رئيسيان، كلاهما لحسابك لا لكل مفتاح، ورقماهما من باقتك:
- سقف الساعة للواجهة البرمجية: كل نداء مصادَق بمفتاح يُحسب، عدا
GET /api/v1/me. السقف في الساعة يساوي حصة الذكاء الاصطناعي اليومية للباقة. - حصة الذكاء الاصطناعي اليومية: لـ
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 |
| الأساسية | 50 | 50 |
| المميزة | 200 | 200 |
| الاحترافية | 1000 | 1000 |
تفاصيل الباقات في الفوترة والباقات.
ترويسات السقف
الترويسات تُرسل فقط مع رد 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 }
الأخطاء
| الحالة | الجسم أو الرمز | متى |
|---|---|---|
| 400 | prompt required / رسائل التحقق من الحقول / PUBLISH_REVISION_REQUIRED / رموز OpenAI مثل n_not_supported وtools_not_supported_for_model | حقل مطلوب غائب أو غير صالح |
| 401 | Invalid API key بالرمز API_KEY_INVALID | نقاط المفتاح: مفتاح غائب أو مشوّه أو مجهول أو مُبطَل أو منتهٍ |
| 401 | غير مصرّح | نقاط إدارة المفاتيح والـWebhooks: لا جلسة متصفح صالحة |
| 402 | AI_PAID_ONLY | باقة بلا ذكاء اصطناعي: في توليد الكود والمحادثة والنماذج والتصميم، قبل سقف الساعة |
| 402 | PLAN_CAPABILITY_REQUIRED | طلب نطاق بباقة لا تشمل النطاق المخصّص، أو Webhooks بباقة لا تشمل الاستضافة |
| 403 | API_REQUIRES_PAID_PLAN | نداء بمفتاح من حساب على باقة المجانية |
| 403 | API_KEY_SCOPE_REQUIRED مع scope | مفتاح لا يحمل صلاحية نقطة النهاية، أو مفتاح قديم خارج نقاطه الثلاث |
| 403 | PUBLISH_NOT_STATIC أو رسالة فحص المحتوى | النشر مرفوض |
| 403 | STACK_NOT_IN_PLAN / PROJECT_QUOTA / رسالة فحص الإساءة | إنشاء مشروع: إطار لا تشمله الباقة، أو بلوغ حدّ المشاريع، أو محتوى مرفوض |
| 404 | المشروع غير موجود / المفتاح غير موجود / DOWNLOAD_UNAVAILABLE | مشروع لا تملكه أو غائب، مفتاح غير موجود أو ليس لك أو مُبطَل، أداة غير متوفرة |
| 409 | رسالة الحد الأقصى / PUBLISH_REVISION_CONFLICT / PUBLISH_ADDRESS_TAKEN / MUBARMIJ_PROJECT_REVISION_CONFLICT | 20 مفتاحاً فعّالاً، أو تغيّرت ملفات المشروع، أو حُجز العنوان |
| 429 | رسالة سقف الساعة (بلا code) أو RATE_LIMITED أو رسالة سقف خاص | سقف الساعة أو حصة اليوم أو سقف نقطة نهاية |
| 500 | رسالة الخطأ | فشل التوليد في POST /api/v1/ai (وتُعاد الحصة) |
| 502 | upstream_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.