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,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Geben Sie Ihren Einsichtigen API-Schlüssel ein. Sie finden diesen unter Benutzereinstellungen > API-Keys.",
"Create Record": "Datensatz erstellen",
"Update Record": "Datensatz aktualisieren",
"Get Record": "Datensatz abrufen",
"Delete Record": "Datensatz löschen",
"Find Records": "Datensätze finden",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "Erstellen Sie einen neuen Datensatz in einem bestimmten Insightly Objekt (Kontakt, Lead, Verkaufschance etc.)",
"Update an existing record's fields in a specified Insightly object": "Aktualisiere die Felder eines vorhandenen Datensatzes in einem angegebenen einsehbaren Objekt",
"Get a record by ID from a specified Insightly object": "Holen Sie sich einen Datensatz durch ID von einem bestimmten einsehbaren Objekt",
"Delete a record by ID from a specified Insightly object": "Lösche einen Datensatz durch ID von einem angegebenen einsehbaren Objekt",
"Find records in a specified Insightly object": "Suchen Sie Datensätze in einem bestimmten einsehbaren Objekt",
"Pod": "Pod",
"Object Type": "Objekttyp",
"Fields": "Felder",
"Record ID": "Datensatz-ID",
"Field Name": "Feldname",
"Field Value": "Feldwert",
"Limit": "Limit",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Dein einsehbarer Pod (z.B. \"na1\", \"eu1\"). Finde dies in deiner API-URL: https://api.{pod}.insightly.com",
"Select the type of record to create": "Wählen Sie den zu erstellenden Datensatztyp",
"Select the type of object that contains the record you want to update": "Wählen Sie den Typ des Objekts, das den Datensatz enthält, den Sie aktualisieren möchten",
"Select the record to update": "Wähle den zu aktualisierenden Datensatz",
"The new field values to update.": "Die neuen Feldwerte werden aktualisiert.",
"Select the type of record to retrieve": "Wählen Sie den Typ des zu empfangenen Datensatzes",
"Select the record to retrieve": "Wählen Sie den Datensatz zum Abrufen",
"Select the type of record to delete": "Wählen Sie den Typ des zu löschenden Datensatzes",
"Select the record to delete": "Wählen Sie den zu löschenden Eintrag",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "Ihr einsehbarer Pod (z.B. \"na1\", \"eu1\").",
"Select the type of records to find": "Wählen Sie die Art der zu findenden Datensätze",
"Select the field to search by": "Wählen Sie das zu suchende Feld",
"The value to search for": "Der zu suchende Wert",
"Maximum number of records to return": "Maximale Anzahl der zurückzusenden Datensätze",
"Contact": "Kontakt",
"Lead": "Lead",
"Opportunity": "Verkaufschance",
"Organization": "Organisation",
"Project": "Projekt",
"Task": "Aufgabe",
"Event": "Ereignis",
"Product": "Produkt",
"Quote": "Zitat",
"New Record": "Neuer Datensatz",
"Updated Record": "Aktualisierte Datensatz",
"Deleted Record": "Löschte Datensatz",
"Fires when a new record is created in Insightly (requires webhook setup)": "Feuer, wenn ein neuer Datensatz in Insightly erstellt wird (erfordert Webhook Setup)",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Feuer, wenn ein existierender Datensatz in Insightly aktualisiert wird (erfordert Webhook Setup)",
"Fires when a record is deleted from Insightly": "Feuert wenn ein Datensatz von Insightly gelöscht wird",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "Die Art des einsichtigen Objekts für neue Datensätze zu überwachen",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Anweisungen:**\n1. Gehen Sie zu **Systemeinstellungen > Workflow-Automatisierung** in Ihrem einsichtigen Konto.\n2. Erstellen Sie einen neuen Workflow-Prozess für den gewünschten **Objekttyp**.\n3. Setze den Trigger auf **\"Wenn ein Datensatz erstellt wird\"**.\n4. Fügen Sie unter \"Sofort Aktionen\" eine neue Aktion hinzu und wählen Sie **\"Neuen Webhook hinzufügen\"**.\n5. Fügen Sie den Webhook URL oben in das Feld **URI** ein und speichern Sie den Workflow.\n ",
"The type of Insightly object to monitor for updates": "Der Typ des einsichtigen Objekts, das auf Updates überwacht werden soll",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Anweisungen:**\n1. Gehen Sie zu **Systemeinstellungen > Workflow-Automatisierung** in Ihrem einsichtigen Konto.\n2. Erstellen Sie einen neuen Workflow-Prozess für den gewünschten **Objekttyp**.\n3. Setze den Trigger auf **\"Wenn ein Datensatz erstellt wird und ein Datensatz bearbeitet wird\"**.\n4. Fügen Sie unter \"Sofort Aktionen\" eine neue Aktion hinzu und wählen Sie **\"Neuen Webhook hinzufügen\"**.\n5. Fügen Sie den Webhook URL oben in das Feld **URI** ein und speichern Sie den Workflow.\n ",
"The type of Insightly object to monitor for deletions": "Der Typ des einsichtigen Objekts, das auf Löschungen überwacht werden soll"
}

View File

@@ -0,0 +1,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Introduzca su clave API Insightly. Puede encontrarla en su cuenta Insightly en Configuración de usuario > Claves API.",
"Create Record": "Crear registro",
"Update Record": "Actualizar registro",
"Get Record": "Obtener registro",
"Delete Record": "Eliminar registro",
"Find Records": "Buscar registros",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "Crear un nuevo registro en un objeto especificado Insightly (Contacto, Lead, Oportunidad, etc.)",
"Update an existing record's fields in a specified Insightly object": "Actualizar los campos de un registro existente en un objeto Insightly especificado",
"Get a record by ID from a specified Insightly object": "Obtener un registro por ID de un objeto Insightly especificado",
"Delete a record by ID from a specified Insightly object": "Elimina un registro por ID de un objeto especificado Insightly",
"Find records in a specified Insightly object": "Buscar registros en un objeto especificado Insightly",
"Pod": "Pod",
"Object Type": "Tipo de objeto",
"Fields": "Campos",
"Record ID": "ID de registro",
"Field Name": "Nombre del campo",
"Field Value": "Valor del campo",
"Limit": "Límite",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Tu pod insightly (por ejemplo, \"na1\", \"eu1\"). Encuentra esto en tu URL de API: https://api.{pod}.insightly.com",
"Select the type of record to create": "Seleccione el tipo de registro a crear",
"Select the type of object that contains the record you want to update": "Seleccione el tipo de objeto que contiene el registro que desea actualizar",
"Select the record to update": "Seleccione el registro a actualizar",
"The new field values to update.": "Los nuevos valores de campo a actualizar.",
"Select the type of record to retrieve": "Seleccione el tipo de registro a recuperar",
"Select the record to retrieve": "Seleccione el registro a recuperar",
"Select the type of record to delete": "Seleccione el tipo de registro a eliminar",
"Select the record to delete": "Seleccione el registro a eliminar",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "Tu pod insightly (por ejemplo, \"na1\", \"eu1\").",
"Select the type of records to find": "Seleccione el tipo de registros a encontrar",
"Select the field to search by": "Seleccione el campo a buscar por",
"The value to search for": "El valor para buscar",
"Maximum number of records to return": "Número máximo de registros a devolver",
"Contact": "Contacto",
"Lead": "Plomo",
"Opportunity": "Oportunidad",
"Organization": "Organización",
"Project": "Projekt",
"Task": "Tarea",
"Event": "Evento",
"Product": "Producto",
"Quote": "Cotización",
"New Record": "Nuevo registro",
"Updated Record": "Registro actualizado",
"Deleted Record": "Registro eliminado",
"Fires when a new record is created in Insightly (requires webhook setup)": "Dispara cuando se crea un nuevo registro en Inightly (requiere configuración de webhook)",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Dispara cuando un registro existente se actualiza en Inightly (requiere configuración de webhook)",
"Fires when a record is deleted from Insightly": "Dispara cuando un registro se borra de Insightly",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "El tipo de objeto Insightly a monitorear para nuevos registros",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for updates": "El tipo de objeto Insightly a monitorear para actualizaciones",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for deletions": "El tipo de objeto insocalvado a monitorizar para eliminaciones"
}

View File

