تخط وانتقل إلى المحتوى الرئيسي

التغييرات والتراجع عنها

اعرض تغييرات الإعدادات التي أُجريت عبر الواجهة البرمجية، واقرأ أي تغيير مع القيم التي استبدلها، ثم تراجع عنه لتعود تلك القيم إلى المتجر.

بقلم: Support

أغلب كتابات الإعدادات التي تمر عبر الواجهة البرمجية تُسجَّل كتغييرات: إعدادات المتجر وتصميمه وقالبه، وأقسام الصفحة الرئيسية، والفئات، والمخزون، وأكواد الخصم، والبيكسلات، وأسعار الشحن وإعدادات التوصيل، وأقسام صفحات الهبوط. يحتفظ كل تغيير بالقيم التي استبدلها، والتراجع يعيد كتابتها عبر الفحوص نفسها التي مرّت بها الكتابة الأصلية. الكتابات التي يُجريها على المتجر Copilot أو مساعد ذكاء اصطناعي متصل (Claude أو ChatGPT) أو تطبيق مثبّت تُسجَّل هي أيضاً. أما التغييرات المحفوظة من لوحة التحكم فلا تُسجَّل.

النقاط الثلاث أدناه تعرض قائمة التغييرات، وتقرأ تغييراً واحداً كاملاً، وتتراجع عن تغيير. الكتابات تحت /v1/store/home-layout ومزامنة الأسعار من شركة التوصيل تُرجع change_id. أما بقية الكتابات فابحث عن تغييرها عبر GET /v1/changes.

ما الذي يُسجَّل

entity

تُسجّله

entity_id

الصلاحية لقراءته كاملاً

الصلاحية للتراجع عنه

store.settings

PATCH /v1/store

settings

store:read

store:write

store.design

PATCH /v1/store/design

design

store:read

store:write

store.theme

POST /v1/store/theme وPOST /v1/store/fast-checkout-theme وPOST /v1/store/variant-style

theme

store:read

store:write

store.home_sections

PATCH /v1/store/home-sections

home_sections

store:read

store:write

store.home_layout

كل كتابة تحت /v1/store/home-layout

layout

store:read

store:write

category

POST /v1/categories وPATCH وDELETE /v1/categories/{id}

رقم الفئة

products:read

products:write

stock

POST /v1/products/{id}/stock

رقم المنتج

products:read

products:write

promo_code

POST /v1/promo-codes وPATCH وDELETE /v1/promo-codes/{id}

رقم كود الخصم

promos:read

promos:write

pixels

POST /v1/pixels وPATCH وDELETE /v1/pixels/{id}

رقم البيكسل في DZBuild، وليس pixel_id

pixels:read

pixels:write

shipping.rates

POST /v1/shipping/rates وPOST /v1/shipping/rates/sync

rates

shipping:read

shipping:write

shipping.settings

PATCH /v1/shipping/settings

settings

shipping:read

shipping:write

lp.section

كتابات الأقسام تحت /v1/landing-pages/{id}/sections

رقم القسم، أو lp: متبوعة برقم الصفحة عند إعادة الترتيب

landing_pages:read

landing_pages:write

  • هذه الكتابات لا تُسجَّل ولا يمكن التراجع عنها: المنتجات مع صورها ومتغيراتها وعروضها وإضافاتها وقواعد الكمية (المخزون يُسجَّل)، والطلبات، وصفحات الهبوط نفسها، وترتيب الفئات، وشركات التوصيل، والـ webhooks، والمفاتيح.

  • القيمة lp.page مقبولة كفلتر لـ entity، لكن لا توجد كتابة تُسجّلها.

  • التسجيل لا يوقف الكتابة. إذا تعذّر تسجيل تغيير، مثلاً لأن قيمه قبل الكتابة أو بعدها تتجاوز 256 KB، تتم الكتابة رغم ذلك ولا يمكن التراجع عنها. كتابات أسعار الشحن هي الاستثناء: تفحص الحجم أولاً وتُرجع 422 snapshot_too_large بدل أن تُنفَّذ.

  • كل صلاحية في الجدول ضمن الصلاحيات الافتراضية للمفتاح الجديد، فالمفتاح المُنشأ من لوحة التحكم (الإعدادات ← واجهة API، /dashboard/api) يستطيع استعمال النقاط الثلاث. الصلاحيات تُجمَّد لحظة إنشاء المفتاح، فالمفتاح القديم الذي تنقصه الصلاحية المطلوبة يُرجع 403 forbidden: أنشئ مفتاحاً جديداً من لوحة التحكم.

GET /v1/changes

تغييرات المتجر، الأحدث أولاً، دون القيم التي استبدلتها.

المصادقة: مفتاح منصة بصلاحية store:read. رمز التطبيق المثبّت يتلقى 403 forbidden (Apps cannot use this endpoint).

معاملات الاستعلام

المعامل

النوع

الافتراضي

ملاحظات

entity

string

