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

Subscriptions API

Subscriptions API هي واجهة الموافقة في Joryio. تدير، لكل جهة اتصال، حالة الموافقة أو الإلغاء في كل قناة رسائل، Email وSMS وWhatsApp وPush وViber، وعضوية قوائم الاشتراك، أي فئات أو موضوعات الموافقة، وحالة ارتداد Email وسجل التدقيق الكامل لتغييرات الموافقة.

تغطي الصفحة ثلاثة موارد:

  • موافقة جهة الاتصال: /subscriptions/contacts/... لقراءة موافقة القناة والقائمة لجهة اتصال وتغييرها.
  • قوائم الاشتراك: /lists لإنشاء القوائم وإدارتها وإجراء عمليات عضوية جماعية.
  • صفحة التفضيلات المستضافة: /subscriptions/hosted-page لتأليف صفحة مركز التفضيلات لمساحة العمل.

كل النقاط هنا نسبية إلى عنوان الأساس https://api-eu1.joryio.com/api. راجع نظرة عامة على API.

المصادقة​

تتطلب كل الطلبات مفتاح API، وتعمل جلسة لوحة تحكم JWT أيضاً:

Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json

النطاقات لكل نقطة نهاية​

نقطة النهايةالنطاق
GET /subscriptions/contacts/:userId و/lists و/channels/:channel/status و/email-validsubscriptions:read أو compliance:read
GET /subscriptions/contacts/:userId/historycompliance:read
GET /subscriptions/unsubscribe-reasonscompliance:read
PUT /subscriptions/contacts/:userId/channels/:channel وPOST /clear-bounce وPOST / DELETE لعضوية قائمة جهة اتصالsubscriptions:write أو compliance:write
POST /lists وPUT / DELETE للقوائم وPOST /restore وعمليات الأعضاء الجماعيةlists:write أو settings:write
GET /lists وGET /lists/:listId وGET /lists/:listId/statslists:read أو settings:read
GET /lists/:listId/memberscompliance:read
GET /subscriptions/hosted-page/preference-center وPOST /previewsettings:read
PUT /subscriptions/hosted-page/preference-centersettings:write

يظل مساران مغلقين عمدًا أمام مفتاح API يحمل نطاقات الاشتراكات: GET .../history هو سجل الموافقة - دليل يُقدَّم لجهة تنظيمية وليس حالة تشغيلية - وGET /lists/:listId/members يكشف جهات الاتصال. ويحتفظ كلاهما بـ compliance:read فقط.

المفاهيم الأساسية​

معرّف جهة الاتصال​

كل مسار /subscriptions/contacts/:userId يأخذ معرّف جهة الاتصال الداخلي في Joryio، وهو id في Users API، وليس userId الخارجي الذي ترسله في الأحداث. يجب أن يكون ObjectId سداسياً من 24 حرفاً أو UUID؛ ويُرفض غير ذلك بـ 400 Bad Request.

الاشتراك وقت الإنشاء​

تُنشأ جهات الاتصال عبر POST /users/track، ويمكن للاستدعاء نفسه أن يضبط اشتراكاتها في القوائم: كل عنصر في attributes يقبل subscriptions (التفاصيل)، وتُطبَّق عبر مسار الموافقة نفسه الذي تستخدمه نقاط النهاية في هذه الصفحة. تبقى نقاط هذه الصفحة الطريقة لإدارة الموافقة بعد الإنشاء: PUT /subscriptions/contacts/:userId/channels/:channel لموافقة القناة وPOST /subscriptions/contacts/:userId/lists/:listId لعضوية القائمة. لا تعيد اشتراكات الإنشاء إحياء إلغاء قائم؛ إعادة الموافقة الصريحة تتطلب POST لعضوية القائمة.

القنوات وحالاتها​

القنوات الخمس هي email وsms وwhatsapp وpush وviber؛ وأي قيمة أخرى تعيد 400.

