Kommo + Aircall: автоматическое сохранение звонков и заметок в карточку сделки

Kommo + Aircall: автоматическое сохранение звонков и заметок в карточку сделки

Aircall — облачная телефония, популярная в EU и US-рынках, с полноценным REST API и webhook’ами на каждое событие звонка. Из коробки Aircall интегрируется с HubSpot, Salesforce, Intercom — но не с Kommo. Кастомная интеграция строится через Aircall Public API: входящий звонок -> создание или обновление контакта и сделки в Kommo -> после звонка запись разговора и заметки агента автоматически появляются в карточке.

Что даёт интеграция Kommo + Aircall

Без интеграции:
— Агент звонит из Aircall, после звонка вручную открывает Kommo
— Вводит результат звонка как Note
— Прикрепляет ссылку на запись из Aircall — вручную
— Обновляет этап сделки — вручную

С интеграцией:
— Входящий звонок от номера в Kommo -> карточка открывается автоматически
— Звонок завершён -> Note с длительностью, результатом и ссылкой на запись создаётся автоматически
— Агент добавил заметку в Aircall -> синхронизируется в Kommo
— Пропущенный звонок -> Task для менеджера с напоминанием перезвонить

Что синхронизируется

Aircall -> Kommo:
call.ended -> Note на сделке: дата, длительность, результат (answered/voicemail/missed)
— Ссылка на аудиозапись -> кастомное поле или Note
call.commented -> заметка агента из Aircall -> Note в Kommo
call.tagged -> теги звонка -> теги или кастомное поле сделки
— Пропущенный звонок -> Task «Перезвонить» с дедлайном

Kommo -> Aircall:
— Создание/обновление Contact в Aircall при изменении контакта в Kommo
— Номер телефона клиента -> Contact в Aircall для определения входящих

Архитектура

Aircall Webhook: call.created (входящий звонок)
  ↓ Backend
  1. Искать контакт по номеру: GET /api/v4/contacts
     params: filter[phone]={caller_number}
     -> найден: получить связанную сделку
     -> не найден: создать сделку на первом этапе
  2. Сохранить aircall_call_id -> кастомное поле сделки
  3. (опционально) Отправить pop-up агенту с данными клиента

Aircall Webhook: call.ended
  ↓ Backend
  1. Получить call_id из payload
  2. Aircall API: GET /v1/calls/{call_id}
     -> длительность, статус, ссылка на запись, user_id агента
  3. Найти deal_id по aircall_call_id в хранилище
  4. Kommo: POST /leads/{deal_id}/notes
     -> Note с результатом: длительность, статус, ссылка на запись
  5. Если missed -> Kommo: POST /tasks
     -> задача «Перезвонить» с дедлайном +2 часа

Aircall Webhook: call.commented
  ↓ Backend
  1. Получить comment и call_id
  2. Найти deal_id
  3. Kommo: POST /leads/{deal_id}/notes
     -> заметка агента из Aircall

Aircall REST API: ключевые запросы

Base URL: https://api.aircall.io/v1/. Аутентификация: Basic Auth (api_id:api_token) или OAuth 2.0.

Получение деталей звонка:

import requests
from requests.auth import HTTPBasicAuth

AIRCALL_ID = 'your_api_id'
AIRCALL_TOKEN = 'your_api_token'
AUTH = HTTPBasicAuth(AIRCALL_ID, AIRCALL_TOKEN)

def get_call_details(call_id: int) -> dict:
    resp = requests.get(
        f'https://api.aircall.io/v1/calls/{call_id}',
        auth=AUTH
    )
    call = resp.json()['call']
    return {
        'duration': call.get('duration'),               # секунды
        'status': call.get('status'),                   # answered, missed, voicemail
        'recording': call.get('recording'),              # URL аудио
        'user_id': call.get('user', {}).get('id'),
        'user_name': call.get('user', {}).get('name'),
        'started_at': call.get('started_at'),
        'tags': [t['name'] for t in call.get('tags', [])]
    }

Создание Note в Kommo с данными звонка:

import requests
from datetime import datetime

def create_call_note(deal_id: int, call: dict, kommo_token: str):
    duration_min = call['duration'] // 60
    duration_sec = call['duration'] % 60
    status_ru = {'answered': 'Состоялся', 'missed': 'Пропущен',
                 'voicemail': 'Голосовая почта'}.get(call['status'], call['status'])

    note_text = (
        f'📞 Звонок {status_ru}\n'
        f'Длительность: {duration_min}:{duration_sec:02d}\n'
        f'Агент: {call["user_name"]}\n'
    )
    if call.get('recording'):
        note_text += f'Запись: {call["recording"]}\n'
    if call.get('tags'):
        note_text += f'Теги: {', '.join(call['tags'])}'

    requests.post(
        f'https://{KOMMO_DOMAIN}.kommo.com/api/v4/leads/{deal_id}/notes',
        headers={'Authorization': f'Bearer {kommo_token}'},
        json=[{
            'note_type': 'common',
            'params': {'text': note_text}
        }]
    )

Обработка webhook’ов:

from flask import Flask, request

app = Flask(__name__)