لا شيء

تغييرات entity واحدة من الجدول أعلاه فقط. أي قيمة أخرى تُتجاهل وتعود القائمة كاملة.

limit

int

25

من 1 إلى 100. القيمة الأصغر تُحسب 1، والأكبر تُحسب 100.

cursor

string

لا شيء

قيمة next_cursor من الصفحة السابقة. انظر الترقيم.

الطلب

curl 'https://api.dzbuild.app/v1/changes?limit=2' \
  -H "Authorization: Bearer $DZ_KEY"

الاستجابة 200

{
  "data": {
    "items": [
      {
        "id": 120,
        "entity": "shipping.rates",
        "entity_id": "rates",
        "action": "update",
        "summary": "Shipping rates updated for 2 wilaya(s)",
        "undone_at": null,
        "created_at": "2026-10-06 11:02:17",
        "undone": false
      },
      {
        "id": 119,
        "entity": "promo_code",
        "entity_id": "7",
        "action": "update",
        "summary": "Updated promo code SUMMER10",
        "undone_at": null,
        "created_at": "2026-10-06 10:52:30",
        "undone": false
      }
    ],
    "next_cursor": "MTE5",
    "has_more": true
  }
}

الحقل

المعنى

id

رقم التغيير، لـ GET /v1/changes/{id} وللتراجع.

entity

ما الذي تغيّر. انظر الجدول أعلاه.

entity_id

العنصر الذي تغيّر، كنص. انظر الجدول أعلاه.

action

create أو update أو delete. التراجع يُسجَّل كـ update.

summary

وصف قصير بالإنجليزية. التراجع يُكتب Undo of change # متبوعاً برقم التغيير الذي تراجع عنه.

undone

true بعد التراجع عن التغيير.

undone_at

وقت التراجع عن التغيير، وإلا null.

created_at

YYYY-MM-DD HH:MM:SS بتوقيت الخادم. وundone_at بالصيغة نفسها.

GET /v1/changes/{id}

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

المصادقة: مفتاح منصة بصلاحية store:read، إضافة إلى صلاحية القراءة الخاصة بنوع التغيير في الجدول أعلاه. رمز التطبيق المثبّت يتلقى 403 forbidden.

الطلب

curl 'https://api.dzbuild.app/v1/changes/118' \
  -H "Authorization: Bearer $DZ_KEY"

الاستجابة 200

{
  "data": {
    "id": 118,
    "key_id": "dzpk_live_xxxxxxxxxxxxxx",
    "entity": "category",
    "entity_id": "12",
    "action": "update",
    "summary": "Updated category #12 (name, slug)",
    "undone_at": null,
    "undone_by_id": null,
    "created_at": "2026-10-06 10:41:05",
    "before": {"name": "Shoes", "slug": "shoes"},
    "after": {"name": "Sneakers", "slug": "sneakers"},
    "undone": false
  }
}

تحمل الاستجابة حقول القائمة، وهذه الحقول أيضاً.

الحقل

المعنى

key_id

المفتاح الذي أجرى التغيير، أو null لتراجع أُجري من لوحة التحكم.

undone_by_id

رقم التغيير الذي تراجع عن هذا التغيير، وإلا null.

before

القيم التي استبدلها التغيير. null في حالة create.

after

القيم التي كتبها التغيير. null في حالة delete وفي مزامنة الأسعار من شركة التوصيل.

رمز الوصول (access token) الخاص بالبيكسل لا يُحفظ أبداً في التغيير. إذا كان للبيكسل رمز، يظهر •••••••• مكانه في before وafter.

الأخطاء

HTTP

الرمز

السبب

400

bad_request

رقم التغيير في المسار ليس أرقاماً فقط.

403

forbidden

المفتاح لا يملك store:read أو صلاحية القراءة الخاصة بنوع التغيير (Missing scope: ...)، أو النداء من رمز تطبيق مثبّت.

404

not_found

لا يوجد تغيير بهذا الرقم في المتجر.

POST /v1/changes/{id}/undo

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

المصادقة: مفتاح منصة بصلاحية التراجع الخاصة بنوع التغيير في الجدول أعلاه، ولا حاجة إلى store:read. يتطلب Idempotency-Key. رمز التطبيق المثبّت يتلقى 403 forbidden (Apps cannot use this endpoint). يرى مالك المتجر آخر 20 تغييراً أجراها كل تطبيق مثبّت في صفحة ذلك التطبيق في لوحة التحكم (/dashboard/apps/{id}، قسم آخر التغييرات التي أجراها)، ويستطيع التراجع عنها من هناك بزر تراجع.

