Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,33 @@
{
"extends": [
"../../../../.eslintrc.base.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {}
},
{
"files": [
"*.ts",
"*.tsx"
],
"rules": {}
},
{
"files": [
"*.js",
"*.jsx"
],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-kommo
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-kommo` to build the library.

View File

@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-kommo",
"version": "0.0.7"
}

View File

@@ -0,0 +1,60 @@
{
"name": "pieces-kommo",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/kommo/src",
"projectType": "library",
"release": {
"version": {
"currentVersionResolver": "git-tag",
"preserveLocalDependencyProtocols": false,
"manifestRootsToUpdate": [
"dist/{projectRoot}"
]
}
},
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/kommo",
"tsConfig": "packages/pieces/community/kommo/tsconfig.lib.json",
"packageJson": "packages/pieces/community/kommo/package.json",
"main": "packages/pieces/community/kommo/src/index.ts",
"assets": [
"packages/pieces/community/kommo/*.md"
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectRoot}"
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/kommo",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "Subdomain",
"Token": "Token",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nBitte folge [Long Live Token](https://developers.kommo.com/docs/long-lived-token) Anleitung zur Generierung von Token.\n\nIhr Kommo Konto Subdomain (z.B. \"mycompany\" wenn Ihre URL mycompany.kommo.com ist).\n\n",
"Find Lead": "Lead finden",
"Update Contact": "Kontakt aktualisieren",
"Create New Lead": "Neuen Lead erstellen",
"Update Lead": "Lead aktualisieren",
"Create New Contact": "Neuen Kontakt erstellen",
"Find Contact": "Kontakt finden",
"Find Company": "Firma finden",
"Custom API Call": "Eigener API-Aufruf",
"Finds an existing lead.": "Findet einen existierenden Blei.",
"Updates an existing contact.": "Aktualisiert einen bestehenden Kontakt.",
"Creates a new lead.": "Erstellt einen neuen Vorsprung.",
"Update existing lead info.": "Vorhandene Lead-Informationen aktualisieren.",
"Add a new contact.": "Neuen Kontakt hinzufügen.",
"Finds an existing contact.": "Findet einen bestehenden Kontakt.",
"Find an existing company.": "Finden Sie ein bestehendes Unternehmen.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Query": "Abfrage",
"Contact": "Kontakt",
"Full Name": "Voller Name",
"First Name": "Vorname",
"Last Name": "Nachname",
"Email": "E-Mail",
"Phone": "Telefon",
"Unique identified of a responsible user": "Einzigartig von einem verantwortlichen Benutzer identifiziert",
"Tags to Add": "Tags hinzufügen",
"Tags to Delete": "Zu löschende Tags",
"Lead Name": "Leadname",
"Price": "Preis",
"Pipeline": "Pipeline",
"Status": "Status",
"Loss Reason": "Verlustgrund",
"Lead": "Lead",
"Name": "Name",
"Method": "Methode",
"Headers": "Kopfzeilen",
"Query Parameters": "Abfrageparameter",
"Body": "Körper",
"Response is Binary ?": "Antwort ist binär?",
"No Error on Failure": "Kein Fehler bei Fehler",
"Timeout (in seconds)": "Timeout (in Sekunden)",
"Search query (Searches through the filled fields of the lead).": "Suchanfrage (Sucht durch die ausgefüllten Felder der Lead).",
"List of tag names or IDs to add.": "Liste der hinzuzufügenden Tagnamen oder IDs.",
"List of tag names or IDs to remove.": "Liste der zu löschenden Tag-Namen oder IDs.",
"List of tags to add.": "Liste der hinzuzufügenden Tags.",
"Search query (Searches through the filled fields of the contact).": "Suchanfrage (Sucht durch die ausgefüllten Felder des Kontaktes).",
"Search query (Searches through the filled fields of the company).": "Suchanfrage (Sucht nach den ausgefüllten Feldern des Unternehmens).",
"Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
"Enable for files like PDFs, images, etc..": "Aktivieren für Dateien wie PDFs, Bilder, etc..",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"Lead Status Changed": "Lead-Status geändert",
"New Contact Added": "Neuer Kontakt hinzugefügt",
"New Lead Created": "Neuer Lead erstellt",
"New Task Created": "Neue Aufgabe erstellt",
"Triggers when a lead status is changed.": "Wird ausgelöst, wenn ein Lead-Status geändert wird.",
"Triggers when a new contact is added.": "Wird ausgelöst, wenn ein neuer Kontakt hinzugefügt wird.",
"Triggers when a new lead is created.": "Wird ausgelöst, wenn ein neuer Lead erstellt wird.",
"Triggered when a new task is created.": "Wird ausgelöst, wenn eine neue Aufgabe erstellt wird."
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "Subdominio",
"Token": "Token",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n",
"Find Lead": "Buscar plomo",
"Update Contact": "Actualizar contacto",
"Create New Lead": "Crear nuevo plomo",
"Update Lead": "Actualizar plomo",
"Create New Contact": "Crear nuevo contacto",
"Find Contact": "Encontrar contacto",
"Find Company": "Buscar empresa",
"Custom API Call": "Llamada API personalizada",
"Finds an existing lead.": "Encuentra un plomo existente.",
"Updates an existing contact.": "Actualiza un contacto existente.",
"Creates a new lead.": "Crea un nuevo cliente potencial.",
"Update existing lead info.": "Actualizar información de plomo existente.",
"Add a new contact.": "Añadir un nuevo contacto.",
"Finds an existing contact.": "Encuentra un contacto existente.",
"Find an existing company.": "Encuentre una empresa existente.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Query": "Consulta",
"Contact": "Contacto",
"Full Name": "Nombre completo",
"First Name": "Nombre",
"Last Name": "Apellido",
"Email": "E-mail",
"Phone": "Teléfono",
"Unique identified of a responsible user": "Único identificado de un usuario responsable",
"Tags to Add": "Etiquetas a añadir",
"Tags to Delete": "Etiquetas a eliminar",
"Lead Name": "Nombre del jefe",
"Price": "Precio",
"Pipeline": "Pipeline",
"Status": "Estado",
"Loss Reason": "Razón de la pérdida",
"Lead": "Plomo",
"Name": "Nombre",
"Method": "Método",
"Headers": "Encabezados",
"Query Parameters": "Parámetros de consulta",
"Body": "Cuerpo",
"Response is Binary ?": "¿Respuesta es binaria?",
"No Error on Failure": "No hay ningún error en fallo",
"Timeout (in seconds)": "Tiempo de espera (en segundos)",
"Search query (Searches through the filled fields of the lead).": "Búsqueda (búsquedas a través de los campos rellenados del prospecto).",
"List of tag names or IDs to add.": "Lista de nombres de etiquetas o IDs a añadir.",
"List of tag names or IDs to remove.": "Lista de nombres de etiquetas o identificadores a eliminar.",
"List of tags to add.": "Lista de etiquetas a añadir.",
"Search query (Searches through the filled fields of the contact).": "Búsqueda (Búsqueda a través de los campos rellenados del contacto).",
"Search query (Searches through the filled fields of the company).": "Búsqueda (Búsqueda a través de los campos rellenados de la empresa).",
"Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
"Enable for files like PDFs, images, etc..": "Activar para archivos como PDFs, imágenes, etc.",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"Lead Status Changed": "Estado del plomo cambiado",
"New Contact Added": "Nuevo contacto añadido",
"New Lead Created": "Nuevo plomo creado",
"New Task Created": "Nueva tarea creada",
"Triggers when a lead status is changed.": "Dispara cuando se cambia el estado de un plomo.",
"Triggers when a new contact is added.": "Se activa cuando se añade un nuevo contacto.",
"Triggers when a new lead is created.": "Dispara cuando se crea un nuevo plomo.",
"Triggered when a new task is created.": "Se activa cuando se crea una nueva tarea."
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "Sous-domaine",
"Token": "Jeton",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n",
"Find Lead": "Trouver un prospect",
"Update Contact": "Mettre à jour le contact",
"Create New Lead": "Créer un nouveau prospect",
"Update Lead": "Mettre à jour le prospect",
"Create New Contact": "Créer un nouveau contact",
"Find Contact": "Trouver un contact",
"Find Company": "Trouver une entreprise",
"Custom API Call": "Appel API personnalisé",
"Finds an existing lead.": "Trouve un prospect existant.",
"Updates an existing contact.": "Met à jour un contact existant.",
"Creates a new lead.": "Crée un nouveau prospect.",
"Update existing lead info.": "Mettre à jour les informations de plomb existantes.",
"Add a new contact.": "Ajouter un nouveau contact.",
"Finds an existing contact.": "Trouve un contact existant.",
"Find an existing company.": "Trouver une société existante.",
"Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un point de terminaison spécifique",
"Query": "Requête",
"Contact": "Contacter",
"Full Name": "Nom complet",
"First Name": "First Name",
"Last Name": "Last Name",
"Email": "Courriel",
"Phone": "Téléphone",
"Unique identified of a responsible user": "Unique identifié d'un utilisateur responsable",
"Tags to Add": "Tags à ajouter",
"Tags to Delete": "Tags à supprimer",
"Lead Name": "Nom du prospect",
"Price": "Prix",
"Pipeline": "Pipeline",
"Status": "Statut",
"Loss Reason": "Raison de la perte",
"Lead": "Prospect",
"Name": "Nom",
"Method": "Méthode",
"Headers": "En-têtes",
"Query Parameters": "Paramètres de requête",
"Body": "Corps",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'attente (en secondes)",
"Search query (Searches through the filled fields of the lead).": "Requête de recherche (recherche dans les champs remplis du plomb).",
"List of tag names or IDs to add.": "Liste des noms de tags ou identifiants à ajouter.",
"List of tag names or IDs to remove.": "Liste des noms de tags ou identifiants à supprimer.",
"List of tags to add.": "Liste des tags à ajouter.",
"Search query (Searches through the filled fields of the contact).": "Requête de recherche (recherche dans les champs remplis du contact).",
"Search query (Searches through the filled fields of the company).": "Requête de recherche (recherche dans les champs remplis de l'entreprise).",
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
"GET": "OBTENIR",
"POST": "POSTER",
"PATCH": "PATCH",
"PUT": "EFFACER",
"DELETE": "SUPPRIMER",
"HEAD": "TÊTE",
"Lead Status Changed": "Statut du prospect modifié",
"New Contact Added": "Nouveau contact ajouté",
"New Lead Created": "Nouveau prospect créé",
"New Task Created": "Nouvelle tâche créée",
"Triggers when a lead status is changed.": "Déclenche quand un statut de prospect est changé.",
"Triggers when a new contact is added.": "Déclenche lorsqu'un nouveau contact est ajouté.",
"Triggers when a new lead is created.": "Déclenche lorsqu'un nouveau prospect est créé.",
"Triggered when a new task is created.": "Déclenché lorsqu'une nouvelle tâche est créée."
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "サブドメイン",
"Token": "トークン",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n",
"Find Lead": "リードを見つける",
"Update Contact": "連絡先を更新",
"Create New Lead": "新しいリードを作成",
"Update Lead": "潜在顧客を更新",
"Create New Contact": "新しい連絡先を作成",
"Find Contact": "連絡先を探す",
"Find Company": "会社を検索",
"Custom API Call": "カスタムAPI通話",
"Finds an existing lead.": "既存のリードを検索します。",
"Updates an existing contact.": "既存のコンタクトを更新します。",
"Creates a new lead.": "新しいリードを作成します。",
"Update existing lead info.": "既存のリード情報を更新します",
"Add a new contact.": "新しい連絡先を追加します。",
"Finds an existing contact.": "既存の連絡先を検索します。",
"Find an existing company.": "既存の会社を検索します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Query": "クエリ",
"Contact": "お問い合わせ",
"Full Name": "フルネーム",
"First Name": "名",
"Last Name": "Last Name",
"Email": "Eメールアドレス",
"Phone": "電話番号",
"Unique identified of a responsible user": "責任あるユーザーの一意を特定しました",
"Tags to Add": "追加するタグ",
"Tags to Delete": "削除するタグ",
"Lead Name": "リード名",
"Price": "価格",
"Pipeline": "パイプライン",
"Status": "Status",
"Loss Reason": "損失の理由",
"Lead": "リード",
"Name": "Name",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Search query (Searches through the filled fields of the lead).": "検索クエリ(リードの約定フィールドを検索します)。",
"List of tag names or IDs to add.": "追加するタグ名またはIDの一覧。",
"List of tag names or IDs to remove.": "削除するタグ名またはIDのリストです。",
"List of tags to add.": "追加するタグのリストです。",
"Search query (Searches through the filled fields of the contact).": "検索クエリ (連絡先の約定フィールドを検索します)。",
"Search query (Searches through the filled fields of the company).": "検索クエリ (会社の約定フィールドを検索します)。",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"Lead Status Changed": "リードのステータスが変更されました",
"New Contact Added": "新しい連絡先が追加されました",
"New Lead Created": "新しいリードが作成されました",
"New Task Created": "新しいタスクが作成されました",
"Triggers when a lead status is changed.": "リードステータスが変更されたときにトリガーします。",
"Triggers when a new contact is added.": "新しい連絡先が追加されたときにトリガーします。",
"Triggers when a new lead is created.": "新しいリードが作成されたときにトリガーします。",
"Triggered when a new task is created.": "新しいタスクが作成されたときにトリガーされます。"
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "Subdomein",
"Token": "Token",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nVolg [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) handleiding voor het genereren van token.\n\nUw Kommo account subdomein (bijv. \"mijnbedrijf\" als uw URL mijnbedrijf.kommo.com is).\n\n",
"Find Lead": "Zoek Lead",
"Update Contact": "Contactpersoon bijwerken",
"Create New Lead": "Maak nieuwe Lead",
"Update Lead": "Lead bijwerken",
"Create New Contact": "Nieuw contactpersoon aanmaken",
"Find Contact": "Contactpersoon zoeken",
"Find Company": "Bedrijf zoeken",
"Custom API Call": "Custom API Call",
"Finds an existing lead.": "Vindt een bestaande lood.",
"Updates an existing contact.": "Werkt een bestaand contact bij.",
"Creates a new lead.": "Maakt een nieuwe lood.",
"Update existing lead info.": "Bestaande lead info bijwerken.",
"Add a new contact.": "Nieuw contact toevoegen.",
"Finds an existing contact.": "Een bestaand contact vinden.",
"Find an existing company.": "Zoek een bestaand bedrijf.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Query": "Zoekopdracht",
"Contact": "Contactpersoon",
"Full Name": "Volledige naam",
"First Name": "Voornaam",
"Last Name": "Achternaam",
"Email": "E-mail",
"Phone": "Telefoonnummer",
"Unique identified of a responsible user": "Unieke geïdentificeerd van een verantwoordelijke gebruiker",
"Tags to Add": "Tags om toe te voegen",
"Tags to Delete": "Tags om te verwijderen",
"Lead Name": "Lead naam",
"Price": "Prijs",
"Pipeline": "Pijplijn",
"Status": "status",
"Loss Reason": "Verlies Reden",
"Lead": "Lood",
"Name": "Naam",
"Method": "Methode",
"Headers": "Kopteksten",
"Query Parameters": "Query parameters",
"Body": "Lichaam",
"Response is Binary ?": "Antwoord is binair?",
"No Error on Failure": "Geen fout bij fout",
"Timeout (in seconds)": "Time-out (in seconden)",
"Search query (Searches through the filled fields of the lead).": "Zoek query (door de gevulde velden van de lood).",
"List of tag names or IDs to add.": "Lijst van toe te voegen tagnamen of ID's.",
"List of tag names or IDs to remove.": "Lijst van tagnamen of ID's om te verwijderen.",
"List of tags to add.": "Lijst van tags om toe te voegen.",
"Search query (Searches through the filled fields of the contact).": "Zoek query (door de gevulde velden van het contact).",
"Search query (Searches through the filled fields of the company).": "Zoek zoekopdracht (door de gevulde velden van het bedrijf).",
"Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
"Enable for files like PDFs, images, etc..": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc..",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"Lead Status Changed": "Lead status veranderd",
"New Contact Added": "Nieuwe contactpersoon toegevoegd",
"New Lead Created": "Nieuwe Lead aangemaakt",
"New Task Created": "Nieuwe taak aangemaakt",
"Triggers when a lead status is changed.": "Triggert wanneer een lead status wordt veranderd.",
"Triggers when a new contact is added.": "Triggert wanneer een nieuwe contactpersoon wordt toegevoegd.",
"Triggers when a new lead is created.": "Triggert wanneer een nieuwe lead wordt gemaakt.",
"Triggered when a new task is created.": "Uitgelokt wanneer een nieuwe taak wordt aangemaakt."
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "Subdomínio",
"Token": "Identificador",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nPor favor, siga [Gerar um Token de Vida](https://developers.kommo.com/docs/long-lived-token) guia para geração de token.\n\nSeu subdomínio da conta Kommo (ex: \"minhaempresa\" se a URL for minhaempresa.kommo.com).\n\n",
"Find Lead": "Encontrar Potencial",
"Update Contact": "Atualizar contato",
"Create New Lead": "Criar Novo Potencial",
"Update Lead": "Atualizar Lead",
"Create New Contact": "Criar Novo Contato",
"Find Contact": "Localizar contato",
"Find Company": "Encontrar empresa",
"Custom API Call": "Chamada de API personalizada",
"Finds an existing lead.": "Encontra um lead existente.",
"Updates an existing contact.": "Atualiza um contato existente.",
"Creates a new lead.": "Cria um novo lead.",
"Update existing lead info.": "Atualizar informações do lead existente.",
"Add a new contact.": "Adicionar um novo contato.",
"Finds an existing contact.": "Localiza um contato existente.",
"Find an existing company.": "Encontre uma empresa existente.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Query": "Requisição",
"Contact": "contato",
"Full Name": "Nome Completo",
"First Name": "Nome",
"Last Name": "Sobrenome",
"Email": "e-mail",
"Phone": "Smartphone",
"Unique identified of a responsible user": "Única identificada por um usuário responsável",
"Tags to Add": "Marcadores a adicionar",
"Tags to Delete": "Tags para Excluir",
"Lead Name": "Nome do Potencial",
"Price": "Quantidade",
"Pipeline": "Pipeline",
"Status": "Estado",
"Loss Reason": "Motivo da perda",
"Lead": "Conduzir",
"Name": "Nome",
"Method": "Método",
"Headers": "Cabeçalhos",
"Query Parameters": "Parâmetros da consulta",
"Body": "Conteúdo",
"Response is Binary ?": "A resposta é binária ?",
"No Error on Failure": "Nenhum erro no Failure",
"Timeout (in seconds)": "Tempo limite (em segundos)",
"Search query (Searches through the filled fields of the lead).": "Consulta de pesquisa (Searches através dos campos preenchidos do lead).",
"List of tag names or IDs to add.": "Lista de nomes ou IDs de etiquetas a adicionar.",
"List of tag names or IDs to remove.": "Lista de nomes ou IDs de etiquetas a remover.",
"List of tags to add.": "Lista de etiquetas para adicionar.",
"Search query (Searches through the filled fields of the contact).": "Consulta de pesquisa (Searches através dos campos preenchidos do contato).",
"Search query (Searches through the filled fields of the company).": "Consulta de pesquisa (Searches através dos campos preenchidos da empresa).",
"Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
"Enable for files like PDFs, images, etc..": "Habilitar para arquivos como PDFs, imagens, etc..",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"Lead Status Changed": "Status do Lead Alterado",
"New Contact Added": "Novo contato adicionado",
"New Lead Created": "Novo Potencial Criado",
"New Task Created": "Nova tarefa criada",
"Triggers when a lead status is changed.": "Dispara quando um status de lead é alterado.",
"Triggers when a new contact is added.": "Aciona quando um novo contato é adicionado.",
"Triggers when a new lead is created.": "Dispara quando um novo lead é criado.",
"Triggered when a new task is created.": "Acionada quando uma nova tarefa é criada."
}

View File

@@ -0,0 +1,66 @@
{
"Kommo": "Kommo",
"Subdomain": "Поддомен",
"Token": "Токен",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nПожалуйста, следуйте [Генерировать длинный Live Token](https://developers.kommo.com/docs/long-lived-token) для генерации токена.\n\nПоддомен вашей учетной записи Kommo (например, «mycompany», если ваш URL mycompany.kommo.com).\n\n",
"Find Lead": "Найти предв. контакт",
"Update Contact": "Обновить контакт",
"Create New Lead": "Создать нового предварительного контакта",
"Update Lead": "Обновить предв. контакт",
"Create New Contact": "Создать новый контакт",
"Find Contact": "Найти контакт",
"Find Company": "Найти компанию",
"Custom API Call": "Пользовательский вызов API",
"Finds an existing lead.": "Поиск существующего свинца.",
"Updates an existing contact.": "Обновляет существующий контакт.",
"Creates a new lead.": "Создает нового лидера.",
"Update existing lead info.": "Обновить существующую информацию о клиенте.",
"Add a new contact.": "Добавить новый контакт.",
"Finds an existing contact.": "Ищет существующий контакт.",
"Find an existing company.": "Найти существующую компанию.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Query": "Запрос",
"Contact": "Контакт",
"Full Name": "Полное имя",
"First Name": "First Name",
"Last Name": "Last Name",
"Email": "Почта",
"Phone": "Телефон",
"Unique identified of a responsible user": "Уникальная идентификация ответственного пользователя",
"Tags to Add": "Теги для добавления",
"Tags to Delete": "Теги для удаления",
"Lead Name": "Имя предварительного контакта",
"Price": "Цена",
"Pipeline": "Трубопровод",
"Status": "Status",
"Loss Reason": "Причина потерь",
"Lead": "Предв. контакт",
"Name": "Наименование",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Search query (Searches through the filled fields of the lead).": "Поисковый запрос (Изучает заполненные поля свинца).",
"List of tag names or IDs to add.": "Список имен или идентификаторов тегов для добавления.",
"List of tag names or IDs to remove.": "Список имен или идентификаторов тэгов для удаления.",
"List of tags to add.": "Список тегов для добавления.",
"Search query (Searches through the filled fields of the contact).": "Поисковый запрос (Показывает через заполненные поля контакта).",
"Search query (Searches through the filled fields of the company).": "Поисковый запрос (Поиски по заполненным полям компании).",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"Lead Status Changed": "Статус предварительного контакта изменен",
"New Contact Added": "Добавлен новый контакт",
"New Lead Created": "Создан новый контакт",
"New Task Created": "Новая задача создана",
"Triggers when a lead status is changed.": "Триггеры при изменении статуса клиента.",
"Triggers when a new contact is added.": "Триггеры при добавлении нового контакта.",
"Triggers when a new lead is created.": "Триггеры при создании нового свинца.",
"Triggered when a new task is created.": "Срабатывает при создании новой задачи."
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "Subdomain",
"Token": "Token",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n",
"Find Lead": "Find Lead",
"Update Contact": "Update Contact",
"Create New Lead": "Create New Lead",
"Update Lead": "Update Lead",
"Create New Contact": "Create New Contact",
"Find Contact": "Find Contact",
"Find Company": "Find Company",
"Custom API Call": "Custom API Call",
"Finds an existing lead.": "Finds an existing lead.",
"Updates an existing contact.": "Updates an existing contact.",
"Creates a new lead.": "Creates a new lead.",
"Update existing lead info.": "Update existing lead info.",
"Add a new contact.": "Add a new contact.",
"Finds an existing contact.": "Finds an existing contact.",
"Find an existing company.": "Find an existing company.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Query": "Query",
"Contact": "Contact",
"Full Name": "Full Name",
"First Name": "First Name",
"Last Name": "Last Name",
"Email": "Email",
"Phone": "Phone",
"Unique identified of a responsible user": "Unique identified of a responsible user",
"Tags to Add": "Tags to Add",
"Tags to Delete": "Tags to Delete",
"Lead Name": "Lead Name",
"Price": "Price",
"Pipeline": "Pipeline",
"Status": "Status",
"Loss Reason": "Loss Reason",
"Lead": "Lead",
"Name": "Name",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Search query (Searches through the filled fields of the lead).": "Search query (Searches through the filled fields of the lead).",
"List of tag names or IDs to add.": "List of tag names or IDs to add.",
"List of tag names or IDs to remove.": "List of tag names or IDs to remove.",
"List of tags to add.": "List of tags to add.",
"Search query (Searches through the filled fields of the contact).": "Search query (Searches through the filled fields of the contact).",
"Search query (Searches through the filled fields of the company).": "Search query (Searches through the filled fields of the company).",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Lead Status Changed": "Lead Status Changed",
"New Contact Added": "New Contact Added",
"New Lead Created": "New Lead Created",
"New Task Created": "New Task Created",
"Triggers when a lead status is changed.": "Triggers when a lead status is changed.",
"Triggers when a new contact is added.": "Triggers when a new contact is added.",
"Triggers when a new lead is created.": "Triggers when a new lead is created.",
"Triggered when a new task is created.": "Triggered when a new task is created."
}

View File

@@ -0,0 +1,66 @@
{
"Kommo": "Kommo",
"Subdomain": "Subdomain",
"Token": "Token",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n",
"Find Lead": "Find Lead",
"Update Contact": "Update Contact",
"Create New Lead": "Create New Lead",
"Update Lead": "Update Lead",
"Create New Contact": "Create New Contact",
"Find Contact": "Find Contact",
"Find Company": "Find Company",
"Custom API Call": "Custom API Call",
"Finds an existing lead.": "Finds an existing lead.",
"Updates an existing contact.": "Updates an existing contact.",
"Creates a new lead.": "Creates a new lead.",
"Update existing lead info.": "Update existing lead info.",
"Add a new contact.": "Add a new contact.",
"Finds an existing contact.": "Finds an existing contact.",
"Find an existing company.": "Find an existing company.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Query": "Query",
"Contact": "Contact",
"Full Name": "Full Name",
"First Name": "First Name",
"Last Name": "Last Name",
"Email": "Email",
"Phone": "Phone",
"Unique identified of a responsible user": "Unique identified of a responsible user",
"Tags to Add": "Tags to Add",
"Tags to Delete": "Tags to Delete",
"Lead Name": "Lead Name",
"Price": "Price",
"Pipeline": "Pipeline",
"Status": "Status",
"Loss Reason": "Loss Reason",
"Lead": "Lead",
"Name": "Name",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Search query (Searches through the filled fields of the lead).": "Search query (Searches through the filled fields of the lead).",
"List of tag names or IDs to add.": "List of tag names or IDs to add.",
"List of tag names or IDs to remove.": "List of tag names or IDs to remove.",
"List of tags to add.": "List of tags to add.",
"Search query (Searches through the filled fields of the contact).": "Search query (Searches through the filled fields of the contact).",
"Search query (Searches through the filled fields of the company).": "Search query (Searches through the filled fields of the company).",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Lead Status Changed": "Lead Status Changed",
"New Contact Added": "New Contact Added",
"New Lead Created": "New Lead Created",
"New Task Created": "New Task Created",
"Triggers when a lead status is changed.": "Triggers when a lead status is changed.",
"Triggers when a new contact is added.": "Triggers when a new contact is added.",
"Triggers when a new lead is created.": "Triggers when a new lead is created.",
"Triggered when a new task is created.": "Triggered when a new task is created."
}

View File

@@ -0,0 +1,67 @@
{
"Subdomain": "Subdomain",
"Token": "Token",
"\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n": "\nPlease follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.\n\nYour Kommo account subdomain (e.g., \"mycompany\" if your URL is mycompany.kommo.com).\n\n",
"Find Lead": "Find Lead",
"Update Contact": "Update Contact",
"Create New Lead": "Create New Lead",
"Update Lead": "Update Lead",
"Create New Contact": "Create New Contact",
"Find Contact": "Find Contact",
"Find Company": "Find Company",
"Custom API Call": "自定义 API 呼叫",
"Finds an existing lead.": "Finds an existing lead.",
"Updates an existing contact.": "Updates an existing contact.",
"Creates a new lead.": "Creates a new lead.",
"Update existing lead info.": "Update existing lead info.",
"Add a new contact.": "Add a new contact.",
"Finds an existing contact.": "Finds an existing contact.",
"Find an existing company.": "Find an existing company.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Query": "Query",
"Contact": "Contact",
"Full Name": "Full Name",
"First Name": "First Name",
"Last Name": "名字",
"Email": "电子邮件地址",
"Phone": "Phone",
"Unique identified of a responsible user": "Unique identified of a responsible user",
"Tags to Add": "Tags to Add",
"Tags to Delete": "Tags to Delete",
"Lead Name": "Lead Name",
"Price": "Price",
"Pipeline": "Pipeline",
"Status": "状态",
"Loss Reason": "Loss Reason",
"Lead": "Lead",
"Name": "名称",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Search query (Searches through the filled fields of the lead).": "Search query (Searches through the filled fields of the lead).",
"List of tag names or IDs to add.": "List of tag names or IDs to add.",
"List of tag names or IDs to remove.": "List of tag names or IDs to remove.",
"List of tags to add.": "List of tags to add.",
"Search query (Searches through the filled fields of the contact).": "Search query (Searches through the filled fields of the contact).",
"Search query (Searches through the filled fields of the company).": "Search query (Searches through the filled fields of the company).",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"Lead Status Changed": "Lead Status Changed",
"New Contact Added": "New Contact Added",
"New Lead Created": "New Lead Created",
"New Task Created": "New Task Created",
"Triggers when a lead status is changed.": "Triggers when a lead status is changed.",
"Triggers when a new contact is added.": "Triggers when a new contact is added.",
"Triggers when a new lead is created.": "Triggers when a new lead is created.",
"Triggered when a new task is created.": "Triggered when a new task is created."
}

View File

@@ -0,0 +1,55 @@
import { createPiece, PieceAuth, PiecePropValueSchema } from '@activepieces/pieces-framework';
import { PieceCategory } from '@activepieces/shared';
import { leadStatusChangedTrigger, newContactAddedTrigger, newLeadCreatedTrigger, newTaskCreatedTrigger } from "./lib/triggers";
import { findLeadAction, updateContactAction, createLeadAction, createContactAction, findContactAction, findCompanyAction, updateLeadAction } from "./lib/actions";
import { createCustomApiCallAction } from '@activepieces/pieces-common';
const markdownDescription = `
Please follow [Generate Long Live Token](https://developers.kommo.com/docs/long-lived-token) guide for generating token.
Your Kommo account subdomain (e.g., "mycompany" if your URL is mycompany.kommo.com).
`;
export const kommoAuth = PieceAuth.CustomAuth({
description: markdownDescription,
required: true,
props: {
subdomain: PieceAuth.SecretText({
displayName: 'Subdomain',
required: true,
}),
apiToken: PieceAuth.SecretText({
displayName: 'Token',
required: true,
}),
},
});
export const kommo = createPiece({
displayName: 'Kommo',
auth: kommoAuth,
logoUrl: 'https://cdn.activepieces.com/pieces/kommo.png',
categories: [PieceCategory.COMMUNICATION, PieceCategory.SALES_AND_CRM],
authors: ['krushnarout', 'kishanprmr'],
actions: [findLeadAction, updateContactAction, createLeadAction, updateLeadAction, createContactAction, findContactAction, findCompanyAction,
createCustomApiCallAction({
auth: kommoAuth,
baseUrl: (auth) => {
if (!auth) {
return '';
}
const authValue = auth.props;
return `https://${authValue.subdomain}.kommo.com/api/v4`
},
authMapping: async (auth) => {
const authValue = auth.props;
return {
Authorization: `Bearer ${authValue.apiToken}`
}
}
})
],
triggers: [leadStatusChangedTrigger, newContactAddedTrigger, newLeadCreatedTrigger, newTaskCreatedTrigger],
});