@app.route('/webhooks/aircall', methods=['POST'])
def aircall_webhook():
    data = request.json
    event = data.get('event')
    call_id = data.get('data', {}).get('id')

    if event == 'call.ended':
        call = get_call_details(call_id)
        deal_id = get_deal_by_call_id(call_id)  # из вашего хранилища

        if deal_id:
            create_call_note(deal_id, call, KOMMO_TOKEN)
            if call['status'] == 'missed':
                create_kommo_task(deal_id, 'Перезвонить клиенту', KOMMO_TOKEN)

    elif event == 'call.commented':
        comment = data.get('data', {}).get('comment', '')
        deal_id = get_deal_by_call_id(call_id)
        if deal_id and comment:
            create_simple_note(deal_id, f'Заметка по звонку: {comment}', KOMMO_TOKEN)

    return '', 200

Определение звонящего по номеру телефона

При входящем звонке (call.created) нужно быстро найти контакт в Kommo:

def find_kommo_contact_by_phone(phone: str) -> dict | None:
    # Нормализовать номер (убрать +, пробелы)
    clean_phone = ''.join(filter(str.isdigit, phone))

    resp = requests.get(
        f'https://{KOMMO_DOMAIN}.kommo.com/api/v4/contacts',
        headers={'Authorization': f'Bearer {KOMMO_TOKEN}'},
        params={
            'query': clean_phone,
            'with': 'leads'
        }
    )
    contacts = resp.json().get('_embedded', {}).get('contacts', [])
    return contacts[0] if contacts else None

Если контакт найден — берём его активную сделку. Если нет — создаём новую сделку на первом этапе воронки.

Синхронизация контактов Kommo -> Aircall

Для корректного определения входящих Aircall должен знать телефоны клиентов из Kommo:

def upsert_aircall_contact(name: str, phone: str, email: str,
                           kommo_contact_id: int):
    # Поиск существующего контакта
    resp = requests.get(
        'https://api.aircall.io/v1/contacts',
        auth=AUTH,
        params={'phone_number': phone}
    )
    contacts = resp.json().get('contacts', [])

    payload = {
        'first_name': name.split()[0] if name else '',
        'last_name': ' '.join(name.split()[1:]) if len(name.split()) > 1 else '',
        'phone_numbers': [{'label': 'Work', 'value': phone}],
        'emails': [{'label': 'Work', 'value': email}] if email else []
    }

    if contacts:
        requests.put(f'https://api.aircall.io/v1/contacts/{contacts[0]['id']}',
                     auth=AUTH, json=payload)
    else:
        requests.post('https://api.aircall.io/v1/contacts',
                      auth=AUTH, json=payload)

Реальный кейс

SaaS-компания (EU-рынок, команда 8 агентов, 150–200 звонков в день):

  • До: агент после каждого звонка вручную открывал Kommo, писал Note, копировал ссылку на запись. 3–5 минут на каждый звонок — из 200 звонков это до 15 часов команды в неделю только на ведение CRM.
  • После: все данные звонка появляются в Kommo автоматически в течение 30 секунд после окончания разговора. Агент добавляет только заметку о результате — она тоже синхронизируется из Aircall.
  • Дополнительный эффект: руководитель видит сводку звонков прямо в Kommo — без переключения в Aircall. Пропущенные звонки превращаются в задачи автоматически, ни один не теряется.

Аналогичная интеграция реализована для Twilio и Kommo — там программная телефония через API, Aircall — готовое SaaS-решение для команд продаж.

Для кого актуально

  • Команда использует Aircall как основную телефонию
  • 50+ звонков в день — ручное ведение CRM нерентабельно
  • Нужна история звонков прямо в карточке клиента в Kommo
  • Важен контроль: руководитель должен видеть кто звонил, сколько, с каким результатом
  • Пропущенные звонки должны превращаться в задачи автоматически

Часто задаваемые вопросы

Есть ли нативная интеграция Aircall и Kommo?

Нативной интеграции нет — Aircall поддерживает нативные коннекторы для HubSpot, Salesforce, Pipedrive, Intercom. Для Kommo интеграция строится через Aircall Public API и Kommo Webhooks. Это 2–3 недели разработки, но результат полностью кастомный под логику вашей воронки.

Aircall API — Basic Auth или OAuth?

Оба варианта. Basic Auth с api_id:api_token — проще для серверных интеграций, подходит для большинства кейсов. OAuth 2.0 — если нужно чтобы каждый менеджер авторизовался индивидуально (действия от имени конкретного пользователя). Для интеграции с CRM — Basic Auth достаточен.

Как получить ссылку на запись звонка?

Через GET /v1/calls/{id} — поле recording содержит прямую ссылку на аудиофайл. Записи доступны только если запись включена в настройках номера Aircall. Ссылки временные (истекают через N дней) — лучше скачивать и хранить в собственном S3/R2.

Какие тарифы Aircall включают API?

API доступен на тарифе Professional ($50/пользователь/мес) и выше. Essential ($40/польз./мес) API не включает. Webhook’и доступны с Professional.

Итого

  • Aircall Webhooks: call.created, call.ended, call.commented, call.tagged — основа интеграции
  • Aircall API: GET /v1/calls/{id} для деталей звонка, POST /v1/contacts для синхронизации контактов
  • Kommo: Note с результатом звонка, Task при пропущенном, кастомные поля с метаданными
  • Типовой срок — 2 недели разработки + 1 неделя тестирования на реальных звонках

Если вы используете Aircall и Kommo — опишите вашу схему работы со звонками: что агенты сейчас делают вручную. Exceltic.dev спроектирует автоматический workflow и покроет все сценарии (входящий, исходящий, пропущенный, голосовая почта).

Ещё статьи

Все →