Subscriptions API
Subscriptions API הוא ממשק ההסכמה של Joryio. הוא מנהל, לכל איש קשר, את מצב ה־opt-in/opt-out בכל ערוץ הודעות (אימייל, SMS, WhatsApp, פוש ו־Viber), חברות ברשימות הרשמה (קטגוריות הסכמה או נושאים), מצב החזרות באימייל והיסטוריית ביקורת מלאה של שינויי ההסכמה.
העמוד מכסה שלושה משאבים:
- הסכמה של איש קשר -
/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
הרשאות לכל נקודת קצה
| Endpoint | Scope |
|---|---|
GET /subscriptions/contacts/:userId | subscriptions:read or compliance:read |
PUT /subscriptions/contacts/:userId/channels/:channel | subscriptions:write or compliance:write |
POST /subscriptions/contacts/:userId/clear-bounce | subscriptions:write or compliance:write |
GET /subscriptions/contacts/:userId/lists | subscriptions:read or compliance:read |
POST /subscriptions/contacts/:userId/lists/:listId | subscriptions:write or compliance:write |
DELETE /subscriptions/contacts/:userId/lists/:listId | subscriptions:write or compliance:write |
GET /subscriptions/contacts/:userId/history | compliance:read |
GET /subscriptions/unsubscribe-reasons | compliance:read |
GET /subscriptions/contacts/:userId/channels/:channel/status | subscriptions:read or compliance:read |
GET /subscriptions/contacts/:userId/email-valid | subscriptions:read or compliance:read |
POST /lists | lists:write or settings:write |
GET /lists, GET /lists/:listId, GET /lists/:listId/stats | lists:read or settings:read |
GET /lists/:listId/members | compliance:read |
PUT /lists/:listId, DELETE /lists/:listId, POST /lists/:listId/restore | lists:write or settings:write |
POST /lists/:listId/members/bulk, DELETE /lists/:listId/members/bulk | lists:write or settings:write |
GET /subscriptions/hosted-page/preference-center, POST /subscriptions/hosted-page/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. הרשמות בזמן היצירה לעולם אינן מבטלות opt-out קיים - הצטרפות מפורשת מחדש חייבת להתבצע באמצעות POST /subscriptions/contacts/:userId/lists/:listId.
ערוצים
קיימים חמישה ערוצי הרשמה: email, sms, whatsapp, push, viber. כל ערך ערוץ אחר מחזיר 400 Bad Request.
ערכי סטטוס
| סטטוס | תיאור |
|---|---|
optedIn | הצטרפות מפורשת (למשל אישור double opt-in) |
subscribed | מנוי (single opt-in / ברירת מחדל) |
unsubscribed | ביטל הרשמה |
pending | ממתין לאישור: ביקש להצטרף ועדיין לא אישר את ה-double opt-in. לא ניתן לשלוח אליו עד שיאשר; האישור הופך אותו ל-subscribed. נקבע על ידי תהליך אישור (למשל double opt-in של Delivyr), אף פעם לא על ידי ה-SDK. |
ערכי הסטטוס הם camelCase - optedIn, לא opted_in. איש קשר ללא סטטוס רשום לערוץ נחשב מנוי מבחינת שערי השליחה ("אין רשומה" אינו opt-out).
שינויי הסכמה נרשמים ומשוכפלים
כל כתיבה דרך ה־API הזה נרשמת ביומן ביקורת ההרשמות של איש הקשר (עם המקור, כתובת ה־IP, ה־user agent וזהות מפתח ה־API או המנהל שביצע את הפעולה), וניתנת לשליפה דרך נקודת הקצה להיסטוריה. בנוסף, ביטולי הרשמה משוכפלים לרשימות חסימה לפי מזהה - ביטול הרשמה ב־SMS או ב־WhatsApp חל לפי מספר הטלפון, וביטול הרשמה באימייל חל לפי הכתובת בכל סביבת העבודה, כך שגם אנשי קשר כפולים שחולקים את המזהה מכוסים. ראו Suppressions API.
הסכמה של איש קשר
קבלת ההרשמות של איש קשר
מחזיר את מצב ההסכמה לכל ערוץ של איש הקשר, יחד עם החברות שלו ברשימות.
Endpoint
GET /subscriptions/contacts/:userId
פרמטרים בנתיב
| פרמטר | סוג | תיאור |
|---|---|---|
userId | string | מזהה איש הקשר ב-Joryio |
דוגמת בקשה
curl -X GET https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0 \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
{
"channels": {
"email": {
"status": "subscribed",
"optInDate": "2026-05-14T09:21:07.000Z",
"optInSource": "api",
"consentText": "Send me product updates",
"isValid": true,
"bounceType": null,
"bounceCount": 0
},
"sms": {
"status": "unsubscribed",
"optOutDate": "2026-06-02T18:40:00.000Z",
"optInSource": "preference_center"
}
},
"lists": [
{
"_id": "665f2e11aa22bb33cc44dd55",
"organizationId": "org-uuid",
"workspaceId": "ws-uuid",
"contactId": "665f1c2ab3d4e5f6a7b8c9d0",
"listId": "3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b",
"channel": "email",
"status": "subscribed",
"subscribedAt": "2026-05-14T09:21:07.000Z",
"optInSource": "api",
"createdAt": "2026-05-14T09:21:07.000Z",
"updatedAt": "2026-05-14T09:21:07.000Z"
}
]
}
ערוצים שאין לאיש הקשר מצב רשום עבורם פשוט אינם מופיעים ב־channels. ערוץ האימייל כולל גם את שדות ההחזרה (isValid, bounceType, bounceCount, lastBounceAt). lists מחזיר את 500 רשומות החברות הראשונות של איש הקשר.
מחזיר 404 Not Found אם איש הקשר אינו קיים בסביבת העבודה.
עדכון הרשמה לערוץ
מגדיר את סטטוס ההסכמה של איש קשר לערוץ אחד.
Endpoint
PUT /subscriptions/contacts/:userId/channels/:channel
פרמטרים בנתיב
| פרמטר | סוג | תיאור |
|---|---|---|
userId | string | מזהה איש הקשר ב-Joryio |
channel | string | email, sms, whatsapp, push או viber |
גוף הבקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
channel | string | כן | חייב להתאים לערוץ שבנתיב (אם הם שונים - הערך שבנתיב גובר) |
status | string | כן | optedIn, subscribed או unsubscribed. גם pending (ממתין לאישור) מתקבל כאן. |
source | string | לא | מקור השינוי, למשל api, preference_center (ברירת מחדל api) |
consentText | string | לא | טקסט ההסכמה שהוצג בעת ה־opt-in (נשמר לצורכי ציות) |
reason | string | לא | סיבה בטקסט חופשי, שנשמרת ברשומת הביקורת |
דוגמת בקשה
curl -X PUT https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/channels/email \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channel": "email",
"status": "unsubscribed",
"source": "preference_center",
"reason": "User requested via support ticket"
}'
תגובה
אובייקט ה־channels המעודכן והמלא של איש הקשר:
{
"email": {
"status": "unsubscribed",
"optOutDate": "2026-07-12T10:15:00.000Z",
"optInSource": "preference_center",
"isValid": true,
"bounceType": null,
"bounceCount": 0
},
"sms": {
"status": "subscribed",
"optInDate": "2026-05-14T09:21:07.000Z"
}
}
הערות התנהגות
- הצטרפות בערוץ האימייל מנקה מצב זמני של החזרה רכה, אך לעולם אינה מבטלת החזרה קשה או תלונת ספאם - רק התמיכה של Joryio יכולה להסיר אותן.
unsubscribedבערוציsmsאוwhatsappמשוכפל לרשימת החסימה לפי מספר טלפון (ה־opt-out חל לפי המספר בכל הארגון). שינוי מצב באימייל משוכפל לרשימה לפי כתובת בסביבת העבודה.- השינוי נרשם ביומן הביקורת עם כתובת ה־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 יש אישור כפול משלה.
אנשי קשר כפולים והרשמה מחדש
- ביטול הרשמה חל על כל איש קשר עם אותו אימייל או טלפון בסביבת העבודה: הסטטוס של כל אחד (או החברות ברשימה, ברשימה) מוגדר ל־
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".
Endpoint
POST /subscriptions/contacts/:userId/clear-bounce
גוף הבקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
reason | string | לא | סיבה בטקסט חופשי, שנשמרת ברשומת הביקורת |
דוגמת בקשה
curl -X POST https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/clear-bounce \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "reason": "Mailbox restored, confirmed with customer" }'
תגובה
{ "success": true }
מנקה את bounceType, bounceCount ו־lastBounceAt של החזרה רכה. אינו מוחק שורות hard_bounce / complaint מפנקס החסימות.
קבלת הרשמות לרשימות
מחזיר את כל רשומות החברות של איש הקשר ברשימות, בין שההרשמה בהן פעילה ובין שבוטלה.
Endpoint
GET /subscriptions/contacts/:userId/lists
דוגמת בקשה
curl -X GET https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/lists \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
[
{
"_id": "665f2e11aa22bb33cc44dd55",
"organizationId": "org-uuid",
"workspaceId": "ws-uuid",
"contactId": "665f1c2ab3d4e5f6a7b8c9d0",
"listId": "3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b",
"channel": "email",
"status": "subscribed",
"subscribedAt": "2026-05-14T09:21:07.000Z",
"optInSource": "api",
"createdAt": "2026-05-14T09:21:07.000Z",
"updatedAt": "2026-05-14T09:21:07.000Z"
}
]
החברות ייחודית לכל שילוב של איש קשר + רשימה + ערוץ: אותו איש קשר יכול להיות מנוי לרשימה ב־email ומבוטל ממנה ב־sms, כשתי רשומות נפרדות.
צירוף איש קשר לרשימה
מצרף איש קשר לרשימה בערוץ אחד. הפעולה אידמפוטנטית - קריאה חוזרת מאשרת מחדש את ההרשמה. זהו גם נתיב ה־opt-in המפורש והמתועד ביומן הביקורת, שבאמצעותו אפשר לצרף מחדש איש קשר שביטל בעבר את הרשמתו לרשימה; הוספה באצווה לעולם אינה עושה זאת.
Endpoint
POST /subscriptions/contacts/:userId/lists/:listId
פרמטרים בנתיב
| פרמטר | סוג | תיאור |
|---|---|---|
userId | string | מזהה איש הקשר ב-Joryio |
listId | string | מזהה רשימת ההרשמה (UUID) |
גוף הבקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
channel | string | כן | email, sms, whatsapp, push או viber |
source | string | לא | למשל api, form, import, preference_center (ברירת מחדל api) |
consentText | string | לא | טקסט ההסכמה שהוצג בעת ה־opt-in |
דוגמת בקשה
curl -X POST https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/lists/3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "channel": "email", "source": "api", "consentText": "Weekly newsletter signup" }'
תגובה
רשומת החברות שנוצרה או עודכנה:
{
"_id": "665f2e11aa22bb33cc44dd55",
"organizationId": "org-uuid",
"workspaceId": "ws-uuid",
"contactId": "665f1c2ab3d4e5f6a7b8c9d0",
"listId": "3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b",
"channel": "email",
"status": "subscribed",
"subscribedAt": "2026-07-12T10:20:00.000Z",
"optInSource": "api",
"consentText": "Weekly newsletter signup",
"createdAt": "2026-07-12T10:20:00.000Z",
"updatedAt": "2026-07-12T10:20:00.000Z"
}
ביטול הרשמת איש קשר מרשימה
מבטל הרשמה של איש קשר מרשימה בערוץ אחד. הערוץ עובר בגוף הבקשה, לא בנתיב.
Endpoint
DELETE /subscriptions/contacts/:userId/lists/:listId
גוף הבקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
channel | string | כן | email, sms, whatsapp, push או viber |
source | string | לא | למשל api, preference_center (ברירת מחדל api) |
דוגמת בקשה
curl -X DELETE https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/lists/3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "channel": "email", "source": "preference_center" }'
תגובה
{ "success": true }
אם לאיש הקשר לא הייתה רשומת חברות לרשימה + ערוץ אלה, נוצרת בכל זאת רשומת unsubscribed מפורשת - משיכת הסכמה לעולם אינה הולכת לאיבוד בשקט, ושער השליחה יחסום מעתה שליחות רשימה לאיש קשר זה.
קבלת היסטוריית הרשמות
מחזיר את יומן הביקורת של הסכמות איש הקשר, מהחדש לישן.
Endpoint
GET /subscriptions/contacts/:userId/history
פרמטרי שאילתה
| פרמטר | סוג | ברירת מחדל | תיאור |
|---|---|---|---|
limit | number | 50 | רשומות לעמוד (ערך לא מספרי חוזר לברירת המחדל) |
offset | number | 0 | היסט עימוד |
דוגמת בקשה
curl -X GET "https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/history?limit=50&offset=0" \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
{
"items": [
{
"id": "8a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"organizationId": "org-uuid",
"workspaceId": "ws-uuid",
"contactId": "665f1c2ab3d4e5f6a7b8c9d0",
"channel": "email",
"listId": null,
"action": "unsubscribe",
"previousStatus": "subscribed",
"newStatus": "unsubscribed",
"source": "preference_center",
"ipAddress": "203.0.113.7",
"userAgent": "Mozilla/5.0 ...",
"consentText": null,
"metadata": { "reason": "User requested via support ticket", "unsubscribeSource": "preferences_page", "sinceSendMs": 3600000 },
"createdAt": "2026-07-12T10:15:00.000Z",
"changeKind": "unsubscribed",
"changeLabel": "Unsubscribed",
"sourceKind": "preference_center",
"sourceLabel": "Preference center",
"sourcePlatform": null,
"page": null
}
],
"total": 12
}
action הוא אחד מ־subscribe, unsubscribe, resubscribe, bounce, hard_bounce, soft_bounce, complaint, import, api_update. listId מוגדר עבור שינויים ברמת רשימה ו־null עבור שינויים ברמת ערוץ.
כל רשומת 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 רק עם ה-scope הזה) מקבל 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.
בדיקת סטטוס הרשמה לערוץ
בדיקה בוליאנית קלה - האם מותר לשלוח לאיש הקשר בערוץ הזה מבחינת הסכמה?
Endpoint
GET /subscriptions/contacts/:userId/channels/:channel/status
דוגמת בקשה
curl -X GET https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/channels/email/status \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
{ "subscribed": true }
subscribed הוא true אלא אם איש הקשר unsubscribed במפורש בערוץ - איש קשר ללא סטטוס רשום נחשב מנוי. מזהה איש קשר לא מוכר מחזיר { "subscribed": false } (לא 404).
בדיקת תקינות אימייל
האם כתובת האימייל של איש הקשר ניתנת למסירה, כלומר לא סומנה כלא תקינה בעקבות החזרה קשה?
Endpoint
GET /subscriptions/contacts/:userId/email-valid
דוגמת בקשה
curl -X GET https://api-eu1.joryio.com/api/subscriptions/contacts/665f1c2ab3d4e5f6a7b8c9d0/email-valid \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
{ "valid": true }
valid הוא false רק כאשר החזרה קשה סימנה את הכתובת כלא תקינה. מזהה איש קשר לא מוכר מחזיר { "valid": false } (ולא 404). שימו לב: הערך משקף יכולת מסירה, לא הסכמה - איש קשר שביטל הרשמה אך כתובתו תקינה עדיין מחזיר true.
רשימות הרשמה
רשימות הן קטגוריות הסכמה או נושאים שאנשי קשר יכולים להירשם אליהם (ניוזלטר, עדכוני מוצר וכדומה). הגדרות הרשימות נמצאות תחת /lists; החברות של כל איש קשר מנוהלת באמצעות נקודות הקצה להסכמת איש קשר שלמעלה או באמצעות נקודות הקצה לפעולות באצווה שבהמשך.
יצירת רשימה
Endpoint
POST /lists
גוף הבקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
name | string | כן | שם הרשימה (עד 255 תווים, ייחודי בסביבת העבודה) |
description | string | לא | תיאור (עד 1000 תווים) |
channels | string[] | לא | הערוצים שהרשימה חלה עליהם (ברירת מחדל ["email"]) |
isPublic | boolean | לא | הצגה במרכז ההעדפות (ברירת מחדל true) |
type | string | לא | marketing או transactional (ברירת מחדל marketing) |
requireDoubleOptIn | boolean | לא | דרישת opt-in מאושר (ברירת מחדל false) |
דוגמת בקשה
curl -X POST https://api-eu1.joryio.com/api/lists \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Weekly Newsletter",
"description": "Our weekly digest of product updates",
"channels": ["email"],
"isPublic": true,
"type": "marketing",
"requireDoubleOptIn": false
}'
תגובה
{
"id": "3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b",
"organizationId": "org-uuid",
"workspaceId": "ws-uuid",
"name": "Weekly Newsletter",
"description": "Our weekly digest of product updates",
"channels": ["email"],
"isPublic": true,
"type": "marketing",
"requireDoubleOptIn": false,
"isDefault": false,
"displayOrder": 0,
"senderId": null,
"archivedAt": null,
"createdAt": "2026-07-12T10:30:00.000Z",
"updatedAt": "2026-07-12T10:30:00.000Z"
}
isDefault מסמן את קטגוריית ה־Marketing שנוצרת אוטומטית כברירת מחדל; senderId מוגדר כאשר הרשימה היא קבוצת הרשמה לפי מספר ב־SMS או ב־WhatsApp, שמשויכת לשולח מסוים.
הצגת כל הרשימות
Endpoint
GET /lists
פרמטרי שאילתה
| פרמטר | סוג | ברירת מחדל | תיאור |
|---|---|---|---|
includeArchived | string | false | העבירו true כדי לכלול רשימות בארכיון |
דוגמת בקשה
curl -X GET "https://api-eu1.joryio.com/api/lists?includeArchived=false" \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
מערך של אובייקטי רשימה (באותו מבנה כמו יצירת רשימה), מהחדש לישן, עד 200 רשימות.
קבלת רשימה
GET /lists/:listId
מחזיר את אובייקט הרשימה. 404 Not Found אם הרשימה אינה קיימת או שהיא בארכיון.
עדכון רשימה
PUT /lists/:listId
גוף הבקשה: כל תת־קבוצה של השדות שמתוארים תחת יצירת רשימה (name, description, channels, isPublic, type, requireDoubleOptIn). מחזיר את אובייקט הרשימה המעודכן.
העברת רשימה לארכיון
DELETE /lists/:listId
מחיקה רכה - הפעולה מגדירה את archivedAt ושומרת את רשומות החברות. היא מחזירה 204 No Content. כדי לשחזר, השתמשו ב:
POST /lists/:listId/restore
שמחזיר את אובייקט הרשימה המשוחזר.
קבלת חברי רשימה
Endpoint
GET /lists/:listId/members
פרמטרי שאילתה
| פרמטר | סוג | ברירת מחדל | תיאור |
|---|---|---|---|
channel | string | - | מסנן אופציונלי: email, sms, whatsapp, push, viber |
status | string | - | מסנן אופציונלי: subscribed או unsubscribed |
limit | number | 50 | רשומות לעמוד |
offset | number | 0 | היסט עימוד |
דוגמת בקשה
curl -X GET "https://api-eu1.joryio.com/api/lists/3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b/members?channel=email&status=subscribed&limit=50" \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
{
"members": [
{
"_id": "665f2e11aa22bb33cc44dd55",
"contactId": "665f1c2ab3d4e5f6a7b8c9d0",
"listId": "3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b",
"channel": "email",
"status": "subscribed",
"subscribedAt": "2026-05-14T09:21:07.000Z",
"optInSource": "api",
"organizationId": "org-uuid",
"workspaceId": "ws-uuid",
"createdAt": "2026-05-14T09:21:07.000Z",
"updatedAt": "2026-05-14T09:21:07.000Z"
}
],
"total": 1234
}
קבלת סטטיסטיקות רשימה
Endpoint
GET /lists/:listId/stats
דוגמת בקשה
curl -X GET https://api-eu1.joryio.com/api/lists/3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b/stats \
-H "Authorization: Bearer jry_live_your_api_key"
תגובה
{
"total": 1500,
"byChannel": {
"email": 1180,
"sms": 120,
"whatsapp": 0,
"push": 0,
"viber": 0
},
"subscribed": 1300,
"unsubscribed": 200
}
byChannel סופר חברויות שאינן מבוטלות לכל ערוץ.
הוספת חברים באצווה
מוסיף עד 10,000 אנשי קשר לרשימה בערוץ אחד בקריאה בודדת.
Endpoint
POST /lists/:listId/members/bulk
גוף הבקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
contactIds | string[] | כן | מזהי אנשי קשר ב-Joryio (עד 10,000) |
channel | string | כן | email, sms, whatsapp, push או viber |
source | string | לא | נשמר כ־optInSource של החברות |
דוגמת בקשה
curl -X POST https://api-eu1.joryio.com/api/lists/3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b/members/bulk \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"contactIds": ["665f1c2ab3d4e5f6a7b8c9d0", "665f1c2ab3d4e5f6a7b8c9d1"],
"channel": "email",
"source": "import"
}'
תגובה
{ "added": 2, "updated": 0, "skippedUnsubscribed": 0 }
הוספה באצווה יוצרת חברויות חדשות בלבד. אנשי קשר שכבר נמצאים ברשימה נשארים ללא שינוי, ואנשי קשר שביטלו הרשמה במפורש לעולם אינם מצורפים מחדש בהוספה באצווה - הם נספרים ב־skippedUnsubscribed. צירוף מחדש של איש קשר שביטל את הרשמתו מחייב את הקריאה המפורשת והמתועדת ביומן הביקורת צירוף איש קשר לרשימה. updated הוא תמיד 0 (ונשמר לצורך תאימות לאחור).
הסרת חברים באצווה
מבטל הרשמה של עד 10,000 אנשי קשר מרשימה בערוץ אחד.
Endpoint
DELETE /lists/:listId/members/bulk
גוף הבקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
contactIds | string[] | כן | מזהי אנשי קשר ב-Joryio (עד 10,000) |
channel | string | כן | email, sms, whatsapp, push או viber |
דוגמת בקשה
curl -X DELETE https://api-eu1.joryio.com/api/lists/3f6c1a2e-9d4b-4f0a-8c7e-1b2d3e4f5a6b/members/bulk \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"contactIds": ["665f1c2ab3d4e5f6a7b8c9d0"],
"channel": "email"
}'
תגובה
{ "removed": 1 }
ההסרה משנה רשומות חברות קיימות ל־unsubscribed (הרשומות נשמרות לצורך תיעוד הביקורת), ולכן שער השליחה חוסם את אנשי הקשר שהוסרו משליחות עתידיות לרשימה.
עמוד העדפות מתארח
API לעריכת העמוד המתארח של מרכז ההעדפות בסביבת העבודה - העמוד שאליו נמענים מגיעים מקישור לביטול הרשמה או לניהול העדפות. הגרסה הציבורית של העמוד מוגשת דרך נקודות קצה ציבוריות שמבוססות על טוקן (ללא מפתח API), ואינן מתוארות בעמוד הזה.
קבלת תבנית מרכז ההעדפות
GET /subscriptions/hosted-page/preference-center
תגובה
{
"type": "preference_center",
"mode": "default",
"html": "",
"redirectUrl": "",
"designJson": null,
"updatedAt": null
}
mode הוא אחד מ־default (העמוד המובנה של Joryio), custom (תבנית HTML/Liquid משלכם), dnd (נוצר בעורך החזותי ומפיק את אותו html) או redirect (רישום ה־opt-out ולאחר מכן הפניה אל 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 של ספקים - Webhooks על החזרות ועל מילות מפתח נכנסות ב־SMS (
/webhooks/email/...,/webhooks/sms/...) הם אינטגרציות עם ספקים שמאומתות באמצעות חתימה. - חסימות - לרשימת ה"לא לשלוח" ברמת סביבת העבודה יש Suppressions API משלה.
הצעדים הבאים
- Users API - יצירת איש הקשר לפני הגדרת ההסכמה
- Suppressions API - רשימת ה"לא לשלוח" לפי מזהה
- מדריך ניהול ההרשמות - מושגים, שימוש ב-SDK, מילות מפתח, ציות