View File

@@ -0,0 +1,100 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { makeRequest } from '../common';
import { kommoAuth } from '../../index';
import { userDropdown } from '../common/props';
interface KommoCustomFieldValue {
field_id?: number;
field_code?: string;
values: Array<{ value: string | number; enum_id?: number }>;
}
export const createContactAction = createAction({
auth: kommoAuth,
name: 'create_contact',
displayName: 'Create New Contact',
description: 'Add a new contact.',
props: {
name: Property.ShortText({
displayName: 'Full Name',
required: true,
}),
first_name: Property.ShortText({
displayName: 'First Name',
required: false,
}),
last_name: Property.ShortText({
displayName: 'Last Name',
required: false,
}),
email: Property.ShortText({
displayName: 'Email',
required: false,
}),
phone: Property.ShortText({
displayName: 'Phone',
required: false,
}),
responsible_user_id: userDropdown(),
tags_to_add: Property.Array({
displayName: 'Tags to Add',
required: false,
})
},
async run(context) {
const {
name,
first_name,
last_name,
email,
phone,
responsible_user_id,
} = context.propsValue;
const tagsToAdd = context.propsValue.tags_to_add ?? [];
const { subdomain, apiToken } = context.auth.props
const customFields: KommoCustomFieldValue[] = [];
if (email) {
customFields.push({
field_code: 'EMAIL',
values: [{ value: email }],
});
}
if (phone) {
customFields.push({
field_code: 'PHONE',
values: [{ value: phone }],
});
}
const contactPayload: Record<string, any> = {
...(customFields.length > 0 ? { custom_fields_values: customFields } : {}),
};
if (name) contactPayload['name'] = name;
if (first_name) contactPayload['first_name'] = first_name;
if (last_name) contactPayload['last_name'] = last_name;
if (responsible_user_id) contactPayload['responsible_user_id'] = responsible_user_id;
if (tagsToAdd.length > 0) {
contactPayload['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }))
}
const result = await makeRequest(
{ apiToken, subdomain },
HttpMethod.POST,
`/contacts`,
[contactPayload]
);
return result;
},
});

View File

@@ -0,0 +1,62 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { makeRequest } from '../common';
import { kommoAuth } from '../../index';
import {
pipelineDropdown,
statusDropdown,
userDropdown,
lossReasonDropdown,
} from '../common/props';
export const createLeadAction = createAction({
auth: kommoAuth,
name: 'create_lead',
displayName: 'Create New Lead',
description: 'Creates a new lead.',
props: {
name: Property.ShortText({
displayName: 'Lead Name',
required: true,
}),
price: Property.Number({
displayName: 'Price',
required: false,
}),
pipelineId: pipelineDropdown(true),
statusId: statusDropdown(true),
responsible_user_id: userDropdown(),
loss_reason_id: lossReasonDropdown(),
tags_to_add: Property.Array({
displayName: 'Tags to Add',
description: 'List of tags to add.',
required: false,
}),
},
async run(context) {
const { name, price, statusId, pipelineId, loss_reason_id, responsible_user_id } =
context.propsValue;
const tagsToAdd = context.propsValue.tags_to_add ?? [];
const { apiToken, subdomain } = context.auth.props;
const body: Record<string, unknown> = {
name,
};
if (price) body['price'] = price;
if (statusId) body['status_id'] = statusId;
if (pipelineId) body['pipeline_id'] = pipelineId;
if (loss_reason_id) body['loss_reason_id'] = loss_reason_id;
if (responsible_user_id) body['responsible_user_id'] = responsible_user_id;
if (tagsToAdd.length > 0) {
body['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }));
}
const response = await makeRequest({ apiToken, subdomain }, HttpMethod.POST, '/leads', [body]);
return response;
},
});

View File

@@ -0,0 +1,35 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { makeRequest } from '../common';
import { kommoAuth } from '../../index';
export const findCompanyAction = createAction({
auth: kommoAuth,
name: 'find_company',
displayName: 'Find Company',
description: 'Find an existing company.',
props: {
query: Property.ShortText({
displayName: 'Query',
required: true,
description: 'Search query (Searches through the filled fields of the company).'
}),
},
async run(context) {
const { query } = context.propsValue;
const { subdomain, apiToken } = context.auth.props
const result = await makeRequest(
{ apiToken, subdomain },
HttpMethod.GET,
`/companies?query=${encodeURIComponent(query || '')}`
);
const companies = result?._embedded?.companies ?? [];
return {
found: companies.length > 0,
result: companies
};
},
});

View File

@@ -0,0 +1,35 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { kommoAuth } from '../../index';
import { makeRequest } from '../common';
import { HttpMethod } from '@activepieces/pieces-common';
export const findContactAction = createAction({
auth: kommoAuth,
name: 'find_contact',
displayName: 'Find Contact',
description: 'Finds an existing contact.',
props: {
query: Property.ShortText({
displayName: 'Query',
required: true,
description: 'Search query (Searches through the filled fields of the contact).'
}),
},
async run(context) {
const { query } = context.propsValue;
const { subdomain, apiToken } = context.auth.props
const result = await makeRequest(
{ apiToken, subdomain },
HttpMethod.GET,
`/contacts?query=${encodeURIComponent(query)}`
);
const contacts = result?._embedded?.contacts ?? [];
return {
found: contacts.length > 0,
result: contacts
};
},
});

View File

@@ -0,0 +1,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { makeRequest } from '../common';
import { kommoAuth } from '../../index';
export const findLeadAction = createAction({
auth: kommoAuth,
name: 'find_lead',
displayName: 'Find Lead',
description: "Finds an existing lead.",
props: {
query: Property.ShortText({
displayName: 'Query',
required: true,
description: 'Search query (Searches through the filled fields of the lead).'
}),
},
async run(context) {
const { subdomain, apiToken } = context.auth.props
const result = await makeRequest(
{ apiToken, subdomain },
HttpMethod.GET,
`/leads?query=${encodeURIComponent(context.propsValue.query)}`
);
const leads = result?._embedded?.leads ?? [];
return {
found: leads.length > 0,
result: leads
};
},
});

View File

@@ -0,0 +1,9 @@
import { findLeadAction } from './find-lead';
import { updateContactAction } from './update-contact';
import { createLeadAction } from './create-new-lead';
import { createContactAction } from './create-new-contact';
import { findContactAction } from './find-contact';
import { findCompanyAction } from './find-company';
import { updateLeadAction } from './update-lead'
export { findLeadAction, updateContactAction, createLeadAction, createContactAction, findContactAction, findCompanyAction, updateLeadAction };

View File

@@ -0,0 +1,110 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { kommoAuth } from '../../index';
import { makeRequest } from '../common';
import { contactDropdown, userDropdown } from '../common/props';
interface KommoCustomFieldValue {
field_id?: number;
field_code?: string;
values: Array<{ value: string | number; enum_id?: number }>;
}
export const updateContactAction = createAction({
auth: kommoAuth,
name: 'update_contact',
displayName: 'Update Contact',
description: 'Updates an existing contact.',
props: {
contactId: contactDropdown,
name: Property.ShortText({
displayName: 'Full Name',
required: false,
}),
first_name: Property.ShortText({
displayName: 'First Name',
required: false,
}),
last_name: Property.ShortText({
displayName: 'Last Name',
required: false,
}),
email: Property.ShortText({
displayName: 'Email',
required: false,
}),
phone: Property.ShortText({
displayName: 'Phone',
required: false,
}),
responsible_user_id: userDropdown(),
tags_to_add: Property.Array({
displayName: 'Tags to Add',
description: 'List of tag names or IDs to add.',
required: false,
}),
tags_to_delete: Property.Array({
displayName: 'Tags to Delete',
description: 'List of tag names or IDs to remove.',
required: false,
})
},
async run(context) {
const {
contactId,
name,
first_name,
last_name,
email,
phone,
responsible_user_id,
} = context.propsValue;
const tagsToAdd = context.propsValue.tags_to_add ?? [];
const tagsToDelete = context.propsValue.tags_to_delete ?? [];
const { subdomain, apiToken } = context.auth.props;
const customFields: KommoCustomFieldValue[] = [];
if (email) {
customFields.push({
field_code: 'EMAIL',
values: [{ value: email }],
});
}
if (phone) {
customFields.push({
field_code: 'PHONE',
values: [{ value: phone }],
});
}
const updatePayload: Record<string, any> = {
...(customFields.length > 0 ? { custom_fields_values: customFields } : {}),
};
if (name) updatePayload['name'] = name;
if (first_name) updatePayload['first_name'] = first_name;
if (last_name) updatePayload['last_name'] = last_name;
if (responsible_user_id) updatePayload['responsible_user_id'] = responsible_user_id;
if (tagsToAdd.length > 0) {
updatePayload['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }))
}
if (tagsToDelete.length > 0) {
updatePayload['tags_to_delete'] = tagsToDelete.map((tag) => ({ name: tag }))
}
const result = await makeRequest(
{ subdomain, apiToken },
HttpMethod.PATCH,
`/contacts/${contactId}`,
updatePayload
);
return result;
},
});

View File

@@ -0,0 +1,78 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { makeRequest } from '../common';
import { kommoAuth } from '../../index';
import { pipelineDropdown, statusDropdown, userDropdown, lossReasonDropdown, leadDropdown } from '../common/props';
export const updateLeadAction = createAction({
auth: kommoAuth,
name: 'update_lead',
displayName: 'Update Lead',
description: 'Update existing lead info.',
props: {
leadId: leadDropdown,
name: Property.ShortText({
displayName: 'Name',
required: false,
}),
price: Property.Number({
displayName: 'Price',
required: false,
}),
pipelineId: pipelineDropdown(false),
statusId: statusDropdown(false),
responsible_user_id: userDropdown(false),
loss_reason_id: lossReasonDropdown(false),
tags_to_add: Property.Array({
displayName: 'Tags to Add',
required: false,
}),
tags_to_delete: Property.Array({
displayName: 'Tags to Delete',
required: false,
}),
},
async run(context) {
const {
leadId,
name,
price,
statusId,
pipelineId,
responsible_user_id,
loss_reason_id,
} = context.propsValue;
const tagsToAdd = context.propsValue.tags_to_add ?? [];
const tagsToDelete = context.propsValue.tags_to_delete ?? [];
const { subdomain, apiToken } = context.auth.props;
const updatePayload: Record<string, any> = {};
if (name) updatePayload['name'] = name;
if (price) updatePayload['price'] = price;
if (statusId) updatePayload['status_id'] = statusId;
if (pipelineId) updatePayload['pipeline_id'] = pipelineId;
if (loss_reason_id) updatePayload['loss_reason_id'] = loss_reason_id;
if (responsible_user_id) updatePayload['responsible_user_id'] = responsible_user_id;
if (tagsToAdd.length > 0) {
updatePayload['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }))
}
if (tagsToDelete.length > 0) {
updatePayload['tags_to_delete'] = tagsToDelete.map((tag) => ({ name: tag }))
}
const result = await makeRequest(
{ apiToken, subdomain },
HttpMethod.PATCH,
`/leads/${leadId}`,
updatePayload
);
return result;
},
});

View File

@@ -0,0 +1,27 @@
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
interface KommoAuth {
subdomain: string;
apiToken: string;
}
export async function makeRequest(
auth: KommoAuth,
method: HttpMethod,
path: string,
body?: unknown
) {
const url = `https://${auth.subdomain}.kommo.com/api/v4${path}`;
const response = await httpClient.sendRequest({
method,
url,
headers: {
Authorization: `Bearer ${auth.apiToken}`,
'Content-Type': 'application/json',
},
body,
});
return response.body;
}

View File

@@ -0,0 +1,226 @@
import { Property, DropdownOption } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { makeRequest } from './index';
import { kommoAuth } from '../..';
interface KommoAuth {
subdomain: string;
apiToken: string;
}
export const pipelineDropdown = (required = false) => Property.Dropdown({
auth: kommoAuth,
displayName: 'Pipeline',
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your Kommo account',
options: [],
};
}
const { subdomain, apiToken } = auth.props;
const pipelines = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/leads/pipelines');
const options: DropdownOption<number>[] = (pipelines._embedded?.pipelines || []).map(
(pipeline: any) => ({
label: pipeline.name,
value: pipeline.id
})
);
return {
disabled: false,
options,
};
},
});
export const statusDropdown = (required = false) => Property.Dropdown({
auth: kommoAuth,
displayName: 'Status',
required,
refreshers: ['pipelineId'],
options: async ({ auth, pipelineId }) => {
if (!auth || !pipelineId) {
return {
disabled: true,
placeholder: 'Select a pipeline first',
options: [],
};
}
const { subdomain, apiToken } = auth.props;
const statuses = await makeRequest(
{ subdomain, apiToken },
HttpMethod.GET,
`/leads/pipelines/${pipelineId}/statuses`
);
const options: DropdownOption<number>[] = (statuses._embedded?.statuses || []).map(
(status: any) => ({
label: status.name,
value: status.id,
})
);
return {
disabled: false,
options,
};
},
});
export const userDropdown = (required = false) => Property.Dropdown({
auth: kommoAuth,
displayName: 'Unique identified of a responsible user',
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your Kommo account',
options: [],
};
}
const { subdomain, apiToken } = auth.props;
const users = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/users');
const options: DropdownOption<number>[] = (users._embedded?.users || []).map((user: any) => ({
label: `${user.name} (${user.email})`,
value: user.id,
}));
return {
disabled: false,
options,
};
},
});
export const lossReasonDropdown = (required = false) => Property.Dropdown({
auth: kommoAuth,
displayName: 'Loss Reason',
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your Kommo account',
options: [],
};
}
const { subdomain, apiToken } = auth.props;
const reasons = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/leads/loss_reasons');
const options: DropdownOption<number>[] = (reasons._embedded?.loss_reasons || []).map(
(reason: any) => ({
label: reason.name,
value: reason.id,
})
);
return {
disabled: false,
options,
};
},
});
export const leadDropdown = Property.Dropdown({
auth: kommoAuth,
displayName: 'Lead',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your Kommo account',
options: [],
};
}
const { subdomain, apiToken } = auth.props;
const leads = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/leads');
const options: DropdownOption<number>[] = (leads._embedded?.leads || []).map((lead: any) => ({
label: lead.name,
value: lead.id,
}));
return {
disabled: false,
options,
};
},
});
export const companyDropdown = Property.Dropdown({
auth: kommoAuth,
displayName: 'Company',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your Kommo account',
options: [],
};
}
const { subdomain, apiToken } = auth.props;
const companies = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/companies');
const options: DropdownOption<string>[] = (companies._embedded?.companies || []).map(
(company: any) => ({
label: company.name,
value: company.id.toString(),
})
);
return {
disabled: false,
options,
};
},
});
export const contactDropdown = Property.Dropdown({
auth: kommoAuth,
displayName: 'Contact',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your Kommo account',
options: [],
};
}
const { subdomain, apiToken } = auth.props;
const contacts = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/contacts');
const options: DropdownOption<number>[] = (contacts._embedded?.contacts || []).map(
(contact: any) => ({
label: contact.name,
value: contact.id,
})
);
return {
disabled: false,
options,
};
},
});

