Kommo + RingCentral: записи разговоров и итоги звонков в карточку сделки
RingCentral имеет нативную интеграцию с Kommo: click-to-call, автоматическое создание лида при входящем звонке от незнакомого номера, базовый лог звонков в таймлайне сделки. Но нативная интеграция фиксирует только сам факт звонка — продолжительность и номер. Ни записи разговора, ни итога звонка, ни транскрипта в карточке нет. Это закрывается через RingCentral REST API.
Что упускает нативная интеграция Kommo + RingCentral
Стандартная интеграция RingCentral через Kommo Marketplace даёт:
— Click-to-call из карточки контакта
— Входящий звонок -> уведомление в Kommo, создание лида если контакт новый
— Запись факта звонка (кто позвонил, длительность) в таймлайн сделки
Чего нет:
— Запись разговора не прикрепляется к сделке — она остаётся только в RingCentral
— Итог звонка (статус, комментарий менеджера) не попадает в кастомные поля
— Транскрипт недоступен в CRM даже если RingCentral AI его создал
— Логика маршрутизации — кому назначить сделку после звонка — не настраивается
Для команд с 20+ звонками в день это означает, что Sales Director не видит контекст разговоров в Kommo без перехода в RingCentral. Customer Success не знает, о чём говорили с клиентом до передачи. При смене менеджера история теряется.
Архитектура расширенной интеграции
RingCentral Webhook: telephony/sessions -> сессия завершена (Disconnected)
↓ Backend
1. Получить session_id, extension_id, from/to номера
2. Подождать 60 сек (запись обрабатывается асинхронно)
3. GET /account/~/call-log?sessionId={session_id}&view=Detailed
-> duration, result, recording.id
4. GET /account/~/recording/{recording_id}/content
-> скачать аудио MP3
5. Загрузить MP3 в хранилище (S3/R2)
-> получить публичный URL
6. Kommo: найти сделку по номеру телефона (контакт -> сделки)
7. Kommo: POST /leads/{deal_id}/notes
-> Note с типом «звонок»: длительность, ссылка на запись
8. Kommo: PATCH /leads/{deal_id}
-> кастомное поле last_call_result = 'Completed' / 'No Answer' / 'Busy'
-> last_call_date = timestamp
RingCentral REST API: ключевые запросы
Base URL: https://platform.ringcentral.com/restapi/v1.0/. Аутентификация: JWT flow для server-to-server (создать JWT credential в Developer Console -> обменять на access_token).
Получение access token через JWT:
import requests
RC_CLIENT_ID = 'your_client_id'
RC_CLIENT_SECRET = 'your_client_secret'
RC_JWT = 'your_jwt_credential'
def get_access_token() -> str:
resp = requests.post(
'https://platform.ringcentral.com/restapi/oauth/token',
auth=(RC_CLIENT_ID, RC_CLIENT_SECRET),
data={
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion': RC_JWT
}
)
resp.raise_for_status()
return resp.json()['access_token']
Получение деталей звонка:
def get_call_details(session_id: str, token: str) -> dict:
headers = {'Authorization': f'Bearer {token}'}
resp = requests.get(
'https://platform.ringcentral.com/restapi/v1.0/account/~/call-log',
headers=headers,
params={
'sessionId': session_id,
'view': 'Detailed',
'dateFrom': '2024-01-01T00:00:00Z' # или минус 1 час
}
)
resp.raise_for_status()
records = resp.json().get('records', [])
if not records:
return {}
record = records[0]
return {
'duration': record.get('duration'),
'result': record.get('result'), # 'Accepted', 'No Answer', 'Busy', etc.
'from': record.get('from', {}).get('phoneNumber'),
'to': record.get('to', {}).get('phoneNumber'),
'recording_id': record.get('recording', {}).get('id')
}
Скачать запись разговора:
def download_recording(recording_id: str, token: str) -> bytes:
headers = {'Authorization': f'Bearer {token}'}
resp = requests.get(
f'https://platform.ringcentral.com/restapi/v1.0'
f'/account/~/recording/{recording_id}/content',
headers=headers
)
resp.raise_for_status()
return resp.content # MP3 bytes
Обработка telephony/sessions webhook:
from flask import Flask, request
import time
app = Flask(__name__)
@app.route('/webhooks/ringcentral', methods=['POST'])
def ringcentral_webhook():
# RingCentral требует валидацию при регистрации webhook
validation_token = request.headers.get('Validation-Token')
if validation_token:
return validation_token, 200, {'Validation-Token': validation_token}
payload = request.json
event = payload.get('event', '')
# Обрабатываем только завершённые сессии
if 'telephony/sessions' not in event:
return '', 200
body = payload.get('body', {})
session_id = body.get('sessionId')
parties = body.get('parties', [])
# Проверяем что хотя бы одна сторона в статусе Disconnected
has_disconnected = any(
p.get('status', {}).get('code') == 'Disconnected'
for p in parties
)
if not has_disconnected:
return '', 200
# Очередь для асинхронной обработки (запись появляется с задержкой)
enqueue_call_processing(session_id, delay_seconds=60)
return '', 200
def process_completed_call(session_id: str):
token = get_access_token()
details = get_call_details(session_id, token)
if not details:
return
from_number = details['from']
result = details['result']
duration = details['duration']
recording_id = details.get('recording_id')
# Найти сделку в Kommo по номеру телефона
deal_id = find_kommo_deal_by_phone(from_number)
if not deal_id:
return
# Скачать и сохранить запись
recording_url = None
if recording_id:
audio = download_recording(recording_id, token)
recording_url = upload_to_storage(audio, f'{session_id}.mp3')
# Note в Kommo
note_text = f'RingCentral звонок: {duration} сек, результат: {result}'
if recording_url:
note_text += f'\nЗапись: {recording_url}'
create_kommo_note(deal_id, note_text)
# Обновить кастомные поля
update_kommo_deal(deal_id, {
'last_call_result': result,
'last_call_duration': duration
})
Регистрация webhook в RingCentral:
def register_webhook(webhook_url: str, token: str):
resp = requests.post(
'https://platform.ringcentral.com/restapi/v1.0/subscription',
headers={'Authorization': f'Bearer {token}'},
json={
'eventFilters': [
'/restapi/v1.0/account/~/telephony/sessions'
],
'deliveryMode': {
'transportType': 'WebHook',
'address': webhook_url
},
'expiresIn': 604800 # 7 дней, нужно обновлять
}
)
return resp.json()
Важно: Подписка на RingCentral webhook истекает (по умолчанию 7 дней). Необходимо обновлять её по расписанию через PUT /subscription/{subscriptionId} или подписаться на событие /restapi/v1.0/subscription/~?threshold=60&interval=30 для автоматического обновления.
Интеграция с RingCentral AI — транскрипты
RingCentral RingSense AI создаёт транскрипты и саммари звонков на тарифах с AI-функциями. Они доступны через GET /account/~/call-log/{callId}?view=Detailed — поле aiTranscriptUrl содержит ссылку на транскрипт.
def get_call_transcript(call_id: str, token: str) -> str:
headers = {'Authorization': f'Bearer {token}'}
resp = requests.get(
f'https://platform.ringcentral.com/restapi/v1.0'
f'/account/~/call-log/{call_id}',
headers=headers,
params={'view': 'Detailed'}
)
data = resp.json()
transcript_url = data.get('aiTranscriptUrl')
if not transcript_url:
return ''
tr = requests.get(transcript_url, headers=headers)
return tr.text
Транскрипт сохраняется как отдельный Note в Kommo с тегом «Транскрипт RingCentral» — отдельно от Note со ссылкой на запись. Аналогичный подход используется при интеграции Kommo с Fireflies.ai.
Маршрутизация сделок после звонка
Дополнительная возможность: автоматически переназначать сделку или менять этап воронки в зависимости от исхода звонка.
CALL_RESULT_ACTIONS = {
'Accepted': None, # звонок принят - ничего не меняем
'No Answer': 'schedule_followup', # перезвонить через час
'Busy': 'schedule_followup',
'Voicemail': 'send_followup_email'
}
def handle_call_outcome(deal_id: int, result: str):
action = CALL_RESULT_ACTIONS.get(result)
if action == 'schedule_followup':
create_kommo_task(
deal_id,
f'Перезвонить - клиент не ответил ({result})',
due_in_minutes=60
)
Реальный кейс
B2B-компания (EU, SaaS, 8 продавцов, 80–100 исходящих звонков в день через RingCentral + Kommo):
- До: записи звонков существовали только в RingCentral. Менеджер после звонка вручную вносил итог в Kommo. 30–40% звонков не логировались — менеджеры «забывали». Sales Director слушал записи в RingCentral, не имея контекста CRM рядом.
- После: каждый завершённый звонок -> Note в Kommo с записью и результатом за 90 секунд. Итог «No Answer» -> автоматическая задача на перезвон через час. Sales Director ревьюит звонки прямо из карточки сделки.
- Дополнительно: при передаче сделки новому менеджеру тот сразу видит в таймлайне записи последних 5 звонков — контекст не теряется.
Для кого актуально
- Команды, использующие RingCentral как корпоративную телефонию и Kommo как CRM
- 20+ звонков в день — ручное логирование становится нерентабельным
- Требуется история разговоров в карточке сделки: для передачи клиента, онбординга, Customer Success
- Нативная интеграция установлена, но записей в CRM нет
Часто задаваемые вопросы
Чем JWT-авторизация RingCentral отличается от OAuth?
JWT (RFC 7523) — server-to-server поток без участия пользователя. JWT credential создаётся в Developer Console и позволяет получить access_token для доступа к данным аккаунта. OAuth Authorization Code используется когда пользователь должен сам авторизовать доступ (multi-tenant SaaS). Для серверной интеграции с Kommo — JWT.
Какие разрешения нужны для доступа к записям?
Два API permissions обязательны: ReadCallLog для доступа к журналу звонков и ReadCallRecording для скачивания аудио. Задаются в настройках приложения в RingCentral Developer Console. Без них /recording/{id}/content вернёт 403.
Запись появляется сразу после окончания звонка?
Нет. RingCentral обрабатывает запись асинхронно — обычно 30–90 секунд. Если запросить call-log сразу после события Disconnected, поле recording.id будет пустым. Рекомендуется задержка 60 секунд или polling с проверкой раз в 30 секунд.
Нужен ли Premium-тариф RingCentral для API?
Доступ к REST API доступен на Premium и Ultimate тарифах. На Standard тарифе API ограничен. Запись разговоров также требует Premium+. Перед внедрением проверьте текущий тариф: Settings -> Billing в RingCentral Admin Portal.
Как связать звонок с нужной сделкой если у контакта несколько открытых сделок?
Логика: искать активную сделку в статусах кроме Won/Lost. Если несколько — выбирать последнюю по дате обновления. Или добавить кастомное поле «основной номер ответственного» в сделку и матчить по нему.
Итого
- Нативная интеграция Kommo + RingCentral: click-to-call и базовый лог. Записей и транскриптов в CRM нет
- RingCentral REST API: JWT auth, event filter
/account/~/telephony/sessions - После
Disconnected: call-log -> recording -> upload -> Note в Kommo + кастомные поля - Подписка webhook истекает через 7 дней — нужно автообновление
- Задержка 60 сек перед запросом recording (асинхронная обработка)
- Типовой срок разработки — 1–2 недели
Если у вас RingCentral и Kommo и записи звонков не появляются в карточках — опишите текущую конфигурацию. Exceltic.dev настроит кастомную интеграцию IP-телефонии с полным логированием разговоров.