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

الرموز الترويجية

اعرض الرموز الترويجية لمتجرك وأنشئها وعدّلها واحذفها من برنامجك الخاص، مع شرط تفعيل الإضافة وتأكيد خصم 100% والتراجع عن التغييرات.

بقلم: Support

هذه النقاط الأربع تدير الرموز الترويجية للمتجر، أي الرموز التي يكتبها الزبون عند إتمام الطلب ليدفع أقل. وهي تعمل على الرموز نفسها الموجودة في صفحة الرموز الترويجية بلوحة التحكم، المشروحة في رموز الخصم، وتستطيع أيضاً تغيير نص الرمز، وهذا ما لا تسمح به لوحة التحكم.

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

قبل أن تبدأ

  • يجب أن تكون إضافة الرموز الترويجية مفعّلة في المتجر (/dashboard/addons). القائمة تعمل بدونها وتُخبرك بحالتها في addon_enabled. كل كتابة تُرجع 409 addon_inactive ما دامت الإضافة معطّلة، ولا يستطيع الزبائن استعمال أي رمز عند إتمام الطلب خلال ذلك.

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

  • الحقلان starts_at وexpires_at بتوقيت الجزائر، بالشكل YYYY-MM-DD HH:MM:SS.

النطاق

الوصف

promos:read

الاطلاع على الرموز الترويجية.

promos:write

إنشاء الرموز الترويجية وتعديلها وحذفها. هذا يغيّر الأسعار التي يدفعها زبائنك.

كائن الرمز الترويجي

الحقل

النوع

المعنى

id

int

رقم الرمز في المتجر.

code

string

ما يكتبه الزبون. بأحرف كبيرة، A-Z و0-9 و- و_، وفريد داخل المتجر.

discount_type

string

percentage أو fixed.

discount_value

number

النسبة (أكبر من 0 وحتى 100) أو المبلغ بالدينار.

min_order_amount

number أو null

المجموع الفرعي للمنتجات الذي يجب أن يبلغه الطلب حتى يُطبَّق الرمز. null تعني بلا حد أدنى.

max_uses

int أو null

عدد الطلبات التي يمكنها استعمال الرمز. null تعني بلا حد.

used_count

int

عدد الطلبات التي استعملته. للقراءة فقط.

is_active

bool

الرمز غير المفعّل يُرفض عند إتمام الطلب.

starts_at

string أو null

قبل هذا الوقت يُرفض الرمز. null تعني أنه يعمل فوراً.

expires_at

string أو null

بعد هذا الوقت يُرفض الرمز. null تعني أنه لا ينتهي أبداً.

created_at، updated_at

string

YYYY-MM-DD HH:MM:SS، بتوقيت الخادم.

GET /v1/promo-codes

رموز المتجر، الأحدث أولاً. لا يوجد نداء يقرأ رمزاً واحداً برقمه: تصفّح هذه القائمة.

المصادقة: مفتاح منصة بصلاحية promos:read.

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

المعامل

النوع

الافتراضي

ملاحظات

is_active

string

لا شيء

true أو 1 أو yes أو on تُرجع الرموز المفعّلة. أي قيمة أخرى تُرجع الرموز المعطّلة. اتركه للحصول على كل الرموز.

limit

int

50

من 1 إلى 200.

cursor

string

لا شيء

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

الطلب

curl 'https://api.dzbuild.app/v1/promo-codes?is_active=true' \
  -H "Authorization: Bearer $DZ_KEY"

الاستجابة 200

{
  "data": {
    "items": [
      {
        "id": 20,
        "code": "WELCOME10",
        "discount_type": "percentage",
        "discount_value": 10,
        "min_order_amount": 3000,
        "max_uses": 100,
        "used_count": 7,
        "is_active": true,
        "starts_at": null,
        "expires_at": "2026-11-30 23:59:00",
        "created_at": "2026-10-06 14:20:11",
        "updated_at": "2026-10-06 14:20:11"
      }
    ],
    "next_cursor": null,
    "has_more": false,
    "addon_enabled": true
  }
}