View File

@@ -0,0 +1,6 @@
import { leadStatusChangedTrigger } from './lead-status-changed';
import { newContactAddedTrigger } from './new-contact-added';
import { newLeadCreatedTrigger } from './new-lead-created';
import { newTaskCreatedTrigger } from './new-task-created';
export { leadStatusChangedTrigger, newContactAddedTrigger, newLeadCreatedTrigger, newTaskCreatedTrigger };

View File

@@ -0,0 +1,102 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { kommoAuth } from '../../index';
import { makeRequest } from '../common';
import { HttpMethod } from '@activepieces/pieces-common';
export const leadStatusChangedTrigger = createTrigger({
auth: kommoAuth,
name: 'lead_status_changed',
displayName: 'Lead Status Changed',
description: 'Triggers when a lead status is changed.',
type: TriggerStrategy.WEBHOOK,
props: {},
async onEnable(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const webhook = await makeRequest(
{ subdomain, apiToken },
HttpMethod.POST,
`/webhooks`,
{
destination: context.webhookUrl,
settings: ['status_lead']
}
);
await context.store.put('webhookId', webhook.id);
},
async onDisable(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const webhookId = await context.store.get('webhookId');
if (webhookId) {
await makeRequest(
{ subdomain, apiToken },
HttpMethod.DELETE,
`/webhooks`,
{destination:context.webhookUrl}
);
}
},
async run(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const payload = context.payload.body as { leads: { status: { id: string }[] } }
const leadId = payload.leads.status[0].id;
if (!leadId) return [];
const response = await makeRequest({ apiToken, subdomain }, HttpMethod.GET, `/leads/${leadId}`)
return [response]
},
async test(context) {
const { subdomain, apiToken } = context.auth.props;
const response = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/leads?limit=5&order[updated_at]=desc');
const leads = response?._embedded?.leads ?? [];
return leads;
},
sampleData: {
"id": 256988,
"name": "John Doe",
"price": 100,
"responsible_user_id": 13290567,
"group_id": 0,
"status_id": 86521115,
"pipeline_id": 11273979,
"loss_reason_id": null,
"created_by": 13290567,
"updated_by": 13290567,
"created_at": 1748800059,
"updated_at": 1748800060,
"closed_at": null,
"closest_task_at": null,
"is_deleted": false,
"custom_fields_values": null,
"score": null,
"account_id": 34678947,
"labor_cost": null,
"is_price_computed": false,
"_links": {
"self": {
"href": ""
}
},
"_embedded": {
"tags": [],
"companies": [
{
"id": 722828,
"_links": {
"self": {
"href": ""
}
}
}
]
}
}
});

