مقدمة
KD Push خدمة إشعارات مُدارة بالكامل للمنصات وتجارها. التاجر لا يتعامل مع OneSignal أو Firebase أو شهادات Apple: يضيف تطبيقه في البوابة، ويأخذ App Key و Server Key، ومنصته ترسل عبر هذه الواجهة.
كل الطلبات والردود بصيغة JSON عبر HTTPS، والتواريخ بصيغة ISO 8601، والمعرّفات العامة بصيغة ULID.
البدء السريع
- 1أنشئ تطبيقك وخذ المفاتيح
- 2سجّل الجهاز من التطبيقcURL
curl -X POST https://push.kd-app.com/api/v1/sdk/devices \ -H "X-KD-App-Key: kdp_app_…" \ -H "Content-Type: application/json" \ -d '{ "platform": "android", "token": "fcm-registration-token", "installation_id": "3f0c9a2e-6b1d-4c8e-9f7a-2d5e8b1c4a90", "android": { "fcm_project_id": "neon-push" }, "external_user_id": "42", "user_signature": "9f2c4e…", "locale": "ar", "app_version": "2.1.0" }' - 3أرسل من خادمكcURL
curl -X POST https://push.kd-app.com/api/v1/messages \ -H "Authorization: Bearer kdp_live_…" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: app-created-1234" \ -d '{ "title": "تطبيق جديد", "body": "تمت إضافة واتساب الذهبي للمتجر", "url": "neonstore://app/1234", "image_url": "https://cdn.example.com/icons/1234.png", "data": { "app_id": "1234" }, "audience": { "type": "all" } }'
المصادقة
لكل تطبيق نوعان من المفاتيح، ولكل واحد مكان واحد فقط:
kdp_app_…X-KD-App-Key: kdp_app_…- مكانه:
- داخل تطبيق الجوال (عام)
- يستطيع:
- تسجيل الأجهزة، قراءة الإعدادات، تسجيل الفتح
- لا يستطيع الإرسال أبداً
kdp_live_…Authorization: Bearer kdp_live_…- مكانه:
- في خادم منصتك فقط (سري)
- يستطيع:
- الإرسال، المتابعة، الإلغاء، الإحصائيات
- يظهر مرة واحدة — يُخزَّن عندنا كـ hash
404.الأخطاء
كل الأخطاء بنفس الشكل، ولا تحتوي تفاصيل داخلية:
{
"error": {
"code": "validation_failed",
"message": "The body field is required.",
"fields": {
"body": [
"The body field is required."
]
}
}
}invalid_app_keyinvalid_server_keysubscription_inactivequota_exceededinvalid_user_signatureweb_disabled · origin_not_allowedinvalid_subscription · provider_mismatchapp_disabled · account_bannednot_foundnot_cancelablevalidation_failedfields.invalid_tokenrate_limitedRetry-After.server_errorحدود الاستخدام
عند التجاوز تحصل على 429 rate_limited مع ترويسة Retry-After. الإرسال لعدد كبير من الأجهزة طلب واحد — المحرك يقسمه داخلياً.
منع الإرسال المكرر
أرسل ترويسة Idempotency-Key مع كل طلب إرسال (مثلاً معرّف الحدث عندك). إعادة نفس الطلب بنفس المفتاح خلال 24 ساعة تعيد نفس الإشعار بـ 200 بدل إنشاء إشعار جديد — فإعادة المحاولة بعد انقطاع الشبكة آمنة دائماً.
Idempotency-Key: app-created-1234-v2.1.0إعدادات التشغيل
/sdk/configApp Key — تطبيق الجوالاطلبها عند فتح التطبيق. أندرويد يأخذ منها خيارات Firebase، فتغيير مشروع Firebase أو المزوّد لا يحتاج إعادة بناء التطبيق.
Cache-Control: max-age=300.curl https://push.kd-app.com/api/v1/sdk/config \
-H "X-KD-App-Key: kdp_app_…"{
"app": {
"id": "01JB2Q6V8K4Y3N5M7R9T1W0XZC",
"name": "My Store"
},
"identity_verification": "required",
"android": {
"provider": "fcm",
"firebase": {
"project_id": "neon-push",
"app_id": "1:123456789:android:abcdef",
"api_key": "AIza…",
"sender_id": "123456789",
"storage_bucket": null
}
},
"ios": {
"provider": "apns"
},
"web": {
"provider": "webpush",
"vapid_public_key": "BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U",
"icon_url": null,
"prompt": {
"enabled": true,
"delay_seconds": 6,
"title": null,
"text": null
}
}
}تسجيل الجهاز
/sdk/devicesApp Key — تطبيق الجوالاستدعه عند كل فتح للتطبيق، وعند تجدد التوكن، وعند تسجيل الدخول والخروج. أول مرة يرجع 201 وبعدها 200.
platformios | android | webإلزاميtokenstringإلزاميinstallation_iduuidاختياريproviderapns | fcm | webpushاختياريios.bundle_idstringاختياريBundle.main.bundleIdentifier.ios.profile_app_idstringاختياريapplication-identifier من embedded.mobileprovision بدون بادئة الفريق.ios.team_idstring(10)اختياريTeamIdentifier من نفس الملف.ios.environmentproduction | sandboxاختياريaps-environment.android.fcm_project_idstringاختياريweb.p256dh · web.authbase64urlحسب الحالةexternal_user_idstring | nullاختياريnull عند تسجيل الخروج.user_signaturehexحسب الحالةexternal_user_id طالما التحقق من الهوية مفعّل. كيف تحسبهtagsobjectاختياريlocale · timezone · app_version · os_version · device_model · sdk_versionstringاختياريcurl -X POST https://push.kd-app.com/api/v1/sdk/devices \
-H "X-KD-App-Key: kdp_app_…" \
-H "Content-Type: application/json" \
-d '{
"platform": "android",
"token": "fcm-registration-token",
"installation_id": "3f0c9a2e-6b1d-4c8e-9f7a-2d5e8b1c4a90",
"android": { "fcm_project_id": "neon-push" },
"external_user_id": "42",
"user_signature": "9f2c4e…",
"locale": "ar",
"app_version": "2.1.0"
}'{
"device": {
"installation_id": "3f0c9a2e-6b1d-4c8e-9f7a-2d5e8b1c4a90",
"platform": "android",
"status": "active",
"external_user_id": "42"
}
}{
"error": {
"code": "invalid_user_signature",
"message": "user_signature does not match external_user_id."
}
}إلغاء الاشتراك
/sdk/devices/unsubscribeApp Key — تطبيق الجوالعندما يطفئ المستخدم الإشعارات من داخل التطبيق. يتوقف الإرسال للجهاز حتى يسجّل مرة أخرى.
installation_iduuidإلزاميcurl -X POST https://push.kd-app.com/api/v1/sdk/devices/unsubscribe \
-H "X-KD-App-Key: kdp_app_…" \
-H "Content-Type: application/json" \
-d '{ "installation_id": "3f0c9a2e-6b1d-4c8e-9f7a-2d5e8b1c4a90" }'{
"unsubscribed": true
}تسجيل فتح الإشعار
/sdk/eventsApp Key — تطبيق الجوالعند ضغط المستخدم على الإشعار. يُحسب مرة واحدة لكل جهاز وإشعار، ويظهر في عدّاد "فُتح".
type"opened"إلزاميmessage_idULIDإلزاميkd_message_id من الإشعار.installation_iduuidإلزاميcurl -X POST https://push.kd-app.com/api/v1/sdk/events \
-H "X-KD-App-Key: kdp_app_…" \
-H "Content-Type: application/json" \
-d '{
"type": "opened",
"message_id": "01JB2QA4N7C2X9V5B8M3K6P1RD",
"installation_id": "3f0c9a2e-6b1d-4c8e-9f7a-2d5e8b1c4a90"
}'{
"accepted": true
}إشعارات الموقع (المتصفحات)
نفس الإشعارات تصل إلى زوار موقعك من المتصفح، بدون تطبيق وبدون Firebase أو شهادات: لكل تطبيق مفتاح VAPID خاص به تنشئه KD Push تلقائياً. تعمل في Chrome وEdge وFirefox وSamsung Internet وSafari على الماك، وعلى الآيفون والآيباد بعد إضافة الموقع إلى الشاشة الرئيسية (iOS 16.4 فأحدث).
- في بوابة التاجر: التطبيق ←
الويب، فعّل إشعارات الموقع وأضف دومينك (أو من خادمك عبر PUT /app/web). - أنشئ الملف
/kdpush-sw.jsفي جذر موقعك بهذا السطر:
importScripts('https://push.kd-app.com/sdk/web/v1/kdpush-sw.js');- أضف سكربت الـ SDK في كل الصفحات قبل
</head>:
<script src="https://push.kd-app.com/sdk/web/v1/kdpush.js"
data-app-key="kdp_app_…" async></script>هذا كل شيء: بطاقة صغيرة تطلب من الزائر تفعيل الإشعارات (نصها ومدتها من البوابة)، ثم يُسجَّل المتصفح تلقائياً، ويعود ليتحقق مرة يومياً. الضغط على الإشعار يفتح رابطه ويُسجَّل في عدّاد "فُتح".
خيارات وواجهة برمجية
<!-- data-* options -->
data-app-key required
data-service-worker /kdpush-sw.js (default)
data-prompt "off" hides the built-in card
data-lang ar | en | es | fr | de (default: the page language)
data-user-id your user id + data-user-signature (identity verification)
data-tags JSON, e.g. '{"plan":"vip"}'
// JavaScript
KDPush.subscribe() // ask (from a click) and subscribe → "subscribed" | "denied" | "default" | "unsupported" | "disabled"
KDPush.unsubscribe()
KDPush.isSubscribed() // Promise<boolean>
KDPush.login('42', signature) // link the browser to your user
KDPush.logout()
KDPush.setTags({ plan: 'vip' })os تلقائياً (ios · android · desktop)، فتستطيع مثلاً إرسال إعلان تطبيق آيفون لزوار الموقع من الآيفون فقط: {"platforms":["web"],"audience":{"type":"tags","tags":{"os":"ios"}}}. وإن كان لموقعك Service Worker خاص، أضف سطر importScripts إليه واجعل data-service-worker مساره.إعدادات الويب
/app/webServer Key — خادمكلمنصة تربط مواقع تجارها: فعّل الويب وحدّد الدومينات عند ربط المتجر أو عند تغيّر الدومين. التفعيل يحتاج دوميناً واحداً على الأقل وينشئ مفتاح VAPID للتطبيق. الحقول غير المرسلة تبقى كما هي.
enabledbooleanإلزاميoriginsstring[] ≤ 20حسب الحالةicon_urlhttps URLاختياريdefault_urlURLاختياريprompt{enabled, delay_seconds, title, text}اختياريcurl -X PUT https://push.kd-app.com/api/v1/app/web \
-H "Authorization: Bearer kdp_live_…" \
-H "Content-Type: application/json" \
-d '{"enabled":true,"origins":["shop.example.com"],"icon_url":"https://cdn.example.com/logo.png"}'{
"web": {
"enabled": true,
"origins": [
"https://shop.example.com",
"https://www.shop.example.com"
],
"vapid_public_key": "BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U",
"subscribers": 0,
"icon_url": "https://cdn.example.com/logo.png",
"default_url": null,
"prompt": {
"enabled": true,
"delay_seconds": 6,
"title": null,
"text": null
}
}
}إرسال إشعار
/messagesServer Key — خادمكيُرسل (أو يُجدول) إشعاراً لأجهزة تطبيقك فقط. الرد فوري بحالة queued، والإرسال يتم في الخلفية — تابع الحالة والعدّادات عبر حالة الإشعار.
bodystring ≤ 2000إلزاميtitlestring ≤ 255اختياريurlstringاختياريhttps:// أو رابط داخلي مثل neonstore://app/1234.image_urlhttps URLاختياريdataobject ≤ 30اختياريkd_ محجوزة.audienceobjectاختياري{"type":"all"} (الافتراضي) · users + external_user_ids · devices + installation_ids · tags + tags — حتى 1000 معرّف.platforms["ios","android","web"]اختياريscheduled_atISO 8601اختياريttl_secondsintاختياريpriorityhigh | normalاختياريcollapse_idstring ≤ 64اختياريالترويسات
Idempotency-Keystring ≤ 128اختياري402 subscription_inactive. وبدون اشتراك لا يعمل أي شيء: لا إعدادات (/sdk/config) ولا تسجيل أجهزة ولا تعديل إعدادات التطبيق من خادمك.curl -X POST https://push.kd-app.com/api/v1/messages \
-H "Authorization: Bearer kdp_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: app-created-1234" \
-d '{
"title": "تطبيق جديد",
"body": "تمت إضافة واتساب الذهبي للمتجر",
"url": "neonstore://app/1234",
"image_url": "https://cdn.example.com/icons/1234.png",
"data": { "app_id": "1234" },
"audience": { "type": "all" }
}'{
"message": {
"id": "01JB2QA4N7C2X9V5B8M3K6P1RD",
"status": "queued",
"source": "api",
"title": "تطبيق جديد",
"body": "تمت إضافة واتساب الذهبي للمتجر",
"image_url": "https://cdn.example.com/icons/1234.png",
"url": "neonstore://app/1234",
"data": {
"app_id": "1234"
},
"audience": {
"type": "all"
},
"platforms": null,
"scheduled_at": null,
"counts": {
"targeted": 0,
"sent": 0,
"failed": 0,
"invalid": 0,
"opened": 0
},
"error": null,
"failures": [],
"created_at": "2026-10-03T12:00:00+00:00",
"started_at": null,
"finished_at": null
}
}{
"error": {
"code": "subscription_inactive",
"message": "No active KD Push subscription for this account."
}
}حالة إشعار
/messages/{id}Server Key — خادمكالحالة والعدّادات. راجع كائن الإشعار لمعنى كل حقل.
curl https://push.kd-app.com/api/v1/messages/01JB2QA4N7C2X9V5B8M3K6P1RD \
-H "Authorization: Bearer kdp_live_…"{
"message": {
"id": "01JB2QA4N7C2X9V5B8M3K6P1RD",
"status": "sent",
"source": "api",
"title": "تطبيق جديد",
"body": "تمت إضافة واتساب الذهبي للمتجر",
"image_url": "https://cdn.example.com/icons/1234.png",
"url": "neonstore://app/1234",
"data": {
"app_id": "1234"
},
"audience": {
"type": "all"
},
"platforms": null,
"scheduled_at": null,
"counts": {
"targeted": 1240,
"sent": 1227,
"failed": 3,
"invalid": 10,
"opened": 214
},
"error": null,
"failures": [],
"created_at": "2026-10-03T12:00:00+00:00",
"started_at": "2026-10-03T12:00:01+00:00",
"finished_at": "2026-10-03T12:00:04+00:00"
}
}سجل الإشعارات
/messagesServer Key — خادمكسجل تطبيقك، الأحدث أولاً.
statusstringاختياريscheduled · queued · sending · sent · failed · canceledper_page1–100اختياريcurl "https://push.kd-app.com/api/v1/messages?status=sent&per_page=20" \
-H "Authorization: Bearer kdp_live_…"{
"data": [
{
"id": "01JB2QA4N7C2X9V5B8M3K6P1RD",
"status": "sent",
"source": "api",
"title": "تطبيق جديد",
"body": "تمت إضافة واتساب الذهبي للمتجر",
"image_url": "https://cdn.example.com/icons/1234.png",
"url": "neonstore://app/1234",
"data": {
"app_id": "1234"
},
"audience": {
"type": "all"
},
"platforms": null,
"scheduled_at": null,
"counts": {
"targeted": 0,
"sent": 0,
"failed": 0,
"invalid": 0,
"opened": 0
},
"error": null,
"failures": [],
"created_at": "2026-10-03T12:00:00+00:00",
"started_at": null,
"finished_at": null
}
],
"meta": {
"current_page": 1,
"per_page": 20,
"total": 1,
"last_page": 1
}
}إلغاء إشعار
/messages/{id}/cancelServer Key — خادمكيلغي إشعاراً مجدولاً أو في الطابور أو قيد الإرسال. الدفعات التي لم تُرسل بعد تتوقف فوراً.
curl -X POST https://push.kd-app.com/api/v1/messages/01JB2QA4N7C2X9V5B8M3K6P1RD/cancel \
-H "Authorization: Bearer kdp_live_…"{
"message": {
"id": "01JB2QA4N7C2X9V5B8M3K6P1RD",
"status": "canceled",
"source": "api",
"title": "تطبيق جديد",
"body": "تمت إضافة واتساب الذهبي للمتجر",
"image_url": "https://cdn.example.com/icons/1234.png",
"url": "neonstore://app/1234",
"data": {
"app_id": "1234"
},
"audience": {
"type": "all"
},
"platforms": null,
"scheduled_at": null,
"counts": {
"targeted": 0,
"sent": 0,
"failed": 0,
"invalid": 0,
"opened": 0
},
"error": null,
"failures": [],
"created_at": "2026-10-03T12:00:00+00:00",
"started_at": null,
"finished_at": null
}
}{
"error": {
"code": "not_cancelable",
"message": "Only scheduled, queued or sending messages can be canceled."
}
}التطبيق والاشتراك
/appServer Key — خادمكتحقق من المفتاح ومن إمكانية الإرسال قبل تفعيل الإشعارات التلقائية في منصتك: sending.can_send يجمع حالة الاشتراك وحصة الشهر، وsending.reason يذكر السبب بنفس رموز POST /messages (subscription_inactive · quota_exceeded). plan وusage لعرض وضع التاجر، وportal روابط يصلح منها اشتراكه.
curl https://push.kd-app.com/api/v1/app \
-H "Authorization: Bearer kdp_live_…"{
"app": {
"id": "01JB2Q6V8K4Y3N5M7R9T1W0XZC",
"name": "My Store",
"platform": "neon",
"status": "active",
"ios_bundle_id": "com.store.app",
"android_package": "com.store.app"
},
"subscription": {
"status": "active",
"expires_at": "2026-11-02T12:00:00+00:00",
"grace_until": null,
"days_left": 19,
"can_send": true
},
"plan": {
"name": "Pro",
"period": "monthly",
"monthly_messages": 100000,
"max_devices": null,
"max_apps": 3
},
"usage": {
"deliveries_this_month": 18240,
"remaining_this_month": 81760,
"active_devices": 1240
},
"sending": {
"can_send": true,
"reason": null
},
"portal": {
"plans": "https://push.kd-app.com/portal/plans",
"subscription": "https://push.kd-app.com/portal/subscription"
},
"devices": {
"active": 1240,
"ios": 800,
"android": 440,
"web": 0
},
"web": {
"enabled": false,
"origins": [],
"vapid_public_key": null,
"subscribers": 0,
"icon_url": null,
"default_url": null,
"prompt": {
"enabled": true,
"delay_seconds": 6,
"title": null,
"text": null
}
}
}حزمة أندرويد
/app/androidServer Key — خادمكلمنصة تتيح لتاجرها اختيار حزمة تطبيق أندرويد: أرسل الحزمة التي بُني بها التطبيق عند تغيّرها، فتظهر في بوابة التاجر ويُتحقَّق منها ملف Firebase الذي يرفعه لاحقاً.
packagestringإلزاميcom.store.app.409 package_mismatch ويذكر firebase_package الحزمة المسجّلة — حتى لا تتوقف إشعارات أندرويد بصمت.curl -X PUT https://push.kd-app.com/api/v1/app/android \
-H "Authorization: Bearer kdp_live_…" \
-H "Content-Type: application/json" \
-d '{"package":"com.store.app"}'{
"app": {
"id": "01JB2Q6V8K4Y3N5M7R9T1W0XZC",
"android_package": "com.store.app"
}
}{
"error": {
"code": "package_mismatch",
"message": "The app's Firebase project is registered for com.store.app; upload one for com.other.app first.",
"firebase_package": "com.store.app"
}
}إحصائيات الأجهزة
/devices/statsServer Key — خادمكعدد الأجهزة النشطة لكل منصة.
curl https://push.kd-app.com/api/v1/devices/stats \
-H "Authorization: Bearer kdp_live_…"{
"devices": {
"active": 1240,
"ios": 800,
"android": 440,
"web": 0
}
}ربط مع KD Push
اربط متجر التاجر بتطبيق KD Push بنقرة واحدة، دون أن ينسخ أحد مفتاحاً: التاجر يوافق في صفحة KD Push، ومنصتك تستلم المفاتيح مباشرة من خادم إلى خادم (OAuth 2 بأسلوب authorization code مع PKCE).
- نسجّل منصتك ونعطيك
client_idوclient_secret، مع عناوين العودة الدقيقة المسموحة. - أرسل التاجر إلى
/portal/connect/authorizeبالمعاملات أدناه. - يسجّل دخوله أو ينشئ حساباً (معبّأ مسبقاً مما أرسلته)، يختار تطبيقاً أو ينشئه، ويوافق.
- نعيده إلى
redirect_uri?code=…&state=…— أوerror=access_deniedإن رفض. - خادمك يستبدل الرمز بالمفاتيح عبر POST /connect/token.
معاملات صفحة الموافقة
response_typecodeإلزاميclient_idstringإلزاميredirect_urihttps URLإلزاميstatestring ≤ 255إلزاميcode_challengebase64urlإلزاميBASE64URL(SHA256(code_verifier))؛ احتفظ بـ code_verifier (43–128 حرفاً) في خادمك.code_challenge_methodS256إلزاميapp_namestring ≤ 120اختياريios_bundle_idstringاختياريandroid_packagestringاختياريexternal_refstring ≤ 191اختياريexternal_labelstring ≤ 255اختياريhint_name · hint_email · hint_company · hint_phonestringاختياريstate قبل أي شيء. الرمز صالح 10 دقائق ولمرة واحدة؛ تقديمه مرتين يُلغي ما نتج عنه. لا يصل code_verifier ولا client_secret إلى المتصفح أبداً.// 1. Send the merchant to KD Push (keep $verifier and $state in their session)
$verifier = Str::random(64);
$state = Str::random(40);
session(['kdpush' => compact('verifier', 'state')]);
return redirect('https://push.kd-app.com/portal/connect/authorize?' . http_build_query([
'response_type' => 'code',
'client_id' => config('services.kdpush.connect_client_id'),
'redirect_uri' => 'https://your-platform.example/kdpush/callback',
'state' => $state,
'code_challenge' => rtrim(strtr(base64_encode(hash('sha256', $verifier, true)), '+/', '-_'), '='),
'code_challenge_method' => 'S256',
'app_name' => $store->name, // optional: prefills a new app
'ios_bundle_id' => $store->bundleId, // optional
'android_package' => $store->androidPackage, // optional
'external_ref' => $store->id, // optional: your id for the store
'hint_email' => $owner->email, // optional: prefills sign-up
], '', '&', PHP_QUERY_RFC3986));استبدال الرمز بالمفاتيح
/connect/tokenclient_id + client_secretgrant_typeauthorization_codeإلزاميclient_id · client_secretstringإلزاميcodestringإلزاميredirect_uristringإلزاميcode_verifierstringإلزاميتصلك app_key (للتطبيق)، وserver_key جديد خاص بهذا الربط (يظهر مرة واحدة)، وidentity_secret، ووضع اشتراك التاجر في account بنفس شكل GET /app.
curl -X POST https://push.kd-app.com/api/v1/connect/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"client_id": "kdp_cli_…",
"client_secret": "kdp_cs_…",
"code": "kdp_code_…",
"redirect_uri": "https://your-platform.example/kdpush/callback",
"code_verifier": "…"
}'{
"connection": {
"id": "01JB2QX5V8K4Y3N5M7R9T1W0XZ",
"connected_at": "2026-10-14T12:00:00+00:00"
},
"app": {
"id": "01JB2Q6V8K4Y3N5M7R9T1W0XZC",
"name": "My Store",
"platform": "neon",
"ios_bundle_id": "com.store.app",
"android_package": null
},
"merchant": {
"name": "Store owner",
"email": "[email protected]"
},
"app_key": "kdp_app_…",
"server_key": "kdp_live_…",
"identity_secret": "…",
"api_base": "https://push.kd-app.com/api/v1",
"account": {
"subscription": {
"status": "active",
"expires_at": "2026-11-02T12:00:00+00:00",
"grace_until": null,
"days_left": 19,
"can_send": true
},
"plan": {
"name": "Pro",
"period": "monthly",
"monthly_messages": 100000,
"max_devices": null,
"max_apps": 3
},
"usage": {
"deliveries_this_month": 18240,
"remaining_this_month": 81760,
"active_devices": 1240
},
"sending": {
"can_send": true,
"reason": null
},
"portal": {
"plans": "https://push.kd-app.com/portal/plans",
"subscription": "https://push.kd-app.com/portal/subscription"
}
}
}{
"error": {
"code": "invalid_grant",
"message": "Authorization code already used."
}
}فصل الربط
/connect/revokeServer Key — خادمكيتوقف مفتاح الخادم المرسَل فوراً؛ التطبيق وأجهزته وسجله تبقى للتاجر. التاجر يستطيع الفصل أيضاً من لوحته، وعندها يجيب مفتاحك بـ 401 invalid_server_key — اعتبر ذلك فصلاً.
curl -X POST https://push.kd-app.com/api/v1/connect/revoke \
-H "Authorization: Bearer kdp_live_…"{
"revoked": true
}كائن الإشعار
idULIDاختياريstatusstringاختياريsent إذا وصل لجهاز واحد على الأقل، failed إذا لم يصل لأي جهاز (السبب في error).sourceapi | portal | adminاختياريcounts.targetedintاختياريcounts.sentintاختياريcounts.invalidintاختياريcounts.failedintاختياريcounts.openedintاختياريfailures[{provider, code, http_status, count}]اختياريTopicDisallowed) وحالة HTTP وعدد الأجهزة.created_at · started_at · finished_at · scheduled_atISO 8601اختياريالتحقق من هوية المستخدم
لربط جهاز بمستخدم (لإشعار شخصي مثل "اشتراكك ينتهي")، يحتاج التطبيق توقيعاً يحسبه خادمك بعد تسجيل الدخول — وإلا يستطيع أي شخص تسجيل جهازه باسم مستخدم آخر واستقبال إشعاراته.
user_signature = hex( HMAC-SHA256( external_user_id , identity_secret ) )// After the user logs in — on your backend, never in the app
$signature = hash_hmac('sha256', (string) $user->id, config('services.kdpush.identity_secret'));
return ['user_id' => $user->id, 'push_signature' => $signature];ما يستقبله التطبيق
{
"aps": {
"alert": {
"title": "تطبيق جديد",
"body": "تمت إضافة واتساب الذهبي للمتجر"
},
"sound": "default",
"mutable-content": 1
},
"kd_message_id": "01JB2QA4N7C2X9V5B8M3K6P1RD",
"kd_url": "neonstore://app/1234",
"kd_image": "https://cdn.example.com/icons/1234.png",
"app_id": "1234"
}{
"notification": {
"title": "تطبيق جديد",
"body": "تمت إضافة واتساب الذهبي للمتجر",
"image": "https://cdn.example.com/icons/1234.png"
},
"data": {
"kd_message_id": "01JB2QA4N7C2X9V5B8M3K6P1RD",
"kd_url": "neonstore://app/1234",
"app_id": "1234"
}
}افتح kd_url عند الضغط، وأرسل kd_message_id إلى /sdk/events. قيم data تصل كنصوص.
FirebaseMessaging.onMessageOpenedApp.listen((message) {
final url = message.data['kd_url'];
final id = message.data['kd_message_id'];
if (url != null) openDeepLink(url); // e.g. neonstore://app/1234
if (id != null) reportOpened(id); // POST /sdk/events
});خطوات ربط منصة
- 1التاجر ينشئ تطبيقه في البوابة ويضع App Key و Server Key في لوحة منصتك.
- 2منصتك تبني التطبيق وبداخله App Key — والتطبيق يطلب /sdk/config ثم يسجّل الجهاز.
- 3بعد تسجيل الدخول يعطي خادمك التطبيق user_signature لمعرّف المستخدم.
- 4منصتك ترسل الإشعارات التلقائية (تطبيق جديد، تحديث) مع Idempotency-Key لكل حدث.
- 5عند ربط كتالوج لأول مرة لا ترسل إشعاراً لكل تطبيق — اجمعها في إشعار واحد.
- 6تحقق من subscription.can_send عبر /app قبل تفعيل الإشعارات التلقائية.
Postman
- حمّل المجموعة واستوردها في Postman (Import ← اختر الملف).
- من متغيرات المجموعة ضع
app_keyوserver_key، وتوكن جهاز تجريبي فيdevice_token. - شغّل Register device ثم Send a notification — معرّف الإشعار يُحفظ تلقائياً في
message_idللطلبات التالية. - اختياري: ضع
external_user_idوidentity_secretوالمجموعة تحسبuser_signatureبنفسها.