@@ -0,0 +1,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Entrez votre clé API Insightly . Vous pouvez la trouver dans votre compte Insightly sous Paramètres utilisateur > Clés API.",
"Create Record": "Créer un enregistrement",
"Update Record": "Mettre à jour l'enregistrement",
"Get Record": "Obtenir un enregistrement",
"Delete Record": "Supprimer l'enregistrement",
"Find Records": "Trouver des enregistrements",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "Créer un nouvel enregistrement dans un objet Insightly spécifié (Contact, Prospect, Opportunité, etc.)",
"Update an existing record's fields in a specified Insightly object": "Mettre à jour les champs d'un enregistrement existant dans un objet Insightly spécifié",
"Get a record by ID from a specified Insightly object": "Récupère un enregistrement par ID à partir d'un objet Insightly spécifié",
"Delete a record by ID from a specified Insightly object": "Supprimer un enregistrement par ID à partir d'un objet Insightly spécifié",
"Find records in a specified Insightly object": "Rechercher des enregistrements dans un objet Insightly spécifié",
"Pod": "Pod",
"Object Type": "Type d'objet",
"Fields": "Champs",
"Record ID": "ID de l'enregistrement",
"Field Name": "Nom du champ",
"Field Value": "Valeur du champ",
"Limit": "Limite",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Votre pod Insightly (ex: \"na1\", \"eu1\"). Trouvez ceci dans votre URL API : https://api.{pod}.insightly.com",
"Select the type of record to create": "Sélectionnez le type d'enregistrement à créer",
"Select the type of object that contains the record you want to update": "Sélectionnez le type d'objet qui contient l'enregistrement que vous souhaitez mettre à jour",
"Select the record to update": "Sélectionnez l'enregistrement à mettre à jour",
"The new field values to update.": "Les nouvelles valeurs de champ à mettre à jour.",
"Select the type of record to retrieve": "Sélectionnez le type d'enregistrement à récupérer",
"Select the record to retrieve": "Sélectionnez l'enregistrement à récupérer",
"Select the type of record to delete": "Sélectionnez le type d'enregistrement à supprimer",
"Select the record to delete": "Sélectionnez l'enregistrement à supprimer",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "Votre pod Insightly (ex : \"na1\", \"eu1\").",
"Select the type of records to find": "Sélectionnez le type d'enregistrements à trouver",
"Select the field to search by": "Sélectionnez le champ de recherche par",
"The value to search for": "La valeur à rechercher",
"Maximum number of records to return": "Nombre maximum d'enregistrements à retourner",
"Contact": "Contacter",
"Lead": "Prospect",
"Opportunity": "Opportunité",
"Organization": "Organisation",
"Project": "Votre compte",
"Task": "Tâche",
"Event": "Evénement",
"Product": "Produit",
"Quote": "Devis",
"New Record": "Nouvel enregistrement",
"Updated Record": "Enregistrement mis à jour",
"Deleted Record": "Enregistrement supprimé",
"Fires when a new record is created in Insightly (requires webhook setup)": "Se déclenche lorsqu'un nouvel enregistrement est créé dans Insightly (nécessite la configuration du webhook)",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Déclenche lorsqu'un enregistrement existant est mis à jour dans Insightly (nécessite la configuration du webhook)",
"Fires when a record is deleted from Insightly": "Se déclenche lorsqu'un enregistrement est supprimé de Insightly",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "Le type d'objet Insightly à surveiller pour les nouveaux enregistrements",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**URL du Webhook :**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Allez dans **Paramètres système > Automatisation du flux de travail** dans votre compte Insightly\n2. Créez un nouveau processus de flux de travail pour le **Type d'objet** désiré.\n3. Définissez le déclencheur à **\"Quand un enregistrement est créé\"**.\n4. Sous \"Actions immédiates\", ajoutez une nouvelle action et sélectionnez **\"Ajouter un nouveau Webhook\"**.\n5. Collez l'URL du webhook ci-dessus dans le champ **URI** et enregistrez le workflow.\n ",
"The type of Insightly object to monitor for updates": "Le type d'objet Insightly à surveiller pour les mises à jour",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**URL du Webhook :**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Allez dans **Paramètres système > Automatisation du flux de travail** dans votre compte Insightly\n2. Créer un nouveau processus de flux de travail pour le **Type d'objet**.\n3. Définit le déclencheur à **\"Quand un enregistrement est créé et quand un enregistrement est modifié\"**.\n4. Sous \"Actions immédiates\", ajoutez une nouvelle action et sélectionnez **\"Ajouter un nouveau Webhook\"**.\n5. Collez l'URL du webhook ci-dessus dans le champ **URI** et enregistrez le workflow.\n ",
"The type of Insightly object to monitor for deletions": "Le type d'objet Insightly à surveiller pour les suppressions"
}

View File

@@ -0,0 +1,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Insightly APIキーを入力します。Insightlyアカウントのformat@@0>format@@1キーで確認できます。",
"Create Record": "レコードを作成",
"Update Record": "更新記録",
"Get Record": "レコードを取得",
"Delete Record": "レコードを削除",
"Find Records": "レコードを検索",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "指定されたInsightlyオブジェクト(連絡先、リード、商談など)に新しいレコードを作成します。",
"Update an existing record's fields in a specified Insightly object": "Insightlyオブジェクト内の既存のレコードのフィールドを更新します",
"Get a record by ID from a specified Insightly object": "InsightlyオブジェクトからIDでレコードを取得する",
"Delete a record by ID from a specified Insightly object": "InsightlyオブジェクトからIDでレコードを削除する",
"Find records in a specified Insightly object": "Insightlyオブジェクト内のレコードを検索",
"Pod": "ポッド",
"Object Type": "オブジェクトの種類",
"Fields": "フィールド",
"Record ID": "レコードID",
"Field Name": "フィールド名",
"Field Value": "フィールド値",
"Limit": "制限",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Insightlyポッド\"na1\", \"eu1\"。API URLからこれを見つけてくださいhttps://api.{pod}.insightly.com",
"Select the type of record to create": "作成するレコードの種類を選択します",
"Select the type of object that contains the record you want to update": "更新するレコードを含むオブジェクトの種類を選択します",
"Select the record to update": "更新するレコードを選択してください",
"The new field values to update.": "更新する新しいフィールドの値。",
"Select the type of record to retrieve": "取得するレコードの種類を選択してください",
"Select the record to retrieve": "取得するレコードを選択してください",
"Select the type of record to delete": "削除するレコードの種類を選択します",
"Select the record to delete": "削除するレコードを選択します",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "目を見張るポッド(例:\"na1\", \"eu1\")。",
"Select the type of records to find": "検索するレコードの種類を選択してください",
"Select the field to search by": "検索するフィールドを選択してください",
"The value to search for": "検索する値",
"Maximum number of records to return": "Maximum number of records to return",
"Contact": "お問い合わせ",
"Lead": "リード",
"Opportunity": "機会",
"Organization": "組織",
"Project": "プロジェクト",
"Task": "タスク",
"Event": "イベント",
"Product": "商品",
"Quote": "引用",
"New Record": "新しいレコード",
"Updated Record": "更新されたレコード",
"Deleted Record": "削除されたレコード",
"Fires when a new record is created in Insightly (requires webhook setup)": "Insightlyで新しいレコードが作成されたときに発生しますWebフックの設定が必要です",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Insightly で既存のレコードが更新されたときに発行されます (webhook の設定が必要)",
"Fires when a record is deleted from Insightly": "Insightly からレコードが削除されたときに発生します。",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "新しいレコードを監視するInsightlyオブジェクトのタイプ",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for updates": "更新を監視するInsightlyオブジェクト",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for deletions": "削除を監視するInsightlyオブジェクト"
}

View File

