Kommo + Smartsheet: автоматическое создание проектов из выигранных сделок
Smartsheet — enterprise work management платформа которая сочетает привычный интерфейс электронных таблиц с возможностями project management: Gantt-диаграммы, управление ресурсами, автоматизации, отчётность и интеграции. Популярна в enterprise где команды привыкли к Excel, но нуждаются в коллаборации и трекинге прогресса. В отличие от Jira или Asana, Smartsheet ближе к таблице-проекту — незаменима там где данные проекта нужно видеть в табличном виде и экспортировать в Excel. Без интеграции с Kommo Won данные сделки переносятся в Smartsheet вручную — 15–20 минут с высоким риском ошибок.
Smartsheet vs Jira vs Asana для команд внедрения
| Параметр | Smartsheet | Jira | Asana |
|---|---|---|---|
| Целевая аудитория | Enterprise non-tech | Tech команды | Mixed teams |
| Табличный интерфейс | Да (основной) | Нет | Нет |
| Gantt | Встроенный | Plugin | Встроенный |
| Ресурсное планирование | Да | Ограниченно | Да (Business+) |
| Подходит для | Operations, PMO, construction | Разработка | Маркетинг, продукт |
Smartsheet выбирают компании где PM-команда работает в таблицах, а не в канбан-досках — professional services, строительство, enterprise IT.
Архитектура: что синхронизируется
Kommo -> Smartsheet:
— Won -> создать новую строку в Sheet проекта (название, клиент, сумма, PM, даты)
— Won -> создать дочерние строки (checklist задач) из стандартного шаблона
Smartsheet -> Kommo:
— Изменение статуса строки (In Progress -> Complete) -> Note в сделку
— Webhook на ячейку «Дата сдачи» -> Task в Kommo за 7 дней до дедлайна
Smartsheet REST API: создание строки в Sheet
Base URL: https://api.smartsheet.com/2.0. Аутентификация: Authorization: Bearer {token} (Personal Access Token из Smartsheet -> Account -> Apps & Integrations -> API Access -> Generate new access token).
import requests
SS_TOKEN = "your_personal_access_token"
SS_BASE = "https://api.smartsheet.com/2.0"
SS_HEADERS = {
"Authorization": f"Bearer {SS_TOKEN}",
"Content-Type": "application/json",
}
SS_SHEET_ID = "your_sheet_id" # из URL sheet: smartsheet.com/sheets/{ID}
def get_sheet_columns(sheet_id: str) -> dict:
# Получить маппинг column title -> column id
resp = requests.get(
f"{SS_BASE}/sheets/{sheet_id}",
headers=SS_HEADERS,
)
resp.raise_for_status()
cols = resp.json().get("columns", [])
return {col["title"]: col["id"] for col in cols}
def add_row_to_sheet(sheet_id: str, col_map: dict,
row_data: dict, parent_row_id: int = None) -> dict:
cells = [
{"columnId": col_map[key], "value": value}
for key, value in row_data.items()
if key in col_map
]
row = {"cells": cells, "toBottom": True}
if parent_row_id:
row["parentId"] = parent_row_id
resp = requests.post(
f"{SS_BASE}/sheets/{sheet_id}/rows",
headers=SS_HEADERS,
json={"rows": [row]},
)
resp.raise_for_status()
return resp.json()
# Стандартный checklist задач после Won
ONBOARDING_TASKS = [
"Kickoff call с клиентом",
"Сбор требований",
"Настройка окружения",
"Первая поставка",
"UAT (приёмочное тестирование)",
"Go-live",
"Финальная документация",
]
def on_kommo_deal_won(lead: dict, contact: dict):
company = get_custom_field(lead, COMPANY_FIELD_ID) or contact.get("name", "")
manager = get_custom_field(lead, PM_FIELD_ID) or ""
value = lead.get("price", 0)
col_map = get_sheet_columns(SS_SHEET_ID)
row_data = {
"Project Name": f"{company} - {lead.get('name', '')}",
"Client": company,
"Deal Value": value,
"PM": manager,
"Status": "Not Started",
"Start Date": "",
"CRM Deal ID": str(lead["id"]),
}
result = add_row_to_sheet(SS_SHEET_ID, col_map, row_data)
parent_id = result["result"][0]["id"]
for task in ONBOARDING_TASKS:
add_row_to_sheet(SS_SHEET_ID, col_map,
{"Project Name": task, "Status": "Not Started"},
parent_row_id=parent_id)
sheet_url = f"https://app.smartsheet.com/sheets/{SS_SHEET_ID}"
save_to_kommo_deal(lead["id"], {"smartsheet_row_id": parent_id})
create_kommo_note(
lead["id"],
f"Smartsheet: проект создан, {len(ONBOARDING_TASKS)} задач -> {sheet_url}",
)
Webhook: Smartsheet -> Kommo
Smartsheet поддерживает webhooks на изменение ячеек. Настройка: POST /webhooks с callbackUrl и scopeObjectId (Sheet ID).
def create_smartsheet_webhook(sheet_id: str, callback_url: str) -> dict:
payload = {
"name": "Kommo sync",
"callbackUrl": callback_url,
"scope": "sheet",
"scopeObjectId": int(sheet_id),
"events": ["*.*"],
"version": 1,
}
resp = requests.post(
f"{SS_BASE}/webhooks",
headers=SS_HEADERS,
json=payload,
)
resp.raise_for_status()
return resp.json()
@app.route("/webhooks/smartsheet", methods=["POST"])
def smartsheet_webhook():
# Smartsheet шлёт challenge при первой настройке
challenge = request.headers.get("Smartsheet-Hook-Challenge")
if challenge:
return jsonify({"smartsheetHookResponse": challenge})
payload = request.json
events = payload.get("events", [])
for event in events:
if event.get("objectType") != "cell":
continue
row_id = event.get("rowId")
col_id = event.get("columnId")
new_val = event.get("newValue", "")
lead_id = find_kommo_deal_by_smartsheet_row(row_id)
if not lead_id:
continue
col_name = get_column_name(SS_SHEET_ID, col_id)
if col_name == "Status" and new_val == "Complete":
create_kommo_note(lead_id, "Smartsheet: проект завершён")
elif col_name == "Status" and new_val == "In Progress":
create_kommo_note(lead_id, "Smartsheet: проект в работе")
elif col_name == "Due Date" and new_val:
schedule_kommo_task(lead_id,
"Smartsheet: дедлайн проекта через 7 дней - проверить статус",
due_days=7)
return "", 200
Шаблон проекта: автоматизация через Smartsheet
Smartsheet поддерживает автоматизации (Automations в UI): при изменении статуса строки -> отправить уведомление -> назначить нового ответственного. Для Kommo-интеграции важно: автоматизации Smartsheet работают независимо, webhook только информирует Kommo.
Для создания проекта из шаблона (template Sheet) вместо ручного создания строк:
def copy_sheet_as_template(template_sheet_id: str, new_name: str) -> dict:
# Создать копию template-листа как новый проект
resp = requests.post(
f"{SS_BASE}/sheets/{template_sheet_id}/copy",
headers=SS_HEADERS,
json={
"destinationType": "home",
"newName": new_name,
"include": ["data", "attachments", "automations"],
},
)
resp.raise_for_status()
return resp.json()
Реальный кейс
Professional services компания (US, 60 человек, Kommo + Smartsheet):
- До: Won -> project coordinator получает задание в Slack -> вручную создаёт строку в Smartsheet -> заполняет 12 полей из данных сделки -> создаёт 8 стандартных задач. 30–45 минут. Ошибки в сумме контракта (20% строк).
- После: Won -> Python webhook -> строка + 7 дочерних задач за 3 секунды. Данные из Kommo (клиент, сумма, PM) переносятся без участия человека.
- Дополнительно: «Complete» в Smartsheet -> Note в Kommo -> менеджер инициирует разговор о renewal. Задержка между завершением проекта и renewal conversation сократилась с 3 недель до 2 дней.
Для кого актуально
- Professional services и consulting где каждый Won — новый проект с чеклистом
- Enterprise компании где PM-команда работает в Smartsheet, продажи — в Kommo
- Строительство, IT-внедрения, agency — любой проектный бизнес с фиксированным набором этапов
- Компании где данные проекта нужно видеть в табличном формате и делать сводные отчёты
Часто задаваемые вопросы
Smartsheet Sheet vs Grid vs Project — что использовать для интеграции?
Для интеграции с Kommo через API тип листа не важен — работа идёт через универсальный endpoint POST /sheets/{id}/rows. Отличие только в настройках листа (Grid — чистая таблица, Project — с Gantt и зависимостями). Для project management с Gantt выбирать тип «Project» при создании Sheet в UI, API от этого не меняется.
Как получить Sheet ID для Smartsheet API?
Открыть нужный Sheet в браузере -> URL выглядит как https://app.smartsheet.com/sheets/XXXXXXXXXXXXXXXX -> последний сегмент — это Sheet ID (16 цифр). Или через API: GET /sheets возвращает список всех листов с их ID.
Smartsheet Column ID — как маппить поля?
GET /sheets/{id} возвращает полный Sheet включая массив columns с id, title, type. Функция get_sheet_columns() в примере выше создаёт словарь {title: id}. Column ID — число, оно не меняется при переименовании колонки. Лучше строить маппинг по ID, не по названию — на случай если команда переименует колонку в Smartsheet.
Можно ли создать проект из шаблона (template) Smartsheet через API?
Да, через POST /sheets/{templateId}/copy. Шаблон — обычный Sheet с примерными строками. При копировании через API создаётся новый Sheet с теми же колонками и (опционально) данными. После копирования — обновить нужные строки через PUT /sheets/{newSheetId}/rows.
Итого
- API: Bearer token (Personal Access Token), base URL
https://api.smartsheet.com/2.0 - Won ->
POST /sheets/{id}/rowsсоздаёт строку проекта + дочерние строки задач get_sheet_columns()— всегда строить маппинг по API, не хардкодить column ID- Webhook:
POST /webhooks-> challenge handshake -> события изменения ячеек -> Kommo Notes - Шаблон:
POST /sheets/{templateId}/copyсоздаёт новый Sheet из шаблона для каждого проекта
Если у вас Kommo и Smartsheet и Won требует создания проекта с чеклистом — опишите структуру листа и стандартный набор задач. Exceltic.dev настроит интеграцию с двусторонней синхронизацией.