أنواع الأحداث
كل حدث ترسله إلى POST /api/partner/v1/events يستخدم نفس المظروف؛ يتغير فقط نص eventType ومحتوى payload. هذه الصفحة تسرد كل أنواع الأحداث الـ ١٦ مع مثال body لكل نوع — انسخ، عدّل، وقّع، أرسل.
كل حدث موسوم بحالته الحالية:
- متاحمُعالَج اليوم — أرسله ويأخذ مفعوله.
- مُخططمقبول على مستوى الاتصال لكن الـ handler لم يُوصَل بعد، فيُرجِع
503قابلاً لإعادة المحاولة. طوّر مقابله، لكن توقّع الرفض حتى يُطلَق. - صادرقروش يرسل هذا الحدث إليك (راجع Webhooks). إرساله إلى
/api/partner/v1/eventsيُرجِع400 WRONG_EVENT_DIRECTION. شكل الـ payload موثّق هنا لتعرف ما ستستقبله.
المظروف
يغلّف كل حدث. التاجر يُستخرَج من مفتاح API، ليس من الـ body.
{
"eventId": "<Guid v7 — فريد لكل حدث، يُستخدم لمنع التكرار>",
"occurredAt": "<ISO-8601 UTC — وقت حدوث الحدث في نظامك>",
"entityType": "Invoice | Redemption | LoyaltyRule | Branch | Customer | Product | Coupon | Integration",
"entityId": "<string — معرّف الكيان المتأثر في نظامك>",
"sourceSystem": "Kosoor | Quroosh",
"schemaVersion": 1,
"correlationId": "<Guid — اختياري، يربط الأحداث بين الأنظمة>",
"eventType": "<إحدى القيم الـ ١٦ أدناه>",
"payload": { /* object يعتمد على eventType، راجع كل قسم أدناه */ }
}إعادة المحاولة يجب أن تحمل نفس eventId. قروش يحتفظ بالاستجابة لمدة ٢٤ ساعة ويعيدها — الـ handler التجاري لا يعمل مرتين.
أحداث المعاملات
InvoiceEarned متاح
العميل كسب نقاطاً أو ختماً على عملية شراء.
{
"eventType": "InvoiceEarned",
"payload": {
"externalInvoiceId": "0195d1c7-8000-7000-8000-000000000123",
"externalCustomerId": "cust_012345",
"externalBranchId": "0195d0a0-0000-7000-8000-000000000001",
"subtotalAfterDiscountBeforeVat": 104.35,
"earnType": "Points",
"stampCardId": null,
"channel": "Pos"
}
}earnType:PointsأوStamps. عدد النقاط أو الأختام يُحسَب على الخادم من قواعد التاجر النشطة — لا يُرسَل من الشريك.stampCardId: مطلوب فقط عندما يكونearnType = "Stamps". Null للنقاط.channel:PosأوKiosk.- منفعة واحدة لكل فاتورة: أي
externalInvoiceIdسبق احتسابه يُرفض بـPARTNER_INVOICE_ALREADY_EARNEDحتى معeventIdجديد. - بطاقة أختام
PerVisitما زالت ضمن فترة الانتظار تُرجِع200بدون أختام — قبول وليس خطأ.
InvoiceRefunded مُخطط
تم إرجاع فاتورة. قروش يعكس الكسب الأصلي.
{
"eventType": "InvoiceRefunded",
"payload": {
"externalInvoiceId": "0195d1c7-8000-7000-8000-000000000124",
"externalOriginalInvoiceId": "0195d1c7-8000-7000-8000-000000000123",
"refundedAmount": 104.35,
"isOverride": false
}
}externalInvoiceId: معرّف فاتورة الإرجاع نفسها.externalOriginalInvoiceId: الفاتورة الأصلية التي تُرجَع.isOverride:trueفقط إذا فرض المدير الإرجاع رغم منع التحقق.
RefundReversalCompleted صادر
متابعة قروش لـ InvoiceRefunded — يُبلغ بما حدث فعلياً بعد تطبيق السياسة. أنت تستقبل هذا الحدث؛ ولا ترسله أبداً.
{
"eventType": "RefundReversalCompleted",
"payload": {
"externalInvoiceId": "0195d1c7-8000-7000-8000-000000000124",
"status": "Reversed",
"pointsReversed": 120,
"stampsReversed": null,
"newBalance": 380
}
}status:Reversed(نظيف)،OverrideApplied، أوNegativeBalanceByPolicy.- يُسلَّم كـ webhook صادر بمجرد إطلاق عكس الإرجاع؛ لم يُطلَق بعد.
استخدام الكوبونات
CouponUsed متاح
تم استخدام كوبون على فاتورة.
{
"eventType": "CouponUsed",
"payload": {
"externalCouponId": "0195d1c7-9000-7000-8000-000000000010",
"externalCustomerId": "cust_012345",
"externalInvoiceId": "0195d1c7-8000-7000-8000-000000000123"
}
}CouponUsageCancelled متاح
يعكس CouponUsed سابقاً.
{
"eventType": "CouponUsageCancelled",
"payload": {
"externalCouponId": "0195d1c7-9000-7000-8000-000000000010",
"externalInvoiceId": "0195d1c7-8000-7000-8000-000000000123"
}
}أحداث المزامنة (كيان واحد)
BranchSynced متاح
{
"eventType": "BranchSynced",
"payload": {
"externalBranchId": "0195d0a0-0000-7000-8000-000000000001",
"name": "الرياض — العليا",
"isActive": true
}
}CustomerSynced متاح
{
"eventType": "CustomerSynced",
"payload": {
"externalCustomerId": "cust_012345",
"phone": "+9665XXXXXXXX",
"firstName": "أحمد",
"lastName": "العتيبي"
}
}firstName و lastName اختياريان.
ProductSynced متاح
{
"eventType": "ProductSynced",
"payload": {
"externalProductId": "sku_00042",
"name": "كورتادو — ١٢ أونصة",
"price": 18.00,
"isActive": true
}
}أرسل isActive: false عند حذف المنتج أو تعطيله — أي مكافأة قروش مربوطة به تصبح غير قابلة للربط وتُرفض عمليات الاستبدال التي تعتمد عليها. عدم إرسال isActive يعتبرهtrue افتراضياً.
CouponSynced متاح
{
"eventType": "CouponSynced",
"payload": {
"externalCouponId": "0195d1c7-9000-7000-8000-000000000010",
"name": "رمضان ٢٠٪",
"discountType": "Percentage",
"discountValue": 20.00,
"isLoyaltyProgramCoupon": false
}
}discountType:FixedAmount(مبلغ بالريال) أوPercentage(نسبة من الفاتورة).isLoyaltyProgramCoupon:trueلكوبون أنشأه قروش لاستبدال ضمن برنامج الولاء؛falseلكوبونات التاجر الخاصة. القيمة الافتراضيةfalse.
أحداث المزامنة (دفعات)
للاستيراد المبدئي الكبير أو المطابقة الدورية. الـ payload يغلّف نفس شكل الكيان الواحد في items.
BranchesSyncedBatch مُخطط
{
"eventType": "BranchesSyncedBatch",
"payload": {
"items": [
{ "externalBranchId": "0195d0a0-...-001", "name": "الرياض — العليا", "isActive": true },
{ "externalBranchId": "0195d0a0-...-002", "name": "جدة — الكورنيش", "isActive": true }
]
}
}CustomersSyncedBatch مُخطط
{
"eventType": "CustomersSyncedBatch",
"payload": {
"items": [
{ "externalCustomerId": "cust_012345", "phone": "+9665XXXXXXX1" },
{ "externalCustomerId": "cust_012346", "phone": "+9665XXXXXXX2", "firstName": "سارة" }
]
}
}ProductsSyncedBatch مُخطط
{
"eventType": "ProductsSyncedBatch",
"payload": {
"items": [
{ "externalProductId": "sku_00042", "name": "كورتادو — ١٢ أونصة", "price": 18.00, "isActive": true },
{ "externalProductId": "sku_00043", "name": "لاتيه — ١٦ أونصة", "price": 22.00, "isActive": true }
]
}
}CouponsSyncedBatch مُخطط
{
"eventType": "CouponsSyncedBatch",
"payload": {
"items": [
{ "externalCouponId": "0195...010", "name": "رمضان ٢٠٪", "discountType": "Percentage", "discountValue": 20.00 },
{ "externalCouponId": "0195...011", "name": "أول زيارة", "discountType": "FixedAmount", "discountValue": 5.00 }
]
}
}تغييرات القواعد
LoyaltyRuleChanged صادر
التاجر غيّر طريقة الكسب. قروش يرسل هذا إلى الـ webhook الخاص بك لتحدّث قواعدك المخزّنة؛ ولا ترسله أبداً. الـ payload الداخلي يتبدل حسب ruleType. طبّق أي payload فقط عندما يكونruleVersion فيه أكبر من الإصدار الذي خزّنته آخر مرة — فالأحداث ليس لها ترتيب عام.
معدل الكسب (ruleType = "EarnRate")
{
"eventType": "LoyaltyRuleChanged",
"payload": {
"externalStoreId": "0195d0a0-0000-7000-8000-000000000000",
"ruleType": "EarnRate",
"ruleVersion": 3,
"effectiveFrom": "2026-07-15T00:00:00Z",
"payload": {
"methodType": "OnPurchase",
"pointCostAmount": 1.00,
"pointCostPoints": 1,
"pointsPerVisit": null,
"minimumPurchase": 20.00,
"isActive": true
}
}
}methodType:OnPurchase(كسب لكل ريال) أوOnVisit(كسب ثابت لكل زيارة).- مع
OnPurchase: عيّنpointCostAmountوpointCostPoints؛ اتركpointsPerVisitnull. - مع
OnVisit: عيّنpointsPerVisit؛ اترك حقلَي التكلفة null. FreeEntryليست طريقة كسب مقبولة من الشركاء — قروش يرفضها.
قاعدة الأختام (ruleType = "StampRule")
{
"eventType": "LoyaltyRuleChanged",
"payload": {
"externalStoreId": "0195d0a0-0000-7000-8000-000000000000",
"ruleType": "StampRule",
"ruleVersion": 2,
"effectiveFrom": "2026-07-15T00:00:00Z",
"payload": {
"stampCardId": "0195d1c7-a000-7000-8000-000000000100",
"name": "بطاقة الأختام — قهوة",
"mode": "PerAmount",
"minInvoiceAmount": 15.00,
"amountPerStamp": 15.00,
"cooldownDays": null,
"isActive": true
}
}
}mode:PerVisit(ختم لكل زيارة مؤهلة) أوPerAmount(ختم لكل مبلغ ريالات محدد).cooldownDays: انتظار اختياري بين الأختام لنفس العميل.
دورة الحياة
RedemptionExpiredOrCancelled صادر
استرداد معلّق سقط بدون إتمام. أنت تستقبل هذا من قروش؛ ولا ترسله أبداً.
{
"eventType": "RedemptionExpiredOrCancelled",
"payload": {
"redemptionId": "0195d1c7-b000-7000-8000-000000000500",
"externalInvoiceId": null,
"reason": "Expired"
}
}reason:Expired(انتهى الوقت) أوCancelled(الموظف ألغى).externalInvoiceId: يُعيَّن إذا كان الاسترداد قد ارتبط بفاتورة؛ وإلا null.
IntegrationStatusChanged صادر
التاجر فعّل أو أوقف أو فصل التكامل. قروش يرسل هذا إلى الـ webhook الخاص بك.
{
"eventType": "IntegrationStatusChanged",
"payload": {
"status": "Enabled"
}
}status:Enabled،Disabled، أوDisconnected.- توقّف عن إرسال الأحداث بعد
DisabledأوDisconnected.
كل السكيمات الـ ١٦ متوفرة أيضاً في مرجع APIضمن سكيما جسم الطلب — استخدم أي عرض تفضّله.