@@ -0,0 +1,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Voer je Insightly API-sleutel in. Je vindt dit in je Insight-account onder Gebruikersinstellingen > API-sleutels.",
"Create Record": "Record Maken",
"Update Record": "Update Record",
"Get Record": "Krijg Record",
"Delete Record": "Record verwijderen",
"Find Records": "Records zoeken",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "Maak een nieuw record in een geïnformeerd object (Contact, Lead, Opportunity, etc.)",
"Update an existing record's fields in a specified Insightly object": "Update een bestaand record velden in een specifiek Insightly object",
"Get a record by ID from a specified Insightly object": "Krijg een record via ID van een geïnstrueerd Insightly object",
"Delete a record by ID from a specified Insightly object": "Verwijder een record via ID van een geïnsight-object",
"Find records in a specified Insightly object": "Vind records in een specifiek Insightly object",
"Pod": "Pod",
"Object Type": "Object type",
"Fields": "Velden",
"Record ID": "Record ID",
"Field Name": "Veld naam",
"Field Value": "Veld waarde",
"Limit": "Limiet",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Uw Insightly pod (bijv. \"na1\", \"eu1\"). Vind dit in uw API URL: https://api.{pod}.insightly.com",
"Select the type of record to create": "Selecteer het te maken type record",
"Select the type of object that contains the record you want to update": "Selecteer het type object dat het record bevat dat u wilt bijwerken",
"Select the record to update": "Selecteer de te updaten record",
"The new field values to update.": "Het nieuwe veld waarden bij te werken.",
"Select the type of record to retrieve": "Selecteer het type record dat u wilt ophalen",
"Select the record to retrieve": "Selecteer de op te halen record",
"Select the type of record to delete": "Selecteer het type record dat u wilt verwijderen",
"Select the record to delete": "Selecteer het record om te verwijderen",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "Je Insightly pod (bijv. \"na1\", \"eu1\").",
"Select the type of records to find": "Selecteer het type records te vinden",
"Select the field to search by": "Selecteer het veld waarop gezocht moet worden",
"The value to search for": "De waarde waarnaar gezocht moet worden",
"Maximum number of records to return": "Maximum aantal records om te retourneren",
"Contact": "Contactpersoon",
"Lead": "Lood",
"Opportunity": "Kans",
"Organization": "Rekening",
"Project": "Project",
"Task": "Opdracht",
"Event": "Gebeurtenis",
"Product": "product",
"Quote": "Offerte",
"New Record": "Nieuwe Record",
"Updated Record": "Bijgewerkt Record",
"Deleted Record": "Verwijderde record",
"Fires when a new record is created in Insightly (requires webhook setup)": "Schiet wanneer een nieuwe record wordt gemaakt in Insightly (vereist webhook setup)",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Vuurt wanneer een bestaand record wordt bijgewerkt in het Insightly (vereist webhook setup)",
"Fires when a record is deleted from Insightly": "Vuurt wanneer een record wordt verwijderd uit Insightly",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "Het type Insightly object om te monitoren voor nieuwe records",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructies:**\n1. Ga naar **System Settings > Workflow Automation** in uw Insightly account.\n2. Maak een nieuw Workflow Proces voor het gewenste **Object Type**.\n3. Stel de trigger in op **\"Wanneer een record is aangemaakt\"**.\n4. Onder \"Onmiddellijke acties\" voeg een nieuwe actie toe en selecteer **\"Nieuwe Webhook toevoegen\"**.\n5. Plak de webhook URL hierboven in het **URI** veld en sla de workflow op.\n ",
"The type of Insightly object to monitor for updates": "Het type Insightly object om te monitoren voor updates",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructies:**\n1. Ga naar **Systeeminstellingen > Workflow Automation** in uw Insightly account.\n2. Maak een nieuw workflow proces voor het gewenste **objecttype**.\n3. Stel de trigger in op **\"Wanneer een record is aangemaakt en wanneer een record is bewerkt\"**.\n4. Onder \"Onmiddellijke acties\" voeg een nieuwe actie toe en selecteer **\"Nieuwe Webhook toevoegen\"**.\n5. Plak de webhook URL hierboven in het **URI** veld en sla de workflow op.\n ",
"The type of Insightly object to monitor for deletions": "Het type Insightly object om te monitoren voor verwijderingen"
}

View File

@@ -0,0 +1,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Digite sua chave de API Insightly . Você pode encontrar isso em sua conta Insightly em configurações de usuário > chaves de API.",
"Create Record": "Criar Registro",
"Update Record": "Atualizar Registro",
"Get Record": "Obter Registro",
"Delete Record": "Excluir registro",
"Find Records": "Encontrar registros",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "Criar um novo registro em um objeto Insightly especificado (Contato, Potencial, Oportunidade, etc.)",
"Update an existing record's fields in a specified Insightly object": "Atualizar campos de registro existente em um objeto Insightly especificado",
"Get a record by ID from a specified Insightly object": "Obter um registro de um objeto Insightly especificado",
"Delete a record by ID from a specified Insightly object": "Exclua um registro por ID de um objeto Insightly especificado",
"Find records in a specified Insightly object": "Encontrar registros em um objeto Insightly especificado",
"Pod": "Pod",
"Object Type": "Tipo de objeto",
"Fields": "campos",
"Record ID": "ID do Registro",
"Field Name": "Nome do campo",
"Field Value": "Valor do Campo",
"Limit": "Limitar",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Seu pod Insightly (ex: \"na1\", \"eu1\"). Encontre isso na URL da sua API: https://api.{pod}.insightly.com",
"Select the type of record to create": "Selecione o tipo de registro a criar",
"Select the type of object that contains the record you want to update": "Selecione o tipo de objeto que contém o registro que deseja atualizar.",
"Select the record to update": "Selecione o registro para atualização",
"The new field values to update.": "Os novos valores de campo para atualizar.",
"Select the type of record to retrieve": "Selecione o tipo de registro a ser recuperado",
"Select the record to retrieve": "Selecione o registro para recuperar",
"Select the type of record to delete": "Selecione o tipo de registro para excluir",
"Select the record to delete": "Selecione o registro para excluir",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "Seu pod Insightly (ex: \"na1\", \"eu1\").",
"Select the type of records to find": "Selecione o tipo de registros a serem encontrados.",
"Select the field to search by": "Selecione o campo para pesquisar por",
"The value to search for": "O valor para pesquisar",
"Maximum number of records to return": "Número máximo de registros para retornar",
"Contact": "contato",
"Lead": "Conduzir",
"Opportunity": "Oportunidade",
"Organization": "Cliente",
"Project": "Projecto",
"Task": "Tarefas",
"Event": "Evento",
"Product": "Produto:",
"Quote": "Cotação",
"New Record": "Novo Registro",
"Updated Record": "Registro atualizado",
"Deleted Record": "Registro excluído",
"Fires when a new record is created in Insightly (requires webhook setup)": "Atira quando um novo registro é criado na Insightly (requer configuração do webhook)",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Atira quando um registro existente é atualizado na Insightly (requer configuração do webhook)",
"Fires when a record is deleted from Insightly": "Atira quando um registro é excluído da Insightly",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "O tipo de objeto Insightly para monitorar novos registros",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for updates": "O tipo de objeto Insightly a ser monitorado para atualizações",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for deletions": "O tipo de objeto Insightly a monitorar para exclusões"
}

View File

@@ -0,0 +1,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.",
"Create Record": "Create Record",
"Update Record": "Update Record",
"Get Record": "Get Record",
"Delete Record": "Delete Record",
"Find Records": "Find Records",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)",
"Update an existing record's fields in a specified Insightly object": "Update an existing record's fields in a specified Insightly object",
"Get a record by ID from a specified Insightly object": "Get a record by ID from a specified Insightly object",
"Delete a record by ID from a specified Insightly object": "Delete a record by ID from a specified Insightly object",
"Find records in a specified Insightly object": "Find records in a specified Insightly object",
"Pod": "Pod",
"Object Type": "Object Type",
"Fields": "Fields",
"Record ID": "Record ID",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Limit": "Limit",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com",
"Select the type of record to create": "Select the type of record to create",
"Select the type of object that contains the record you want to update": "Select the type of object that contains the record you want to update",
"Select the record to update": "Select the record to update",
"The new field values to update.": "The new field values to update.",
"Select the type of record to retrieve": "Select the type of record to retrieve",
"Select the record to retrieve": "Select the record to retrieve",
"Select the type of record to delete": "Select the type of record to delete",
"Select the record to delete": "Select the record to delete",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "Your Insightly pod (e.g., \"na1\", \"eu1\").",
"Select the type of records to find": "Select the type of records to find",
"Select the field to search by": "Select the field to search by",
"The value to search for": "The value to search for",
"Maximum number of records to return": "Maximum number of records to return",
"Contact": "Contact",
"Lead": "Lead",
"Opportunity": "Opportunity",
"Organization": "Organization",
"Project": "Project",
"Task": "Task",
"Event": "Event",
"Product": "Product",
"Quote": "Quote",
"New Record": "New Record",
"Updated Record": "Updated Record",
"Deleted Record": "Deleted Record",
"Fires when a new record is created in Insightly (requires webhook setup)": "Fires when a new record is created in Insightly (requires webhook setup)",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Fires when an existing record is updated in Insightly (requires webhook setup)",
"Fires when a record is deleted from Insightly": "Fires when a record is deleted from Insightly",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "The type of Insightly object to monitor for new records",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for updates": "The type of Insightly object to monitor for updates",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for deletions": "The type of Insightly object to monitor for deletions"
}

View File

