Kommo + Gong: AI call analysis and transcripts in the deal card

Kommo + Gong: AI call analysis and transcripts in the deal card

Gong is a revenue intelligence platform: it records manager calls, builds transcripts, highlights key topics (objections, competitors, budget, next step), and analyzes talk/listen ratio. Without Kommo integration, Gong data lives separately — the manager must manually transfer call outcomes to CRM. With integration, every completed Gong call automatically appears in the deal card: recording link, AI summary, key topics.

Why integrate Gong with Kommo

A typical problem: the manager conducted a call, the client mentioned a competitor and a budget constraint. Three days later — the next call with a different manager. Without a CRM record, context is lost. With Gong + Kommo, call history is in the deal: every conversation, its summary, identified objections — all in one place.

Comparison with other tools from this blog:
Kommo + Fireflies.ai — meeting transcripts, cheaper, no revenue intelligence
Kommo + TL;DV — meeting timestamps, focused on video
Kommo + Gong — enterprise revenue intelligence: AI coaching, forecasting, analysis of won/lost deals

What gets synchronized

Gong -> Kommo:
— Call completed -> Note with AI summary, recording link, duration
— Key conversation topics (competitors, objections, next step) -> Note
— Manager talk ratio -> Note (for coaching)
— Update “Last Contact” field in deal

Kommo -> Gong:
— Won -> add won_customer tag to contact in Gong
— Deal data (plan, amount) -> custom call fields in Gong (for won deal analysis)

Gong API: key requests

Base URL: https://api.gong.io/v2.
Authentication: Basic Auth — access_key:access_key_secret (Base64).
Credentials: Gong Settings -> Company Settings -> API.

import requests
from requests.auth import HTTPBasicAuth

GONG_ACCESS_KEY = "your_access_key"
GONG_ACCESS_SECRET = "your_access_key_secret"
GONG_BASE_URL = "https://api.gong.io/v2"
GONG_AUTH = HTTPBasicAuth(GONG_ACCESS_KEY, GONG_ACCESS_SECRET)

def get_call(call_id: str) -> dict:
    resp = requests.get(
        f"{GONG_BASE_URL}/calls/{call_id}",
        auth=GONG_AUTH
    )
    resp.raise_for_status()
    return resp.json()

def get_call_transcript(call_id: str) -> list:
    # Returns array of utterances with text and speaker
    resp = requests.get(
        f"{GONG_BASE_URL}/calls/{call_id}/transcript",
        auth=GONG_AUTH
    )
    resp.raise_for_status()
    return resp.json().get("transcript", [])

def list_calls(from_dt: str, to_dt: str, cursor: str = None) -> dict:
    # from_dt, to_dt: ISO 8601. Use for polling new calls
    params = {"fromDateTime": from_dt, "toDateTime": to_dt}
    if cursor:
        params["cursor"] = cursor
    resp = requests.get(
        f"{GONG_BASE_URL}/calls",
        auth=GONG_AUTH,
        params=params
    )
    resp.raise_for_status()
    return resp.json()

def get_call_highlights(call_id: str) -> dict:
    # AI-highlighted key moments (key points, next steps, risks)
    resp = requests.get(
        f"{GONG_BASE_URL}/calls/{call_id}/highlights",
        auth=GONG_AUTH
    )
    resp.raise_for_status()
    return resp.json()

Main synchronization logic (polling or webhook):

from datetime import datetime, timezone, timedelta

def find_kommo_deal_by_email(email: str) -> int | None:
    # Find deal by call participant email
    # Search contact by email in Kommo, then find their open deal
    ...

def build_call_note(call: dict, highlights: dict) -> str:
    duration_sec = call.get("duration", 0)
    duration = f"{duration_sec // 60} min {duration_sec % 60} sec"
    url = call.get("url", "")
    title = call.get("title", "Call")
    started = call.get("started", "")[:10]

    # Talk ratio from metaData
    talk_ratio = call.get("metaData", {}).get("talkRatio", {})
    manager_ratio = round(talk_ratio.get("speakerRatio", {}).get("0", 0) * 100)

    lines = [
        f"Gong: {title} ({started}), {duration}",
        f"Recording: {url}",
        f"Manager spoke: {manager_ratio}% of the time",
    ]

    # Key points from AI
    key_points = highlights.get("keyPoints", [])
    if key_points:
        lines.append("\nKey moments:")
        for kp in key_points[:5]:
            lines.append(f"  • {kp.get('text', '')}")

    next_steps = highlights.get("nextSteps", [])
    if next_steps:
        lines.append("\nNext steps:")
        for ns in next_steps[:3]:
            lines.append(f"  -> {ns.get('text', '')}")

    return "\n".join(lines)