الحالةالوصف
optedInموافقة صريحة، مثل تأكيد الموافقة المزدوجة.
subscribedمشترك، موافقة مفردة أو افتراضية.
unsubscribedألغى الاشتراك.
pendingبانتظار التأكيد: طلب الاشتراك ولم يؤكد الموافقة المزدوجة بعد. لا تصله الرسائل حتى يؤكد، والتأكيد يجعله subscribed. تضبطه عملية تأكيد (مثل الموافقة المزدوجة في Delivyr) ولا تضبطه حزم SDK أبدًا.

الحالات بصيغة camelCase، أي optedIn لا opted_in. تعامل بوابات الإرسال جهة الاتصال بلا حالة مسجلة لقناة كأنها مشتركة؛ غياب السجل ليس إلغاءً.

التغييرات مدققة ومعكوسة في السجلات​

تسجل كل كتابة في API في سجل تدقيق الاشتراكات لجهة الاتصال، بالمصدر وIP وuser agent وهوية مفتاح API أو المشرف، ويمكن استرجاعها من سجل الاشتراك. تُعكس الإلغاءات أيضاً إلى دفاتر منع مرتبطة بالمعرّف: إلغاء SMS أو WhatsApp يتبع رقم الهاتف، وإلغاء Email يتبع العنوان في مساحة العمل، لذلك تغطى جهات الاتصال المكررة أيضاً. راجع Suppressions API.

موافقة جهة الاتصال​

الحصول على اشتراكات جهة اتصال​

GET /subscriptions/contacts/:userId

يعيد حالة موافقة كل قناة وعضويات القوائم. تكون القنوات بلا حالة مسجلة غائبة ببساطة من channels. يحمل Email حقول الارتداد الإضافية: isValid وbounceType وbounceCount وlastBounceAt. يعيد lists أول 500 صف عضوية للجهة. يعيد 404 إن لم توجد جهة الاتصال في مساحة العمل.

تحديث اشتراك قناة​

PUT /subscriptions/contacts/:userId/channels/:channel
الحقلالنوعمطلوبالوصف
channelstringنعميجب أن يطابق القناة في URL؛ قيمة URL هي الفائزة عند الاختلاف.
statusstringنعمoptedIn أو subscribed أو unsubscribed. ويُقبل هنا أيضًا pending (بانتظار التأكيد).
sourcestringلامصدر التغيير، مثل api أو preference_center؛ الافتراضي api.
consentTextstringلانص الموافقة المعروض عند الاشتراك، يحفظ للامتثال.
reasonstringلاسبب نصي حر يحفظ في سجل التدقيق.
{
"channel": "email",
"status": "unsubscribed",
"source": "preference_center",
"reason": "User requested via support ticket"
}

يعيد كائن channels المحدّث بالكامل.

  • تؤدي الموافقة على Email إلى مسح حالة ارتداد مؤقت فقط، ولا تحيي أبداً ارتداداً دائماً أو شكوى بريد عشوائي - لا يرفعهما إلا دعم Joryio.
  • يُعكس إلغاء sms أوwhatsapp في دفتر المنع المرتبط بالهاتف، ويُعكس تغيير Email في الدفتر المرتبط بالعنوان لمساحة العمل.
  • تُدقق العملية مع IP وuser agent وهوية المفتاح أو المشرف.

التأكيد المزدوج لاشتراك SMS​

عندما تفعّل مساحة العمل التأكيد المزدوج لاشتراك SMS (الإعدادات > الاشتراكات)، فإن طلب PUT .../channels/sms بالقيمة subscribed أو optedIn لجهة اتصال بلا حالة SMS لا يجعلها مشتركة: تُحفظ الحالة pending وتتلقى جهة الاتصال رسالة "Reply YES" واحدة. وتُظهر الاستجابة ذلك:

{ "sms": { "status": "pending", "optInSource": "api", "confirmation": { "requestedAt": "2026-10-17T10:00:00.000Z", "expiresAt": "2026-10-24T10:00:00.000Z", "sentAt": "2026-10-17T10:00:01.000Z" } } }
  • تصبح جهة الاتصال subscribed (مع optInSource: "double_opt_in") فقط بالرد YES (أو START، أو كلمة اشتراك أخرى) على رقمك. لا يمكن لأي طلب API تأكيد جهة اتصال معلقة (409).
  • الطلب مرة أخرى بينما جهة الاتصال pending يعيد 200 مع الطلب المفتوح نفسه - دون رسالة ثانية.
  • جهة الاتصال التي ألغت اشتراكها، أو التي على رقمها إلغاء اشتراك، تُعامل كاشتراك جديد (قرار المالك 2026-10-17): pending ورسالة تأكيد واحدة، ولا تصبح مشتركة إلا بعد YES؛ ودون رد ينتهي الطلب وتعود unsubscribed ولا يُرسل شيء آخر. جهة الاتصال التي أرسلت STOP تحصل أيضا على عنصر warnings المعتاد sms_stop_provider_block؛ وإذا رفض المزود الرسالة برمز STOP الخاص به تعود غير مشتركة. لا يزال الارتداد الدائم أو شكوى البريد المزعج أو الحظر على مستوى المؤسسة مرفوضا (409).
  • تنتهي الطلبات التي لم يُرد عليها بعد عدد الأيام المحدد (الافتراضي 7): تُحذف حالة SMS (وليست unsubscribed).
  • لا يُطبق عندما يكون رقم SMS لمساحة العمل على حساب Delivyr - فلدى Delivyr تأكيد مزدوج خاص بها.

انظر التأكيد المزدوج لاشتراك SMS.


جهات الاتصال المكررة وإعادة الاشتراك​

  • ينطبق إلغاء الاشتراك على كل جهة اتصال بالبريد أو الهاتف نفسه في مساحة العمل: تُضبط حالة كل منها (أو عضويتها، للقائمة) على unsubscribed ويُضاف سجل بالمصدر shared_identifier.
  • إعادة الاشتراك عبر الـ API مسموحة وتنطبق على جهة الاتصال هذه فقط. تبقى الجهات الأخرى بالبريد أو الهاتف نفسه ملغاة. يُسجَّل التغيير بالمصدر api ومعرّف مفتاح الـ API في metadata.principal.
  • قيمة source في الطلب التي تنتهي بـ _keyword، أو تساوي shared_identifier أو complaint_webhook أو staff، تُسجَّل كـ api - لا يضبط هذه القيم إلا Joryio.
  • يمكن تجاوز إلغاء STOP (SMS وWhatsApp وViber، من أي مزوّد) بهذا التحديث العادي - دون علامة إضافية. ينطبق على جهة الاتصال هذه وحدها، ويسجّل السجل أنه تجاوز STOP (metadata.overrodeStop) ومفتاح الـ API. ويستمر رد START في العمل كما في السابق.
  • SMS فقط: إعادة اشتراك جهة اتصال SMS أرسلت STOP تُرجع 200 OK مع حقل warnings ليس خطأً، لأن مزوّد SMS قد يُبقي حظره الخاص إلى أن ترسل جهة الاتصال START. لا يُرجع WhatsApp وViber أي تحذير. وتُرجع نقطة نهاية القوائم (POST /subscriptions/contacts/:userId/lists/:listId، لقائمة SMS) ونقطة نهاية القناة في الـ SDK الحقل نفسه.
{
"sms": { "status": "subscribed", "optInSource": "api" },
"warnings": [
{
"code": "sms_stop_provider_block",
"channel": "sms",
"message": "This contact opted out by texting STOP. Your SMS provider may keep blocking messages until they text START."
}
]
}
  • الإرسال الذي يرفضه مزوّد SMS بعد ذلك بسبب حظر STOP الخاص به (مثل Twilio 21610 أو رفض opted-out من Delivyr) يُسجَّل بوصفه محظوراً من المزوّد (ألغى الاشتراك) - لا فشلاً، ولا يُحتسب في تنبيهات معدل الارتداد أو الفشل. يُطبَّق الإلغاء مجدداً، مع ملاحظة السجل provider still blocks: re-opted out.
  • بعض أنواع الحظر لا تُرفع بإعادة الاشتراك. يُرفض الطلب بـ 409 Conflict ولا يتغير شيء:
