Subscriptions API
Το Subscriptions API είναι η επιφάνεια συγκατάθεσης του Joryio. Διαχειρίζεται, ανά επαφή, την κατάσταση opt-in/opt-out κάθε καναλιού μηνυμάτων (email, SMS, WhatsApp, push, Viber), τη συμμετοχή σε λίστες συνδρομών (κατηγορίες συγκατάθεσης / θέματα), την κατάσταση bounce email και το πλήρες ιστορικό ελέγχου των αλλαγών συγκατάθεσης.
Αυτή η σελίδα καλύπτει τρεις πόρους:
- Συγκατάθεση επαφής -
/subscriptions/contacts/...: ανάγνωση και αλλαγή της συγκατάθεσης καναλιών και λιστών μίας επαφής. - Λίστες συνδρομών -
/lists: δημιουργία και διαχείριση των ίδιων των λιστών, καθώς και μαζικές λειτουργίες συμμετοχής. - Φιλοξενούμενη σελίδα προτιμήσεων -
/subscriptions/hosted-page: σύνταξη της φιλοξενούμενης σελίδας του κέντρου προτιμήσεων του χώρου εργασίας.
Όλα τα endpoints αυτής της σελίδας είναι σχετικά ως προς το βασικό URL: https://api-eu1.joryio.com/api - δείτε Επισκόπηση API.
Έλεγχος ταυτότητας
Όλα τα αιτήματα απαιτούν έλεγχο ταυτότητας με κλειδί API (λειτουργεί και JWT συνεδρίας dashboard):
Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json
Scopes ανά endpoint
| 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 με τα scopes συνδρομών: το GET .../history είναι το ιστορικό συγκατάθεσης - αποδεικτικό για ρυθμιστική αρχή, όχι λειτουργική κατάσταση - και το GET /lists/:listId/members αποκαλύπτει επαφές. Και τα δύο διατηρούν μόνο compliance:read.
Βασικές έννοιες
Το id επαφής
Κάθε διαδρομή /subscriptions/contacts/:userId δέχεται το εσωτερικό id επαφής του Joryio - το id που επιστρέφει το Users API - όχι το εξωτερικό userId που στέλνετε στα συμβάντα. Πρέπει να είναι 24-χαρακτήρων δεκαεξαδικό ObjectId (ή UUID)· οτιδήποτε άλλο απορρίπτεται με 400 Bad Request.
Εγγραφή κατά τη δημιουργία
Οι επαφές δημιουργούνται μέσω του POST /users/track, και η ίδια κλήση μπορεί να ορίσει τις συνδρομές τους σε λίστες: κάθε στοιχείο του attributes δέχεται subscriptions (λεπτομέρειες), που εφαρμόζονται μέσω της ίδιας διαδρομής συγκατάθεσης με τα endpoints αυτής της σελίδας. Τα αυτόνομα endpoints αυτής της σελίδας παραμένουν ο τρόπος διαχείρισης της συγκατάθεσης μετά τη δημιουργία: ορίστε τη συγκατάθεση καναλιού με PUT /subscriptions/contacts/:userId/channels/:channel και τη συμμετοχή σε λίστες με POST /subscriptions/contacts/:userId/lists/:listId. Οι εγγραφές κατά τη δημιουργία δεν αναιρούν ποτέ ένα υπάρχον opt-out - μια ρητή επανεγγραφή (re-opt-in) πρέπει να γίνει με POST /subscriptions/contacts/:userId/lists/:listId.
Κανάλια
Υπάρχουν πέντε κανάλια συνδρομών: email, sms, whatsapp, push, viber. Οποιαδήποτε άλλη τιμή καναλιού επιστρέφει 400 Bad Request.
Τιμές κατάστασης
| Κατάσταση | Περιγραφή |
|---|---|
optedIn | Ρητό opt-in (π.χ. επιβεβαιωμένο 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 / διαχειριστή) και ανακτάται μέσω του endpoint ιστορικού. Τα opt-out αντικατοπτρίζονται επιπλέον σε λίστες καταστολής με κλειδί το αναγνωριστικό - μια απεγγραφή SMS/WhatsApp ακολουθεί τον αριθμό τηλεφώνου και μια απεγγραφή email ακολουθεί τη διεύθυνση (σε όλο τον χώρο εργασίας), ώστε να καλύπτονται και διπλότυπες επαφές που μοιράζονται το αναγνωριστικό. Δείτε το Suppressions API.
Συγκατάθεση επαφής
Λήψη συνδρομών επαφής
Επιστρέφει την κατάσταση συγκατάθεσης ανά κανάλι μιας επαφής, μαζί με τις συμμετοχές της σε λίστες.
Endpoint
GET /subscriptions/contacts/:userId
Παράμετροι διαδρομής
| Παράμετρος | Τύπος | Περιγραφή |
|---|---|---|
userId | string | Id επαφής 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. Το κανάλι email φέρει τα επιπλέον πεδία bounce (isValid, bounceType, bounceCount, lastBounceAt). Το lists επιστρέφει τις πρώτες 500 γραμμές συμμετοχής της επαφής.
Επιστρέφει 404 Not Found αν η επαφή δεν υπάρχει στον χώρο εργασίας.
Ενημέρωση συνδρομής καναλιού
Ορίστε την κατάσταση συγκατάθεσης μιας επαφής για ένα κανάλι.
Endpoint
PUT /subscriptions/contacts/:userId/channels/:channel
Παράμετροι διαδρομής
| Παράμετρος | Τύπος | Περιγραφή |
|---|---|---|
userId | string | Id επαφής Joryio |
channel | string | email, sms, whatsapp, push ή viber |
Σώμα αιτήματος
| Πεδίο | Τύπος | Απαιτείται | Περιγραφή |
|---|---|---|---|
channel | string | Ναι | Πρέπει να ταιριάζει με το κανάλι του URL (αν διαφέρουν, υπερισχύει η τιμή του URL) |
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"
}
}
Σημειώσεις συμπεριφοράς
- Ένα opt-in στο κανάλι email καθαρίζει την προσωρινή κατάσταση soft bounce, αλλά δεν αναβιώνει ποτέ hard bounce ή καταγγελία spam - μόνο η υποστήριξη του Joryio μπορεί να τα άρει.
- Ένα
unsubscribedσεsms/whatsappαντικατοπτρίζεται στη λίστα καταστολής με κλειδί τον αριθμό τηλεφώνου (το opt-out ακολουθεί τον αριθμό, σε επίπεδο οργανισμού). Μια αλλαγή κατάστασης email αντικατοπτρίζεται στη λίστα με κλειδί τη διεύθυνση για τον χώρο εργασίας. - Η αλλαγή καταγράφεται στο ημερολόγιο ελέγχου με IP, user agent και την ταυτότητα του ενεργούντος διαχειριστή/κλειδιού.
Double opt-in για SMS
Όταν ο χώρος εργασίας έχει ενεργοποιήσει το Double opt-in για 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 λαμβάνει επίσης τη συνήθη εγγραφήwarningssms_stop_provider_block· αν ο πάροχος απορρίψει το μήνυμα με τον κωδικό STOP του, η επαφή διαγράφεται ξανά. Μια μόνιμη αναπήδηση, καταγγελία spam ή αποκλεισμός σε επίπεδο οργανισμού εξακολουθεί να απορρίπτεται (409). - Αιτήματα χωρίς απάντηση λήγουν μετά τις ημέρες που ορίστηκαν (προεπιλογή 7): η κατάσταση SMS αφαιρείται (όχι
unsubscribed). - Δεν εφαρμόζεται όταν ο αριθμός SMS του χώρου εργασίας είναι σε λογαριασμό Delivyr - το Delivyr έχει δικό του double opt-in.
Δείτε Double opt-in για SMS.
Διπλότυπες επαφές και επανεγγραφή
- Μια διαγραφή ισχύει για κάθε επαφή με το ίδιο email ή τηλέφωνο στο workspace: η κατάσταση καθεμίας (ή η συμμετοχή, για λίστα) γίνεται
unsubscribedκαι παίρνει εγγραφή ιστορικού με πηγήshared_identifier. - Η επανεγγραφή μέσω API επιτρέπεται και ισχύει μόνο για αυτή την επαφή. Οι άλλες επαφές με το ίδιο email ή τηλέφωνο παραμένουν διαγραμμένες. Η αλλαγή καταγράφεται με πηγή
apiκαι το id του API key στοmetadata.principal. - Ένα
sourceστο σώμα που τελειώνει σε_keyword, ή είναιshared_identifier,complaint_webhookήstaff, καταγράφεται ωςapi- μόνο το Joryio ορίζει αυτές τις τιμές. - Μια διαγραφή
STOPμπορεί να παρακαμφθεί (SMS, WhatsApp, Viber, οποιοσδήποτε πάροχος) με αυτή την κανονική ενημέρωση - χωρίς επιπλέον flag. Ισχύει μόνο για αυτή την επαφή, και το ιστορικό καταγράφει ότι παρέκαμψε έναSTOP(metadata.overrodeStop) και το κλειδί API. Μια απάντησηSTARTσυνεχίζει να λειτουργεί όπως πριν. - Μόνο SMS: η επανεγγραφή επαφής SMS που έστειλε
STOPαπαντά200 OKμε ένα πεδίοwarningsπου δεν είναι σφάλμα, επειδή ο πάροχος SMS μπορεί να κρατήσει δικό του μπλοκάρισμα μέχρι η επαφή να στείλειSTART. Το WhatsApp και το Viber δεν επιστρέφουν προειδοποίηση. Το endpoint λιστών (POST /subscriptions/contacts/:userId/lists/:listId, για λίστα SMS) και το endpoint καναλιού του 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) καταγράφεται ως μπλοκαρισμένη από τον πάροχο (διαγραμμένη) - όχι αποτυχία, και δεν μετρά στις ειδοποιήσεις ποσοστού bounce ή αποτυχιών. Η διαγραφή εφαρμόζεται ξανά, με τη σημείωση ιστορικού 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 - Μόνο endpoints του SDK (/v1/subscriptions/channel, /v1/subscriptions/group): επανεγγραφή προσώπου που διαγράφηκε ρητά (δική του διαγραφή ή από λίστα, STOP, διαγραφή στο email ή στο τηλέφωνό του - και από άλλη επαφή) από μη επαληθευμένο υποκείμενο - ένα userId χωρίς SDK Authentication, ή ένα anonymousId που ανήκει σε ταυτοποιημένο πρόσωπο. Η πρώτη εγγραφή γίνεται δεκτή· μια λίστα με διπλό opt-in απαντά pending: true και στέλνει το email επιβεβαίωσης. Η διαγραφή επιτρέπεται πάντα. |
{ "statusCode": 409, "error": "Conflict", "code": "deliverability", "message": "This address hard-bounced or marked a message as spam. Only Joryio support can lift that block." }
Το endpoint λιστών (POST /subscriptions/contacts/:userId/lists/:listId) δεν απορρίπτεται ποτέ για αυτά· ούτε μια εγγραφή σε λίστα τα αίρει. Επαφές που μοιράζονται email ή τηλέφωνο.
Καθαρισμός κατάστασης bounce
Μηδενίζει τους μετρητές soft bounce μιας επαφής. Ένα hard bounce ή μια καταγγελία spam αίρεται μόνο από την υποστήριξη του 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 ενός soft bounce. Δεν διαγράφει γραμμές 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, ως δύο ξεχωριστές γραμμές.
Εγγραφή επαφής σε λίστα
Εγγράψτε μια επαφή σε μια λίστα σε ένα κανάλι. Είναι idempotent - η επανάληψη της κλήσης επιβεβαιώνει ξανά τη συνδρομή. Είναι επίσης η ρητή, ελεγχόμενη διαδρομή opt-in που μπορεί να επανεγγράψει μια επαφή που είχε προηγουμένως απεγγραφεί από τη λίστα (η μαζική προσθήκη δεν το κάνει ποτέ).
Endpoint
POST /subscriptions/contacts/:userId/lists/:listId
Παράμετροι διαδρομής
| Παράμετρος | Τύπος | Περιγραφή |
|---|---|---|
userId | string | Id επαφής Joryio |
listId | string | Id λίστας συνδρομών (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"
}
Απεγγραφή επαφής από λίστα
Απεγγράψτε μια επαφή από μια λίστα σε ένα κανάλι. Το κανάλι περνά στο σώμα του αιτήματος, όχι στο URL.
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
Παράμετροι query
| Παράμετρος | Τύπος | Προεπιλογή | Περιγραφή |
|---|---|---|---|
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 είναι το κουμπί διαγραφής της ίδιας της εφαρμογής email (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 είναι η σελίδα όπου δόθηκε η συναίνεση, όπου αποθηκεύτηκε (URL σελίδας ή καταστήματος, ή slug σελίδας προορισμού), αλλιώς null. Το consentText είναι η ακριβής διατύπωση που είδε το άτομο. Το ipAddress είναι προσωπικό δεδομένο: καλών χωρίς pii:view (κλειδί API μόνο με αυτό το scope) λαμβάνει null και ipHidden: true όταν είχε αποθηκευτεί. Το location είναι το σημείο του καταστήματος όπου συλλέχθηκε η συναίνεση - checkout, block_checkout, registration, customer_record ή newsletter - και το collectedAt πότε συλλέχθηκε (ISO-8601, με το ρολόι του καταστήματος· μπορεί να είναι νωρίτερα από το createdAt όταν η επιλογή κρατήθηκε μέχρι την παραγγελία)· και τα δύο null όταν δεν καταγράφηκαν.
Λίστα πρόσφατων αιτιών απεγγραφής
Οι πρόσφατες απεγγραφές του χώρου εργασίας που έχουν αιτία ή επισημάνθηκαν ως πιθανώς αυτόματες, με τις νεότερες πρώτες. Μία γραμμή ανά ενέργεια απεγγραφής: όταν μία ενέργεια αφαίρεσε πολλά κανάλια (π.χ. ένας παλιός σύνδεσμος που αφαίρεσε τα πάντα), τα κανάλια ομαδοποιούνται σε μία γραμμή.
Endpoint
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.
Έλεγχος κατάστασης συνδρομής καναλιού
Ελαφρύς boolean έλεγχος - μπορεί η επαφή να λάβει μηνύματα σε αυτό το κανάλι από πλευράς συγκατάθεσης;
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 στο κανάλι - μια επαφή χωρίς καταγεγραμμένη κατάσταση μετρά ως εγγεγραμμένη. Ένα άγνωστο id επαφής επιστρέφει { "subscribed": false } (όχι 404).
Έλεγχος εγκυρότητας email
Είναι η διεύθυνση email της επαφής παραδόσιμη (δεν έχει επισημανθεί ως μη έγκυρη από hard bounce);
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 μόνο όταν ένα hard bounce έχει επισημάνει τη διεύθυνση ως μη έγκυρη. Ένα άγνωστο id επαφής επιστρέφει { "valid": false } (όχι 404). Σημειώστε ότι αυτό αντανακλά παραδοσιμότητα, όχι συγκατάθεση - μια απεγγραμμένη επαφή με λειτουργική διεύθυνση εξακολουθεί να επιστρέφει true.
Λίστες συνδρομών
Οι λίστες είναι οι κατηγορίες συγκατάθεσης / τα θέματα στα οποία μπορούν να εγγραφούν οι επαφές (newsletter, ενημερώσεις προϊόντος κ.ο.κ.). Οι ορισμοί των λιστών βρίσκονται κάτω από το /lists· η συμμετοχή ανά επαφή διαχειρίζεται με τα endpoints συγκατάθεσης επαφής παραπάνω ή με τα μαζικά endpoints παρακάτω.
Δημιουργία λίστας
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 επισημαίνει την αυτόματα δημιουργημένη προεπιλεγμένη κατηγορία Μάρκετινγκ· το senderId ορίζεται όταν η λίστα είναι ομάδα συνδρομών SMS/WhatsApp ανά αριθμό, δεσμευμένη σε συγκεκριμένο αποστολέα.
Λίστα όλων των λιστών
Endpoint
GET /lists
Παράμετροι query
| Παράμετρος | Τύπος | Προεπιλογή | Περιγραφή |
|---|---|---|---|
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
Παράμετροι query
| Παράμετρος | Τύπος | Προεπιλογή | Περιγραφή |
|---|---|---|---|
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[] | Ναι | Ids επαφών 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[] | Ναι | Ids επαφών 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 σύνταξης για τη φιλοξενούμενη σελίδα του κέντρου προτιμήσεων του χώρου εργασίας - τη σελίδα στην οποία καταλήγουν οι παραλήπτες από έναν σύνδεσμο απεγγραφής/προτιμήσεων. Η δημόσια απόδοση της σελίδας εξυπηρετείται από τα δημόσια endpoints με token (χωρίς κλειδί 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 (μέγιστο 100 KB)· πρέπει να περιλαμβάνει την υποδοχή {{ preferences_form }} |
redirectUrl | string | Όχι | Προορισμός για λειτουργία redirect (μέγιστο 2048 χαρακτήρες) |
designJson | object | Όχι | Κατάσταση round-trip του οπτικού επεξεργαστή (μόνο σε λειτουργία dnd· καθαρίζεται στις άλλες λειτουργίες) |
Επιστρέφει το αποθηκευμένο πρότυπο στην ίδια μορφή με την απόκριση του GET.
Προεπισκόπηση προτύπου
POST /subscriptions/hosted-page/preview
Σώμα: { "html": "..." } - το πρότυπο προς απόδοση με δείγματα δεδομένων. Απόκριση: { "html": "<rendered, sanitized html>" }.
Σχετικές επιφάνειες (εκτός αυτής της σελίδας)
- Endpoints προς παραλήπτες - η απεγγραφή με ένα κλικ (
POST /u/:token, το κουμπί της εφαρμογής email), το κουμπί διαγραφής της φιλοξενούμενης σελίδας (POST /u/:token/confirm, μόνο με κλικ ατόμου) και οι φιλοξενούμενες σελίδες προτιμήσεων είναι δημόσια endpoints με έλεγχο ταυτότητας token για παραλήπτες, όχι endpoints κλειδιού API. - Web SDK - τα
POST /v1/subscriptions/channelκαιPOST /v1/subscriptions/groupελέγχονται με κλειδί SDK (X-SDK-Key), για UI προτιμήσεων στην πλευρά του πελάτη. Δείτε τον οδηγό Διαχείρισης συνδρομών. - Webhooks παρόχων - τα webhooks για bounces και εισερχόμενες λέξεις-κλειδιά SMS (
/webhooks/email/...,/webhooks/sms/...) είναι ενσωματώσεις παρόχων με επαλήθευση υπογραφής. - Καταστολές - η λίστα «να μην αποσταλεί» σε επίπεδο χώρου εργασίας έχει το δικό της Suppressions API.
Επόμενα βήματα
- Users API - δημιουργήστε την επαφή πριν ορίσετε τη συγκατάθεση
- Suppressions API - η λίστα «να μην αποσταλεί» με κλειδί το αναγνωριστικό
- Οδηγός Διαχείρισης συνδρομών - έννοιες, χρήση SDK, λέξεις-κλειδιά, συμμόρφωση