@@ -0,0 +1,55 @@
{
"Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.": "Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.",
"Create Record": "Create Record",
"Update Record": "Update Record",
"Get Record": "Get Record",
"Delete Record": "Delete Record",
"Find Records": "Find Records",
"Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)": "Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)",
"Update an existing record's fields in a specified Insightly object": "Update an existing record's fields in a specified Insightly object",
"Get a record by ID from a specified Insightly object": "Get a record by ID from a specified Insightly object",
"Delete a record by ID from a specified Insightly object": "Delete a record by ID from a specified Insightly object",
"Find records in a specified Insightly object": "Find records in a specified Insightly object",
"Pod": "Pod",
"Object Type": "Object Type",
"Fields": "Fields",
"Record ID": "Record ID",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Limit": "Limit",
"Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com": "Your Insightly pod (e.g., \"na1\", \"eu1\"). Find this in your API URL: https://api.{pod}.insightly.com",
"Select the type of record to create": "Select the type of record to create",
"Select the type of object that contains the record you want to update": "Select the type of object that contains the record you want to update",
"Select the record to update": "Select the record to update",
"The new field values to update.": "The new field values to update.",
"Select the type of record to retrieve": "Select the type of record to retrieve",
"Select the record to retrieve": "Select the record to retrieve",
"Select the type of record to delete": "Select the type of record to delete",
"Select the record to delete": "Select the record to delete",
"Your Insightly pod (e.g., \"na1\", \"eu1\").": "Your Insightly pod (e.g., \"na1\", \"eu1\").",
"Select the type of records to find": "Select the type of records to find",
"Select the field to search by": "Select the field to search by",
"The value to search for": "The value to search for",
"Maximum number of records to return": "Maximum number of records to return",
"Contact": "Contact",
"Lead": "Lead",
"Opportunity": "Opportunity",
"Organization": "Organization",
"Project": "项目",
"Task": "Task",
"Event": "Event",
"Product": "Product",
"Quote": "Quote",
"New Record": "New Record",
"Updated Record": "Updated Record",
"Deleted Record": "Deleted Record",
"Fires when a new record is created in Insightly (requires webhook setup)": "Fires when a new record is created in Insightly (requires webhook setup)",
"Fires when an existing record is updated in Insightly (requires webhook setup)": "Fires when an existing record is updated in Insightly (requires webhook setup)",
"Fires when a record is deleted from Insightly": "Fires when a record is deleted from Insightly",
"Markdown": "Markdown",
"The type of Insightly object to monitor for new records": "The type of Insightly object to monitor for new records",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for updates": "The type of Insightly object to monitor for updates",
"\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ": "\n**Webhook URL:**\n```text\n{{webhookUrl}}\n```\n**Instructions:**\n1. Go to **System Settings > Workflow Automation** in your Insightly account.\n2. Create a new Workflow Process for the desired **Object Type**.\n3. Set the trigger to **\"When a record is created and when a record is edited\"**.\n4. Under \"Immediate Actions,\" add a new action and select **\"Add New Webhook\"**.\n5. Paste the webhook URL above into the **URI** field and save the workflow.\n ",
"The type of Insightly object to monitor for deletions": "The type of Insightly object to monitor for deletions"
}

View File

@@ -0,0 +1,20 @@
import { createPiece } from '@activepieces/pieces-framework';
import { insightlyAuth } from './lib/common/common';
import { createRecord } from './lib/actions/create-record';
import { updateRecord } from './lib/actions/update-record';
import { getRecord } from './lib/actions/get-record';
import { deleteRecord } from './lib/actions/delete-record';
import { findRecords } from './lib/actions/find-records';
import { newRecord } from './lib/triggers/new-record';
import { updatedRecord } from './lib/triggers/updated-record';
import { deletedRecord } from './lib/triggers/deleted-record';
export const insightly = createPiece({
displayName: 'Insightly',
auth: insightlyAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: 'https://cdn.activepieces.com/pieces/insightly.png',
authors: ['fortunamide', 'onyedikachi-david'],
actions: [createRecord, updateRecord, getRecord, deleteRecord, findRecords],
triggers: [newRecord, updatedRecord, deletedRecord]
});

View File