يُبيّن addon_enabled إن كانت إضافة الرموز الترويجية مفعّلة. عندما تكون قيمته false تبقى القائمة تعمل، لكن الكتابة تفشل ولا يستطيع الزبائن استعمال الرموز.

POST /v1/promo-codes

يُنشئ رمزاً. يعمل الرمز عند إتمام الطلب بمجرد إنشائه، إلا إذا أرسلت is_active: false أو starts_at بتاريخ لاحق.

المصادقة: مفتاح منصة بصلاحية promos:write. يتطلب Idempotency-Key.

الجسم

الحقل

النوع

إلزامي

ملاحظات

code

string

نعم

تُحذف المسافات من طرفيه وتتحوّل الأحرف إلى كبيرة، ثم يجب أن يكون من 2 إلى 30 حرفاً من A-Z أو 0-9 أو - أو _. الرمز الموجود من قبل في المتجر يُرجع 409 code_exists.

discount_type

string

نعم

percentage أو fixed، بأحرف كبيرة أو صغيرة. لا توجد قيمة افتراضية.

discount_value

number

نعم

أكبر من 0. لا يتجاوز 100 مع percentage، والقيمة 100 تحتاج تأكيد التاجر (انظر قسم خصم 100% أسفله). لا حد أعلى مع fixed.

min_order_amount

number أو null

لا

الحد الأدنى للمجموع الفرعي للمنتجات بالدينار. 0 أو "" أو null تعني بلا حد أدنى.

max_uses

int أو null

لا

1 أو أكثر. 0 أو "" أو null تعني بلا حد.

is_active

bool

لا

الافتراضي true. أرسل قيمة JSON منطقية: النص "false" مثلاً يُقرأ true.

starts_at

string أو null

لا

صيغة تاريخ وساعة شائعة، مثل 2026-11-01 08:00 أو نص بصيغة ISO 8601. يُخزَّن بالشكل YYYY-MM-DD HH:MM:SS بتوقيت الجزائر، والقيمة التي تحمل فارقاً عن UTC تُحوَّل. null أو "" تعني بلا تاريخ بدء.

expires_at

string أو null

لا

الصيغ نفسها. يجب أن يكون في المستقبل وبعد starts_at. null أو "" تعني بلا تاريخ انتهاء.

confirm_token

string

لا

لخصم 100% فقط.

confirm_full_discount

bool

لا

لخصم 100% فقط.

الطلب

curl -X POST 'https://api.dzbuild.app/v1/promo-codes' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: promo-welcome10-create" \
  -d '{"code": "welcome10", "discount_type": "percentage", "discount_value": 10, "min_order_amount": 3000, "max_uses": 100, "expires_at": "2026-11-30 23:59"}'

الاستجابة 201

{
  "data": {
    "id": 20,
    "code": "WELCOME10",
    "discount_type": "percentage",
    "discount_value": 10,
    "min_order_amount": 3000,
    "max_uses": 100,
    "used_count": 0,
    "is_active": true,
    "starts_at": null,
    "expires_at": "2026-11-30 23:59:00",
    "created_at": "2026-10-06 14:20:11",
    "updated_at": "2026-10-06 14:20:11"
  }
}

PATCH /v1/promo-codes/{id}

يغيّر الحقول التي ترسلها فقط، بقواعد الإنشاء نفسها. الحقل الذي لا ترسله يحتفظ بقيمته.

المصادقة: مفتاح منصة بصلاحية promos:write. يتطلب Idempotency-Key.

  • يمكن تغيير code. يجب ألا يكون النص الجديد مستعملاً في المتجر، وإلا يُرجع النداء 409 code_exists.

  • يُفحص discount_type وdiscount_value معاً. إرسال discount_type: "percentage" وحده على رمز fixed بـ 500 د.ج يُرجع 422 invalid_discount_value، لأن 500 أكبر من 100. أرسل الحقلين.

  • يجب أن يكون expires_at الجديد في المستقبل. الرمز المنتهي الصلاحية يبقى قابلاً للتعديل ما دمت لا ترسل expires_at.

  • لا يمكن كتابة used_count.

  • الجسم الفارغ لا يغيّر شيئاً ويُرجع الرمز.

  • رمز متجر آخر يُرجع 404، مثل رمز غير موجود.