codemessage
deliverabilityThis address hard-bounced or marked a message as spam. Only Joryio support can lift that block.
organization_blockThis identifier is blocked for the whole organization. Only Joryio support can lift that block.
verified_identity_required403 - نقاط نهاية SDK فقط (/v1/subscriptions/channel، /v1/subscriptions/group): إعادة اشتراك شخص ألغى صراحةً (إلغاؤه أو من قائمة، STOP، إلغاء على بريده أو هاتفه - بما في ذلك من جهة اتصال أخرى) من جهة غير مُتحقق منها - userId بدون SDK Authentication، أو anonymousId يخص شخصًا معرّفًا. يُقبل الاشتراك الأول؛ والقائمة التي تتطلب التأكيد المزدوج تجيب pending: true وترسل بريد التأكيد. إلغاء الاشتراك مسموح دائمًا.
{ "statusCode": 409, "error": "Conflict", "code": "deliverability", "message": "This address hard-bounced or marked a message as spam. Only Joryio support can lift that block." }

نقطة نهاية القوائم (POST /subscriptions/contacts/:userId/lists/:listId) لا تُرفض أبداً بسببها؛ ولا يرفعها الاشتراك في قائمة أيضاً. جهات الاتصال التي تشترك في بريد إلكتروني أو هاتف.

مسح حالة الارتداد​

أعد ضبط عدادات الارتداد المؤقت لجهة اتصال. الارتداد الدائم أو شكوى البريد العشوائي لا يرفعهما إلا دعم Joryio: عندما يكون للعنوان أحدهما، يُرفض الطلب بـ 403 وcode: "deliverability".

POST /subscriptions/contacts/:userId/clear-bounce

يقبل reason اختيارياً، ويعيد { "success": true }. يمسح bounceType وbounceCount وlastBounceAt لارتداد مؤقت، ولا يحذف صفوف hard_bounce أو complaint من دفتر المنع.

الحصول على اشتراكات القوائم​

GET /subscriptions/contacts/:userId/lists

يعيد كل صفوف عضوية قوائم جهة الاتصال، المشتركة والملغاة. تكون العضوية فريدة لكل جهة اتصال + قائمة + قناة؛ يمكن للجهة أن تكون مشتركة في قائمة على email وملغية منها على sms كسجلين منفصلين.

اشتراك جهة اتصال في قائمة​

POST /subscriptions/contacts/:userId/lists/:listId

الطلب idempotent؛ تؤكد إعادة الطلب الاشتراك. وهو مسار إعادة الموافقة الصريح والمدقق الوحيد الذي يمكنه إعادة اشتراك جهة ألغت القائمة، إذ لا تفعل الإضافة الجماعية ذلك.

الحقلالنوعمطلوبالوصف
channelstringنعمemail أو sms أو whatsapp أو push أو viber.
sourcestringلامثل api أو form أو import أو preference_center؛ الافتراضي api.
consentTextstringلانص الموافقة المعروض.

يعيد صف العضوية المنشأ أو المحدّث.

إلغاء جهة اتصال من قائمة​

DELETE /subscriptions/contacts/:userId/lists/:listId

تمر القناة في نص الطلب لا URL:

{ "channel": "email", "source": "preference_center" }

يعيد { "success": true }. إذا لم يكن للجهة صف عضوية للقائمة والقناة، ينشئ النظام صف unsubscribed صريحاً على أي حال؛ فلا يفقد سحب الموافقة بصمت وتمنع بوابة الإرسال إرسالات القائمة لاحقاً.

الحصول على سجل الاشتراك​

GET /subscriptions/contacts/:userId/history
المعاملالنوعالافتراضيالوصف
limitnumber50مدخلات الصفحة؛ القيم غير الرقمية ترجع للافتراضي.
offsetnumber0إزاحة الترقيم.

يعيد items، الأحدث أولاً، وtotal. يحتوي كل مدخل على القناة والقائمة، إن وجدت، وaction والحالة السابقة والجديدة والمصدر وIP وuser agent ونص الموافقة وmetadata ووقت الإنشاء. تكون action إحدى subscribe وunsubscribe وresubscribe وbounce وhard_bounce وsoft_bounce وcomplaint وimport وapi_update.