@@ -0,0 +1,122 @@
import { createAction, Property, DynamicPropsValue } from '@activepieces/pieces-framework';
import {
HttpMethod,
} from '@activepieces/pieces-common';
import { insightlyAuth, makeInsightlyRequest } from '../common/common';
import {
contactFields,
leadFields,
opportunityFields,
organisationFields,
projectFields,
taskFields,
eventFields,
productFields,
quotationFields,
} from '../common/props';
export const createRecord = createAction({
auth: insightlyAuth,
name: 'create_record',
displayName: 'Create Record',
description:
'Create a new record in a specified Insightly object (Contact, Lead, Opportunity, etc.)',
props: {
pod: Property.ShortText({
displayName: 'Pod',
description: 'Your Insightly pod (e.g., "na1", "eu1"). Find this in your API URL: https://api.{pod}.insightly.com',
required: true,
defaultValue: 'na1'
}),
objectName: Property.StaticDropdown({
displayName: 'Object Type',
description: 'Select the type of record to create',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' },
{ label: 'Product', value: 'Products' },
{ label: 'Quote', value: 'Quotations' }
]
}
}),
fields: Property.DynamicProperties({
auth: insightlyAuth,
displayName: 'Fields',
required: true,
refreshers: ['objectName'],
props: async ({ auth, objectName }) => {
if (!objectName) return {};
const objName = objectName as unknown as string;
const fields: DynamicPropsValue = {};
switch (objName) {
case 'Contacts':
Object.assign(fields, contactFields);
break;
case 'Leads':
Object.assign(fields, leadFields);
break;
case 'Opportunities':
Object.assign(fields, opportunityFields);
break;
case 'Organisations':
Object.assign(fields, organisationFields);
break;
case 'Projects':
Object.assign(fields, projectFields);
break;
case 'Tasks':
Object.assign(fields, taskFields);
break;
case 'Events':
Object.assign(fields, eventFields);
break;
case 'Products':
Object.assign(fields, productFields);
break;
case 'Quotations':
Object.assign(fields, quotationFields);
break;
}
return fields;
}
})
},
async run(context) {
const { pod, objectName, fields } = context.propsValue;
const recordData = { ...fields };
if (!recordData || Object.keys(recordData).length === 0) {
throw new Error('Field values must be provided to create the record');
}
try {
const response = await makeInsightlyRequest(
context.auth,
`/${objectName as string}`,
pod as string,
HttpMethod.POST,
recordData
);
const recordIdKey = Object.keys(response.body).find(key => key.endsWith('_ID'));
const recordId = recordIdKey ? response.body[recordIdKey] : undefined;
return {
success: true,
recordId: recordId,
...response.body
};
} catch (error: any) {
throw new Error(`Failed to create record: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,104 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import {
HttpMethod
} from '@activepieces/pieces-common';
import { insightlyAuth, makeInsightlyRequest } from '../common/common';
export const deleteRecord = createAction({
auth: insightlyAuth,
name: 'delete_record',
displayName: 'Delete Record',
description: 'Delete a record by ID from a specified Insightly object',
props: {
pod: Property.ShortText({
displayName: 'Pod',
description: 'Your Insightly pod (e.g., "na1", "eu1"). Find this in your API URL: https://api.{pod}.insightly.com',
required: true,
defaultValue: 'na1'
}),
objectName: Property.StaticDropdown({
displayName: 'Object Type',
description: 'Select the type of record to delete',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' },
{ label: 'Product', value: 'Products' },
{ label: 'Quote', value: 'Quotations' }
]
}
}),
recordId: Property.Dropdown({
auth: insightlyAuth,
displayName: 'Record ID',
description: 'Select the record to delete',
required: true,
refreshers: ['objectName', 'pod'],
options: async ({ auth, objectName, pod }) => {
if (!objectName || !pod || !auth) {
return {
disabled: true,
placeholder: 'Please select an object type and pod first',
options: []
};
}
const response = await makeInsightlyRequest(
auth,
`/${objectName}?top=100&brief=true`,
pod as string
);
const records = Array.isArray(response.body) ? response.body : [];
return {
options: records.map((record: any) => {
const idKey = Object.keys(record).find(key => key.endsWith('_ID'));
const recordId = idKey ? record[idKey] : 'Unknown ID';
const nameKey = Object.keys(record).find(key => key.endsWith('_NAME') || key === 'TITLE' || key === 'FIRST_NAME');
let recordName = nameKey ? record[nameKey] : `Record ${recordId}`;
if (objectName === 'Contacts' || objectName === 'Leads') {
recordName = `${record.FIRST_NAME || ''} ${record.LAST_NAME || ''}`.trim();
}
return {
label: `${recordName} (ID: ${recordId})`,
value: recordId
};
})
};
}
})
},
async run(context) {
const { pod, objectName, recordId } = context.propsValue;
try {
await makeInsightlyRequest(
context.auth,
`/${objectName as string}/${recordId as string}`,
pod as string,
HttpMethod.DELETE
);
return {
success: true,
message: `Record ${recordId} successfully deleted from ${objectName}`
};
} catch (error: any) {
if (error.response?.status === 404) {
throw new Error(`Record with ID ${recordId} not found in ${objectName}`);
} else {
throw new Error(`Failed to delete record: ${error.message}`);
}
}
},
});

View File

@@ -0,0 +1,118 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import {
HttpMethod
} from '@activepieces/pieces-common';
import { insightlyAuth, makeInsightlyRequest } from '../common/common';
import {
contactFields,
leadFields,
opportunityFields,
organisationFields,
projectFields,
taskFields,
eventFields,
productFields,
quotationFields,
} from '../common/props';
export const findRecords = createAction({
auth: insightlyAuth,
name: 'find_records',
displayName: 'Find Records',
description: 'Find records in a specified Insightly object',
props: {
pod: Property.ShortText({
displayName: 'Pod',
description: 'Your Insightly pod (e.g., "na1", "eu1").',
required: true,
defaultValue: 'na1'
}),
objectName: Property.StaticDropdown({
displayName: 'Object Type',
description: 'Select the type of records to find',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' },
{ label: 'Product', value: 'Products' },
{ label: 'Quote', value: 'Quotations' }
]
}
}),
fieldName: Property.Dropdown({
auth: insightlyAuth,
displayName: 'Field Name',
description: 'Select the field to search by',
required: true,
refreshers: ['objectName'],
options: async ({ objectName }) => {
if (!objectName) {
return {
disabled: true,
placeholder: 'Select an object type first',
options: []
};
}
let fields: any = {};
switch (objectName as string) {
case 'Contacts': fields = contactFields; break;
case 'Leads': fields = leadFields; break;
case 'Opportunities': fields = opportunityFields; break;
case 'Organisations': fields = organisationFields; break;
case 'Projects': fields = projectFields; break;
case 'Tasks': fields = taskFields; break;
case 'Events': fields = eventFields; break;
case 'Products': fields = productFields; break;
case 'Quotations': fields = quotationFields; break;
}
return {
options: Object.keys(fields).map(key => ({
label: fields[key].displayName,
value: key
}))
};
}
}),
fieldValue: Property.ShortText({
displayName: 'Field Value',
description: 'The value to search for',
required: true
}),
top: Property.Number({
displayName: 'Limit',
description: 'Maximum number of records to return',
required: false
})
},
async run(context) {
const { pod, objectName, fieldName, fieldValue, top } = context.propsValue;
const queryParams = new URLSearchParams({
field_name: fieldName as string,
field_value: fieldValue as string,
});
if (top) {
queryParams.append('top', top.toString());
}
try {
const response = await makeInsightlyRequest(
context.auth,
`/${objectName}/Search?${queryParams.toString()}`,
pod as string,
HttpMethod.GET
);
return response.body;
} catch (error: any) {
throw new Error(`Failed to find records: ${error.message}`);
}
}
});

View File

@@ -0,0 +1,102 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import {
HttpMethod
} from '@activepieces/pieces-common';
import { insightlyAuth, makeInsightlyRequest } from '../common/common';
export const getRecord = createAction({
auth: insightlyAuth,
name: 'get_record',
displayName: 'Get Record',
description: 'Get a record by ID from a specified Insightly object',
props: {
pod: Property.ShortText({
displayName: 'Pod',
description: 'Your Insightly pod (e.g., "na1", "eu1"). Find this in your API URL: https://api.{pod}.insightly.com',
required: true,
defaultValue: 'na1'
}),
objectName: Property.StaticDropdown({
displayName: 'Object Type',
description: 'Select the type of record to retrieve',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' },
{ label: 'Product', value: 'Products' },
{ label: 'Quote', value: 'Quotations' }
]
}
}),
recordId: Property.Dropdown({
auth: insightlyAuth,
displayName: 'Record ID',
description: 'Select the record to retrieve',
required: true,
refreshers: ['objectName', 'pod'],
options: async ({ auth, objectName, pod }) => {
if (!objectName || !pod || !auth) {
return {
disabled: true,
placeholder: 'Please select an object type and pod first',
options: []
};
}
const response = await makeInsightlyRequest(
auth,
`/${objectName}?top=100&brief=true`,
pod as string
);
const records = Array.isArray(response.body) ? response.body : [];
return {
options: records.map((record: any) => {
const idKey = Object.keys(record).find(key => key.endsWith('_ID'));
const recordId = idKey ? record[idKey] : 'Unknown ID';
const nameKey = Object.keys(record).find(key => key.endsWith('_NAME') || key === 'TITLE' || key === 'FIRST_NAME');
let recordName = nameKey ? record[nameKey] : `Record ${recordId}`;
if (objectName === 'Contacts' || objectName === 'Leads') {
recordName = `${record.FIRST_NAME || ''} ${record.LAST_NAME || ''}`.trim();
}
return {
label: `${recordName} (ID: ${recordId})`,
value: recordId
};
})
};
}
})
},
async run(context) {
const { pod, objectName, recordId } = context.propsValue;
try {
const response = await makeInsightlyRequest(
context.auth,
`/${objectName as string}/${recordId as string}`,
pod as string,
HttpMethod.GET
);
return response.body;
} catch (error: any) {
// Handle specific error cases
if (error.response?.status === 404) {
throw new Error(`Record with ID ${recordId} not found in ${objectName}`);
} else {
throw new Error(`Failed to retrieve record: ${error.message}`);
}
}
},
});

View File

@@ -0,0 +1,211 @@
import { createAction, Property, DynamicPropsValue } from '@activepieces/pieces-framework';
import {
HttpMethod,
} from '@activepieces/pieces-common';
import { insightlyAuth, makeInsightlyRequest } from '../common/common';
import {
contactFields,
leadFields,
opportunityFields,
organisationFields,
projectFields,
taskFields,
eventFields,
productFields,
quotationFields,
} from '../common/props';
export const updateRecord = createAction({
auth: insightlyAuth,
name: 'update_record',
displayName: 'Update Record',
description:
"Update an existing record's fields in a specified Insightly object",
props: {
pod: Property.ShortText({
displayName: 'Pod',
description: 'Your Insightly pod (e.g., "na1", "eu1"). Find this in your API URL: https://api.{pod}.insightly.com',
required: true,
defaultValue: 'na1'
}),
objectName: Property.StaticDropdown({
displayName: 'Object Type',
description: 'Select the type of object that contains the record you want to update',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' },
{ label: 'Product', value: 'Products' },
{ label: 'Quote', value: 'Quotations' }
]
}
}),
recordId: Property.Dropdown({
auth: insightlyAuth,
displayName: 'Record ID',
description: 'Select the record to update',
required: true,
refreshers: ['objectName', 'pod'],
options: async ({ auth, objectName, pod }) => {
if (!objectName || !pod || !auth) {
return {
disabled: true,
placeholder: 'Please select an object type and pod first',
options: []
};
}
const response = await makeInsightlyRequest(
auth,
`/${objectName}?top=100&brief=true`,
pod as string
);
const records = Array.isArray(response.body) ? response.body : [];
return {
options: records.map((record: any) => {
const idKey = Object.keys(record).find(key => key.endsWith('_ID'));
const recordId = idKey ? record[idKey] : 'Unknown ID';
const nameKey = Object.keys(record).find(key => key.endsWith('_NAME') || key === 'TITLE' || key === 'FIRST_NAME');
let recordName = nameKey ? record[nameKey] : `Record ${recordId}`;
if (objectName === 'Contacts' || objectName === 'Leads') {
recordName = `${record.FIRST_NAME || ''} ${record.LAST_NAME || ''}`.trim();
}
return {
label: `${recordName} (ID: ${recordId})`,
value: recordId
};
})
};
}
}),
fields: Property.DynamicProperties({
auth: insightlyAuth,
displayName: 'Fields',
description: 'The new field values to update.',
required: true,
refreshers: ['objectName', 'recordId', 'pod'],
props: async ({ auth, objectName, recordId, pod }) => {
if (!objectName || !recordId || !pod || !auth) {
return {};
}
const objName = objectName as unknown as string;
const podName = pod as unknown as string;
const record = await makeInsightlyRequest(
auth,
`/${objName}/${recordId as unknown as string}`,
podName
);
let fieldDefinitions: any = {};
switch (objName) {
case 'Contacts':
fieldDefinitions = contactFields;
break;
case 'Leads':
fieldDefinitions = leadFields;
break;
case 'Opportunities':
fieldDefinitions = opportunityFields;
break;
case 'Organisations':
fieldDefinitions = organisationFields;
break;
case 'Projects':
fieldDefinitions = projectFields;
break;
case 'Tasks':
fieldDefinitions = taskFields;
break;
case 'Events':
fieldDefinitions = eventFields;
break;
case 'Products':
fieldDefinitions = productFields;
break;
case 'Quotations':
fieldDefinitions = quotationFields;
break;
}
// Clone the field definitions and set default values from the record
const fields: DynamicPropsValue = {};
for (const key in fieldDefinitions) {
const fieldDef = fieldDefinitions[key];
fields[key] = {
...fieldDef,
defaultValue: record.body[key]
};
}
return fields;
}
})
},
async run(context) {
const { pod, objectName, recordId, fields } = context.propsValue;
// Use the provided field values as the record data
const recordData = { ...fields };
// The API requires the ID in the body for PUT requests.
// We create the ID key dynamically, e.g., 'CONTACT_ID', 'OPPORTUNITY_ID'
const idKey = `${(objectName as string).slice(0, -1).toUpperCase()}_ID`;
recordData[idKey] = recordId;
try {
const response = await makeInsightlyRequest(
context.auth,
`/${objectName as string}/${recordId as string}`,
pod as string,
HttpMethod.PUT,
recordData
);
return {
success: true,
...response.body
};
} catch (error: any) {
// Handle specific error cases
if (error.response?.status === 400) {
const errorMessage =
error.response.body?.message ||
error.response.body?.error ||
'Invalid data provided or record not found';
const errorDetails = error.response.body
? JSON.stringify(error.response.body, null, 2)
: 'No details available';
throw new Error(
`Data validation error for ${objectName} ID ${recordId}: ${errorMessage}. ` +
`Sent data: ${JSON.stringify(recordData, null, 2)}. ` +
`API response: ${errorDetails}`
);
} else if (error.response?.status === 401) {
throw new Error(
'Authentication failed. Please check your API key and pod.'
);
} else if (error.response?.status === 402) {
throw new Error('Record limit reached for your Insightly plan.');
} else if (error.response?.status === 404) {
throw new Error(
`Record with ID ${recordId} not found in ${objectName}`
);
} else {
throw new Error(`Failed to update record: ${error.message}`);
}
}
}
});

View File

@@ -0,0 +1,51 @@
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
import { AppConnectionValueForAuthProperty, PieceAuth } from '@activepieces/pieces-framework';
export const insightlyAuth = PieceAuth.SecretText({
displayName: 'API Key',
description: 'Enter your Insightly API key. You can find this in your Insightly account under User Settings > API Keys.',
required: true,
});
export const INSIGHTLY_OBJECTS = [
'Contacts',
'Leads',
'Opportunities',
'Organisations',
'Projects',
'Tasks',
'Events',
'Notes',
'Products',
'Quotations'
];
export async function makeInsightlyRequest(
auth: AppConnectionValueForAuthProperty<typeof insightlyAuth>,
endpoint: string,
pod = 'na1',
method: HttpMethod = HttpMethod.GET,
body?: any
) {
const baseUrl = `https://api.${pod}.insightly.com/v3.1`;
const url = `${baseUrl}${endpoint}`;
const requestConfig: any = {
method,
url,
authentication: {
type: AuthenticationType.BASIC,
username: auth.secret_text,
password: '',
},
};
if (body && (method === HttpMethod.POST || method === HttpMethod.PUT)) {
requestConfig.headers = {
'Content-Type': 'application/json',
};
requestConfig.body = body;
}
return await httpClient.sendRequest(requestConfig);
}

View File

@@ -0,0 +1,689 @@
import { Property } from '@activepieces/pieces-framework';
// Helper function to create a common set of fields
const NameFields = {
SALUTATION: Property.ShortText({
displayName: 'Salutation',
required: false,
}),
FIRST_NAME: Property.ShortText({
displayName: 'First Name',
required: false,
}),
LAST_NAME: Property.ShortText({
displayName: 'Last Name',
required: false,
}),
TITLE: Property.ShortText({
displayName: 'Title',
required: false,
}),
};
const ContactInfoFields = {
PHONE: Property.ShortText({
displayName: 'Phone',
required: false,
}),
PHONE_HOME: Property.ShortText({
displayName: 'Home Phone',
required: false,
}),
PHONE_MOBILE: Property.ShortText({
displayName: 'Mobile Phone',
required: false,
}),
PHONE_OTHER: Property.ShortText({
displayName: 'Other Phone',
required: false,
}),
PHONE_ASSISTANT: Property.ShortText({
displayName: 'Assistant Phone',
required: false,
}),
PHONE_FAX: Property.ShortText({
displayName: 'Fax',
required: false,
}),
EMAIL_ADDRESS: Property.ShortText({
displayName: 'Email Address',
required: false,
}),
};
const AddressFields = (type: 'Mail' | 'Other') => ({
[`ADDRESS_${type.toUpperCase()}_STREET`]: Property.ShortText({
displayName: `${type} Street`,
required: false,
}),
[`ADDRESS_${type.toUpperCase()}_CITY`]: Property.ShortText({
displayName: `${type} City`,
required: false,
}),
[`ADDRESS_${type.toUpperCase()}_STATE`]: Property.ShortText({
displayName: `${type} State`,
required: false,
}),
[`ADDRESS_${type.toUpperCase()}_POSTCODE`]: Property.ShortText({
displayName: `${type} Postcode`,
required: false,
}),
[`ADDRESS_${type.toUpperCase()}_COUNTRY`]: Property.ShortText({
displayName: `${type} Country`,
required: false,
}),
});
export const contactFields = {
...NameFields,
...ContactInfoFields,
...AddressFields('Mail'),
...AddressFields('Other'),
BACKGROUND: Property.LongText({
displayName: 'Background',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: false,
}),
SOCIAL_LINKEDIN: Property.ShortText({
displayName: 'LinkedIn',
required: false,
}),
SOCIAL_FACEBOOK: Property.ShortText({
displayName: 'Facebook',
required: false,
}),
SOCIAL_TWITTER: Property.ShortText({
displayName: 'Twitter',
required: false,
}),
DATE_OF_BIRTH: Property.ShortText({
displayName: 'Date of Birth',
description: 'Format: YYYY-MM-DD',
required: false,
}),
ASSISTANT_NAME: Property.ShortText({
displayName: 'Assistant Name',
required: false,
}),
ORGANISATION_ID: Property.Number({
displayName: 'Organization ID',
required: false,
}),
EMAIL_OPTED_OUT: Property.Checkbox({
displayName: 'Email Opted Out',
required: false,
}),
};
export const leadFields = {
...NameFields,
LEAD_SOURCE_ID: Property.Number({
displayName: 'Lead Source ID',
required: true,
}),
LEAD_STATUS_ID: Property.Number({
displayName: 'Lead Status ID',
required: true,
}),
EMAIL: Property.ShortText({
displayName: 'Email',
required: false,
}),
EMPLOYEE_COUNT: Property.Number({
displayName: 'Employee Count',
required: false,
}),
FAX: Property.ShortText({
displayName: 'Fax',
required: false,
}),
INDUSTRY: Property.ShortText({
displayName: 'Industry',
required: false,
}),
LEAD_DESCRIPTION: Property.LongText({
displayName: 'Lead Description',
required: false,
}),
LEAD_RATING: Property.Number({
displayName: 'Lead Rating',
required: false,
}),
MOBILE: Property.ShortText({
displayName: 'Mobile',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: false,
}),
PHONE: Property.ShortText({
displayName: 'Phone',
required: false,
}),
RESPONSIBLE_USER_ID: Property.Number({
displayName: 'Responsible User ID',
required: false,
}),
WEBSITE: Property.ShortText({
displayName: 'Website',
required: false,
}),
ADDRESS_STREET: Property.ShortText({
displayName: 'Street',
required: false,
}),
ADDRESS_CITY: Property.ShortText({
displayName: 'City',
required: false,
}),
ADDRESS_STATE: Property.ShortText({
displayName: 'State',
required: false,
}),
ADDRESS_POSTCODE: Property.ShortText({
displayName: 'Postcode',
required: false,
}),
ADDRESS_COUNTRY: Property.ShortText({
displayName: 'Country',
required: false,
}),
ORGANISATION_NAME: Property.ShortText({
displayName: 'Organization Name',
required: false,
}),
EMAIL_OPTED_OUT: Property.Checkbox({
displayName: 'Email Opted Out',
required: false,
}),
};
// TODO: Define fields when API documentation is available
export const opportunityFields = {
OPPORTUNITY_NAME: Property.ShortText({
displayName: 'Opportunity Name',
required: true,
}),
OPPORTUNITY_DETAILS: Property.LongText({
displayName: 'Opportunity Details',
required: false,
}),
OPPORTUNITY_STATE: Property.StaticDropdown({
displayName: 'Opportunity State',
required: false,
options: {
options: [
{ label: 'Open', value: 'Open' },
{ label: 'Suspended', value: 'Suspended' },
{ label: 'Abandoned', value: 'Abandoned' },
{ label: 'Lost', value: 'Lost' },
{ label: 'Won', value: 'Won' },
]
}
}),
RESPONSIBLE_USER_ID: Property.Number({
displayName: 'Responsible User ID',
required: false,
}),
CATEGORY_ID: Property.Number({
displayName: 'Category ID',
required: false,
}),
BID_CURRENCY: Property.ShortText({
displayName: 'Bid Currency',
description: '3-letter currency code (e.g., USD)',
required: false,
}),
BID_AMOUNT: Property.Number({
displayName: 'Bid Amount',
required: false,
}),
BID_TYPE: Property.ShortText({
displayName: 'Bid Type',
description: 'e.g., "Fixed Bid", "Per Hour"',
required: false,
}),
BID_DURATION: Property.Number({
displayName: 'Bid Duration',
required: false,
}),
PROBABILITY: Property.Number({
displayName: 'Probability',
description: 'Value from 0 to 100',
required: false,
}),
FORECAST_CLOSE_DATE: Property.ShortText({
displayName: 'Forecast Close Date',
description: 'Format: YYYY-MM-DD',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: false,
}),
ORGANISATION_ID: Property.Number({
displayName: 'Organization ID',
required: false,
}),
PIPELINE_ID: Property.Number({
displayName: 'Pipeline ID',
required: false,
}),
STAGE_ID: Property.Number({
displayName: 'Stage ID',
required: false,
}),
PRICEBOOK_ID: Property.Number({
displayName: 'Pricebook ID',
required: false,
}),
};
export const organisationFields = {
ORGANISATION_NAME: Property.ShortText({
displayName: 'Organisation Name',
required: true,
}),
BACKGROUND: Property.LongText({
displayName: 'Background',
required: false,
}),
PHONE: Property.ShortText({
displayName: 'Phone',
required: false,
}),
PHONE_FAX: Property.ShortText({
displayName: 'Fax',
required: false,
}),
WEBSITE: Property.ShortText({
displayName: 'Website',
required: false,
}),
ADDRESS_BILLING_STREET: Property.ShortText({
displayName: 'Billing Street',
required: false,
}),
ADDRESS_BILLING_CITY: Property.ShortText({
displayName: 'Billing City',
required: false,
}),
ADDRESS_BILLING_STATE: Property.ShortText({
displayName: 'Billing State',
required: false,
}),
ADDRESS_BILLING_POSTCODE: Property.ShortText({
displayName: 'Billing Postcode',
required: false,
}),
ADDRESS_BILLING_COUNTRY: Property.ShortText({
displayName: 'Billing Country',
required: false,
}),
ADDRESS_SHIP_STREET: Property.ShortText({
displayName: 'Shipping Street',
required: false,
}),
ADDRESS_SHIP_CITY: Property.ShortText({
displayName: 'Shipping City',
required: false,
}),
ADDRESS_SHIP_STATE: Property.ShortText({
displayName: 'Shipping State',
required: false,
}),
ADDRESS_SHIP_POSTCODE: Property.ShortText({
displayName: 'Shipping Postcode',
required: false,
}),
ADDRESS_SHIP_COUNTRY: Property.ShortText({
displayName: 'Shipping Country',
required: false,
}),
SOCIAL_LINKEDIN: Property.ShortText({
displayName: 'LinkedIn',
required: false,
}),
SOCIAL_FACEBOOK: Property.ShortText({
displayName: 'Facebook',
required: false,
}),
SOCIAL_TWITTER: Property.ShortText({
displayName: 'Twitter',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: false,
}),
};
export const projectFields = {
PROJECT_NAME: Property.ShortText({
displayName: 'Project Name',
required: true,
}),
STATUS: Property.StaticDropdown({
displayName: 'Status',
required: true,
options: {
options: [
{ label: 'Not Started', value: 'NOT STARTED' },
{ label: 'In Progress', value: 'IN PROGRESS' },
{ label: 'On Hold', value: 'ON HOLD' },
{ label: 'Completed', value: 'COMPLETED' },
{ label: 'Cancelled', value: 'CANCELLED' },
]
}
}),
PROJECT_DETAILS: Property.LongText({
displayName: 'Project Details',
required: false,
}),
STARTED_DATE: Property.ShortText({
displayName: 'Started Date',
description: 'Format: YYYY-MM-DD',
required: false,
}),
COMPLETED_DATE: Property.ShortText({
displayName: 'Completed Date',
description: 'Format: YYYY-MM-DD',
required: false,
}),
OPPORTUNITY_ID: Property.Number({
displayName: 'Opportunity ID',
required: false,
}),
CATEGORY_ID: Property.Number({
displayName: 'Category ID',
required: false,
}),
PIPELINE_ID: Property.Number({
displayName: 'Pipeline ID',
required: false,
}),
STAGE_ID: Property.Number({
displayName: 'Stage ID',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: false,
}),
RESPONSIBLE_USER_ID: Property.Number({
displayName: 'Responsible User ID',
required: false,
}),
};
export const taskFields = {
TITLE: Property.ShortText({
displayName: 'Title',
required: true,
}),
STATUS: Property.StaticDropdown({
displayName: 'Status',
required: false,
options: {
options: [
{ label: 'Not Started', value: 'NOT STARTED' },
{ label: 'In Progress', value: 'IN PROGRESS' },
{ label: 'Waiting', value: 'WAITING' },
{ label: 'Completed', value: 'COMPLETED' },
{ label: 'Deferred', value: 'DEFERRED' },
]
}
}),
DETAILS: Property.LongText({
displayName: 'Details',
required: false,
}),
START_DATE: Property.ShortText({
displayName: 'Start Date',
description: 'Format: YYYY-MM-DD',
required: false,
}),
DUE_DATE: Property.ShortText({
displayName: 'Due Date',
description: 'Format: YYYY-MM-DD',
required: false,
}),
PERCENT_COMPLETE: Property.Number({
displayName: 'Percent Complete',
required: false,
}),
PRIORITY: Property.Number({
displayName: 'Priority',
description: '1 (Low), 2 (Normal), 3 (High)',
required: false,
}),
COMPLETED: Property.Checkbox({
displayName: 'Completed',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: true,
}),
RESPONSIBLE_USER_ID: Property.Number({
displayName: 'Responsible User ID',
required: false,
}),
PROJECT_ID: Property.Number({
displayName: 'Project ID',
required: false,
}),
OPPORTUNITY_ID: Property.Number({
displayName: 'Opportunity ID',
required: false,
}),
CATEGORY_ID: Property.Number({
displayName: 'Category ID',
required: false,
}),
MILESTONE_ID: Property.Number({
displayName: 'Milestone ID',
required: false,
}),
};
export const eventFields = {
TITLE: Property.ShortText({
displayName: 'Title',
required: true,
}),
LOCATION: Property.ShortText({
displayName: 'Location',
required: false,
}),
START_DATE_UTC: Property.ShortText({
displayName: 'Start Date (UTC)',
description: 'Format: YYYY-MM-DDTHH:MM:SSZ',
required: true,
}),
END_DATE_UTC: Property.ShortText({
displayName: 'End Date (UTC)',
description: 'Format: YYYY-MM-DDTHH:MM:SSZ',
required: true,
}),
ALL_DAY: Property.Checkbox({
displayName: 'All Day',
required: false,
}),
DETAILS: Property.LongText({
displayName: 'Details',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: false,
}),
};
export const noteFields = {
TITLE: Property.ShortText({
displayName: 'Title',
required: true,
}),
BODY: Property.LongText({
displayName: 'Body',
required: false,
}),
};
export const productFields = {
PRODUCT_NAME: Property.ShortText({
displayName: 'Product Name',
required: true,
}),
PRODUCT_CODE: Property.ShortText({
displayName: 'Product Code',
required: false,
}),
PRODUCT_SKU: Property.ShortText({
displayName: 'Product SKU',
required: false,
}),
DESCRIPTION: Property.LongText({
displayName: 'Description',
required: false,
}),
PRODUCT_FAMILY: Property.ShortText({
displayName: 'Product Family',
required: false,
}),
PRODUCT_IMAGE_URL: Property.ShortText({
displayName: 'Product Image URL',
required: false,
}),
DEFAULT_PRICE: Property.Number({
displayName: 'Default Price',
required: false,
}),
ACTIVE: Property.Checkbox({
displayName: 'Active',
required: false,
}),
OWNER_USER_ID: Property.Number({
displayName: 'Owner User ID',
required: false,
}),
CURRENCY_CODE: Property.ShortText({
displayName: 'Currency Code',
description: '3-letter currency code (e.g., USD)',
required: false,
}),
};
export const quotationFields = {
QUOTATION_NAME: Property.ShortText({
displayName: 'Quotation Name',
required: true,
}),
OPPORTUNITY_ID: Property.Number({
displayName: 'Opportunity ID',
required: true,
}),
QUOTE_STATUS: Property.StaticDropdown({
displayName: 'Quote Status',
required: false,
options: {
options: [
{ label: 'Draft', value: 'Draft' },
{ label: 'Awaiting Approval', value: 'Awaiting Approval' },
{ label: 'Approved', value: 'Approved' },
{ label: 'Sent', value: 'Sent' },
{ label: 'Accepted', value: 'Accepted' },
{ label: 'Declined', value: 'Declined' },
]
}
}),
QUOTATION_DESCRIPTION: Property.LongText({
displayName: 'Description',
required: false,
}),
QUOTATION_EXPIRATION_DATE: Property.ShortText({
displayName: 'Expiration Date',
description: 'Format: YYYY-MM-DD',
required: false,
}),
CONTACT_ID: Property.Number({
displayName: 'Contact ID',
required: false,
}),
ORGANISATION_ID: Property.Number({
displayName: 'Organisation ID',
required: false,
}),
PRICEBOOK_ID: Property.Number({
displayName: 'Pricebook ID',
required: false,
}),
QUOTATION_PHONE: Property.ShortText({
displayName: 'Phone',
required: false,
}),
QUOTATION_EMAIL: Property.ShortText({
displayName: 'Email',
required: false,
}),
QUOTATION_FAX: Property.ShortText({
displayName: 'Fax',
required: false,
}),
SHIPPING_HANDLING: Property.Number({
displayName: 'Shipping & Handling',
required: false,
}),
TAX: Property.Number({
displayName: 'Tax',
required: false,
}),
ADDRESS_BILLING_NAME: Property.ShortText({
displayName: 'Billing Name',
required: false,
}),
ADDRESS_BILLING_STREET: Property.ShortText({
displayName: 'Billing Street',
required: false,
}),
ADDRESS_BILLING_CITY: Property.ShortText({
displayName: 'Billing City',
required: false,
}),
ADDRESS_BILLING_STATE: Property.ShortText({
displayName: 'Billing State',
required: false,
}),
ADDRESS_BILLING_POSTCODE: Property.ShortText({
displayName: 'Billing Postcode',
required: false,
}),
ADDRESS_BILLING_COUNTRY: Property.ShortText({
displayName: 'Billing Country',
required: false,
}),
ADDRESS_SHIPPING_NAME: Property.ShortText({
displayName: 'Shipping Name',
required: false,
}),
ADDRESS_SHIPPING_STREET: Property.ShortText({
displayName: 'Shipping Street',
required: false,
}),
ADDRESS_SHIPPING_CITY: Property.ShortText({
displayName: 'Shipping City',
required: false,
}),
ADDRESS_SHIPPING_STATE: Property.ShortText({
displayName: 'Shipping State',
required: false,
}),
ADDRESS_SHIPPING_POSTCODE: Property.ShortText({
displayName: 'Shipping Postcode',
required: false,
}),
ADDRESS_SHIPPING_COUNTRY: Property.ShortText({
displayName: 'Shipping Country',
required: false,
}),
};

View File

@@ -0,0 +1,145 @@
import {
createTrigger,
Property,
TriggerStrategy
} from '@activepieces/pieces-framework';
import {
HttpMethod
} from '@activepieces/pieces-common';
import { insightlyAuth, makeInsightlyRequest } from '../common/common';
export const deletedRecord = createTrigger({
auth: insightlyAuth,
name: 'deleted_record',
displayName: 'Deleted Record',
description: 'Fires when a record is deleted from Insightly',
type: TriggerStrategy.POLLING,
props: {
pod: Property.ShortText({
displayName: 'Pod',
description: 'Your Insightly pod (e.g., "na1", "eu1").',
required: true,
defaultValue: 'na1'
}),
objectType: Property.StaticDropdown({
displayName: 'Object Type',
description: 'The type of Insightly object to monitor for deletions',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' },
{ label: 'Product', value: 'Products' },
{ label: 'Quote', value: 'Quotations' }
]
}
})
},
async onEnable(context) {
await context.store.put(`known_records_${context.propsValue.objectType}`, {});
},
async onDisable(context) {
await context.store.delete(`known_records_${context.propsValue.objectType}`);
},
async run(context) {
const { pod, objectType } = context.propsValue;
const response = await makeInsightlyRequest(
context.auth,
`/${objectType}?brief=true&top=500`,
pod as string,
HttpMethod.GET
);
const records = Array.isArray(response.body) ? response.body : [];
const currentTimeMs = Date.now();
const currentTime = new Date(currentTimeMs).toISOString();
const getRecordId = (record: any) => {
const idKey = Object.keys(record).find(key => key.endsWith('_ID'));
return idKey ? String(record[idKey]) : String(record['ID'] || '');
};
const getRecordName = (record: any) => {
if (record.FIRST_NAME || record.LAST_NAME) {
return `${record.FIRST_NAME || ''} ${record.LAST_NAME || ''}`.trim();
}
const nameKey = Object.keys(record).find(key =>
key.endsWith('_NAME') || key === 'TITLE'
);
return nameKey ? String(record[nameKey]) : undefined;
};
const currentRecordIds = new Set(records.map(getRecordId));
const storeKey = `known_records_${objectType}`;
const storedRecords = (await context.store.get<Record<string, { name: string; lastSeenMs: number }>>(storeKey)) || {};
const storedRecordIds = new Set(Object.keys(storedRecords));
const deletedRecords: any[] = [];
const DELETION_THRESHOLD_MS = 15 * 60 * 1000;
for (const storedId of storedRecordIds) {
if (!currentRecordIds.has(storedId)) {
const timeSinceLastSeen = currentTimeMs - storedRecords[storedId].lastSeenMs;
if (timeSinceLastSeen > DELETION_THRESHOLD_MS) {
deletedRecords.push({
recordId: storedId,
recordName: storedRecords[storedId].name || `Record ${storedId}`,
deletedAt: currentTime,
objectType,
lastSeenAt: new Date(storedRecords[storedId].lastSeenMs).toISOString()
});
delete storedRecords[storedId];
}
} else {
const recordId = storedId;
const record = records.find(r => getRecordId(r) === recordId);
if (record) {
storedRecords[recordId] = {
name: getRecordName(record) || storedRecords[recordId].name,
lastSeenMs: currentTimeMs
};
}
}
}
for (const record of records) {
const recordId = getRecordId(record);
if (!storedRecords[recordId]) {
storedRecords[recordId] = {
name: getRecordName(record) || `Record ${recordId}`,
lastSeenMs: currentTimeMs
};
}
}
const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
Object.keys(storedRecords).forEach((id) => {
if (currentTimeMs - storedRecords[id].lastSeenMs > THIRTY_DAYS_MS) {
delete storedRecords[id];
}
});
await context.store.put(storeKey, storedRecords);
return deletedRecords;
},
test: async (context) => {
return [
{
recordId: 123456,
recordName: 'Test Deleted Record',
deletedAt: new Date().toISOString(),
objectType: context.propsValue.objectType,
}
];
},
sampleData: {}
});

