تخطيط الصفحة الرئيسية هو القائمة المرتّبة للأقسام التي يعرضها المتجر في صفحته الرئيسية. لكل قسم نوع وإعدادات. يمكن إضافة عشرة أنواع في كل قالب: category-products وfeatured وcategories وbanner وimage-with-text وrich-text وtrust-badges وtestimonials وfaq وvideo. ويقدّم قالب مبني على الأقسام مثل atlas أيضاً hero وproduct-grid. يعطي types في استجابة GET إعدادات كل نوع. كل كتابة في هذه الصفحة تظهر في المتجر بمجرد أن تُرجع استجابتها.
هذه النقاط ليست GET /v1/store/home-sections التي تقرأ مفاتيح الصفحة الرئيسية في قوالب Digital وAriana وPrestige. وهذه المفاتيح مشروحة في آخر هذه الصفحة.
قبل أن تبدأ
تحتاج
GETإلىstore:read، وتحتاج الكتابات إلىstore:write. مفاتيح التاجر تحمل الاثنتين.تحتاج
POSTوPATCHوDELETEإلىIdempotency-Key. وهو اختياري معPUT. انظر Idempotency.رقم الفئة يأتي من
GET /v1/categoriesالتي تحتاج إلىproducts:read.
كائن القسم
الحقل | النوع | ملاحظات |
| int | ثابت ما دام القسم موجوداً. القسم الذي يعود بالتراجع يأخذ رقماً جديداً. |
| string | إحدى قيم |
| object | كل إعدادات النوع، والقيم الافتراضية مملوءة. |
| bool |
|
| bool |
|
إعدادات category-products
الإعداد | النوع | الافتراضي | القواعد |
| رقم فئة |
| فئة من هذا المتجر. |
| text |
| حتى 80 حرفاً، ويُزال منه HTML. الفارغ يُظهر اسم الفئة. |
| range |
| من 4 إلى 12. الرقم خارج هذا المجال يُنقل إلى أقرب حدّ. |
| select |
|
|
| checkbox |
| رابط إلى صفحة الفئة. |
الفئة التي لا منتجات فيها لا تعرض شيئاً للزبائن كذلك. اقرأ قواعد أي نوع من settings_schema الخاص به بدل كتابتها في برنامجك: قائمة الأنواع تتبع قالب المتجر.
صيغ الإعدادات
نوع الإعداد | القيمة المقبولة |
| رقم من |
|
|
| رابط فيديو YouTube أو معرّفه ذو 11 حرفاً. يُحفظ المعرّف. |
| مسار صورة رُفعت من لوحة التحكم لهذا المتجر، |
متى يرى الزبائن القسم
القسم الذي لم يُملأ محتواه بعد يُخزَّن وتُرجع الكتابة 2xx، لكن الزبائن لا يرونه حتى يُملأ:
النوع | يراه الزبائن عندما |
| تكون |
| تكون في |
| تكون في المتجر فئة فيها منتجات، أو أي فئة عندما تكون |
| تُملأ |
| تُملأ |
| يُملأ |
| دائماً. الشارتان 1 و2 الفارغتان تُظهران سطري التوصيل والدفع عند الاستلام الافتراضيين. |
| يُملأ |
| يُملأ |
| تحمل |
لا تتغيّر rendered لهذا السبب: فهي تقول إن كان القالب يعرض الأقسام المخزّنة، لا إن كان قسم بعينه ظاهراً. في قالب مبني على الأقسام (atlas) لا تحلّ الأقسام المحفوظة محل الصفحة الرئيسية للقالب إلا ما دامت تتضمن قسم product-grid ظاهراً، وتبقى rendered بقيمة false حتى ذلك الحين؛ وقبل ذلك يرى الزبائن الصفحة الأصلية للقالب، ولا تعرض GET إلا الأقسام المحفوظة، لا أقسام القالب نفسه.
GET /v1/store/home-layout
الأقسام بترتيب عرضها، وأنواع الأقسام التي يمكن إضافتها في قالب المتجر، وحدّ الخطة.
المصادقة: مفتاح منصة بصلاحية store:read.
الطلب
curl 'https://api.dzbuild.app/v1/store/home-layout' \ -H "Authorization: Bearer $DZ_KEY"
الاستجابة 200
{
"data": {
"theme": "starter",
"rendered": true,
"max_sections": 25,
"cap": 25,
"version": "9c1e04b7a2d35f68",
"sections": [
{
"id": 412,
"type": "category-products",
"settings": {
"category": 57,
"title": "",
"count": 8,
"layout": "grid",
"show_view_all": true
},
"is_active": true,
"available": true
},
{
"id": 415,
"type": "category-products",
"settings": {
"category": 61,
"title": "Nos parfums",
"count": 10,
"layout": "slider",
"show_view_all": false
},
"is_active": false,
"available": true
}
],
"types": [
{
"type": "category-products",
"name": {"ar": "منتجات فئة", "fr": "Produits d'une catégorie"},
"description": {"ar": "اعرض منتجات فئة واحدة في شبكة أو شريط تمرير.", "fr": "Affichez les produits d'une catégorie en grille ou en carrousel."},
"icon": "bi-grid-3x3-gap",
"limit": 12,
"settings_schema": [
{"id": "category", "type": "category", "default": 0, "label": {"ar": "الفئة", "fr": "Catégorie"}},
{"id": "title", "type": "text", "max": 80, "default": "", "label": {"ar": "العنوان (إذا تركته فارغاً يظهر اسم الفئة)", "fr": "Titre (si vide, le nom de la catégorie s'affiche)"}},
{"id": "count", "type": "range", "min": 4, "max": 12, "default": 8, "label": {"ar": "عدد المنتجات", "fr": "Nombre de produits"}},
{"id": "layout", "type": "select", "options": ["grid", "slider"], "default": "grid", "label": {"ar": "طريقة العرض", "fr": "Affichage"}, "option_labels": {"ar": ["شبكة", "شريط تمرير"], "fr": ["Grille", "Carrousel"]}},
{"id": "show_view_all", "type": "checkbox", "default": true, "label": {"ar": "زر عرض الكل", "fr": "Lien « Voir tout »"}}
]
}
]
},
"meta": {"request_id": "8f2c1a9d4b7e6035", "api_version": "v1"}
}
الحقل | المعنى |
| مفتاح قالب المتجر. |
|
|
| 25، أقصى عدد من الأقسام تحمله صفحة رئيسية واحدة. |
| عدد الأقسام الذي تسمح به خطة المتجر: 3 في الخطة المجانية أو خطة منتهية، و25 ابتداءً من Pro. |
| بصمة التخطيط المخزَّن. أرسلها في |
| الأقسام بترتيب عرضها، ومعها الأقسام المخفية. |
| الأنواع التي يمكن إضافتها في هذا القالب، مع |
القراءة بعد الكتابة
عبر api.dzbuild.app يُخدَم كل طلب GET حديثًا: طلب GET المُرسَل مباشرة بعد الكتابة يُرجع التخطيط الجديد. ونادرًا ما تحتاج إليه، لأن كل كتابة تُرجع القائمة كاملة بترتيب العرض مع version الجديدة.
POST /v1/store/home-layout/sections
يضيف قسماً واحداً.
المصادقة: مفتاح منصة بصلاحية store:write. يتطلب Idempotency-Key.
الجسم
الحقل | النوع | إلزامي | ملاحظات |
| string | نعم | قيمة |
| object | لا | الإعدادات التي لا ترسلها تأخذ القيم الافتراضية للنوع. |
| int | لا | 0 يضع القسم في الأعلى، و24 آخر مكان. بدونه يُضاف القسم في النهاية. |
الطلب
curl -X POST 'https://api.dzbuild.app/v1/store/home-layout/sections' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hs-add-sacs-1" \
-d '{"type": "category-products", "settings": {"category": 64, "layout": "slider"}, "position": 0}'
الاستجابة 201
{
"data": {
"section": {
"id": 418,
"type": "category-products",
"settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true},
"is_active": true,
"available": true
},
"sections": [
{"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true}, "is_active": true, "available": true},
{"id": 412, "type": "category-products", "settings": {"category": 57, "title": "", "count": 8, "layout": "grid", "show_view_all": true}, "is_active": true, "available": true},
{"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 10, "layout": "slider", "show_view_all": false}, "is_active": false, "available": true}
],
"version": "e27a90c4b1f36d05",
"change_id": 90231,
"rendered": true
},
"meta": {"request_id": "3b7d0e5a9c14f862", "api_version": "v1"}
}
PATCH /v1/store/home-layout/sections/{id}
يغيّر قسماً واحداً. الإعدادات التي ترسلها تُدمج فوق الإعدادات المخزّنة. أرسل settings أو is_active أو كليهما.
المصادقة: مفتاح منصة بصلاحية store:write. يتطلب Idempotency-Key.
الجسم
الحقل | النوع | إلزامي | ملاحظات |
| object | لا | تُدمج فوق الإعدادات المخزّنة. |
| bool | لا |
|
| bool | لا | مع |
الطلب
curl -X PATCH 'https://api.dzbuild.app/v1/store/home-layout/sections/415' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hs-415-show-1" \
-d '{"settings": {"count": 6}, "is_active": true}'
الاستجابة 200
للاستجابة الحقول نفسها التي لاستجابة POST: section (القسم بعد التغيير)، وsections، وversion، وchange_id، وrendered.
{
"data": {
"section": {
"id": 415,
"type": "category-products",
"settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false},
"is_active": true,
"available": true
},
"sections": [
{"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true}, "is_active": true, "available": true},
{"id": 412, "type": "category-products", "settings": {"category": 57, "title": "", "count": 8, "layout": "grid", "show_view_all": true}, "is_active": true, "available": true},
{"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false}, "is_active": true, "available": true}
],
"version": "51d8c3e06fa2b974",
"change_id": 90232,
"rendered": true
},
"meta": {"request_id": "c90a6e1f2d7b4538", "api_version": "v1"}
}
DELETE /v1/store/home-layout/sections/{id}
يحذف قسماً واحداً.
المصادقة: مفتاح منصة بصلاحية store:write. يتطلب Idempotency-Key.
الطلب
curl -X DELETE 'https://api.dzbuild.app/v1/store/home-layout/sections/412' \ -H "Authorization: Bearer $DZ_KEY" \ -H "Idempotency-Key: hs-del-412-1"
الاستجابة 200
{
"data": {
"deleted": true,
"id": 412,
"sections": [
{"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true}, "is_active": true, "available": true},
{"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false}, "is_active": true, "available": true}
],
"version": "0f6b2d9e84a1c357",
"change_id": 90233,
"rendered": true
},
"meta": {"request_id": "71e4b08c3a5d9f26", "api_version": "v1"}
}
POST /v1/store/home-layout/reorder
يحدّد ترتيب العرض. تذكر ids كل أقسام الصفحة مرة واحدة بالضبط، ومعها الأقسام المخفية.
المصادقة: مفتاح منصة بصلاحية store:write. يتطلب Idempotency-Key.
الطلب
curl -X POST 'https://api.dzbuild.app/v1/store/home-layout/reorder' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hs-order-2" \
-d '{"ids": [415, 418]}'
الاستجابة 200
تحمل الاستجابة sections بالترتيب الجديد، وversion، وchange_id، وrendered. الرقم الذي ليس في الصفحة يُرجع 404 section_not_found. والرقم الناقص أو المكرر يُرجع 422 invalid_order.
PUT /v1/store/home-layout
يستبدل التخطيط كله بالقائمة التي ترسلها، بترتيبها.
المصادقة: مفتاح منصة بصلاحية store:write. Idempotency-Key اختياري.
الجسم
الحقل | النوع | إلزامي | ملاحظات |
| array | نعم | 25 عنصراً على الأكثر، كل عنصر |
| string | لا | قيمة |
كيف يُقرأ كل عنصر:
العنصر الذي يحمل
idيُبقي ذلك القسم. ويجب أن يكونtypeهو النوع الحالي للقسم.العنصر الذي بلا
idينشئ قسماً.كل قسم في الصفحة غير موجود في القائمة يُحذف.
settingsهو الكائن كاملاً: الإعداد الذي تتركه يعود إلى قيمته الافتراضية. أرسل الإعدادات كاملة لكل قسم تُبقيه.قيمة
is_activeالافتراضيةtrue.
الطلب
curl -X PUT 'https://api.dzbuild.app/v1/store/home-layout' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hs-replace-7" \
-d '{
"version": "0f6b2d9e84a1c357",
"sections": [
{"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false}},
{"type": "category-products", "settings": {"category": 57}}
]
}'
الاستجابة 200
تحمل الاستجابة sections وversion وchange_id وrendered. القسم 418 لم يُرسل، لذلك يُحذف. وإعادة إرسال التخطيط الذي قرأته كما هو تُرجع change_id: null.
مع Idempotency-Key، إعادة المحاولة بالمفتاح نفسه والجسم نفسه تُرجع الاستجابة المخزّنة لمدة 24 ساعة مع Idempotency-Replay: 1، والمفتاح نفسه مع جسم آخر يُرجع 422 idempotency_key_reuse. وبدون مفتاح يُنفَّذ النداء في كل مرة، وهذا آمن: إرسال القائمة نفسها مرتين يترك التخطيط نفسه.
التراجع
كل كتابة تُرجع change_id، أو null عندما لا تغيّر شيئاً. يُرجع POST /v1/changes/{change_id}/undo الصفحة الرئيسية كلها كما كانت قبل ذلك التغيير.
يمكن التراجع عن إضافة قسم أيضاً: التراجع يزيله. في الموارد الأخرى يرفض التراجع أي تغيير أنشأ شيئاً.
إذا تغيّرت الصفحة الرئيسية بعد ذلك التغيير، عبر الواجهة البرمجية أو من لوحة التحكم، يُرجع التراجع
409 layout_changedولا يكتب شيئاً. اقرأ التخطيط واكتب ما تريده مباشرة.القسم الذي يعود بعد حذفه يأخذ رقماً جديداً.
التراجع نفسه يُسجَّل تغييراً مستقلاً،
undo_change_id، ويمكنك التراجع عنه بدوره. التراجع عن تراجعٍ عن حذف يُرجع409 layout_changed، لأن القسم عاد برقم جديد.التغييرات التي يحفظها التاجر من لوحة التحكم لا تُسجَّل، فلا يمكن التراجع عنها عبر الواجهة البرمجية.
يعرض
GET /v1/changes?entity=store.home_layoutتغييرات تخطيط الصفحة الرئيسية، الأحدث أولاً، بصلاحيةstore:read.لا يستطيع رمز التطبيق المثبّت قراءة التغييرات ولا التراجع عنها: يُرجع
GET /v1/changesوالتراجع403 forbidden(Apps cannot use this endpoint). وتبقى استجابات الكتابة تحملchange_id.لا تحمل استجابة التراجع التخطيط. اقرأه من جديد عبر
GET /v1/store/home-layout؛ القراءة تُخدَم حديثًا.
يحتاج التراجع إلى store:write وإلى Idempotency-Key.
curl -X POST 'https://api.dzbuild.app/v1/changes/90231/undo' \ -H "Authorization: Bearer $DZ_KEY" \ -H "Idempotency-Key: undo-90231"
{
"data": {
"undone": true,
"change_id": 90231,
"entity": "store.home_layout",
"undo_change_id": 90240
},
"meta": {"request_id": "5ad2f7c01e9b8634", "api_version": "v1"}
}
التغيير الذي تتراجع عنه مرة ثانية يُرجع 409 already_undone.
الأخطاء
HTTP | الرمز | السبب |
400 |
| الجسم ليس كائن JSON، أو حقل من نوع خاطئ ( |
401 |
| مفتاح خاطئ أو غائب. |
402 |
| انتهت حصة الطلبات الشهرية للمتجر. انظر حدود المعدل. |
403 |
|
|
403 |
| الكتابة تترك أقساماً أكثر مما تسمح به الخطة. يحمل الخطأ |
404 |
| لا يوجد قسم بهذا الرقم في الصفحة. |
409 |
| وصلت كتابة أخرى قبلك، أو |
409 |
| للتراجع فقط: تغيّرت الصفحة الرئيسية بعد هذا التغيير. |
409 |
| للتراجع فقط: سبق التراجع عن هذا التغيير. |
413 |
| الجسم أكبر من 1 ميغابايت. |
422 |
| رُفضت قيمة. تذكر |
422 |
| النوع غير موجود أو لا يمكن إضافته في هذا القالب. تعطي |
422 |
| أكثر من 25 قسماً، أو أكثر من |
422 |
|
|
422 |
|
|
422 |
| استُعمل |
429 |
| طلبات كثيرة، ومنها أكثر من 30 كتابة على تخطيط الصفحة الرئيسية في الدقيقة للمتجر. انتظر المدة في |
429 |
| أكثر من 5 كتابات على تخطيط الصفحة الرئيسية تعمل في الوقت نفسه للمتجر. أعد المحاولة بعد ثوانٍ. |
500 |
| فشل الطلب. أعد المحاولة بالـ |
هكذا تبدو استجابة invalid_settings.
{
"error": {
"code": "invalid_settings",
"message": "Invalid value at settings.category: category not found in this store; accepted values are in settings_schema of GET /v1/store/home-layout",
"fields": [{"path": "settings.category", "code": "invalid"}]
},
"meta": {"request_id": "e4c19a0b7d2f5836", "api_version": "v1"}
}
الحدود
25 قسماً في الصفحة الرئيسية (
max_sections).حدّ الخطة (
cap): 3 أقسام في الخطة المجانية أو خطة منتهية، و25 ابتداءً من Pro. الأقسام المخفية تُحسب. المتجر الذي تجاوز حدّه بعد نزول خطته يُبقي أقسامه ويستطيع تعديلها وإخفاءها وترتيبها وحذفها. الكتابة التي تترك أقساماً أكثر من الحدّ وأكثر مما كانت تُرجع403 plan_required.لكل نوع: لكل نوع
limitفيtypes، وهو 12 لـcategory-products.الإعدادات: 8 كيلوبايت لكل قسم بعد الترميز. النص الأطول يُقصّ عند
maxالخاص بالإعداد.الجسم: 1 ميغابايت.
الكتابات: 30 في الدقيقة و5 في الوقت نفسه لكل متجر، فوق حدّ المتجر في الدقيقة. انظر حدود المعدل.
مفاتيح الصفحة الرئيسية في Digital وAriana وPrestige
تبني قوالب Digital وAriana وPrestige صفحتها الرئيسية من كتل ثابتة. ومجموعة أقدم من المفاتيح تُظهر هذه الكتل أو تخفيها وتحدّد عناوينها وفئاتها وبنراتها. يقرأ GET وPATCH /v1/store/home-sections هذه المفاتيح ويغيّرانها. وهي محفوظة بمعزل عن تخطيط الصفحة الرئيسية المشروح أعلاه، فالكتابة في أحدهما لا تغيّر الآخر أبداً.
القالب | الحقول التي يقرؤها |
Digital وAriana |
|
Prestige |
|
لا يقرأ أي قالب آخر هذه المفاتيح: في قالب آخر تُحفظ الكتابة وتُرجع 200، ولا يرى الزبائن أي تغيير. والمفتاح الذي لم يُحفظ أبداً يغيب عن الاستجابة، وعندها يُظهر Digital وAriana كتلته بينما يخفي Prestige آراء العملاء. يحدّد section_order ترتيب كتل Digital وAriana بالقيم hero_slider وcategory_cards وtop_sellers وpopular_by_category وpromo_banners وmulti_column_lists. والكتلة التي لا تَرِد في هذه القائمة لا تظهر.
GET /v1/store/home-sections
المصادقة: مفتاح منصة بصلاحية store:read. وكما في GET /v1/store/home-layout، تُخدَم الاستجابة حديثًا في كل نداء.
curl 'https://api.dzbuild.app/v1/store/home-sections' \ -H "Authorization: Bearer $DZ_KEY"
{
"data": {
"theme": "digital",
"settings": {"show_top_sellers": 1, "top_sellers_title": "Meilleures ventes", "column_1_category_id": 57}
},
"meta": {"request_id": "...", "api_version": "v1"}
}
لا يحمل settings إلا الحقول التي حُفظت. والمتجر الذي لم يحفظ أي حقل يُرجع "settings": [].
PATCH /v1/store/home-sections
المصادقة: مفتاح منصة بصلاحية store:write. يتطلب Idempotency-Key.
أرسل الحقول التي تريد تغييرها فقط: تحتفظ البقية بقيمها، وتُتجاهل الحقول غير المعروفة. تُحفظ حقول show_* على شكل 1 أو 0. ويأخذ *_category_id فئة من فئات هذا المتجر، و0 يُفرغه. يُنزع الفراغ من طرفي النص ثم يُقصّ عند 500 حرف، وtestimonials_title عند 200. ويقبل banner_1_button_link وbanner_2_button_link رابط https:// أو http:// أو mailto: أو tel:، أو /path، أو #anchor. ويحتفظ testimonials بـ 24 عنصراً كحد أقصى، لكل منها name وcomment وstars من 1 إلى 5.
curl -X PATCH 'https://api.dzbuild.app/v1/store/home-sections' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hs-top-sellers-off-1" \
-d '{"show_top_sellers": false, "column_1_category_id": 61}'
{
"data": {
"updated": ["show_top_sellers", "column_1_category_id"],
"settings": {"show_top_sellers": 0, "top_sellers_title": "Meilleures ventes", "column_1_category_id": 61}
},
"meta": {"request_id": "...", "api_version": "v1"}
}
يسرد updated الحقول التي كُتبت، ويحمل settings كل الحقول المحفوظة بعد الكتابة. ولا تحمل الاستجابة change_id: يسرد GET /v1/changes?entity=store.home_sections هذه التغييرات، وPOST /v1/changes/{change_id}/undo يتراجع عن أحدها. التراجع عن أول كتابة لمفتاح لا يُرجع قيمته الافتراضية: يعود مفتاح show_* بالقيمة 0 ويعود section_order بالقيمة []، وهذا يخفي في Digital وAriana تلك الكتلة، أو كل الكتل. وللرجوع إلى القيم الافتراضية، أرسل 1 أو قائمة section_order كاملة عبر PATCH.
HTTP | الرمز | السبب |
400 |
| الجسم ليس JSON، أو |
403 |
|
|
422 |
| لا يحمل الجسم أيّاً من الحقول التي تقبلها نقطة النهاية هذه. |
422 |
|
|
422 |
| رابط زر يستعمل مخططاً آخر، مثل |
422 |
| استُعمل |
معنى 401 و402 و413 و500 هو نفسه في كتابات تخطيط الصفحة الرئيسية. أما 429 rate_limited فيأتي فقط من الحدود العامة في الدقيقة المشروحة في حدود المعدل: حدود كتابات تخطيط الصفحة الرئيسية لا تنطبق هنا.