تحمل كل مدخلة unsubscribe مكتوبة منذ 2026-10-15 الحقل metadata.unsubscribeSource - طريقة وصول الإلغاء: header_one_click, page_button, preferences_page, page_everything, api, admin, sdk, import, keyword, complaint, esp_unsubscribe, store_sync, other. header_one_click هو زر إلغاء الاشتراك في تطبيق البريد نفسه (RFC 8058)، وpage_button يعني أن شخصًا ضغط إلغاء الاشتراك في الصفحة المستضافة. عندما تكون الرسالة معروفة، فإن metadata.sinceSendMs هو الوقت من إرسالها حتى الإلغاء. يُخزَّن userAgent دون محارف تحكم ومقتطعًا إلى 256 محرفًا. المدخلات التي تحمل metadata.pageMode بقيمة auto أنشأتها الصفحة المستضافة دون نقر، بين 2026-10-11 و2026-10-15.

إثبات الموافقة (منذ 2026-11-02). يحمل كل مدخل أيضًا changeKind / changeLabel - ما فعله التغيير: subscribed وresubscribed وunsubscribed وpending_order (تحديد عند الدفع في متجر محتجز حتى طلب أو رابط التأكيد) وpending_confirmation وwithdrawn (أزيل التحديد في نفس عملية الدفع) وconfirmed_by_order وconfirmed وconfirmation_expired وbounce وcomplaint وimport وupdated - وsourceKind / sourceLabel / sourcePlatform - من أين جاء: store_checkout وstore_registration وstore_customer_record وstore_newsletter وstore_sync (مع sourcePlatform بقيمة woocommerce أو shopify أو magento أو prestashop) وlanding_page وin_app_form وwebsite_form وapi وadmin وsdk وimport وunsubscribe_link وpreference_center وbounce وcomplaint وkeyword_stop وkeyword_start وdouble_opt_in وpush_permission وjourney وemail_provider وshared_identifier وcontact_merge (حالة نُقلت عند دمج جهتي اتصال) وsupport وother. حقول *Label صياغة بالإنجليزية. page هي الصفحة التي أُعطيت فيها الموافقة حيثما خُزّنت (رابط صفحة أو متجر، أو slug صفحة هبوط)، وإلا null. consentText هو النص الدقيق الذي عُرض على الشخص. ipAddress بيانات شخصية: المستدعي دون pii:view (مفتاح API فقط مع هذا النطاق) يتلقى null وipHidden: true عند وجود عنوان مخزن. location هو المكان في المتجر الذي جُمعت فيه الموافقة - checkout أو block_checkout أو registration أو customer_record أو newsletter - وcollectedAt هو وقت جمعها (ISO-8601 بتوقيت المتجر، وقد يسبق createdAt عندما تُحتجز العلامة حتى الطلب)؛ وكلاهما null عند عدم تسجيلهما.

عرض أحدث أسباب إلغاء الاشتراك​

أحدث إلغاءات الاشتراك في مساحة العمل التي تحمل سبباً أو التي وُسمت بأنها تلقائية على الأرجح، الأحدث أولاً. صف واحد لكل عملية إلغاء: عندما تُلغي عملية واحدة عدة قنوات (مثل رابط قديم يلغي كل شيء)، تُجمع القنوات في صف واحد.

GET /subscriptions/unsubscribe-reasons
المعاملالنوعالافتراضيالوصف
limitnumber50صفوف الصفحة (الحد الأقصى 100).
offsetnumber0إزاحة الترقيم.
daysnumber90المدة إلى الوراء بالأيام (الحد الأقصى 365).
flaggedbooleanfalsetrue يعيد فقط الإلغاءات الموسومة بأنها تلقائية على الأرجح.
curl -X GET "https://api-eu1.joryio.com/api/subscriptions/unsubscribe-reasons?limit=50&offset=0&days=90" \
-H "Authorization: Bearer jry_live_your_api_key"
{
"items": [
{
"at": "2026-10-11T09:12:44.000Z",
"contactId": "665f1c2ab3d4e5f6a7b8c9d0",
"email": "[email protected]",
"name": "Dana Levi",
"channels": ["email"],
"listId": null,
"reason": "too_frequent",
"campaignId": "3f2a1b0c-9d8e-4f7a-b6c5-d4e3f2a1b0c9",
"source": "one_click",
"suspectedAutomatic": false,
"suspectedAutomaticReasons": []
}
],
"total": 37
}

