الفئات
الفئات تجمع منتجات المتجر، وهي على مستويين: الفئة الرئيسية يمكن أن تضم فئات فرعية، والفئة الفرعية لا تضم أي فئة. هذه النقاط الست تعرض الفئات وتقرأها وتنشئها وتعدّلها وتحذفها وترتّبها.
ينضم المنتج إلى فئة عبر حقله category_id، انظر المنتجات. وقسم category-products في الصفحة الرئيسية يأخذ رقم فئة أيضاً، انظر أقسام الصفحة الرئيسية.
قبل أن تبدأ
- تحتاج القراءة إلى
products:readوتحتاج الكتابات إلىproducts:write، وهما صلاحيتا المنتجات نفسهما. مفاتيح التاجر تحمل الاثنتين. - تحتاج
POSTوPATCHوDELETEإلىIdempotency-Key. انظر Idempotency. - صورة الفئة تُضاف من لوحة التحكم. الواجهة البرمجية تُرجع رابطها ولا تستطيع رفعها أو تغييرها.
كائن الفئة
| الحقل | النوع | ملاحظات |
|---|---|---|
id | int | رقم الفئة. |
name | string | من 1 إلى 100 حرف. |
slug | string | يُصنع من الاسم وهو فريد في المتجر. صفحة الفئة في المتجر تستعمله في عنوانها. |
description | string أو null | نص حر. |
image | string أو null | الرابط الكامل للصورة، أو null. |
parent_id | int أو null | الفئة الأم، أو null للفئة الرئيسية. |
show_subcategories | bool | يعرض الفئات الفرعية كبطاقات في صفحة الفئة على المتجر (عرض قسم الفئات الفرعية في نموذج الفئة). يُحفظ true للفئة الفرعية. وما دام الفئات الفرعية داخل الفئة الرئيسية فقط مفعّلاً (/dashboard/categories)، يعرض المتجر البطاقات في صفحة كل فئة مهما كانت قيمة هذا الحقل. |
sort_order | int | الموضع في قوائم الفئات بالمتجر، الأصغر أولاً. |
status | string | active أو inactive. |
created_at | string | بصيغة YYYY-MM-DD HH:MM:SS بتوقيت الخادم. |
تضيف القائمة والقراءة الفردية product_count، وهو عدد المنتجات في الفئة. وتضيف القراءة الفردية أيضاً children، أي فئاتها الفرعية.
GET /v1/categories
فئات المتجر، الأحدث أولاً، في قائمة بمؤشر. رتّبها حسب sort_order لتحصل على ترتيب المتجر.
المصادقة: مفتاح منصة بصلاحية products:read.
معاملات الاستعلام
| المعامل | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
parent_id | رقم أو 0 أو null | لا شيء | رقم فئة يُرجع فئاتها الفرعية. و0 أو null أو قيمة فارغة تُرجع الفئات الرئيسية. وأي قيمة أخرى تُرجع 400 bad_request. |
status | active أو inactive | لا شيء | الفئات التي لها هذه الحالة فقط. وأي قيمة أخرى تُتجاهل. |
limit | int | 50 | من 1 إلى 200. |
cursor | string | لا شيء | قيمة next_cursor من الصفحة السابقة. انظر الترقيم. |
الطلب
curl 'https://api.dzbuild.app/v1/categories?parent_id=0' \
-H "Authorization: Bearer $DZ_KEY"
الاستجابة 200
{
"data": {
"items": [
{
"id": 14,
"name": "Montres",
"slug": "montres",
"description": null,
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 4,
"status": "active",
"created_at": "2026-09-30 11:20:05",
"product_count": 0
},
{
"id": 10,
"name": "Parfums",
"slug": "parfums",
"description": "Eaux de parfum et coffrets",
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 1,
"status": "active",
"created_at": "2026-09-12 09:41:37",
"product_count": 18
}
],
"next_cursor": null,
"has_more": false
}
}
GET /v1/categories/{id}
فئة واحدة مع product_count وchildren، أي فئاتها الفرعية مرتبة حسب sort_order.
المصادقة: مفتاح منصة بصلاحية products:read.
إذا لم يكن رقم الفئة في المسار أرقاماً فقط، يُرجع النداء 400 bad_request. وفئة متجر آخر تُرجع 404 not_found، مثل فئة غير موجودة.
الطلب
curl 'https://api.dzbuild.app/v1/categories/10' \
-H "Authorization: Bearer $DZ_KEY"
الاستجابة 200
{
"data": {
"id": 10,
"name": "Parfums",
"slug": "parfums",
"description": "Eaux de parfum et coffrets",
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 1,
"status": "active",
"created_at": "2026-09-12 09:41:37",
"children": [
{"id": 11, "name": "Parfums femme", "slug": "parfums-femme", "sort_order": 2, "status": "active"},
{"id": 12, "name": "Parfums homme", "slug": "parfums-homme", "sort_order": 3, "status": "active"}
],
"product_count": 18
}
}
POST /v1/categories
تنشئ فئة وتضعها في الأخير: قيمة sort_order لها تزيد بواحد على أكبر قيمة في المتجر.
المصادقة: مفتاح منصة بصلاحية products:write. يتطلب Idempotency-Key.
الجسم
| الحقل | النوع | إلزامي | ملاحظات |
|---|---|---|---|
name | string | نعم | تُحذف المسافات من الطرفين، من 1 إلى 100 حرف. |
description | string أو null | لا | تُحذف المسافات من الطرفين. النص الفارغ يُحفظ null. |
parent_id | int أو null | لا | فئة رئيسية من هذا المتجر: تصبح الفئة الجديدة فئة فرعية لها. وnull أو 0 تُنشئ فئة رئيسية. |
status | active أو inactive | لا | القيمة الافتراضية active. |
show_subcategories | bool | لا | القيمة الافتراضية true. تُتجاهل وتُحفظ true للفئة الفرعية، أو ما دام الفئات الفرعية داخل الفئة الرئيسية فقط مفعّلاً. |
يُصنع الـ slug من الاسم: بأحرف صغيرة، مع الإبقاء على الحروف والأرقام، وتتحول كل سلسلة من الرموز الأخرى إلى - واحدة. الاسم العربي يحتفظ بحروفه العربية. وإذا كان لفئة أخرى في المتجر الـ slug نفسه، تُضاف -2 ثم -3 وهكذا.
الطلب
curl -X POST 'https://api.dzbuild.app/v1/categories' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cat-create-coffrets-1" \
-d '{"name": "Coffrets cadeaux", "parent_id": 10}'
الاستجابة 201
الاستجابة هي كائن الفئة، دون product_count وchildren.
{
"data": {
"id": 15,
"name": "Coffrets cadeaux",
"slug": "coffrets-cadeaux",
"description": null,
"image": null,
"parent_id": 10,
"show_subcategories": true,
"sort_order": 5,
"status": "active",
"created_at": "2026-10-06 14:02:11"
}
}
PATCH /v1/categories/{id}
تغيّر الحقول التي ترسلها فقط. يأخذ الجسم حقول POST نفسها، وكلها اختيارية.
المصادقة: مفتاح منصة بصلاحية products:write. يتطلب Idempotency-Key.
nameجديد يعطيslugجديداً، فيتغير عنوان صفحة الفئة في المتجر وتتوقف الروابط إلى العنوان القديم عن العمل. وإرسال الاسم نفسه يُبقي الـslug.parent_idينقل الفئة. رقم فئة رئيسية يجعلها فئة فرعية، وnullأو0يجعلها فئة رئيسية. الفئة التي لها فئات فرعية لا يمكن أن تصبح فئة فرعية، ولا يمكن أن تكون الفئة أُمّاً لنفسها.- الجسم الفارغ لا يغيّر شيئاً ويُرجع الفئة كما هي.
الطلب
curl -X PATCH 'https://api.dzbuild.app/v1/categories/15' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cat-15-move-1" \
-d '{"parent_id": null, "status": "inactive"}'
الاستجابة 200
{
"data": {
"id": 15,
"name": "Coffrets cadeaux",
"slug": "coffrets-cadeaux",
"description": null,
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 5,
"status": "inactive",
"created_at": "2026-10-06 14:02:11"
}
}
DELETE /v1/categories/{id}
تحذف فئة فارغة مع صورتها.
المصادقة: مفتاح منصة بصلاحية products:write. يتطلب Idempotency-Key.
الفئة التي ما زالت تضم منتجات أو فئات فرعية تُرجع 409 category_not_empty ولا يُحذف شيء. رسالة الخطأ تذكر العدد. لتفريغ الفئة:
- الفئات الفرعية: اجعل كل واحدة فئة رئيسية بـ
PATCHو"parent_id": null، أو احذفها أولاً. - المنتجات: الواجهة البرمجية لا تستطيع إخراج منتج من فئة. تحديد
category_idلمنتج يضيف فئة ويُبقي الفئات التي ينتمي إليها من قبل، انظر المنتجات. غيّر فئات تلك المنتجات من لوحة التحكم.
الطلب
curl -X DELETE 'https://api.dzbuild.app/v1/categories/14' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: cat-14-delete-1"
الاستجابة 200
{
"data": {
"deleted": true,
"id": 14
}
}
POST /v1/categories/reorder
تضبط sort_order للفئات التي تذكرها دفعة واحدة: إما أن تتغير كلها أو لا يتغير أي منها.
المصادقة: مفتاح منصة بصلاحية products:write. يتطلب Idempotency-Key.
الجسم
| الحقل | النوع | إلزامي | ملاحظات |
|---|---|---|---|
categories | array | نعم | الفئات بترتيبها الجديد. كل عنصر هو {"id": 10} أو {"id": 10, "sort_order": 7} أو رقم وحده مثل 10. |
- العنصر الذي ليس فيه
sort_orderيأخذ موضعه في المصفوفة: 1 ثم 2 ثم 3 وهكذا. والعنصر الذي فيهsort_orderيأخذ ذلك الرقم. - كل رقم يجب أن يكون من المتجر وأن يظهر مرة واحدة.
- الفئات التي لا تذكرها تحتفظ بقيمة
sort_orderالخاصة بها. - إعادة الترتيب لا تُسجَّل في سجل التغييرات، فلا يمكن التراجع عنها. اقرأ القائمة أولاً إن كنت قد تحتاج إلى الترتيب القديم.
الطلب
curl -X POST 'https://api.dzbuild.app/v1/categories/reorder' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cat-reorder-1" \
-d '{"categories": [{"id": 14}, {"id": 10}]}'
الاستجابة 200
{
"data": {
"reordered": 2,
"categories": [
{"id": 14, "sort_order": 1},
{"id": 10, "sort_order": 2}
]
}
}
التراجع
تُسجَّل POST وPATCH وDELETE في سجل تغييرات المتجر. استجاباتها لا تحمل رقم التغيير: GET /v1/changes?entity=category تعرض تغييرات الفئات، الأحدث أولاً، بصلاحية store:read. والحقل entity_id هو رقم الفئة.
الطلب
curl 'https://api.dzbuild.app/v1/changes?entity=category&limit=1' \
-H "Authorization: Bearer $DZ_KEY"
الاستجابة 200
{
"data": {
"items": [
{
"id": 120,
"entity": "category",
"entity_id": "15",
"action": "update",
"summary": "Updated category #15 (parent_id, status, show_subcategories)",
"undone_at": null,
"created_at": "2026-10-06 14:05:48",
"undone": false
}
],
"next_cursor": "MTIw",
"has_more": true
}
}
يتراجع POST /v1/changes/{id}/undo عن تغيير واحد. ويحتاج إلى products:write وIdempotency-Key.
- التراجع عن
PATCHيُرجع القيم السابقة للحقول التي غيّرها ذلك النداء، مع فحوصPATCHنفسها. - التراجع عن
DELETEيُنشئ الفئة من جديد برقمها القديم، دون صورتها. وإذا حُذفت فئتها الأم القديمة أو صارت فئة فرعية، يُرجع التراجع422 invalid_parent. - لا يمكن التراجع عن الإنشاء: يُرجع التراجع
422 nothing_to_restore. احذف الفئة بدلاً من ذلك. - إذا لم تعد الفئة موجودة، أو أُخذ رقمها القديم، يُرجع التراجع
422 restore_target_missing. - التغيير الذي يُتراجع عنه مرة ثانية يُرجع
409 already_undone. - التغييرات المحفوظة من لوحة التحكم لا تُسجَّل، فلا يمكن التراجع عنها عبر الواجهة البرمجية.
- لا يستطيع رمز التطبيق المثبّت قراءة التغييرات ولا التراجع عنها: كلاهما يُرجع
403 forbidden(Apps cannot use this endpoint).
curl -X POST 'https://api.dzbuild.app/v1/changes/120/undo' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: undo-120"
{
"data": {
"undone": true,
"change_id": 120,
"entity": "category",
"undo_change_id": 121
}
}
الأخطاء
| HTTP | الرمز | السبب |
|---|---|---|
| 400 | bad_request | الرقم في المسار ليس أرقاماً فقط، أو الجسم ليس JSON صالحاً، أو مرشّح parent_id ليس رقماً ولا 0 ولا null ولا قيمة فارغة، أو categories غائب أو ليس مصفوفة، أو Idempotency-Key غائب أو غير صالح. |
| 401 | unauthorized | مفتاح خاطئ أو غائب. |
| 402 | quota_exceeded | انتهت حصة الطلبات الشهرية للمتجر. انظر حدود المعدل. |
| 403 | forbidden | Missing scope: products:read أو Missing scope: products:write أو Missing scope: store:read، أو API access requires an active Enterprise plan لمفتاح تاجر متجره ليس على خطة Enterprise سارية، أو Apps cannot use this endpoint عندما يقرأ رمز تطبيق مثبّت التغييرات أو يتراجع عنها. |
| 404 | not_found | لا توجد فئة بهذا الرقم في المتجر، أو تذكر إعادة الترتيب رقماً ليس في المتجر، أو يذكر التراجع تغييراً ليس في سجل تغييرات المتجر. |
| 409 | category_not_empty | الفئة ما زالت تضم منتجات أو فئات فرعية. |
| 409 | already_undone | للتراجع فقط: سبق التراجع عن هذا التغيير. |
| 413 | payload_too_large | الجسم أكبر من 1 ميغابايت. |
| 422 | validation_error | name غائب أو فارغ أو أطول من 100 حرف، أو status ليست active ولا inactive، أو parent_id ليس رقماً، أو إعادة الترتيب فارغة أو تكرر رقماً أو فيها رقم ليس عدداً صحيحاً موجباً أو sort_order ليس عدداً صحيحاً. |
| 422 | invalid_parent | parent_id ليس فئة من هذا المتجر، أو هو نفسه فئة فرعية، أو هو الفئة نفسها، أو للفئة فئات فرعية فلا يمكن نقلها تحت فئة أخرى. |
| 422 | nothing_to_restore | للتراجع فقط: التغيير أنشأ الفئة. |
| 422 | restore_target_missing | للتراجع فقط: الفئة لم تعد موجودة، أو أُخذ رقمها القديم. |
| 422 | idempotency_key_reuse | استُعمل Idempotency-Key نفسه مع جسم آخر. |
| 429 | rate_limited | نداءات كثيرة في الدقيقة الحالية. انتظر الثواني المذكورة في Retry-After. انظر حدود المعدل. |
| 500 | server_error | فشل الطلب. أعد المحاولة بالـ Idempotency-Key نفسه. |