View File

@@ -0,0 +1,75 @@
import {
createTrigger,
Property,
TriggerStrategy
} from '@activepieces/pieces-framework';
import { insightlyAuth } from '../common/common';
export const newRecord = createTrigger({
auth: insightlyAuth,
name: 'new_record',
displayName: 'New Record',
description: 'Fires when a new record is created in Insightly (requires webhook setup)',
type: TriggerStrategy.WEBHOOK,
props: {
objectType: Property.StaticDropdown({
displayName: 'Object Type',
description: 'The type of Insightly object to monitor for new records',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' }
]
}
}),
webhookUrl: Property.MarkDown({
value: `
**Webhook URL:**
\`\`\`text
{{webhookUrl}}
\`\`\`
**Instructions:**
1. Go to **System Settings > Workflow Automation** in your Insightly account.
2. Create a new Workflow Process for the desired **Object Type**.
3. Set the trigger to **"When a record is created"**.
4. Under "Immediate Actions," add a new action and select **"Add New Webhook"**.
5. Paste the webhook URL above into the **URI** field and save the workflow.
`,
}),
},
async onEnable(context) {
// Required for WEBHOOK triggers, but we don't need to do anything here
// The user will manually configure the webhook in Insightly
},
async onDisable(context) {
// Required for WEBHOOK triggers, but we don't need to do anything here
// The user will manually disable the webhook in Insightly
},
async run(context) {
const payload = context.payload.body as { entity: Record<string, unknown> };
if (payload && payload.entity) {
return [payload.entity];
}
return [];
},
async test(context) {
// The user needs to trigger the webhook manually from Insightly to test it
// We can return a sample payload for the test button
return [
{
CONTACT_ID: 123456,
FIRST_NAME: 'John',
LAST_NAME: 'Doe',
EMAIL_ADDRESS: 'john.doe@example.com',
DATE_CREATED_UTC: new Date().toISOString(),
}
];
},
sampleData: {} // Webhook triggers don't need sample data in the same way
});