reason هو السبب الذي اختاره الشخص في صفحة التفضيلات (null إذا لم يذكر سبباً). تكون suspectedAutomatic بقيمة true إذا تم الإلغاء في الصفحة المستضافة خلال 10 ثوانٍ من إرسال الرسالة، أو إذا بدا الطلب كحركة ماسح روابط؛ وتوضح suspectedAutomaticReasons أيهما. يُحفظ الوسم نفسه في metadata لمدخل سجل التدقيق. يخضع name لقواعد pii:view: من لا يملك الصلاحية يحصل عليه مُقنَّعاً. يتطلب compliance:read.

فحص حالة اشتراك قناة​

GET /subscriptions/contacts/:userId/channels/:channel/status

يعيد { "subscribed": true } ما لم تكن جهة الاتصال unsubscribed صراحة في القناة؛ الجهة بلا حالة مسجلة تعد مشتركة. يعيد معرّف جهة اتصال غير معروف { "subscribed": false } لا 404.

فحص صلاحية Email​

GET /subscriptions/contacts/:userId/email-valid

يعيد { "valid": true }. تكون valid خاطئة فقط عندما يجعل ارتداد دائم العنوان غير صالح. يعيد معرّف غير معروف { "valid": false } لا 404. يقيس هذا قابلية التسليم لا الموافقة، فتظل الجهة الملغية ذات العنوان العامل true.

قوائم الاشتراك​

القوائم فئات أو موضوعات الموافقة التي يشترك بها الأشخاص، مثل النشرة وتحديثات المنتج. تعيش تعريفاتها تحت /lists، وتدار العضوية لكل جهة بنقاط الموافقة أعلاه أو بالنقاط الجماعية أدناه.

إنشاء قائمة​

POST /lists
الحقلالنوعمطلوبالوصف
namestringنعماسم القائمة، حتى 255 حرفاً وفريد لكل مساحة عمل.
descriptionstringلاوصف، حتى 1000 حرف.
channelsstring[]لاالقنوات التي تنطبق عليها القائمة؛ الافتراضي ["email"].
isPublicbooleanلاتظهر في مركز التفضيلات؛ الافتراضي true.
typestringلاmarketing أو transactional؛ الافتراضي marketing.
requireDoubleOptInbooleanلاطلب موافقة مؤكدة؛ الافتراضي false.

يعيد كائن القائمة، وهو يشمل isDefault لفئة التسويق الافتراضية المنشأة تلقائياً وsenderId عند كون القائمة مجموعة اشتراك SMS أو WhatsApp لكل رقم مرتبطة بمرسل.

عرض القوائم والحصول عليها​

GET /lists
GET /lists/:listId

يدعم العرض includeArchived=true لإدراج المؤرشفة ويعيد القوائم الأحدث أولاً بحد 200. يعيد الحصول على قائمة 404 إن لم توجد أو كانت مؤرشفة.

تحديث قائمة أو أرشفتها​

PUT /lists/:listId
DELETE /lists/:listId
POST /lists/:listId/restore

يقبل PUT أي مجموعة فرعية من حقول الإنشاء. يؤرشف DELETE بحذف ناعم ويضبط archivedAt مع حفظ صفوف العضوية، ويعيد 204 No Content. يعيد مسار restore كائن القائمة المستعاد.

الحصول على أعضاء قائمة​

GET /lists/:listId/members
المعاملالنوعالافتراضيالوصف
channelstring-فلتر اختياري لقناة.
statusstring-subscribed أو unsubscribed.
limitnumber50الصفوف في الصفحة.
offsetnumber0إزاحة الترقيم.

يعيد members وtotal، ويضم كل عضو معرّف جهة الاتصال والقائمة والقناة والحالة وتواريخ الاشتراك ومصدره وسياق المنظمة ومساحة العمل.

إحصاءات قائمة​

GET /lists/:listId/stats