الطلب

curl -X PATCH 'https://api.dzbuild.app/v1/promo-codes/20' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: promo-20-extend" \
  -d '{"max_uses": 200, "expires_at": "2026-12-31 23:59"}'

الاستجابة 200

{
  "data": {
    "id": 20,
    "code": "WELCOME10",
    "discount_type": "percentage",
    "discount_value": 10,
    "min_order_amount": 3000,
    "max_uses": 200,
    "used_count": 7,
    "is_active": true,
    "starts_at": null,
    "expires_at": "2026-12-31 23:59:00",
    "created_at": "2026-10-06 14:20:11",
    "updated_at": "2026-10-20 09:05:42"
  }
}

DELETE /v1/promo-codes/{id}

يحذف الرمز، فلا يستطيع الزبائن استعماله بعدها. الطلبات التي استعملته من قبل تحتفظ بخصمها. لإيقاف رمز مؤقتاً دون أن تفقد عدد استعمالاته، أرسل is_active: false عبر PATCH بدل الحذف.

المصادقة: مفتاح منصة بصلاحية promos:write. يتطلب Idempotency-Key.

الطلب

curl -X DELETE 'https://api.dzbuild.app/v1/promo-codes/20' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Idempotency-Key: promo-20-delete"

الاستجابة 200

{
  "data": {
    "deleted": true,
    "id": 20
  }
}

خصم 100%

رمز percentage بقيمة 100 يجعل المنتجات مجانية لكل زبون يملك الرمز. الإنشاء، أو التعديل الذي يرسل discount_type أو discount_value، لا يُكتب من النداء الأول إذا كانت النتيجة رمز percentage بنسبة 100%:

  1. يُرجع النداء 422 confirmation_required ولا يكتب شيئاً. يحمل الخطأ confirm_token (يُستعمل مرة واحدة، صالح 600 ثانية) وaction وwill_change، وهو ملخّص تعرضه على التاجر.

  2. بعد موافقة التاجر، أعد الجسم نفسه مع إضافة confirm_token وبـ Idempotency-Key جديد (المفتاح الأول مربوط بالجسم الذي لا يحمل رمز التأكيد). رمز التأكيد المنتهي، أو المستعمل من قبل، أو الذي لم يعد يطابق الطلب، يُرجع 422 confirmation_stale مع رمز تأكيد جديد.

بمفتاح مُنشأ من لوحة التحكم يمكنك تجاوز هذه الجولة بإرسال confirm_full_discount: true في النداء الأول. أما DZBuild Copilot فلا يستطيع استعمال هذا الحقل ويمرّ دائماً عبر رمز التأكيد.

{
  "error": {
    "code": "confirmation_required",
    "message": "A 100% discount makes every order free ...",
    "confirm_token": "cft_xxxxxxxxxxxxxxxx",
    "confirm_token_expires_in": 600,
    "action": "promo.full_discount:new",
    "will_change": {
      "action": "Create a promo code that makes orders free",
      "code": "FREEGIFT",
      "discount": "100% off the whole order subtotal",
      "reversible": true,
      "note": "Any customer with this code pays 0 for the goods. Orders already placed with it cannot be reversed by deleting the code."
    }
  }
}

في التعديل، ينتهي action برقم الرمز بدل new، ويصبح نص will_change.action هو Change promo code #20 to make orders free.

curl -X POST 'https://api.dzbuild.app/v1/promo-codes' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: promo-freegift-approved" \
  -d '{"code": "FREEGIFT", "discount_type": "percentage", "discount_value": 100, "max_uses": 1, "confirm_token": "cft_REPLACE_WITH_TOKEN"}'

سجل التغييرات والتراجع

