API ציבורי ו-webhooks
REST API מאפשר ל-CRM שלכם, ל-backend של האתר או לבוט משלכם לעבוד עם לידים ושיחות ב-cenaly.com בדיוק כפי שעשתה הפאנל: לקרוא כרטיסים, לשנות מאפיינים, לשלוח אירועים, להשיב בשיחות. ה-webhooks, לעומת זאת, מודיעים בעצמם לשרת שלכם על לידים חדשים, אירועים והודעות.
מה נדרש להפעלה#
| מה | היכן |
|---|---|
| תפקיד | בעל החשבון — המפתח פועל בשמו; עובדים אינם רואים מפתחות |
| מדור | צ'אט מופעל (לידים ושיחות חיים בו) |
| מפתח | אינטגרציות → 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“).
- בחרו סט הרשאות או סמנו הרשאות אחת-אחת, אם יש כמה סניפים — לאילו סניפים המפתח מורשה, ותוקף.
- העתיקו את הסוד
cnk_…. הוא מוצג פעם אחת: אצלנו נשמר רק טביעת האצבע שלו (SHA-256).
| הרשאה | מה נותנת |
|---|---|
contacts:read |
רשימה, חיפוש וכרטיס ליד, מאפיינים |
contacts:write |
לשנות מאפיינים ותגיות, למזג, למחוק לפי בקשת נושא |
events:read |
פיד אירועים של הליד |
events:write |
לשלוח אירועים (רכישה, הרשמה, כל אירוע משלכם) |
conversations:read |
שיחות והודעות |
conversations:write |
תגובת נציג, הערה, סטטוס, אחראי, תגיות |
messages:send |
הודעה לליד בשיחה האחרונה שלו |
segments:read |
סגמנטים שמורים והמשתתפים בהם |
סטים: CRM / backend (לידים, מאפיינים, אירועים, קריאת שיחות וסגמנטים), בוט משלכם (קורא לידים, משיב בשיחות, כותב ללידים), קריאה בלבד, הכול.
- הרשאות משנות את הרשאות המפתח והסניפים שלו בזמן אמת — האינטגרציה ממשיכה לעבוד.
- הנפקה מחדש מוציאה סוד חדש; הישן מפסיק לעבוד מיד, ההרשאות והיומן נשארים.
- ביטול — מיד ולצמיתות, הבקשה הבאה תקבל
401.
המפתח מועבר בכותרת Authorization: Bearer cnk_… (או X-Api-Key: cnk_…). שמרו אותו רק על השרת — לא בדפדפן ולא באפליקציה לנייד.
שלב 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 שלנו לליד: הוסיפו ?by=user_id, והכתובת תהפוך למזהה המשתמש שלכם. אם אין עדיין ליד עם 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. בכרטיס הליד מחבר העריכה מוצג כ„API: <שם המפתח>“.
שיטות#
| שיטה | מה עושה | הרשאה |
|---|---|---|
GET /v1/me, GET /v1/locations |
מפתח, הרשאות, סניפים | — |
GET /v1/contacts |
לידים: 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 |
תגיות של הליד | contacts:write |
POST /v1/contacts/merge |
מיזוג שני כרטיסים: תצוגה מקדימה, ואז "apply": true |
contacts:write |
POST /v1/contacts/{id}/erase |
מחיקה לבקשת נושא המידע ("confirm": true) |
contacts:write |
GET /v1/contacts/{id}/events |
פיד האירועים של הליד | events:read |
POST /v1/contacts/{id}/events, POST /v1/events |
אירועים (עד 100 בבת אחת) | events:write |
GET /v1/contacts/{id}/conversations |
שיחות של הליד | conversations:read |
POST /v1/contacts/{id}/messages |
לכתוב לליד בשיחה האחרונה שלו | 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.created |
נוצר ליד חדש (איש קשר הושאר בצ׳אט, בטופס או נוצר דרך API) |
lead.props_changed |
מאפייני הליד השתנו — רשימת המפתחות ב-changedProps |
lead.event_tracked |
לליד יש אירוע; כברירת מחדל כל האירועים שלכם ללא מערכתיים ($…), רשימת השמות נקבעת בשדה „אילו אירועים לשלוח“ |
message.goal_reached |
הליד הגיע ליעד של הודעה (חלון קופץ, תפוצה) |
{
"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 } }
}
שם, דוא״ל וטלפון של הליד נכללים בגוף ההודעה רק אם ב-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 נכנסים לכרטיס הליד (פיד, סיכום, סגמנטים), אך לא ליומן הגולמי של ניתוח הביקורים.
- אפשר לכתוב לליד רק בשיחה קיימת: אין שיחה — תשובה
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 |
הליד או השיחה אינם קיימים | עבור מזהים משלכם השתמשו ב-?by=user_id |
429 rate_limited |
יותר מ-60 בקשות בדקה | המתינו Retry-After שניות, קבצו אירועים במקבצים |
502 upstream_error |
תקלה זמנית | נסו שוב מאוחר יותר |
כל בקשה נראית בלשונית יומן קריאות — עם קוד התשובה ושם המפתח.
שאלות נפוצות#
אפשר לקרוא ל-API מהדפדפן? לא: המפתח נותן גישה לכל הלידים של הסניף. קראו ל-API מהשרת שלכם.
במה user_id שונה מ-id של הליד? id של הליד — המזהה שלנו לכרטיס. user_id — המזהה שלכם למשתמש (מספר ב-CRM, id של חשבון באתר); עם ?by=user_id אפשר לפנות לכרטיס לפיו.
מה יקרה בשליחה חוזרת של אירוע? אירוע עם אותו id נספר פעם אחת — אפשר לשלוח שוב בבטחה במקרה של שגיאת רשת.
צריך מפתח נפרד לכל סניף? לא: מפתח אחד יכול לעבוד עם כמה סניפים, והסניף נבחר בפרמטר location.
קטעים קשורים#
- צ׳אט עם אורחים — שיחות, לידים והגדרות Webhooks
- פניות — זרם נכנס אחיד
- API ו-MCP של מרכזיית הטלפון שלכם — API נפרד לטלפוניה
- אינטגרציות