View File

@@ -0,0 +1,98 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { kommoAuth } from '../../index';
import { makeRequest } from '../common';
import { HttpMethod } from '@activepieces/pieces-common';
export const newContactAddedTrigger = createTrigger({
auth: kommoAuth,
name: 'new_contact_added',
displayName: 'New Contact Added',
description: 'Triggers when a new contact is added.',
type: TriggerStrategy.WEBHOOK,
props: {},
async onEnable(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const webhook = await makeRequest(
{ subdomain, apiToken },
HttpMethod.POST,
`/webhooks`,
{
destination: context.webhookUrl,
settings: ['add_contact']
}
);
await context.store.put('webhookId', webhook.id);
},
async onDisable(context) {
const { subdomain, apiToken } = context.auth.props;
const webhookId = await context.store.get('webhookId');
if (webhookId) {
await makeRequest(
{ subdomain, apiToken },
HttpMethod.DELETE,
`/webhooks`,
{destination:context.webhookUrl}
);
}
},
async run(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const payload = context.payload.body as { contacts: { add: { id: string }[] } }
const contactId = payload.contacts.add[0].id;
if (!contactId) return [];
const response = await makeRequest({ apiToken, subdomain }, HttpMethod.GET, `/contacts/${contactId}`)
return [response]
},
async test(context) {
const { subdomain, apiToken } = context.auth.props;
const response = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/contacts?limit=5&order[updated_at]=desc');
const contacts = response?._embedded?.contacts ?? [];
return contacts;
},
sampleData: {
"id": 722830,
"name": "John Doe",
"first_name": "",
"last_name": "",
"responsible_user_id": 13290567,
"group_id": 0,
"created_by": 13290567,
"updated_by": 13290567,
"created_at": 1748800060,
"updated_at": 1748800060,
"closest_task_at": null,
"is_deleted": false,
"is_unsorted": false,
"custom_fields_values": null,
"account_id": 34678947,
"_links": {
"self": {
"href": ""
}
},
"_embedded": {
"tags": [],
"companies": [
{
"id": 722828,
"_links": {
"self": {
"href": ""
}
}
}
]
}
}
});

