API công khai và webhook
REST API cho phép CRM, backend của website hoặc bot riêng của bạn làm việc với lead và hội thoại của cenaly.com giống như bảng điều khiển vẫn làm: đọc thẻ, thay đổi thuộc tính, gửi sự kiện, trả lời trong hội thoại. Ngược lại, webhook tự thông báo cho máy chủ của bạn về lead mới, sự kiện và tin nhắn.
Cần gì để bắt đầu#
| Nội dung | Vị trí |
|---|---|
| Vai trò | chủ tài khoản — khóa hoạt động dưới danh nghĩa của chủ tài khoản; nhân viên không nhìn thấy khóa |
| Mục | chat đã bật (lead và hội thoại nằm trong đó) |
| Khóa | Tích hợp → API và webhook → Khóa → Tạo khóa |
| Địa chỉ API | https://api.cenaly.com/public-api/v1 |
| Tài liệu tham chiếu phương thức | api.cenaly.com/public-api/v1/docs |
| OpenAPI 3.1 | api.cenaly.com/public-api/v1/openapi.json |
Bước 1. Khóa và quyền#
- Mở Tích hợp và nhấn API và webhook ở đầu trang.
- Trên tab Khóa, nhấn Tạo khóa, nhập tên (“CRM”, “Backend của website”, “Bot Telegram”).
- Chọn một bộ quyền hoặc đánh dấu từng quyền một, nếu có nhiều chi nhánh — chọn các chi nhánh mà khóa được phép truy cập, và thời hạn.
- Sao chép secret
cnk_…. Nó chỉ hiển thị một lần: chúng tôi chỉ lưu dấu vân tay của nó (SHA-256).
| Quyền | Cấp những gì |
|---|---|
contacts:read |
danh sách, tìm kiếm và thẻ lead, thuộc tính |
contacts:write |
thay đổi thuộc tính và thẻ, gộp, xóa theo yêu cầu của chủ thể |
events:read |
dòng sự kiện của lead |
events:write |
gửi sự kiện (mua hàng, đăng ký, bất kỳ sự kiện riêng nào) |
conversations:read |
hội thoại và tin nhắn |
conversations:write |
trả lời của nhân viên, ghi chú, trạng thái, người phụ trách, nhãn |
messages:send |
tin nhắn cho lead trong hội thoại gần nhất của lead |
segments:read |
các phân khúc đã lưu và thành viên của chúng |
Các bộ: CRM / backend (lead, thuộc tính, sự kiện, đọc hội thoại và phân khúc), Bot riêng (đọc lead, trả lời trong hội thoại, ghi cho lead), Chỉ đọc, Tất cả.
- Quyền thay đổi quyền và chi nhánh của khóa ngay lập tức — tích hợp vẫn tiếp tục hoạt động.
- Cấp lại phát hành secret mới; secret cũ ngừng hoạt động ngay, quyền và nhật ký vẫn giữ nguyên.
- Thu hồi — ngay lập tức và vĩnh viễn, yêu cầu tiếp theo sẽ nhận
401.
Khóa được truyền qua header Authorization: Bearer cnk_… (hoặc X-Api-Key: cnk_…). Chỉ lưu khóa trên máy chủ — không lưu trong trình duyệt và không lưu trong ứng dụng di động.
Bước 2. Những yêu cầu đầu tiên#
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"
Phản hồi — luôn là một envelope:
{
"meta": { "status": 200, "requestId": "…", "nextCursor": "WyIyMDI2LTEwLTA0…" },
"data": { "total": 128, "contacts": [ { "id": "…", "status": "lead", "name": "Анна", "updatedAt": "2026-10-04T09:12:00Z" } ] }
}
Trang tiếp theo — cùng yêu cầu với cursor=<meta.nextCursor>; không có nextCursor — không còn trang nào nữa. Lỗi — {"meta": {...}, "error": {"code": "…"}}.
Chi nhánh. Nếu khóa chỉ được phép truy cập một chi nhánh, không cần chỉ định chi nhánh đó. Nếu có nhiều chi nhánh — thêm location=<id точки> (danh sách — GET /v1/locations), nếu không phản hồi sẽ là 400 location_required.
Thuộc tính và sự kiện theo user_id của bạn. Không nhất thiết phải lưu id lead của chúng tôi: thêm ?by=user_id, và địa chỉ sẽ trở thành mã định danh người dùng của bạn. Nếu chưa có lead với user_id như vậy — chúng tôi sẽ tạo lead đó.
# свойства: операции 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"
Ghi dữ liệu đi qua cùng hàng đợi như các chỉnh sửa từ bảng điều khiển: thay đổi được áp dụng trong vài giây, còn phản hồi cho yêu cầu ghi theo user_id — 202 với pending. Trong thẻ lead, tác giả của chỉnh sửa hiển thị là “API: <tên khóa>”.
Phương thức#
| Phương thức | Chức năng | Quyền |
|---|---|---|
GET /v1/me, GET /v1/locations |
khóa, quyền, chi nhánh | — |
GET /v1/contacts |
lead: status (anon, lead, user), q, limit, cursor |
contacts:read |
GET /v1/contacts/{id} |
thẻ: thuộc tính, thẻ tag, tóm tắt sự kiện | contacts:read |
POST /v1/contacts/{id}/props |
thuộc tính bằng thao tác (tối đa 250) hoặc {"props":{…}} |
contacts:write |
POST / DELETE /v1/contacts/{id}/tags |
thẻ tag của lead | contacts:write |
POST /v1/contacts/merge |
gộp hai thẻ: xem trước, sau đó "apply": true |
contacts:write |
POST /v1/contacts/{id}/erase |
xóa theo yêu cầu của chủ thể ("confirm": true) |
contacts:write |
GET /v1/contacts/{id}/events |
dòng sự kiện của lead | events:read |
POST /v1/contacts/{id}/events, POST /v1/events |
sự kiện (tối đa 100 mỗi lần) | events:write |
GET /v1/contacts/{id}/conversations |
hội thoại của lead | conversations:read |
POST /v1/contacts/{id}/messages |
nhắn cho lead trong hội thoại gần nhất của họ | messages:send |
GET /v1/conversations, /{id}, /{id}/messages |
hội thoại và tin nhắn | conversations:read |
POST /v1/conversations/{id}/reply |
trả lời của nhân viên hoặc ghi chú ("type": "note") |
conversations:write |
POST /v1/conversations/{id}/status, /assign, /tags |
trạng thái, người phụ trách, nhãn | conversations:write |
GET /v1/segments, GET /v1/segments/{id}/contacts |
phân khúc và thành viên của chúng | segments:read |
Các trường, ví dụ và mã lỗi của từng phương thức — trong tài liệu tham chiếu.
Bước 3. Webhook#
Webhook được thiết lập tại chi nhánh: Chat → Cài đặt → Webhook — địa chỉ https, sự kiện và khóa bí mật ký. Bên cạnh các sự kiện hội thoại (hội thoại mới, tin nhắn mới, trạng thái, đánh giá, nhãn) đã có thêm các sự kiện lead:
| Sự kiện | Khi nào đến |
|---|---|
lead.created |
có lead mới (liên hệ để lại trong chat, biểu mẫu hoặc tạo qua API) |
lead.props_changed |
thuộc tính của lead thay đổi — danh sách khóa trong changedProps |
lead.event_tracked |
lead có sự kiện; mặc định là tất cả sự kiện của bạn trừ sự kiện hệ thống ($…), danh sách tên được đặt bằng trường «Sự kiện nào cần gửi» |
message.goal_reached |
lead đạt mục tiêu của tin nhắn (pop-up, chiến dịch gửi hàng loạt) |
{
"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 } }
}
Tên, email và số điện thoại của lead chỉ vào phần thân nếu webhook bật tùy chọn «Truyền liên hệ của khách». Kiểm tra chữ ký — HMAC-SHA256 của phần thân bằng khóa bí mật của webhook:
# заголовок X-Meni-Signature: sha256=<hex>
echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET"
Hãy trả lời 2xx trong 5 giây — nếu không, việc gửi sẽ được lặp lại; sau một chuỗi dài thất bại, webhook sẽ bị tắt và điều này hiển thị trong cài đặt. Loại bỏ trùng lặp theo deliveryId.
Giới hạn#
- 60 yêu cầu mỗi phút cho mỗi khóa; vượt mức —
429với tiêu đềRetry-After. Số còn lại — trongX-RateLimit-*. - Tối đa 200 bản ghi mỗi trang (mặc định 50), tối đa 100 sự kiện mỗi lô, tối đa 250 thao tác với thuộc tính mỗi yêu cầu, tối đa 30 thẻ tag mỗi lần.
- Tối đa 20 khóa đang hoạt động cho mỗi tài khoản.
- Nhật ký gọi khóa được lưu 30 ngày: thời gian, phương thức, mẫu đường dẫn (không có id và phần thân), mã phản hồi, thời lượng.
- Các sự kiện gửi qua API được ghi vào thẻ lead (dòng sự kiện, tóm tắt, phân khúc), nhưng không vào nhật ký thô của phân tích lượt truy cập.
- Chỉ có thể nhắn cho lead trong hội thoại đã tồn tại: không có hội thoại — phản hồi
409 no_conversation.
Xử lý sự cố#
| Phản hồi | Ý nghĩa | Cần làm gì |
|---|---|---|
401 api_key_missing / api_key_invalid |
không có khóa trong yêu cầu, hoặc khóa sai, đã thu hồi hoặc hết hạn | kiểm tra tiêu đề; nếu cần, phát hành lại khóa |
403 scope_required |
khóa không có quyền cần thiết | Quyền của khóa — thêm quyền |
400 location_required |
khóa có quyền truy cập nhiều chi nhánh | thêm location=<id> |
404 location_not_found |
chi nhánh không nằm trong các chi nhánh của khóa | đối chiếu với GET /v1/locations |
404 not_found |
không có lead hoặc hội thoại | với id của bạn, dùng ?by=user_id |
429 rate_limited |
hơn 60 yêu cầu mỗi phút | đợi Retry-After giây, gom sự kiện thành lô |
502 upstream_error |
sự cố tạm thời | gửi lại yêu cầu sau |
Mỗi yêu cầu đều hiển thị trong tab Nhật ký gọi — kèm mã phản hồi và tên khóa.
Câu hỏi thường gặp#
Có thể gọi API từ trình duyệt không? Không: khóa cho phép truy cập tất cả lead của chi nhánh. Hãy gọi API từ máy chủ của bạn.
user_id khác gì so với id của lead? id của lead là mã định danh thẻ của chúng tôi. user_id là mã định danh người dùng của bạn (số trong CRM, id tài khoản trên website); với ?by=user_id, có thể định địa chỉ thẻ bằng mã này.
Điều gì xảy ra khi gửi lại sự kiện? Sự kiện có cùng id chỉ được tính một lần — có thể yên tâm lặp lại yêu cầu khi gặp lỗi mạng.
Có cần khóa riêng cho mỗi chi nhánh không? Không: một khóa có thể làm việc với nhiều chi nhánh, chi nhánh được chọn bằng tham số location.
Các mục liên quan#
- Chat với khách — hội thoại, lead và cài đặt webhook
- Yêu cầu — luồng tiếp nhận chung
- API và MCP của tổng đài riêng — API điện thoại riêng
- Tích hợp