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-valid | subscriptions:read أو compliance:read |
GET /subscriptions/contacts/:userId/history | compliance:read |
GET /subscriptions/unsubscribe-reasons | compliance: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/stats | lists:read أو settings:read |
GET /lists/:listId/members | compliance:read |
GET /subscriptions/hosted-page/preference-center وPOST /preview | settings:read |
PUT /subscriptions/hosted-page/preference-center | settings: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
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
channel | string | نعم | يجب أن يطابق القناة في URL؛ قيمة URL هي الفائزة عند الاختلاف. |
status | string | نعم | optedIn أو subscribed أو unsubscribed. ويُقبل هنا أيضًا pending (بانتظار التأكيد). |
source | string | لا | مصدر التغيير، مثل api أو preference_center؛ الافتراضي api. |
consentText | string | لا | نص الموافقة المعروض عند الاشتراك، يحفظ للامتثال. |
reason | string | لا | سبب نصي حر يحفظ في سجل التدقيق. |
{
"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ولا يتغير شيء:
code | message |
|---|---|
deliverability | This address hard-bounced or marked a message as spam. Only Joryio support can lift that block. |
organization_block | This identifier is blocked for the whole organization. Only Joryio support can lift that block. |
verified_identity_required | 403 - نقاط نهاية 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؛ تؤكد إعادة الطلب الاشتراك. وهو مسار إعادة الموافقة الصريح والمدقق الوحيد الذي يمكنه إعادة اشتراك جهة ألغت القائمة، إذ لا تفعل الإضافة الجماعية ذلك.
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
channel | string | نعم | email أو sms أو whatsapp أو push أو viber. |
source | string | لا | مثل api أو form أو import أو preference_center؛ الافتراضي api. |
consentText | string | لا | نص الموافقة المعروض. |
يعيد صف العضوية المنشأ أو المحدّث.
إلغاء جهة اتصال من قائمة
DELETE /subscriptions/contacts/:userId/lists/:listId
تمر القناة في نص الطلب لا URL:
{ "channel": "email", "source": "preference_center" }
يعيد { "success": true }. إذا لم يكن للجهة صف عضوية للقائمة والقناة، ينشئ النظام صف unsubscribed صريحاً على أي حال؛ فلا يفقد سحب الموافقة بصمت وتمنع بوابة الإرسال إرسالات القائمة لاحقاً.
الحصول على سجل الاشتراك
GET /subscriptions/contacts/:userId/history
| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
limit | number | 50 | مدخلات الصفحة؛ القيم غير الرقمية ترجع للافتراضي. |
offset | number | 0 | إزاحة الترقيم. |
يعيد 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
| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
limit | number | 50 | صفوف الصفحة (الحد الأقصى 100). |
offset | number | 0 | إزاحة الترقيم. |
days | number | 90 | المدة إلى الوراء بالأيام (الحد الأقصى 365). |
flagged | boolean | false | true يعيد فقط الإلغاءات الموسومة بأنها تلقائية على الأرجح. |
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",
"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
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
name | string | نعم | اسم القائمة، حتى 255 حرفاً وفريد لكل مساحة عمل. |
description | string | لا | وصف، حتى 1000 حرف. |
channels | string[] | لا | القنوات التي تنطبق عليها القائمة؛ الافتراضي ["email"]. |
isPublic | boolean | لا | تظهر في مركز التفضيلات؛ الافتراضي true. |
type | string | لا | marketing أو transactional؛ الافتراضي marketing. |
requireDoubleOptIn | boolean | لا | طلب موافقة مؤكدة؛ الافتراضي 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
| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
channel | string | - | فلتر اختياري لقناة. |
status | string | - | subscribed أو unsubscribed. |
limit | number | 50 | الصفوف في الصفحة. |
offset | number | 0 | إزاحة الترقيم. |
يعيد members وtotal، ويضم كل عضو معرّف جهة الاتصال والقائمة والقناة والحالة وتواريخ الاشتراك ومصدره وسياق المنظمة ومساحة العمل.
إحصاءات قائمة
GET /lists/:listId/stats
يعيد total وbyChannel وsubscribed وunsubscribed. يعد byChannel العضويات غير الملغاة لكل قناة.
إضافة أعضاء جماعياً
أضف حتى 10,000 جهة اتصال إلى قائمة على قناة واحدة:
POST /lists/:listId/members/bulk
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
contactIds | string[] | نعم | معرّفات جهات اتصال Joryio، حتى 10,000. |
channel | string | نعم | قناة القائمة. |
source | string | لا | يسجل كـ 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
| الحقل | النوع | الوصف |
|---|---|---|
mode | string | default أو custom أو dnd أو redirect. |
html | string | جسم HTML/Liquid للوضعين custom وdnd، حتى 100KB؛ يجب أن يتضمن موضع {{ preferences_form }}. |
redirectUrl | string | هدف وضع redirect، حتى 2048 حرفاً. |
designJson | object | حالة المحرر المرئي لدوران 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 خاص به.
الخطوات التالية
- Users API - أنشئ جهة الاتصال قبل ضبط الموافقة.
- Suppressions API - دفتر عدم الإرسال المرتبط بالمعرّف.
- دليل إدارة الاشتراكات - المفاهيم واستخدام SDK والكلمات المفتاحية والامتثال.
اشتراك قناة واحدة لجهة اتصال
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"