View File

@@ -0,0 +1,103 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { kommoAuth } from '../../index';
import { makeRequest } from '../common';
import { HttpMethod } from '@activepieces/pieces-common';
export const newLeadCreatedTrigger = createTrigger({
auth: kommoAuth,
name: 'new_lead_created',
displayName: 'New Lead Created',
description: 'Triggers when a new lead is created.',
type: TriggerStrategy.WEBHOOK,
props: {},
async onEnable(context) {
const { subdomain, apiToken } = context.auth.props;
const webhook = await makeRequest(
{ subdomain, apiToken },
HttpMethod.POST,
`/webhooks`,
{
destination: context.webhookUrl,
settings: ['add_lead']
}
);
await context.store.put('webhookId', webhook.id);
},
async onDisable(context) {
const { subdomain, apiToken } = context.auth.props;
const webhookId = await context.store.get('webhookId');
if (webhookId) {
await makeRequest(
{ subdomain, apiToken },
HttpMethod.DELETE,
`/webhooks`,
{destination:context.webhookUrl}
);
}
},
async run(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const payload = context.payload.body as { leads: { add: { id: string }[] } }
const leadId = payload.leads.add[0].id;
if (!leadId) return [];
const response = await makeRequest({ apiToken, subdomain }, HttpMethod.GET, `/leads/${leadId}`)
return [response]
},
async test(context) {
const { subdomain, apiToken } = context.auth.props;
const response = await makeRequest({ subdomain, apiToken }, HttpMethod.GET, '/leads?limit=5&order[updated_at]=desc');
const leads = response?._embedded?.leads ?? [];
return leads;
},
sampleData: {
"id": 256988,
"name": "John Doe",
"price": 100,
"responsible_user_id": 13290567,
"group_id": 0,
"status_id": 86521115,
"pipeline_id": 11273979,
"loss_reason_id": null,
"created_by": 13290567,
"updated_by": 13290567,
"created_at": 1748800059,
"updated_at": 1748800060,
"closed_at": null,
"closest_task_at": null,
"is_deleted": false,
"custom_fields_values": null,
"score": null,
"account_id": 34678947,
"labor_cost": null,
"is_price_computed": false,
"_links": {
"self": {
"href": ""
}
},
"_embedded": {
"tags": [],
"companies": [
{
"id": 722828,
"_links": {
"self": {
"href": ""
}
}
}
]
}
}
});