ما يفعله التراجع

  1. التغيير الذي أنشأ شيئاً ليس له ما يُستعاد، فيُرجع 422 nothing_to_restore: احذف العنصر بدل ذلك. إضافة قسم للصفحة الرئيسية عبر /v1/store/home-layout هي الاستثناء، لأن كل كتابة على تخطيط الصفحة الرئيسية تُسجَّل كـ update للتخطيط كله.

  2. التراجع عن update يعيد كتابة قيم before فوق ما هو موجود الآن. الصفحة الرئيسية وحدها تفحص التغييرات اللاحقة وتُرجع 409 layout_changed (انظر أقسام الصفحة الرئيسية). للتراجع عن عدة تغييرات على العنصر نفسه، ابدأ بالأحدث.

  3. الفئة المحذوفة تعود برقمها، دون صورتها. وكود الخصم المحذوف يعود برقمه إذا لم يأخذه كود آخر، ومع عدد مرات استعماله.

  4. البيكسل المحذوف يعود برقمه إذا بقي متاحاً، لكن دون رمز الوصول ودون ربطه بالمنتجات والفئات وصفحات الهبوط. والتراجع عن تعديل بيكسل يترك رمز الوصول الحالي كما هو.

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

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

  7. التراجع عن POST /v1/shipping/rates يعيد الأسعار السابقة، ويحذف سعر الولاية التي لم يكن لها سعر قبل التغيير. والتراجع عن مزامنة الأسعار من شركة التوصيل يعيد كل سعر استبدلته المزامنة، ويُبقي الأسعار التي أضافتها لولايات لم يكن لها سعر.

  8. التراجع يُسجَّل تغييراً مستقلاً، undo_change_id، ويمكنك التراجع عنه لتطبيق التغيير الأصلي من جديد. إذا لم يكن للتغيير الأصلي after (حذف أو مزامنة أسعار من شركة التوصيل)، يُرجع التراجع عن التراجع 422 nothing_to_restore.

  9. يمكن التراجع عن التغيير مرة واحدة. أي تراجع لاحق يُرجع 409 already_undone، ومن تراجعَين يُرسَلان في اللحظة نفسها لا يُنفَّذ إلا واحد.

  10. إذا فشلت الاستعادة نفسها (restore_target_missing، أو قيمة مرفوضة، أو 500)، لا يُعلَّم التغيير كمتراجَع عنه، فيمكنك إعادة المحاولة بعد إصلاح السبب. قواعد إعادة المحاولة أسفله.

استجابة التراجع لا تحمل القيم المستعادة. اقرأ العنصر من جديد: كل طلب GET عبر api.dzbuild.app يُخدَم حديثًا، فالقراءة التي تلي التراجع مباشرة تُرجع القيم المستعادة.

الطلب

curl -X POST 'https://api.dzbuild.app/v1/changes/118/undo' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Idempotency-Key: undo-118"

الاستجابة 200

{
  "data": {
    "undone": true,
    "change_id": 118,
    "entity": "category",
    "undo_change_id": 121
  }
}

الحقل

المعنى

undone

دائماً true مع 200.

change_id

التغيير الذي تم التراجع عنه.

entity

نوعه.

undo_change_id

التغيير الذي يسجّل هذا التراجع، أو null إذا تعذّر تسجيله.

الأخطاء

HTTP

الرمز

السبب

400

bad_request

رقم التغيير في المسار ليس أرقاماً فقط، أو Idempotency-Key غائب أو بصيغة خاطئة.

403

forbidden

المفتاح لا يملك صلاحية التراجع الخاصة بنوع التغيير (Missing scope: ...)، أو النداء من رمز تطبيق مثبّت.

404

not_found

لا يوجد تغيير بهذا الرقم في المتجر.

409

already_undone

سبق التراجع عن التغيير.

409

layout_changed

الصفحة الرئيسية فقط: تغيّر التخطيط بعد هذا التغيير.

422

not_undoable

هذا النوع من التغييرات لا يمكن التراجع عنه.

422

nothing_to_restore

التغيير أنشأ شيئاً، أو لا يحمل قيماً تُستعاد. احذف العنصر بدل ذلك.

422

restore_target_missing

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

422

idempotency_key_reuse

استُعمل Idempotency-Key نفسه من قبل لطلب مختلف، مثل التراجع عن تغيير آخر.

4xx

رمز الكتابة الأصلية

فحوص الكتابة الأصلية ترفض القيم، مثلاً invalid_wilaya في أسعار الشحن، أو قالب لم يعد متاحاً.

500

server_error

تعذّر تنفيذ التراجع. يبقى التغيير قابلاً للتراجع عنه.

إعادة المحاولة وIdempotency-Key

أول استجابة لكل مفتاح تُحفظ 24 ساعة، بما فيها استجابات 4xx. إعادة المحاولة بالمفتاح نفسه للتغيير نفسه تُرجع تلك الاستجابة مع Idempotency-Replay: 1، ولا يُنفَّذ تراجع ثانٍ. لذلك بعد إصلاح سبب الخطأ، أعد المحاولة بمفتاح جديد. استجابات 5xx و429 لا تُحفظ أبداً، فأعد المحاولة بالمفتاح نفسه. انظر Idempotency.

هل أجاب هذا عن سؤالك؟