View File

@@ -0,0 +1,74 @@
import {
createTrigger,
Property,
TriggerStrategy
} from '@activepieces/pieces-framework';
import { insightlyAuth } from '../common/common';
export const updatedRecord = createTrigger({
auth: insightlyAuth,
name: 'updated_record',
displayName: 'Updated Record',
description: 'Fires when an existing record is updated in Insightly (requires webhook setup)',
type: TriggerStrategy.WEBHOOK,
props: {
objectType: Property.StaticDropdown({
displayName: 'Object Type',
description: 'The type of Insightly object to monitor for updates',
required: true,
options: {
options: [
{ label: 'Contact', value: 'Contacts' },
{ label: 'Lead', value: 'Leads' },
{ label: 'Opportunity', value: 'Opportunities' },
{ label: 'Organization', value: 'Organisations' },
{ label: 'Project', value: 'Projects' },
{ label: 'Task', value: 'Tasks' },
{ label: 'Event', value: 'Events' }
]
}
}),
webhookUrl: Property.MarkDown({
value: `
**Webhook URL:**
\`\`\`text
{{webhookUrl}}
\`\`\`
**Instructions:**
1. Go to **System Settings > Workflow Automation** in your Insightly account.
2. Create a new Workflow Process for the desired **Object Type**.
3. Set the trigger to **"When a record is created and when a record is edited"**.
4. Under "Immediate Actions," add a new action and select **"Add New Webhook"**.
5. Paste the webhook URL above into the **URI** field and save the workflow.
`,
}),
},
async onEnable(context) {
// Required for WEBHOOK triggers
},
async onDisable(context) {
// Required for WEBHOOK triggers
},
async run(context) {
const payload = context.payload.body as { entity: Record<string, unknown> };
if (payload && payload.entity) {
// Optional: Add a check to ensure it's not a new record if needed
// For now, we'll pass through any update event
return [payload.entity];
}
return [];
},
async test(context) {
return [
{
CONTACT_ID: 123456,
FIRST_NAME: 'John',
LAST_NAME: 'Doe',
EMAIL_ADDRESS: 'john.doe.updated@example.com',
DATE_CREATED_UTC: '2025-10-03T23:29:42.815Z',
DATE_UPDATED_UTC: new Date().toISOString(),
}
];
},
sampleData: {}
});