View File

@@ -0,0 +1,77 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { kommoAuth } from '../../index';
import { makeRequest } from '../common';
import { HttpMethod } from '@activepieces/pieces-common';
export const newTaskCreatedTrigger = createTrigger({
auth: kommoAuth,
name: 'new_task_created',
displayName: 'New Task Created',
description: 'Triggered when a new task is created.',
type: TriggerStrategy.WEBHOOK,
props: {},
async onEnable(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const webhook = await makeRequest(
{ subdomain, apiToken },
HttpMethod.POST,
`/webhooks`,
{
destination: context.webhookUrl,
settings: ['add_task']
}
);
await context.store.put('webhookId', webhook.id);
},
async onDisable(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const webhookId = await context.store.get('webhookId');
if (webhookId) {
await makeRequest(
{ subdomain, apiToken },
HttpMethod.DELETE,
`/webhooks`,
{destination:context.webhookUrl}
);
}
},
async run(context) {
const { subdomain, apiToken } = context.auth.props as { subdomain: string; apiToken: string };
const payload = context.payload.body as { task: { add: { id: number }[] } }
const taskId = payload.task.add[0].id;
if (!taskId) return [];
const response = await makeRequest({ apiToken, subdomain }, HttpMethod.GET, `/tasks/${taskId}`)
return [response]
},
sampleData: {
"id": 12040,
"created_by": 13290567,
"updated_by": 13290567,
"created_at": 1748805952,
"updated_at": 1748805952,
"responsible_user_id": 13290567,
"group_id": 0,
"entity_id": 722830,
"entity_type": "contacts",
"duration": 0,
"is_completed": false,
"task_type_id": 1,
"text": "Test",
"result": [],
"complete_till": 1748975340,
"account_id": 34678947,
"_links": {
"self": {
"href": ""
}
}
}
});

View File

@@ -0,0 +1,19 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}