Kommo + Height: modern project management from won deals

Kommo + Height: modern project management from won deals

Height is a modern task and project management tool aimed at engineering and product teams: AI automation of routine tasks, flexible workflows without rigid constraints, clean UX. Positioned as a Linear alternative for teams that need more flexibility than Linear but less overhead than Jira. There is no native Kommo integration — here is the correct architecture: Won -> automatic project and task creation in Height; task completion -> Note in Kommo.

Height vs Linear vs Asana for teams alongside CRM

ParameterHeightLinearAsana
AI task automationYes (native)PartialVia Rules
Target audienceEngineers + productEngineersAll teams
Workflow flexibilityHighMediumHigh
APIREST (OAuth 2.0)GraphQLREST
PriceFrom $6.99/user/moFrom $8/user/moFrom $10.99/user/mo
Native KommoNoNoNo

Height is chosen by tech teams where the delivery process is closely tied to sales: agencies, SaaS with custom client development, IT service companies.

Architecture: what gets synchronized

Kommo -> Height:
— Won -> create List (project) in Height with template tasks
— Budget/deadline change -> update Height project attributes
— Kommo Note -> Height task comment (for important client messages)

Height -> Kommo:
task.completed -> Note in Kommo: “Task ‘{name}’ completed”
list.completed (all tasks closed) -> stage change + Note: “Project completed”
task.created with flag -> Task in Kommo (for the sales manager)

Height REST API: authentication and basic requests

Height uses OAuth 2.0. For server-side integration: Personal Access Token from Height -> Settings -> API. Base URL: https://api.height.app.

import requests

HEIGHT_TOKEN = "your_height_access_token"
HEIGHT_BASE  = "https://api.height.app"
HEIGHT_HEADERS = {
    "Authorization": f"api-key {HEIGHT_TOKEN}",
    "Content-Type":  "application/json",
}

def get_height_workspace() -> dict:
    resp = requests.get(
        f"{HEIGHT_BASE}/workspace",
        headers=HEIGHT_HEADERS,
    )
    resp.raise_for_status()
    return resp.json()

def create_height_list(name: str, description: str = "",
                        color: str = "blue") -> dict:
    # Create List (project/task folder)
    payload = {
        "name":        name,
        "description": description,
        "color":       color,
        "type":        "list",
    }
    resp = requests.post(
        f"{HEIGHT_BASE}/lists",
        headers=HEIGHT_HEADERS,
        json=payload,
    )
    resp.raise_for_status()
    return resp.json()

def create_height_task(list_id: str, name: str,
                        description: str = "",
                        assignee_ids: list = None,
                        due_at: str = "") -> dict:
    # due_at format: "2025-12-31T00:00:00.000Z"
    payload = {
        "name":        name,
        "description": description,
        "listIds":     [list_id],
        "assigneeIds": assignee_ids or [],
    }
    if due_at:
        payload["dueAt"] = due_at
    resp = requests.post(
        f"{HEIGHT_BASE}/tasks",
        headers=HEIGHT_HEADERS,
        json=payload,
    )
    resp.raise_for_status()
    return resp.json()

def add_task_comment(task_id: str, message: str) -> dict:
    resp = requests.post(
        f"{HEIGHT_BASE}/activities",
        headers=HEIGHT_HEADERS,
        json={"taskId": task_id, "message": message, "type": "comment"},
    )
    resp.raise_for_status()
    return resp.json()

Won -> project creation in Height

DELIVERY_TEMPLATE = [
    {"name": "Kickoff meeting with client",       "days_offset": 3},
    {"name": "Technical specification (Spec)",    "days_offset": 7},
    {"name": "Design / prototype",                "days_offset": 14},
    {"name": "Development - iteration 1",         "days_offset": 28},
    {"name": "Testing and QA",                    "days_offset": 35},
    {"name": "Client delivery",                   "days_offset": 42},
]

from datetime import datetime, timezone, timedelta

