Δημόσιο API και webhooks
Το REST API επιτρέπει στο CRM σας, στο backend του ιστότοπού σας ή στο δικό σας bot να εργάζεται με leads και διαλόγους του cenaly.com όπως ακριβώς κάνει το πάνελ: να διαβάζει κάρτες, να αλλάζει ιδιότητες, να στέλνει συμβάντα, να απαντά σε διαλόγους. Τα webhooks, αντίθετα, ενημερώνουν τα ίδια τον server σας για νέα leads, συμβάντα και μηνύματα.
Τι χρειάζεται για την εκκίνηση#
| Τι | Πού |
|---|---|
| Ρόλος | κάτοχος λογαριασμού — το κλειδί ενεργεί στο όνομά του· οι εργαζόμενοι δεν βλέπουν κλειδιά |
| Ενότητα | ενεργοποιημένη συνομιλία (τα leads και οι διάλογοι ζουν σε αυτήν) |
| Κλειδί | Ενσωματώσεις → API και webhooks → Κλειδιά → Δημιουργία κλειδιού |
| Διεύθυνση API | https://api.cenaly.com/public-api/v1 |
| Οδηγός μεθόδων | api.cenaly.com/public-api/v1/docs |
| OpenAPI 3.1 | api.cenaly.com/public-api/v1/openapi.json |
Βήμα 1. Κλειδί και δικαιώματα#
- Ανοίξτε τις Ενσωματώσεις και πατήστε API και webhooks στην κεφαλίδα της σελίδας.
- Στην καρτέλα Κλειδιά πατήστε Δημιουργία κλειδιού, εισαγάγετε ένα όνομα («CRM», «Backend ιστότοπου», «Telegram-bot»).
- Επιλέξτε ένα σύνολο δικαιωμάτων ή σημειώστε τα δικαιώματα ένα προς ένα, και αν έχετε πολλά καταστήματα — σε ποια καταστήματα έχει πρόσβαση το κλειδί, καθώς και τη διάρκεια.
- Αντιγράψτε το secret
cnk_…. Εμφανίζεται μία φορά: σε εμάς αποθηκεύεται μόνο το αποτύπωμά του (SHA-256).
| Δικαίωμα | Τι παρέχει |
|---|---|
contacts:read |
λίστα, αναζήτηση και κάρτα lead, ιδιότητες |
contacts:write |
αλλαγή ιδιοτήτων και ετικετών, συγχώνευση, διαγραφή κατόπιν αιτήματος του υποκειμένου |
events:read |
ροή συμβάντων του lead |
events:write |
αποστολή συμβάντων (αγορά, εγγραφή, οποιοδήποτε δικό σας) |
conversations:read |
διάλογοι και μηνύματα |
conversations:write |
απάντηση χειριστή, σημείωση, κατάσταση, υπεύθυνος, ετικέτες |
messages:send |
μήνυμα σε lead στον τελευταίο διάλογό του |
segments:read |
αποθηκευμένα τμήματα και τα μέλη τους |
Σύνολα: CRM / backend (leads, ιδιότητες, συμβάντα, ανάγνωση διαλόγων και τμημάτων), Δικό σας bot (διαβάζει leads, απαντά σε διαλόγους, γράφει σε leads), Μόνο ανάγνωση, Όλα.
- Δικαιώματα αλλάζουν τα δικαιώματα και τα καταστήματα του κλειδιού εν κινήσει — η ενσωμάτωση συνεχίζει να λειτουργεί.
- Επανέκδοση εκδίδει νέο secret· το παλιό σταματά να λειτουργεί αμέσως, τα δικαιώματα και το αρχείο καταγραφής παραμένουν.
- Ανάκληση — αμέσως και οριστικά, το επόμενο αίτημα θα λάβει
401.
Το κλειδί μεταδίδεται με την κεφαλίδα Authorization: Bearer cnk_… (ή X-Api-Key: cnk_…). Φυλάξτε το μόνο στον server — όχι στο πρόγραμμα περιήγησης και όχι στην εφαρμογή για κινητά.
Βήμα 2. Πρώτα αιτήματα#
KEY=cnk_ваш_ключ
API=https://api.cenaly.com/public-api/v1
# что умеет ключ: права, точки, лимит
curl -H "Authorization: Bearer $KEY" "$API/me"
# лиды, свежие сверху (20 на страницу)
curl -H "Authorization: Bearer $KEY" "$API/contacts?limit=20"
# поиск по имени, почте или телефону
curl -H "Authorization: Bearer $KEY" "$API/contacts?q=anna"
Η απάντηση είναι πάντα ένας φάκελος:
{
"meta": { "status": 200, "requestId": "…", "nextCursor": "WyIyMDI2LTEwLTA0…" },
"data": { "total": 128, "contacts": [ { "id": "…", "status": "lead", "name": "Анна", "updatedAt": "2026-10-04T09:12:00Z" } ] }
}
Η επόμενη σελίδα είναι το ίδιο αίτημα με cursor=<meta.nextCursor>· αν δεν υπάρχει nextCursor — δεν υπάρχουν άλλες σελίδες. Σφάλμα — {"meta": {...}, "error": {"code": "…"}}.
Κατάστημα. Αν στο κλειδί είναι προσβάσιμο ένα κατάστημα, δεν χρειάζεται να το δηλώσετε. Αν είναι πολλά — προσθέστε location=<id καταστήματος> (λίστα — GET /v1/locations), αλλιώς η απάντηση είναι 400 location_required.
Ιδιότητες και συμβάντα με το δικό σας user_id. Δεν είναι υποχρεωτικό να αποθηκεύετε το δικό μας id του lead: προσθέστε ?by=user_id, και ως διεύθυνση θα χρησιμοποιείται το δικό σας αναγνωριστικό χρήστη. Αν δεν υπάρχει ακόμη lead με τέτοιο user_id — θα τον δημιουργήσουμε.
# свойства: операции update_or_create, set_once, add, delete, append, union, exclude
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"ops":[{"op":"update_or_create","key":"$email","value":"anna@example.com"},
{"op":"add","key":"orders","value":1},
{"op":"union","key":"interests","value":"yoga"}]}' \
"$API/contacts/u-1001/props?by=user_id"
# события пачкой (до 100), повтор с тем же id засчитывается один раз
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"events":[{"id":"ord-5531","userId":"u-1001","name":"order_paid","props":{"sum":45,"currency":"GEL"}}]}' \
"$API/events"
# ответ в диалоге и смена статуса
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"text":"Здравствуйте! Заказ передан курьеру."}' "$API/conversations/<id>/reply"
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"status":"resolved"}' "$API/conversations/<id>/status"
Η εγγραφή περνά από την ίδια ουρά με τις αλλαγές από το πάνελ: οι αλλαγές εφαρμόζονται σε δευτερόλεπτα, και η απάντηση σε εγγραφή με user_id είναι 202 με pending. Στην κάρτα του lead ο συντάκτης της αλλαγής εμφανίζεται ως «API: <όνομα κλειδιού>».
Μέθοδοι#
| Μέθοδος | Τι κάνει | Δικαίωμα |
|---|---|---|
GET /v1/me, GET /v1/locations |
κλειδί, δικαιώματα, καταστήματα | — |
GET /v1/contacts |
leads: status (anon, lead, user), q, limit, cursor |
contacts:read |
GET /v1/contacts/{id} |
καρτέλα: ιδιότητες, ετικέτες, σύνοψη συμβάντων | contacts:read |
POST /v1/contacts/{id}/props |
ιδιότητες με πράξεις (έως 250) ή {"props":{…}} |
contacts:write |
POST / DELETE /v1/contacts/{id}/tags |
ετικέτες lead | contacts:write |
POST /v1/contacts/merge |
συγχώνευση δύο καρτελών: προεπισκόπηση, μετά "apply": true |
contacts:write |
POST /v1/contacts/{id}/erase |
διαγραφή κατόπιν αιτήματος υποκειμένου ("confirm": true) |
contacts:write |
GET /v1/contacts/{id}/events |
ροή συμβάντων lead | events:read |
POST /v1/contacts/{id}/events, POST /v1/events |
συμβάντα (έως 100 τη φορά) | events:write |
GET /v1/contacts/{id}/conversations |
συνομιλίες lead | conversations:read |
POST /v1/contacts/{id}/messages |
στείλτε μήνυμα στον lead στην τελευταία του συνομιλία | messages:send |
GET /v1/conversations, /{id}, /{id}/messages |
συνομιλίες και μηνύματα | conversations:read |
POST /v1/conversations/{id}/reply |
απάντηση χειριστή ή σημείωση ("type": "note") |
conversations:write |
POST /v1/conversations/{id}/status, /assign, /tags |
κατάσταση, υπεύθυνος, ετικέτες | conversations:write |
GET /v1/segments, GET /v1/segments/{id}/contacts |
τμήματα και τα μέλη τους | segments:read |
Πεδία, παραδείγματα και κωδικοί σφάλματος κάθε μεθόδου — στον οδηγό αναφοράς.
Βήμα 3. Webhooks#
Τα webhooks ρυθμίζονται ανά κατάστημα: Συνομιλία → Ρυθμίσεις → Webhooks — διεύθυνση https, συμβάντα και μυστικό υπογραφής. Στα συμβάντα συνομιλίας (νέα συνομιλία, νέο μήνυμα, κατάσταση, αξιολόγηση, ετικέτες) προστέθηκαν συμβάντα lead:
| Συμβάν | Πότε έρχεται |
|---|---|
lead.created |
εμφανίστηκε νέο lead (η επαφή άφησε στοιχεία στη συνομιλία, στη φόρμα ή καταχωρίστηκε μέσω API) |
lead.props_changed |
άλλαξαν οι ιδιότητες του lead — λίστα κλειδιών στο changedProps |
lead.event_tracked |
ο lead έχει συμβάν· από προεπιλογή όλα τα δικά σας συμβάντα χωρίς τα συστημικά ($…), η λίστα ονομάτων ορίζεται στο πεδίο «Ποια συμβάντα να αποστέλλονται» |
message.goal_reached |
ο lead πέτυχε τον στόχο του μηνύματος (pop-up, αποστολή) |
{
"event": "lead.event_tracked",
"deliveryId": "WD…",
"at": "2026-10-04T09:12:03Z",
"webhookId": "…",
"locationId": "…",
"contact": { "id": "…", "status": "user", "userId": "u-1001", "props": { "orders": 3 }, "tags": ["vip"] },
"leadEvent": { "name": "order_paid", "at": "2026-10-04T09:12:00Z", "props": { "sum": 45 } }
}
Το όνομα, το email και το τηλέφωνο του lead μπαίνουν στο σώμα μόνο αν στο webhook είναι ενεργοποιημένο το πλαίσιο «Να διαβιβάζονται τα στοιχεία επαφής του επισκέπτη». Έλεγχος υπογραφής — HMAC-SHA256 του σώματος με το μυστικό του webhook:
# заголовок X-Meni-Signature: sha256=<hex>
echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET"
Απαντήστε 2xx εντός 5 δευτερολέπτων — αλλιώς η παράδοση θα επαναληφθεί· μετά από μεγάλη σειρά αποτυχιών το webhook απενεργοποιείται και αυτό φαίνεται στις ρυθμίσεις. Τα διπλότυπα αποκόπτονται με βάση το deliveryId.
Περιορισμοί#
- 60 αιτήματα το λεπτό ανά κλειδί· πάνω από αυτό —
429με κεφαλίδαRetry-After. Το υπόλοιπο — στοX-RateLimit-*. - Έως 200 εγγραφές ανά σελίδα (από προεπιλογή 50), έως 100 συμβάντα ανά παρτίδα, έως 250 πράξεις με ιδιότητες ανά αίτημα, έως 30 ετικέτες τη φορά.
- Έως 20 ενεργά κλειδιά ανά λογαριασμό.
- Το αρχείο καταγραφής κλήσεων του κλειδιού διατηρείται 30 ημέρες: χρόνος, μέθοδος, πρότυπο διαδρομής (χωρίς id και σώμα), κωδικός απόκρισης, διάρκεια.
- Τα συμβάντα που αποστέλλονται μέσω API καταχωρίζονται στην καρτέλα του lead (ροή, σύνοψη, τμήματα), αλλά όχι στο ακατέργαστο αρχείο καταγραφής αναλυτικών επισκέψεων.
- Μπορείτε να στείλετε μήνυμα στον lead μόνο σε υπάρχουσα συνομιλία: αν δεν υπάρχει συνομιλία — απόκριση
409 no_conversation.
Αντιμετώπιση προβλημάτων#
| Απόκριση | Τι σημαίνει | Τι να κάνετε |
|---|---|---|
401 api_key_missing / api_key_invalid |
το κλειδί λείπει από το αίτημα, ή είναι λανθασμένο, ανακλήθηκε ή έληξε | ελέγξτε την κεφαλίδα· αν χρειάζεται, επανεκδώστε το κλειδί |
403 scope_required |
το κλειδί δεν έχει το απαιτούμενο δικαίωμα | Δικαιώματα στο κλειδί — προσθέστε το δικαίωμα |
400 location_required |
στο κλειδί είναι διαθέσιμα πολλά καταστήματα | προσθέστε location=<id> |
404 location_not_found |
το κατάστημα δεν είναι μεταξύ των καταστημάτων του κλειδιού | ελέγξτε με GET /v1/locations |
404 not_found |
ο lead ή η συνομιλία δεν υπάρχει | για δικά σας id χρησιμοποιήστε ?by=user_id |
429 rate_limited |
περισσότερα από 60 αιτήματα το λεπτό | περιμένετε Retry-After δευτερόλεπτα, ομαδοποιήστε τα συμβάντα σε παρτίδες |
502 upstream_error |
προσωρινή βλάβη | επαναλάβετε το αίτημα αργότερα |
Κάθε αίτημα φαίνεται στην καρτέλα Αρχείο καταγραφής κλήσεων — με τον κωδικό απόκρισης και το όνομα του κλειδιού.
Συχνές ερωτήσεις#
Μπορώ να καλώ το API από τον browser; Όχι: το κλειδί δίνει πρόσβαση σε όλα τα leads του καταστήματος. Καλείτε το API από τον δικό σας διακομιστή.
Σε τι διαφέρει το user_id από το id του lead; Το id του lead είναι το δικό μας αναγνωριστικό της καρτέλας. Το user_id είναι το δικό σας αναγνωριστικό χρήστη (αριθμός στο CRM, id λογαριασμού στον ιστότοπο)· με ?by=user_id μπορείτε να απευθύνετε την καρτέλα με αυτό.
Τι θα συμβεί αν στείλω ξανά το ίδιο συμβάν; Το συμβάν με το ίδιο id μετράει μία φορά — μπορείτε άφοβα να επαναλάβετε το αίτημα σε περίπτωση σφάλματος δικτύου.
Χρειάζεται ξεχωριστό κλειδί για κάθε κατάστημα; Όχι: ένα κλειδί μπορεί να λειτουργεί με πολλά καταστήματα, το κατάστημα επιλέγεται με την παράμετρο location.
Σχετικές ενότητες#
- Συνομιλία με επισκέπτες — συνομιλίες, leads και ρυθμίσεις webhooks
- Αιτήματα — ενιαία εισερχόμενη ροή
- API και MCP του δικού σας τηλεφωνικού κέντρου — ξεχωριστό API τηλεφωνίας
- Ενσωματώσεις