Kommo + Vonage: SMS и звонки из воронки продаж

Kommo + Vonage: SMS и звонки из воронки продаж

Vonage (приобретён Ericsson) - Communications API платформа для SMS, голосовых звонков и мессенджеров. Охват: 200+ стран, поддержка EU номеров (Германия, Нидерланды, Великобритания). Нативной интеграции с Kommo нет - строим через Vonage Messages API v1 и Voice API.

Что строим

SMS-сценарии:

  • При переходе сделки в стадию «Proposal Sent» -> SMS клиенту с напоминанием
  • Входящий SMS от клиента -> Note в Kommo + задача менеджеру

Voice-сценарии:

  • Исходящий звонок из Kommo -> Vonage Voice API -> запись разговора в Note

Аутентификация Vonage

Vonage использует два метода: API Key + Secret (для SMS) и JWT (для Voice API).

API Key + Secret - для Messages API:

import requests, base64

VONAGE_API_KEY    = "your_api_key"
VONAGE_API_SECRET = "your_api_secret"

# Messages API использует Basic Auth
credentials = base64.b64encode(f"{VONAGE_API_KEY}:{VONAGE_API_SECRET}".encode()).decode()
msg_headers = {
    "Authorization": f"Basic {credentials}",
    "Content-Type": "application/json",
}

JWT - для Voice API:

import jwt, time, uuid

VONAGE_APPLICATION_ID  = "your_app_id"
VONAGE_PRIVATE_KEY_PATH = "private.key"  # скачать из Vonage Dashboard

def generate_jwt() -> str:
    private_key = open(VONAGE_PRIVATE_KEY_PATH, "rb").read()
    payload = {
        "application_id": VONAGE_APPLICATION_ID,
        "iat": int(time.time()),
        "jti": str(uuid.uuid4()),
        "exp": int(time.time()) + 3600,
    }
    return jwt.encode(payload, private_key, algorithm="RS256")

Voice API требует RSA private key из Vonage Application. Messages API работает только с API Key + Secret.

Отправка SMS клиенту

def send_sms(to_number: str, text: str, from_number: str = "EXCELTIC") -> dict:
    """Send SMS via Vonage Messages API v1."""
    payload = {
        "from": from_number,     # alphanumeric sender или ваш Vonage номер
        "to":   to_number,       # формат E.164: +49301234567
        "channel": "sms",
        "message_type": "text",
        "text": text,
    }
    r = requests.post(
        "https://api.nexmo.com/v1/messages",
        headers=msg_headers,
        json=payload,
    )
    r.raise_for_status()
    return r.json()  # {"message_uuid": "..."}

Alphanumeric sender ID (например, EXCELTIC) не поддерживается в некоторых странах - в США необходим зарегистрированный 10DLC номер, в Германии - немецкий виртуальный номер.

Триггер из Kommo webhook:

from flask import Flask, request

app = Flask(__name__)

@app.route("/kommo/webhook", methods=["POST"])
def kommo_webhook():
    data = request.json
    if "leads" not in data:
        return "ok", 200

    for event_type in ["update"]:
        leads = data.get("leads", {}).get(event_type, [])
        for lead in leads:
            old_status = lead.get("old_status_id")
            new_status = lead.get("status_id")

            if new_status == PROPOSAL_STAGE_ID and old_status != PROPOSAL_STAGE_ID:
                contact_phone = get_kommo_contact_phone(lead["id"])
                if contact_phone:
                    deal_name = lead.get("name", "")
                    send_sms(
                        to_number=contact_phone,
                        text=f"Ваше предложение от Exceltic готово. Проверьте email или ответьте на это сообщение.",
                    )
    return "ok", 200

Входящие SMS - Note в Kommo

Vonage отправляет входящие SMS на ваш Inbound Webhook URL.

@app.route("/vonage/inbound-sms", methods=["POST", "GET"])
def inbound_sms():
    # Vonage отправляет GET или POST в зависимости от настройки
    data = request.values if request.method == "GET" else request.json or request.form

    from_number = data.get("msisdn", "")  # номер отправителя
    text        = data.get("text", "")
    message_id  = data.get("messageId", "")

    # Найти контакт по номеру телефона в Kommo
    contact = find_kommo_contact_by_phone(from_number)
    if contact:
        deal_id = get_active_deal(contact["id"])
        if deal_id:
            add_kommo_note(
                deal_id=deal_id,
                text=f"SMS от {from_number}: {text}",
                note_type="sms",
            )

    return "ok", 200

Важно: Vonage ждёт HTTP 200 в ответ на входящий SMS. Если сервер отвечает ошибкой - Vonage делает повторные попытки до 72 часов.

Исходящий звонок через Voice API