def on_kommo_deal_won(lead: dict, contact: dict):
    deal_name  = lead.get("name", f"Deal #{lead['id']}")
    budget     = lead.get("price", 0)
    description = (
        f"Client: {contact.get('name', '')}\n"
        f"Budget: {budget}\n"
        f"Kommo deal ID: {lead['id']}"
    )

    height_list = create_height_list(
        name=f"[{deal_name}]",
        description=description,
        color="green",
    )
    list_id = height_list.get("id")

    now = datetime.now(timezone.utc)
    for tmpl in DELIVERY_TEMPLATE:
        due = (now + timedelta(days=tmpl["days_offset"])).strftime(
            "%Y-%m-%dT00:00:00.000Z"
        )
        create_height_task(
            list_id=list_id,
            name=tmpl["name"],
            due_at=due,
        )

    # Save height_list_id in Kommo
    save_to_kommo_deal(lead["id"], {"height_list_id": list_id})
    create_kommo_note(
        lead["id"],
        f"Height: project [{deal_name}] created with {len(DELIVERY_TEMPLATE)} tasks",
    )

Height Webhooks -> Kommo

Height supports webhooks via Settings -> Developer -> Webhooks.

@app.route("/webhooks/height", methods=["POST"])
def height_webhook():
    payload = request.json
    event   = payload.get("type", "")
    data    = payload.get("data", {})

    if event == "task.completed":
        task_name = data.get("task", {}).get("name", "")
        list_ids  = data.get("task", {}).get("listIds", [])

        for list_id in list_ids:
            lead_id = find_kommo_deal_by_custom_field("height_list_id", list_id)
            if lead_id:
                create_kommo_note(lead_id,
                    f"Height: task '{task_name}' completed")
                break

    elif event == "list.completed":
        list_id = data.get("list", {}).get("id", "")
        lead_id = find_kommo_deal_by_custom_field("height_list_id", list_id)
        if lead_id:
            create_kommo_note(lead_id, "Height: all project tasks completed")
            move_kommo_deal_to_stage(lead_id, DELIVERED_STAGE_ID)

    return "", 200

AI automation: Height + Kommo

Height embeds AI for automatic subtask creation from a task description. For the Kommo integration: when creating a project, pass a detailed description from the Kommo Note -> Height AI breaks it into subtasks automatically.

Real-world case

IT agency (EU, 12 people, Kommo + Height):

  • Before: Won -> manager manually created a project in Height, copied deal details, assigned tasks from a template. 30–40 minutes. If forgotten — the project started with a delay.
  • After: Won -> Python webhook -> Height project + 6 tasks with deadlines in 3 seconds. task.completed -> Note in Kommo -> manager sees progress without logging into Height.
  • Additionally: when the deal budget changes in Kommo -> automatic update of the project description in Height via PATCH /lists/{id}.

Who this is relevant for

  • IT agencies and SaaS with custom development: Won -> delivery kickoff
  • Product companies where sales and engineering use different tools
  • Teams that moved from Asana/Trello to Height and want to maintain the Kommo connection
  • Sales managers who need visibility of project progress in CRM without entering the project tool

Frequently asked questions

Height vs Linear — when to choose Height for Kommo integration?

Linear is aimed at software engineers with a strict Issue-based structure. Height is more flexible — supports arbitrary task lists, color labels, any workflow. For agencies and service companies where a project is a set of client tasks, Height is more convenient. For product companies with a strict sprint process — Linear is a better fit.

Does Height support project templates (Templates)?

Yes. Height -> Templates allows creating a List template with tasks. In the API: POST /lists with a templateId parameter creates a List from the template. For the Kommo integration, this is more convenient than creating tasks from the DELIVERY_TEMPLATE array — the template is edited in the Height UI without code changes in the integration.

How do you synchronize assignees between Kommo and Height?

Kommo deals have responsible_user_id. Height has assigneeIds. Mapping: {kommo_user_id: height_user_id} stored in the config. Get list of Height users: GET /users. Get list of Kommo users: GET /users in Kommo API. Mapping by email match — if emails match, auto-assign.

Is Height webhook verification needed?

Height sends the X-Height-Signature header with an HMAC-SHA256 signature (key from webhook settings). Verification is recommended: hmac.new(secret.encode(), request.data, sha256).hexdigest(). Without verification, the endpoint is open to spoofing — anyone can send a fake task.completed event.

Summary

  • API: api-key {token} header, base URL https://api.height.app
  • Won -> POST /lists (project) + POST /tasks with task template and deadlines
  • Webhook -> task.completed / list.completed -> Note in Kommo + stage change
  • Templates: use Height templates via templateId instead of a hardcoded task array
  • User mapping: by email between Kommo responsible_user and Height assignee

If you have an agency or SaaS with Kommo and want to automatically start a project in Height after Won — describe your task template. Exceltic.dev will set up the integration in 1–2 business days.

More articles

All →