def sync_new_calls():
    # Process calls from the last hour, call via cron every 30 min
    now = datetime.now(timezone.utc)
    from_dt = (now - timedelta(hours=1)).isoformat()
    to_dt = now.isoformat()

    result = list_calls(from_dt, to_dt)
    calls = result.get("calls", [])

    for call in calls:
        call_id = call.get("id")
        parties = call.get("parties", [])

        # Find external participant email (client)
        client_email = None
        for p in parties:
            if p.get("speakerType") == "External":
                client_email = p.get("emailAddress")
                break

        if not client_email:
            continue

        deal_id = find_kommo_deal_by_email(client_email)
        if not deal_id:
            continue

        # Check that this call has not been added before
        if call_already_synced(deal_id, call_id):
            continue

        full_call = get_call(call_id)
        highlights = {}
        try:
            highlights = get_call_highlights(call_id)
        except Exception:
            pass

        note = build_call_note(full_call, highlights)
        create_kommo_note(deal_id, note)
        mark_call_synced(deal_id, call_id)

Webhook (if available on your Gong plan):

@app.route("/webhooks/gong", methods=["POST"])
def gong_webhook():
    # Gong Enterprise: webhooks for call.completed, deal.updated
    payload = request.json
    event = payload.get("event")

    if event == "call.completed":
        call_id = payload.get("callId")
        # Async: process via queue (Gong requires response < 3 sec)
        enqueue_call_sync(call_id)

    return "", 200

Gong API: important limitations

  • Rate limits: 100 requests per minute per organization
  • Webhook: available only on the Enterprise plan. On Standard — polling only via GET /calls
  • Transcript lag: AI transcript is ready 1–4 hours after the call (not instant)
  • Data retention: depends on Gong plan, typically 12–24 months of recordings

This is why the real architecture for most teams is cron polling every 30 minutes instead of a webhook.

Real-world case

B2B SaaS (US + EU, enterprise sales, 15–20 calls per day, Kommo + Gong):

  • Before: after each call, the manager manually wrote outcomes in a Note. Took 5–10 minutes. 30% of calls had no Notes at all: “forgot” or “will write later.” The next call — without context from the previous one.
  • After: sync_new_calls() every 30 minutes -> Note with AI summary, link, and next steps. 100% of calls in CRM. The manager comes to the next call with Gong context.
  • Additionally: Gong analysis of won deals showed: managers with a talk ratio < 45% close 28% more often. Data is passed to Kommo -> the head of sales sees the call metric + outcome in the deal card.

Who this is relevant for

  • Enterprise sales teams with 10+ calls per day
  • Companies already using Gong — need to add the CRM layer
  • Head of sales who wants to see communication history without switching out of Kommo
  • Teams with a long deal cycle (60–180 days) — context is critical

Frequently asked questions

Is the Gong API available on all plans?

The Gong API is available on Business and Enterprise plans. On Starter — no API access. Before integrating, check the plan and request API credentials from your Gong account manager.

How do I find the right Kommo deal from Gong data?

Gong stores call participant emails. Search for a Contact in Kommo by email (GET /contacts?query={email}), then find an open deal by contact_id (GET /leads?contact_id={id}). If the email does not match (different format) — matching by phone number is possible.

Is the transcript available via API?

Yes, via GET /calls/{id}/transcript. Returns an array of utterances: speaker, text, start/end time. The full call text can be built for storage in CRM. Note: the transcript appears with a 1–4 hour delay after the call ends.

Does Gong send webhooks or is polling only?

Webhooks (call.completed, deal.updated) — Enterprise plan. Business — polling only via GET /calls with fromDateTime/toDateTime. For most teams, polling every 15–30 minutes is an acceptable delay.

Summary

  • Gong API: Basic Auth (access_key:secret), https://api.gong.io/v2
  • Main flow: GET /calls -> GET /calls/{id} -> GET /calls/{id}/highlights -> Note in Kommo
  • Polling every 30 minutes — a working solution for Business plan without webhook
  • AI highlights: keyPoints, nextSteps, risks — structured content for Notes
  • Talk ratio from metaData — coaching metric in CRM

If you use Gong and Kommo and want to see AI call summaries in deal cards — describe your call structure and which data is critical to capture. Exceltic.dev will configure polling and highlight mapping.

More articles

All →