NCCO_BASE_URL = "https://your-service.com"  # публичный URL для NCCO

def initiate_call(to_number: str, from_number: str, deal_id: int) -> str:
    """Start outbound call. Returns call UUID."""
    payload = {
        "to": [{"type": "phone", "number": to_number}],
        "from": {"type": "phone", "number": from_number},
        "answer_url": [f"{NCCO_BASE_URL}/vonage/ncco/{deal_id}"],
        "event_url":  [f"{NCCO_BASE_URL}/vonage/call-events/{deal_id}"],
        "record": True,
        "recording_channels": "split",  # отдельные дорожки для агента и клиента
    }
    r = requests.post(
        "https://api.nexmo.com/v1/calls",
        headers={"Authorization": f"Bearer {generate_jwt()}", "Content-Type": "application/json"},
        json=payload,
    )
    r.raise_for_status()
    return r.json()["uuid"]

@app.route("/vonage/ncco/<int:deal_id>")
def ncco(deal_id: int):
    """Vonage Call Control Object - инструкции для звонка."""
    return jsonify([
        {"action": "talk", "text": "Соединяю с менеджером Exceltic."},
        {"action": "connect", "from": VONAGE_FROM_NUMBER, "endpoint": [
            {"type": "phone", "number": AGENT_NUMBER}
        ]},
        {"action": "record", "eventUrl": [f"{NCCO_BASE_URL}/vonage/recording/{deal_id}"]},
    ])

Обработка события записи:

@app.route("/vonage/recording/<int:deal_id>", methods=["POST"])
def call_recording(deal_id: int):
    data = request.json
    recording_url = data.get("recording_url", "")
    duration_sec  = data.get("duration", 0)

    note = f"Vonage звонок. Длительность: {duration_sec}s. Запись: {recording_url}"
    add_kommo_note(deal_id, note)
    return "ok", 200

Запись звонка хранится на серверах Vonage 30 дней. URL доступен сразу после окончания звонка - авторизация через тот же JWT.

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

B2B-дистрибьютор в Нидерландах использовал email для первичного контакта, но response rate составлял 18%. После добавления SMS-напоминания при отправке предложения:

  • Response rate вырос до 34% за первые 2 недели
  • Среднее время ответа клиента сократилось с 2.3 дня до 14 часов
  • Входящие SMS от клиентов появляются в Kommo без ручного копирования

В типовом проекте настройка занимает 3-5 рабочих дней включая тестирование EU-номеров.

Для кого подходит

Компании с EU-клиентами, которые уже используют или рассматривают SMS как канал коммуникации. Vonage особенно полезен для команд в DACH и Benelux - регистрация немецких и нидерландских номеров проходит через Vonage без сложных местных процедур.

Для IP-телефонии с записью разговоров - см. также Kommo + CloudTalk и Kommo + RingCentral.

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

Можно ли отправлять WhatsApp через Vonage?

Да. Vonage Messages API поддерживает WhatsApp Business как канал. Меняете "channel": "sms" на "channel": "whatsapp" и передаёте WhatsApp номер. Требуется WhatsApp Business Account и одобренный template для исходящих сообщений вне 24-часового окна.

Как работает alphanumeric sender ID в Европе?

В большинстве стран EU alphanumeric sender (например, название компании вместо номера) разрешён для исходящих SMS. Исключения: Франция, Финляндия, некоторые балтийские страны - там нужен зарегистрированный номер. Vonage автоматически фолбечится на числовой номер если alphanumeric не поддерживается в стране получателя.

Чем Vonage отличается от Twilio?

API схожи, но есть различия: Vonage SMS API использует msisdn вместо from/to, аутентификация разделена (API Key+Secret для Messages, JWT для Voice). Twilio имеет более широкую документацию и экосистему. Vonage лучше по покрытию в DACH и Nordics для SMS delivery rates.

Как обеспечить GDPR при хранении SMS?

SMS-контент логируется в Kommo как Note - подпадает под GDPR как персональные данные. Настройте retention policy в Kommo: по умолчанию Notes хранятся бессрочно. Vonage не хранит содержимое SMS после доставки. Логи delivery report хранятся 72 часа.

Итог

Интеграция Kommo + Vonage покрывает SMS и голосовые звонки в едином стеке:

  • Messages API: Basic Auth, alphanumeric sender, двусторонний SMS
  • Voice API: JWT с RSA private key, NCCO для управления звонком, запись с split-дорожками
  • Входящие SMS: webhook 200 OK в течение 72 часов повтор

Если ваша команда работает с EU-клиентами и SMS нужен как инструмент коммуникации - опишите задачу Exceltic.dev. Настроим интеграцию под ваш стек и набор номеров.

Ещё статьи

Все →