يعيد total وbyChannel وsubscribed وunsubscribed. يعد byChannel العضويات غير الملغاة لكل قناة.

إضافة أعضاء جماعياً​

أضف حتى 10,000 جهة اتصال إلى قائمة على قناة واحدة:

POST /lists/:listId/members/bulk
الحقلالنوعمطلوبالوصف
contactIdsstring[]نعممعرّفات جهات اتصال Joryio، حتى 10,000.
channelstringنعمقناة القائمة.
sourcestringلايسجل كـ optInSource.

يعيد { "added": 2, "updated": 0, "skippedUnsubscribed": 0 }. تنشئ الإضافة الجماعية عضويات جديدة فقط؛ تترك القائمة القائمين كما هم، ولا تعيد اشتراك من ألغى صراحة. يظهر هؤلاء في skippedUnsubscribed. استخدم نقطة الاشتراك الصريحة لإعادة الموافقة. يبقى updated صفراً للتوافق الخلفي.

إزالة أعضاء جماعياً​

ألغِ اشتراك حتى 10,000 جهة اتصال من قائمة على قناة واحدة:

DELETE /lists/:listId/members/bulk

يمر contactIds وchannel في النص ويعيد { "removed": 1 }. تقلب العملية صفوف العضوية إلى unsubscribed، ولا تحذفها، فيبقى أثر التدقيق وتُمنع الإرسالات المستقبلية للقائمة.

صفحة التفضيلات المستضافة​

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

الحصول على قالب مركز التفضيلات​

GET /subscriptions/hosted-page/preference-center

يعيد type وmode وhtml وredirectUrl وdesignJson وupdatedAt. تكون mode إحدى:

  • default: صفحة Joryio المدمجة.
  • custom: قالب HTML/Liquid الخاص بك.
  • dnd: محرر مرئي، مع HTML المعروض نفسه.
  • redirect: سجل الإلغاء ثم أعد التوجيه إلى redirectUrl.

تحديث قالب مركز التفضيلات​

PUT /subscriptions/hosted-page/preference-center
الحقلالنوعالوصف
modestringdefault أو custom أو dnd أو redirect.
htmlstringجسم HTML/Liquid للوضعين custom وdnd، حتى 100KB؛ يجب أن يتضمن موضع {{ preferences_form }}.
redirectUrlstringهدف وضع redirect، حتى 2048 حرفاً.
designJsonobjectحالة المحرر المرئي لدوران dnd؛ تُمسح في الأوضاع الأخرى.

يعيد القالب المحفوظ بشكل استجابة GET نفسه.

معاينة قالب​

POST /subscriptions/hosted-page/preview

النص { "html": "..." } هو القالب للعرض ببيانات نموذجية. تعيد الاستجابة { "html": "<rendered, sanitized html>" }.

واجهات ذات صلة، ليست في الصفحة​

  • نقاط المستلم: إلغاء بنقرة واحدة، POST /u/:token (زر تطبيق البريد)، وزر إلغاء الاشتراك في الصفحة المستضافة، POST /u/:token/confirm (بنقرة شخص فقط)، وصفحات التفضيلات المستضافة هي نقاط عامة مصادق عليها برمز، لا بمفتاح API.
  • Web SDK: POST /v1/subscriptions/channel وPOST /v1/subscriptions/group تصادقان بمفتاح SDK في X-SDK-Key. راجع دليل إدارة الاشتراكات.
  • webhooks الموفرين: ارتدادات Email وكلمات SMS الواردة، /webhooks/email/... و/webhooks/sms/...، تكاملات موفرين يتحقق توقيعها.
  • المنع: دفتر عدم الإرسال لمساحة العمل له Suppressions API خاص به.

الخطوات التالية​

اشتراك قناة واحدة لجهة اتصال​

PUT /subscriptions/contacts/{userId}/channels/email
GET /subscriptions/contacts/{userId}/channels/email/status

اضبط حالة اشتراك جهة اتصال في قناة بعينها، أو اقرأها. تعمل القناة نفسها لـsms وpush وwhatsapp وviber.

curl -X GET https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/channels/email/status \
-H "Authorization: Bearer your_api_key"