كل إنشاء وتعديل وحذف يتم عبر الواجهة البرمجية يُسجَّل. الرموز التي تُعدَّل من صفحة لوحة التحكم لا تُسجَّل، فلا يمكن التراجع عنها عبر الواجهة البرمجية.

  • يعرض GET /v1/changes?entity=promo_code تغييرات الرموز الترويجية، الأحدث أولاً، بصلاحية store:read. كل عنصر يحمل id التغيير، ورقم الرمز في entity_id، وaction (create أو update أو delete) وsummary.

  • يحتاج POST /v1/changes/{id}/undo إلى promos:write وإلى Idempotency-Key وإلى أن تكون الإضافة مفعّلة، مثل أي كتابة.

  • التراجع عن تعديل يُرجع القيم السابقة دون أي تأكيد، حتى لو كانت خصماً بـ 100% أو تاريخ انتهاء قد مضى. وإذا حُذف الرمز بعد ذلك، يُرجع التراجع 422 restore_target_missing.

  • التراجع عن حذف يُعيد إنشاء الرمز مع عدد استعمالاته، ويحتفظ برقمه إذا كان هذا الرقم ما يزال شاغراً.

  • التراجع عن إنشاء يُرجع 422 nothing_to_restore: احذف الرمز بدلاً من ذلك.

  • لا يستطيع رمز التطبيق المثبّت قراءة التغييرات ولا التراجع عنها: كلاهما يُرجع 403 forbidden.

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

{
  "data": {
    "undone": true,
    "change_id": 500,
    "entity": "promo_code",
    "undo_change_id": 510
  }
}

التغيير الذي يُتراجع عنه مرة ثانية يُرجع 409 already_undone.

الأخطاء

HTTP

الرمز

السبب

400

bad_request

الرقم في المسار ليس أرقاماً فقط، أو الجسم ليس JSON صالحاً، أو Idempotency-Key غائب أو غير صالح.

403

forbidden

Missing scope: promos:read أو Missing scope: promos:write، أو API access requires an active Enterprise plan لمفتاح تاجر متجره ليس على خطة Enterprise سارية.

404

not_found

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

409

addon_inactive

إضافة الرموز الترويجية غير مفعّلة في المتجر. في الكتابة فقط.

409

code_exists

رمز آخر في المتجر يحمل هذا النص.

422

invalid_code

code أقصر من حرفين أو أطول من 30 حرفاً، أو يحتوي حرفاً غير A-Z و0-9 و- و_.

422

invalid_discount_type

discount_type غائب، أو ليس percentage ولا fixed.

422

invalid_discount_value

discount_value غائب، أو ليس رقماً، أو يساوي 0 أو أقل، أو أكبر من 100 مع percentage.

422

invalid_min_order_amount

min_order_amount ليس رقماً.

422

invalid_max_uses

max_uses ليس رقماً، أو أقل من 1.

422

invalid_starts_at، invalid_expires_at

تعذّرت قراءة التاريخ.

422

expires_at_in_past

قيمة expires_at التي أرسلتها ليست في المستقبل.

422

invalid_date_window

expires_at ليس بعد starts_at.

422

confirmation_required، confirmation_stale

خصم 100% ينتظر موافقة التاجر. انظر القسم أعلاه.

422

idempotency_key_reuse

استُعمل Idempotency-Key نفسه مع جسم أو مسار مختلف.

500

server_error

فشلت الكتابة. أعد المحاولة بـ Idempotency-Key نفسه.

استجابة 4xx تُحفظ مع Idempotency-Key الخاص بها 24 ساعة، وتُعاد لكل إعادة محاولة بالجسم نفسه. بعد تفعيل الإضافة أو تصحيح الجسم، أرسل النداء بمفتاح جديد. الأخطاء المشتركة بين كل النقاط، مثل 401 و402 و429، موجودة في الأخطاء، وقواعد إعادة المحاولة في Idempotency.

حدود معروفة

  • قد تتجاوز الاستعمالات max_uses. عندما يُتمّ عدة زبائن طلباتهم بالرمز نفسه في اللحظة نفسها، قد يتجاوز used_count قيمة max_uses.

  • لا يوجد webhook. إنشاء رمز ترويجي أو تعديله أو حذفه لا يُرسل أي حدث webhook.

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