Aircall is a cloud telephony platform popular in EU and US markets, with a full REST API and webhooks for every call event. Out of the box, Aircall integrates with HubSpot, Salesforce, and Intercom — but not with Kommo. A custom integration is built via the Aircall Public API: an inbound call triggers creation or update of a contact and deal in Kommo, and after the call the recording and agent notes automatically appear in the deal card.
What the Kommo + Aircall integration provides
Without integration:
— Agent makes a call from Aircall, then manually opens Kommo
— Enters the call outcome as a Note
— Attaches the Aircall recording link — manually
— Updates the deal stage — manually
With integration:
— Inbound call from a number in Kommo -> deal card opens automatically
— Call ends -> Note with duration, outcome, and recording link created automatically
— Agent adds a note in Aircall -> synced to Kommo
— Missed call -> Task for manager with a callback reminder
What gets synced
Aircall -> Kommo:
— call.ended -> Note on the deal: date, duration, outcome (answered/voicemail/missed)
— Recording link -> custom field or Note
— call.commented -> agent note from Aircall -> Note in Kommo
— call.tagged -> call tags -> tags or custom deal field
— Missed call -> Task “Call back” with deadline
Kommo -> Aircall:
— Create/update Contact in Aircall when a Kommo contact changes
— Client phone number -> Contact in Aircall for inbound caller identification
Architecture
Aircall Webhook: call.created (inbound call)
↓ Backend
1. Search contact by phone: GET /api/v4/contacts
params: filter[phone]={caller_number}
-> found: retrieve linked deal
-> not found: create deal at first pipeline stage
2. Save aircall_call_id -> custom deal field
3. (optional) Push pop-up to agent with client data
Aircall Webhook: call.ended
↓ Backend
1. Get call_id from payload
2. Aircall API: GET /v1/calls/{call_id}
-> duration, status, recording link, agent user_id
3. Find deal_id by aircall_call_id from storage
4. Kommo: POST /leads/{deal_id}/notes
-> Note with result: duration, status, recording link
5. If missed -> Kommo: POST /tasks
-> task "Call back" with deadline +2 hours
Aircall Webhook: call.commented
↓ Backend
1. Get comment and call_id
2. Find deal_id
3. Kommo: POST /leads/{deal_id}/notes
-> agent note from Aircall
Aircall REST API: key requests
Base URL: https://api.aircall.io/v1/. Authentication: Basic Auth (api_id:api_token) or OAuth 2.0.
Retrieving call details:
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'), # seconds
'status': call.get('status'), # answered, missed, voicemail
'recording': call.get('recording'), # audio 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', [])]
}
Creating a Note in Kommo with call data:
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_label = {'answered': 'Answered', 'missed': 'Missed',
'voicemail': 'Voicemail'}.get(call['status'], call['status'])
note_text = (
f'📞 Call {status_label}\n'
f'Duration: {duration_min}:{duration_sec:02d}\n'
f'Agent: {call["user_name"]}\n'
)
if call.get('recording'):
note_text += f'Recording: {call["recording"]}\n'
if call.get('tags'):
note_text += f'Tags: {", ".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}
}]
)
Handling webhooks:
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) # from your storage
if deal_id:
create_call_note(deal_id, call, KOMMO_TOKEN)
if call['status'] == 'missed':
create_kommo_task(deal_id, 'Call the client back', 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'Call note: {comment}', KOMMO_TOKEN)
return '', 200
Identifying the caller by phone number
On an inbound call (call.created) you need to quickly find the contact in Kommo:
def find_kommo_contact_by_phone(phone: str) -> dict | None:
# Normalize the number (remove +, spaces)
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
If the contact is found — retrieve their active deal. If not — create a new deal at the first pipeline stage.
Syncing Kommo contacts to Aircall
For accurate inbound caller identification, Aircall needs to know client phone numbers from Kommo:
def upsert_aircall_contact(name: str, phone: str, email: str,
kommo_contact_id: int):
# Search for existing contact
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)
Real-world case study
SaaS company (EU market, 8 agents, 150–200 calls per day):
- Before: after each call, the agent manually opened Kommo, wrote a Note, and copied the recording link. 3–5 minutes per call — across 200 calls, that’s up to 15 hours of team time per week spent just on CRM maintenance.
- After: all call data appears in Kommo automatically within 30 seconds of the call ending. The agent only adds a note about the outcome — which also syncs from Aircall.
- Additional benefit: the team lead sees a call summary directly in Kommo without switching to Aircall. Missed calls automatically become tasks — none are lost.
A similar integration is available for Twilio and Kommo — that uses programmable telephony via API, while Aircall is a turnkey SaaS solution for sales teams.
Who benefits from this integration
- Team uses Aircall as their primary telephony
- 50+ calls per day — manual CRM maintenance is not cost-effective
- Full call history is needed directly in the Kommo client card
- Visibility matters: the manager needs to see who called, how often, and with what result
- Missed calls must automatically become tasks
Frequently asked questions
Is there a native Aircall and Kommo integration?
There is no native integration — Aircall supports native connectors for HubSpot, Salesforce, Pipedrive, and Intercom. For Kommo, integration is built via the Aircall Public API and Kommo Webhooks. This takes 2–3 weeks of development, but the result is fully customized to your pipeline logic.
Aircall API — Basic Auth or OAuth?
Both are available. Basic Auth with api_id:api_token is simpler for server-side integrations and suitable for most use cases. OAuth 2.0 is needed if each manager should authenticate individually (acting as a specific user). For CRM integration — Basic Auth is sufficient.
How to get the call recording link?
Via GET /v1/calls/{id} — the recording field contains a direct link to the audio file. Recordings are only available if recording is enabled in the Aircall number settings. Links are temporary (they expire after N days) — it’s better to download and store them in your own S3/R2.
Which Aircall plans include API access?
The API is available on the Professional plan ($50/user/month) and above. The Essential plan ($40/user/month) does not include API access. Webhooks are available from Professional.
Summary
- Aircall Webhooks:
call.created,call.ended,call.commented,call.tagged— the foundation of the integration - Aircall API:
GET /v1/calls/{id}for call details,POST /v1/contactsfor contact sync - Kommo: Note with call outcome, Task for missed calls, custom fields with metadata
- Typical timeline — 2 weeks development + 1 week testing on real calls
If you use Aircall and Kommo — describe your current call-handling workflow: what agents do manually today. Exceltic.dev will design an automated workflow covering all scenarios (inbound, outbound, missed, voicemail).