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-aircall
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-aircall` to build the library.

View File

@@ -0,0 +1,10 @@
{
"name": "@activepieces/piece-aircall",
"version": "0.0.8",
"type": "commonjs",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"dependencies": {
"tslib": "^2.3.0"
}
}

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-aircall",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/aircall/src",
"projectType": "library",
"release": {
"version": {
"manifestRootsToUpdate": [
"dist/{projectRoot}"
],
"currentVersionResolver": "git-tag",
"fallbackCurrentVersionResolver": "disk"
}
},
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/aircall",
"tsConfig": "packages/pieces/community/aircall/tsconfig.lib.json",
"packageJson": "packages/pieces/community/aircall/package.json",
"main": "packages/pieces/community/aircall/src/index.ts",
"assets": [
"packages/pieces/community/aircall/*.md",
{
"input": "packages/pieces/community/aircall/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"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/aircall",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "Sie können API-Schlüssel erstellen, indem Sie in das **Integrations & API** Menü einsteigen.",
"Comment a Call": "Anruf kommentieren",
"Create a Contact": "Kontakt erstellen",
"Find Call": "Anruf finden",
"Find Contact": "Kontakt finden",
"Get Call": "Anruf erhalten",
"Tag a Call": "Markiere einen Anruf",
"Update Contact": "Kontakt aktualisieren",
"Custom API Call": "Eigener API-Aufruf",
"Adds a comment (note) to a specific call.": "Fügt einen Kommentar (Anmerkung) zu einem bestimmten Anruf hinzu.",
"Creates a new contact.": "Erstellt einen neuen Kontakt.",
"Finds specific call based on provided filter.": "Findet einen bestimmten Aufruf basierend auf dem angegebenen Filter.",
"Finds contact based on phone or email.": "Finden Sie Kontakt basierend auf Telefon oder E-Mail.",
"Retrieves details about a specific call.": "Ruft Details zu einem bestimmten Anruf ab.",
"Add tags to a specific call.": "Tags zu einem bestimmten Anruf hinzufügen.",
"Update an existing contact.": "Aktualisiere einen bestehenden Kontakt.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Call": "Anruf",
"Comment Content": "Kommentar-Inhalt",
"Phone Numbers": "Telefonnummern",
"First Name": "Vorname",
"Last Name": "Nachname",
"Company Name": "Firmenname",
"Information": "Informationen",
"Email Addresses": "E-Mail-Adressen",
"Call Direction": "Anrufrichtung",
"Phone Number": "Telefonnummer",
"Tags": "Tags",
"Email": "E-Mail",
"Contact ID": "Kontakt-ID",
"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)",
"Additional information about the contact.": "Weitere Informationen zum Kontakt.",
"Array of email addresses (optional, max 20)": "Anordnung der E-Mail-Adressen (optional, max. 20)",
"Filter by call direction": "Nach Anrufrichtung filtern",
"The calling or receiving phone number of calls.": "Der Anruf oder Empfangsnummer der Anrufe.",
"Search by phone number (with country code, e.g., +1234567890).": "Suche nach Telefonnummer (mit Landesvorwahl, z.B. +1234567890).",
"Search by email address.": "Suche nach E-Mail-Adresse.",
"Select the contact to update": "Kontakt zum Update auswählen",
"Last name of the contact": "Nachname des Kontakts",
"Additional information about the contact": "Zusätzliche Informationen zum Kontakt",
"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..",
"Inbound": "Eingehend",
"Outbound": "Ausgehend",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"Call Ended": "Anruf beendet",
"New Contact": "Neuer Kontakt",
"New Note": "Neue Notiz",
"New Number Created": "Neue Nummer erstellt",
"New SMS": "Neue SMS",
"Triggers when a call ends.": "Wird ausgelöst, wenn ein Aufruf endet.",
"Triggers when a new contact is created.": "Wird ausgelöst, wenn ein neuer Kontakt erstellt wird.",
"Triggers when a new note is added to a call.": "Wird ausgelöst, wenn eine neue Notiz zu einem Anruf hinzugefügt wird.",
"Triggers when a new number is created.": "Wird ausgelöst, wenn eine neue Nummer erstellt wird.",
"Triggers when a new SMS message is received.": "Wird ausgelöst, wenn eine neue SMS empfangen wird."
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "Puedes crear la clave de API mediante la navegación en el menú **Integraciones y API**.",
"Comment a Call": "Comentar una llamada",
"Create a Contact": "Crear un contacto",
"Find Call": "Encontrar llamada",
"Find Contact": "Encontrar contacto",
"Get Call": "Recibir llamada",
"Tag a Call": "Etiqueta una llamada",
"Update Contact": "Actualizar contacto",
"Custom API Call": "Llamada API personalizada",
"Adds a comment (note) to a specific call.": "Añade un comentario (nota) a una llamada específica.",
"Creates a new contact.": "Crea un nuevo contacto.",
"Finds specific call based on provided filter.": "Encuentra una llamada específica basada en el filtro proporcionado.",
"Finds contact based on phone or email.": "Encuentra contactos basados en teléfono o correo electrónico.",
"Retrieves details about a specific call.": "Devuelve los detalles de una llamada específica.",
"Add tags to a specific call.": "Añadir etiquetas a una llamada específica.",
"Update an existing contact.": "Actualizar un contacto existente.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Call": "Llamar",
"Comment Content": "Contenido del comentario",
"Phone Numbers": "Números de teléfono",
"First Name": "Nombre",
"Last Name": "Apellido",
"Company Name": "Nombre De La Empresa",
"Information": "Información",
"Email Addresses": "Direcciones de email",
"Call Direction": "Dirección de llamada",
"Phone Number": "Número de teléfono",
"Tags": "Etiquetas",
"Email": "E-mail",
"Contact ID": "ID de contacto",
"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)",
"Additional information about the contact.": "Información adicional sobre el contacto.",
"Array of email addresses (optional, max 20)": "Matriz de direcciones de correo electrónico (opcional, máximo 20)",
"Filter by call direction": "Dirección de llamada",
"The calling or receiving phone number of calls.": "El número de llamada o de recepción de llamadas.",
"Search by phone number (with country code, e.g., +1234567890).": "Buscar por número de teléfono (con código de país, por ejemplo, +1234567890).",
"Search by email address.": "Buscar por correo electrónico.",
"Select the contact to update": "Seleccione el contacto a actualizar",
"Last name of the contact": "Apellido del contacto",
"Additional information about the contact": "Información adicional sobre el contacto",
"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.",
"Inbound": "Entrante",
"Outbound": "Salida",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"Call Ended": "Llamada finalizada",
"New Contact": "Nuevo contacto",
"New Note": "Nueva nota",
"New Number Created": "Nuevo número creado",
"New SMS": "Nuevo SMS",
"Triggers when a call ends.": "Dispara cuando termina una llamada.",
"Triggers when a new contact is created.": "Dispara cuando se crea un nuevo contacto.",
"Triggers when a new note is added to a call.": "Se activa cuando se añade una nueva nota a una llamada.",
"Triggers when a new number is created.": "Dispara cuando se crea un nuevo número.",
"Triggers when a new SMS message is received.": "Dispara cuando se recibe un nuevo mensaje SMS."
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "Vous pouvez créer une clé API en marquant vers le menu **Integrations & API**.",
"Comment a Call": "Commenter un appel",
"Create a Contact": "Créer un contact",
"Find Call": "Trouver un appel",
"Find Contact": "Trouver un contact",
"Get Call": "Obtenir un appel",
"Tag a Call": "Taguer un appel",
"Update Contact": "Mettre à jour le contact",
"Custom API Call": "Appel d'API personnalisé",
"Adds a comment (note) to a specific call.": "Ajoute un commentaire (note) à un appel spécifique.",
"Creates a new contact.": "Crée un nouveau contact.",
"Finds specific call based on provided filter.": "Trouve un appel spécifique basé sur le filtre fourni.",
"Finds contact based on phone or email.": "Trouve un contact basé sur le téléphone ou l'email.",
"Retrieves details about a specific call.": "Récupère les détails sur un appel spécifique.",
"Add tags to a specific call.": "Ajouter des tags à un appel spécifique.",
"Update an existing contact.": "Mettre à jour un contact existant.",
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
"Call": "Appel",
"Comment Content": "Contenu du commentaire",
"Phone Numbers": "Numéros de téléphone",
"First Name": "First Name",
"Last Name": "Last Name",
"Company Name": "Nom de lentreprise",
"Information": "Information",
"Email Addresses": "Adresses e-mail",
"Call Direction": "Direction de l'appel",
"Phone Number": "Numéro de téléphone",
"Tags": "Tags",
"Email": "Courriel",
"Contact ID": "ID du contact",
"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'expiration (en secondes)",
"Additional information about the contact.": "Informations complémentaires sur le contact.",
"Array of email addresses (optional, max 20)": "Tableau d'adresses e-mail (optionnel, max 20)",
"Filter by call direction": "Filtrer par direction d'appel",
"The calling or receiving phone number of calls.": "Le numéro d'appel ou de réception des appels.",
"Search by phone number (with country code, e.g., +1234567890).": "Recherche par numéro de téléphone (avec l'indicatif du pays, par exemple: +1234567890).",
"Search by email address.": "Recherche par adresse e-mail.",
"Select the contact to update": "Sélectionnez le contact à mettre à jour",
"Last name of the contact": "Nom du contact",
"Additional information about the contact": "Informations complémentaires sur le contact",
"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 PDF, les images, etc.",
"Inbound": "Entrants",
"Outbound": "Sortant",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Call Ended": "Appel terminé",
"New Contact": "Nouveau contact",
"New Note": "Nouvelle note",
"New Number Created": "Nouveau numéro créé",
"New SMS": "Nouveau SMS",
"Triggers when a call ends.": "Déclenche quand un appel se termine.",
"Triggers when a new contact is created.": "Déclenche lorsqu'un nouveau contact est créé.",
"Triggers when a new note is added to a call.": "Déclenche quand une nouvelle note est ajoutée à un appel.",
"Triggers when a new number is created.": "Déclenche quand un nouveau numéro est créé.",
"Triggers when a new SMS message is received.": "Déclenche quand un nouveau SMS est reçu."
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "**インテグレーションとAPI**メニューにnaviagtingすることでAPIキーを作成できます。",
"Comment a Call": "通話にコメント",
"Create a Contact": "連絡先を作成",
"Find Call": "電話を検索",
"Find Contact": "連絡先を探す",
"Get Call": "通話を取得",
"Tag a Call": "通話にタグを付ける",
"Update Contact": "連絡先を更新",
"Custom API Call": "カスタムAPI通話",
"Adds a comment (note) to a specific call.": "特定の呼び出しにコメント(ノート)を追加します。",
"Creates a new contact.": "新しい連絡先を作成します。",
"Finds specific call based on provided filter.": "提供されたフィルターに基づいて特定の呼び出しを検索します。",
"Finds contact based on phone or email.": "電話または電子メールに基づいて連絡先を検索します。",
"Retrieves details about a specific call.": "特定の呼び出しに関する詳細を取得します。",
"Add tags to a specific call.": "特定の通話にタグを追加します。",
"Update an existing contact.": "既存の連絡先を更新します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Call": "電話",
"Comment Content": "コメント内容",
"Phone Numbers": "電話番号",
"First Name": "名",
"Last Name": "Last Name",
"Company Name": "会社名",
"Information": "情報",
"Email Addresses": "メールアドレス",
"Call Direction": "通話方向",
"Phone Number": "電話番号",
"Tags": "タグ",
"Email": "Eメールアドレス",
"Contact ID": "連絡先ID",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Additional information about the contact.": "連絡先に関する追加情報。",
"Array of email addresses (optional, max 20)": "メールアドレスの配列オプション、最大20",
"Filter by call direction": "通話方向でフィルター",
"The calling or receiving phone number of calls.": "呼び出しまたは電話番号を受信します。",
"Search by phone number (with country code, e.g., +1234567890).": "電話番号で検索します(例:+1234567890",
"Search by email address.": "メールアドレスで検索",
"Select the contact to update": "更新する連絡先を選択してください",
"Last name of the contact": "連絡先の姓",
"Additional information about the contact": "連絡先に関する追加情報",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"Inbound": "Inbound",
"Outbound": "Outbound",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"Call Ended": "通話終了",
"New Contact": "新しい連絡先",
"New Note": "新しいメモ",
"New Number Created": "新しい番号が作成されました",
"New SMS": "新しいSMS",
"Triggers when a call ends.": "通話が終了したときにトリガーします。",
"Triggers when a new contact is created.": "新しい連絡先が作成されたときにトリガーします.",
"Triggers when a new note is added to a call.": "新しいノートが呼び出しに追加されたときにトリガーされます。",
"Triggers when a new number is created.": "新しい番号が作成されたときにトリガーします。",
"Triggers when a new SMS message is received.": "新しいSMSメッセージを受信したときにトリガーします."
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "Je kunt een API-sleutel maken door te marcheren in het **Integraties & API** menu.",
"Comment a Call": "Reageer op een oproep",
"Create a Contact": "Een contactpersoon aanmaken",
"Find Call": "Oproep zoeken",
"Find Contact": "Contactpersoon zoeken",
"Get Call": "Oproep opvragen",
"Tag a Call": "Tag een oproep",
"Update Contact": "Contactpersoon bijwerken",
"Custom API Call": "Custom API Call",
"Adds a comment (note) to a specific call.": "Voegt een opmerking (notitie) toe aan een specifiek gesprek.",
"Creates a new contact.": "Maakt een nieuw contact aan.",
"Finds specific call based on provided filter.": "Vind specifieke oproep op basis van verstrekt filter.",
"Finds contact based on phone or email.": "Zoekt contact op basis van telefoon of e-mail.",
"Retrieves details about a specific call.": "Details over een specifiek gesprek worden opgehaald.",
"Add tags to a specific call.": "Voeg tags toe aan een specifiek gesprek.",
"Update an existing contact.": "Bestaande contactpersoon bijwerken.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Call": "Oproepen",
"Comment Content": "Commentaar inhoud",
"Phone Numbers": "Telefoon nummers",
"First Name": "Voornaam",
"Last Name": "Achternaam",
"Company Name": "Bedrijfsnaam",
"Information": "Informatie",
"Email Addresses": "E-mail adressen",
"Call Direction": "Oproep richting",
"Phone Number": "Telefoon nummer",
"Tags": "Labels",
"Email": "E-mail",
"Contact ID": "Contact ID",
"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)",
"Additional information about the contact.": "Aanvullende informatie over het contact.",
"Array of email addresses (optional, max 20)": "Reeks van e-mailadressen (optioneel, max 20)",
"Filter by call direction": "Filter op oproeprichting",
"The calling or receiving phone number of calls.": "Het aantal oproepen of ontvangen van gesprekken.",
"Search by phone number (with country code, e.g., +1234567890).": "Zoeken op telefoonnummer (met landcode, b.v. +1234567890).",
"Search by email address.": "Zoeken op e-mailadres",
"Select the contact to update": "Selecteer de contactpersoon om te updaten",
"Last name of the contact": "Achternaam van de contactpersoon",
"Additional information about the contact": "Aanvullende informatie over de contactpersoon",
"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..",
"Inbound": "Inkomende",
"Outbound": "Uitgaande",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"Call Ended": "Oproep beëindigd",
"New Contact": "Nieuw contactpersoon",
"New Note": "Nieuwe notitie",
"New Number Created": "Nieuw nummer aangemaakt",
"New SMS": "Nieuwe SMS",
"Triggers when a call ends.": "Triggert wanneer een oproep eindigt.",
"Triggers when a new contact is created.": "Triggert wanneer een nieuw contact wordt aangemaakt.",
"Triggers when a new note is added to a call.": "Triggert wanneer een nieuwe notitie aan een gesprek wordt toegevoegd.",
"Triggers when a new number is created.": "Triggert wanneer een nieuw nummer wordt aangemaakt.",
"Triggers when a new SMS message is received.": "Triggert wanneer een nieuw SMS-bericht wordt ontvangen."
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "Você pode criar uma chave de API por naviagting para o menu **Integrações & API**.",
"Comment a Call": "Comentar uma Chamada",
"Create a Contact": "Criar um contato",
"Find Call": "Encontrar chamada",
"Find Contact": "Localizar contato",
"Get Call": "Obter uma ligação",
"Tag a Call": "Marcar uma chamada",
"Update Contact": "Atualizar contato",
"Custom API Call": "Chamada de API personalizada",
"Adds a comment (note) to a specific call.": "Adiciona um comentário (nota) a uma chamada específica.",
"Creates a new contact.": "Cria um novo contato.",
"Finds specific call based on provided filter.": "Localiza uma chamada específica baseada no filtro fornecido.",
"Finds contact based on phone or email.": "Localiza um contato baseado em telefone ou e-mail.",
"Retrieves details about a specific call.": "Recupera detalhes sobre uma chamada específica.",
"Add tags to a specific call.": "Adicionar etiquetas a uma chamada específica.",
"Update an existing contact.": "Atualizar um contato existente.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Call": "Chamada",
"Comment Content": "Comentar conteúdo",
"Phone Numbers": "Números de telefone",
"First Name": "Nome",
"Last Name": "Sobrenome",
"Company Name": "Nome da Empresa",
"Information": "Informacao",
"Email Addresses": "Endereços de e-mail",
"Call Direction": "Direção da chamada",
"Phone Number": "Número de telefone",
"Tags": "Etiquetas",
"Email": "e-mail",
"Contact ID": "ID do contato",
"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)",
"Additional information about the contact.": "Informações adicionais sobre o contato.",
"Array of email addresses (optional, max 20)": "Array de endereços de e-mail (opcional, max 20)",
"Filter by call direction": "Filtrar por direção da chamada",
"The calling or receiving phone number of calls.": "A ligar ou receber número de telefone de chamadas.",
"Search by phone number (with country code, e.g., +1234567890).": "Pesquise por número de telefone (com código de país, por exemplo, +1234567890).",
"Search by email address.": "Pesquisar por endereço de e-mail.",
"Select the contact to update": "Selecione o contato para atualização",
"Last name of the contact": "Último nome do contato",
"Additional information about the contact": "Informações adicionais sobre o contato",
"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..",
"Inbound": "Entrada",
"Outbound": "Saída",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"Call Ended": "Chamada encerrada",
"New Contact": "Novo Contato",
"New Note": "Nova anotação",
"New Number Created": "Novo número criado",
"New SMS": "Novo SMS",
"Triggers when a call ends.": "Dispara quando uma chamada termina.",
"Triggers when a new contact is created.": "Dispara quando um novo contato é criado.",
"Triggers when a new note is added to a call.": "Aciona quando uma nova nota é adicionada a uma chamada.",
"Triggers when a new number is created.": "Dispara quando um novo número é criado.",
"Triggers when a new SMS message is received.": "Aciona quando uma nova mensagem SMS é recebida."
}

View File

@@ -0,0 +1,69 @@
{
"Aircall": "Aircall",
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "Вы можете создать ключ API через меню **Integrations & API**.",
"Comment a Call": "Комментировать звонок",
"Create a Contact": "Создать контакт",
"Find Call": "Найти вызов",
"Find Contact": "Найти контакт",
"Get Call": "Звонок",
"Tag a Call": "Отметить звонок",
"Update Contact": "Обновить контакт",
"Custom API Call": "Пользовательский вызов API",
"Adds a comment (note) to a specific call.": "Добавляет комментарий (примечание) к конкретному вызову.",
"Creates a new contact.": "Создает новый контакт.",
"Finds specific call based on provided filter.": "Ищет вызов на основе предоставленного фильтра.",
"Finds contact based on phone or email.": "Поиск контакта на основе телефона или электронной почты.",
"Retrieves details about a specific call.": "Получает подробную информацию о конкретном вызове.",
"Add tags to a specific call.": "Добавить теги к конкретному вызову.",
"Update an existing contact.": "Обновить существующий контакт.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Call": "Звонок",
"Comment Content": "Содержание комментария",
"Phone Numbers": "Номера телефонов",
"First Name": "First Name",
"Last Name": "Last Name",
"Company Name": "Название компании",
"Information": "Информация",
"Email Addresses": "Адреса E-mail",
"Call Direction": "Направление вызова",
"Phone Number": "Номер телефона",
"Tags": "Теги",
"Email": "Почта",
"Contact ID": "ID контакта",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Additional information about the contact.": "Дополнительная информация об контакте.",
"Array of email addresses (optional, max 20)": "Массив адресов электронной почты (опционально, максимум 20)",
"Filter by call direction": "Фильтр по направлению вызова",
"The calling or receiving phone number of calls.": "Звонки или прием номера телефонных звонков.",
"Search by phone number (with country code, e.g., +1234567890).": "Поиск по номеру телефона (с кодом страны, например, +1234567890).",
"Search by email address.": "Поиск по email адресу.",
"Select the contact to update": "Выберите контакт для обновления",
"Last name of the contact": "Фамилия контакта",
"Additional information about the contact": "Дополнительная информация о контакте",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"Inbound": "Входящий",
"Outbound": "Исходящий",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"Call Ended": "Вызов завершен",
"New Contact": "Новый контакт",
"New Note": "Новая заметка",
"New Number Created": "Создано новое число",
"New SMS": "Новое SMS",
"Triggers when a call ends.": "Триггеры при завершении вызова.",
"Triggers when a new contact is created.": "Включает при создании нового контакта.",
"Triggers when a new note is added to a call.": "Включает при добавлении новой заметки к вызову.",
"Triggers when a new number is created.": "Триггеры при создании нового номера.",
"Triggers when a new SMS message is received.": "Включает при получении нового SMS-сообщения."
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "You can create API key by naviagting to **Integrations & API** menu.",
"Comment a Call": "Comment a Call",
"Create a Contact": "Create a Contact",
"Find Call": "Find Call",
"Find Contact": "Find Contact",
"Get Call": "Get Call",
"Tag a Call": "Tag a Call",
"Update Contact": "Update Contact",
"Custom API Call": "Custom API Call",
"Adds a comment (note) to a specific call.": "Adds a comment (note) to a specific call.",
"Creates a new contact.": "Creates a new contact.",
"Finds specific call based on provided filter.": "Finds specific call based on provided filter.",
"Finds contact based on phone or email.": "Finds contact based on phone or email.",
"Retrieves details about a specific call.": "Retrieves details about a specific call.",
"Add tags to a specific call.": "Add tags to a specific call.",
"Update an existing contact.": "Update an existing contact.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Call": "Call",
"Comment Content": "Comment Content",
"Phone Numbers": "Phone Numbers",
"First Name": "First Name",
"Last Name": "Last Name",
"Company Name": "Company Name",
"Information": "Information",
"Email Addresses": "Email Addresses",
"Call Direction": "Call Direction",
"Phone Number": "Phone Number",
"Tags": "Tags",
"Email": "Email",
"Contact ID": "Contact ID",
"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)",
"Additional information about the contact.": "Additional information about the contact.",
"Array of email addresses (optional, max 20)": "Array of email addresses (optional, max 20)",
"Filter by call direction": "Filter by call direction",
"The calling or receiving phone number of calls.": "The calling or receiving phone number of calls.",
"Search by phone number (with country code, e.g., +1234567890).": "Search by phone number (with country code, e.g., +1234567890).",
"Search by email address.": "Search by email address.",
"Select the contact to update": "Select the contact to update",
"Last name of the contact": "Last name of the contact",
"Additional information about the contact": "Additional information about the contact",
"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..",
"Inbound": "Inbound",
"Outbound": "Outbound",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Call Ended": "Call Ended",
"New Contact": "New Contact",
"New Note": "New Note",
"New Number Created": "New Number Created",
"New SMS": "New SMS",
"Triggers when a call ends.": "Triggers when a call ends.",
"Triggers when a new contact is created.": "Triggers when a new contact is created.",
"Triggers when a new note is added to a call.": "Triggers when a new note is added to a call.",
"Triggers when a new number is created.": "Triggers when a new number is created.",
"Triggers when a new SMS message is received.": "Triggers when a new SMS message is received."
}

View File

@@ -0,0 +1,69 @@
{
"Aircall": "Aircall",
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "You can create API key by naviagting to **Integrations & API** menu.",
"Comment a Call": "Comment a Call",
"Create a Contact": "Create a Contact",
"Find Call": "Find Call",
"Find Contact": "Find Contact",
"Get Call": "Get Call",
"Tag a Call": "Tag a Call",
"Update Contact": "Update Contact",
"Custom API Call": "Custom API Call",
"Adds a comment (note) to a specific call.": "Adds a comment (note) to a specific call.",
"Creates a new contact.": "Creates a new contact.",
"Finds specific call based on provided filter.": "Finds specific call based on provided filter.",
"Finds contact based on phone or email.": "Finds contact based on phone or email.",
"Retrieves details about a specific call.": "Retrieves details about a specific call.",
"Add tags to a specific call.": "Add tags to a specific call.",
"Update an existing contact.": "Update an existing contact.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Call": "Call",
"Comment Content": "Comment Content",
"Phone Numbers": "Phone Numbers",
"First Name": "First Name",
"Last Name": "Last Name",
"Company Name": "Tên công ty",
"Information": "Information",
"Email Addresses": "Email Addresses",
"Call Direction": "Call Direction",
"Phone Number": "Phone Number",
"Tags": "Tags",
"Email": "Email",
"Contact ID": "Contact ID",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Additional information about the contact.": "Additional information about the contact.",
"Array of email addresses (optional, max 20)": "Array of email addresses (optional, max 20)",
"Filter by call direction": "Filter by call direction",
"The calling or receiving phone number of calls.": "The calling or receiving phone number of calls.",
"Search by phone number (with country code, e.g., +1234567890).": "Search by phone number (with country code, e.g., +1234567890).",
"Search by email address.": "Search by email address.",
"Select the contact to update": "Select the contact to update",
"Last name of the contact": "Last name of the contact",
"Additional information about the contact": "Additional information about the contact",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"Inbound": "Inbound",
"Outbound": "Outbound",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Call Ended": "Call Ended",
"New Contact": "New Contact",
"New Note": "New Note",
"New Number Created": "New Number Created",
"New SMS": "New SMS",
"Triggers when a call ends.": "Triggers when a call ends.",
"Triggers when a new contact is created.": "Triggers when a new contact is created.",
"Triggers when a new note is added to a call.": "Triggers when a new note is added to a call.",
"Triggers when a new number is created.": "Triggers when a new number is created.",
"Triggers when a new SMS message is received.": "Triggers when a new SMS message is received."
}

View File

@@ -0,0 +1,70 @@
{
"API ID": "API ID",
"API Token": "API Token",
"You can create API key by naviagting to **Integrations & API** menu.": "You can create API key by naviagting to **Integrations & API** menu.",
"Comment a Call": "Comment a Call",
"Create a Contact": "Create a Contact",
"Find Call": "Find Call",
"Find Contact": "Find Contact",
"Get Call": "Get Call",
"Tag a Call": "Tag a Call",
"Update Contact": "Update Contact",
"Custom API Call": "自定义 API 呼叫",
"Adds a comment (note) to a specific call.": "Adds a comment (note) to a specific call.",
"Creates a new contact.": "Creates a new contact.",
"Finds specific call based on provided filter.": "Finds specific call based on provided filter.",
"Finds contact based on phone or email.": "Finds contact based on phone or email.",
"Retrieves details about a specific call.": "Retrieves details about a specific call.",
"Add tags to a specific call.": "Add tags to a specific call.",
"Update an existing contact.": "Update an existing contact.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Call": "Call",
"Comment Content": "Comment Content",
"Phone Numbers": "Phone Numbers",
"First Name": "First Name",
"Last Name": "名字",
"Company Name": "Company Name",
"Information": "Information",
"Email Addresses": "Email Addresses",
"Call Direction": "Call Direction",
"Phone Number": "Phone Number",
"Tags": "标签",
"Email": "电子邮件地址",
"Contact ID": "Contact ID",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Additional information about the contact.": "Additional information about the contact.",
"Array of email addresses (optional, max 20)": "Array of email addresses (optional, max 20)",
"Filter by call direction": "Filter by call direction",
"The calling or receiving phone number of calls.": "The calling or receiving phone number of calls.",
"Search by phone number (with country code, e.g., +1234567890).": "Search by phone number (with country code, e.g., +1234567890).",
"Search by email address.": "Search by email address.",
"Select the contact to update": "Select the contact to update",
"Last name of the contact": "Last name of the contact",
"Additional information about the contact": "Additional information about the contact",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"Inbound": "Inbound",
"Outbound": "Outbound",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"Call Ended": "Call Ended",
"New Contact": "New Contact",
"New Note": "New Note",
"New Number Created": "New Number Created",
"New SMS": "New SMS",
"Triggers when a call ends.": "Triggers when a call ends.",
"Triggers when a new contact is created.": "Triggers when a new contact is created.",
"Triggers when a new note is added to a call.": "Triggers when a new note is added to a call.",
"Triggers when a new number is created.": "Triggers when a new number is created.",
"Triggers when a new SMS message is received.": "Triggers when a new SMS message is received."
}

View File

@@ -0,0 +1,53 @@
import { createPiece } from '@activepieces/pieces-framework';
import { aircallAuth } from './lib/common/auth';
import { commentACall } from './lib/actions/comment-a-call';
import { createAContact } from './lib/actions/create-a-contact';
import { findCalls } from './lib/actions/find-calls';
import { findContact } from './lib/actions/find-contact';
import { getCall } from './lib/actions/get-call';
import { tagACall } from './lib/actions/tag-a-call';
import { updateContact } from './lib/actions/update-contact';
import { callEnded } from './lib/triggers/call-ended';
import { newContact } from './lib/triggers/new-contact';
import { newNote } from './lib/triggers/new-note';
import { newNumberCreated } from './lib/triggers/new-number-created';
import { newSms } from './lib/triggers/new-sms';
import { PieceCategory } from '@activepieces/shared';
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import { BASE_URL } from './lib/common/client';
export const aircall = createPiece({
displayName: 'Aircall',
auth: aircallAuth,
minimumSupportedRelease: '0.36.1',
categories:[PieceCategory.BUSINESS_INTELLIGENCE,PieceCategory.COMMUNICATION],
logoUrl: 'https://cdn.activepieces.com/pieces/aircall.png',
authors: ['Sanket6652'],
actions: [
commentACall,
createAContact,
findCalls,
findContact,
getCall,
tagACall,
updateContact,
createCustomApiCallAction({
auth:aircallAuth,
baseUrl:()=>BASE_URL,
authMapping:async (auth)=>{
return {
Authorization: `Basic ${Buffer.from(`${auth.username}:${auth.password}`).toString(
'base64'
)}`,
};
}
})
],
triggers: [
callEnded,
newContact,
newNote,
newNumberCreated,
newSms
],
});

View File

@@ -0,0 +1,37 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { callIdDropdown } from '../common/props';
export const commentACall = createAction({
auth: aircallAuth,
name: 'commentACall',
displayName: 'Comment a Call',
description: 'Adds a comment (note) to a specific call.',
props: {
callId: callIdDropdown,
content: Property.LongText({
displayName: 'Comment Content',
required: true,
}),
},
async run(context) {
const { callId, content } = context.propsValue;
const auth = context.auth;
const response = await makeRequest(
auth,
HttpMethod.POST,
`/calls/${callId}/comments`,
{ content }
);
return {
status: 'success',
message: `Comment added successfully to call ${callId}.`,
comment: content,
data: response,
};
},
});

View File

@@ -0,0 +1,97 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
export const createAContact = createAction({
auth: aircallAuth,
name: 'createAContact',
displayName: 'Create a Contact',
description:'Creates a new contact.',
props: {
phone_numbers: Property.Array({
displayName: 'Phone Numbers',
required: true,
properties: {
label: Property.ShortText({
displayName: 'Label',
description: 'Label for the phone number (e.g., Work, Mobile, Home).',
required: true,
}),
value: Property.ShortText({
displayName: 'Phone Number',
description: 'Phone number with country code (e.g., +19001112222).',
required: true,
}),
},
}),
first_name: Property.ShortText({
displayName: 'First Name',
required: false,
}),
last_name: Property.ShortText({
displayName: 'Last Name',
required: false,
}),
company_name: Property.ShortText({
displayName: 'Company Name',
required: false,
}),
information: Property.LongText({
displayName: 'Information',
description: 'Additional information about the contact.',
required: false,
}),
emails: Property.Array({
displayName: 'Email Addresses',
description: 'Array of email addresses (optional, max 20)',
required: false,
properties: {
label: Property.ShortText({
displayName: 'Label',
description: 'Label for the email (e.g., Office, Personal)',
required: true,
}),
value: Property.ShortText({
displayName: 'Email Address',
description: 'Email address',
required: true,
}),
},
}),
},
async run(context) {
const {
first_name,
last_name,
company_name,
information,
phone_numbers,
emails,
} = context.propsValue;
// Prepare request body
const requestBody: Record<string,any> = {
phone_numbers,
};
if (first_name) requestBody['first_name'] = first_name;
if (last_name) requestBody['last_name'] = last_name;
if (company_name) requestBody['company_name'] = company_name;
if (information) requestBody['information'] = information;
if (emails && emails.length > 0) {
requestBody['emails'] = emails;
}
const response = await makeRequest(
context.auth,
HttpMethod.POST,
'/contacts',
requestBody
);
return response;
},
});

View File

@@ -0,0 +1,59 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { tagIdDropdown } from '../common/props';
export const findCalls = createAction({
auth: aircallAuth,
name: 'findCalls',
displayName: 'Find Call',
description: 'Finds specific call based on provided filter.',
props: {
direction: Property.StaticDropdown({
displayName: 'Call Direction',
description: 'Filter by call direction',
required: false,
options: {
options: [
{ label: 'Inbound', value: 'inbound' },
{ label: 'Outbound', value: 'outbound' },
],
},
}),
phone_number: Property.ShortText({
displayName: 'Phone Number',
description: 'The calling or receiving phone number of calls.',
required: false,
}),
tags: tagIdDropdown,
},
async run(context) {
const { direction, phone_number, tags } = context.propsValue;
// Build query parameters
const queryParams = new URLSearchParams();
queryParams.set('order', 'desc');
queryParams.set('fetch_contact', 'true');
queryParams.set('fetch_short_urls', 'true');
if (direction) queryParams.set('direction', direction);
if (phone_number) queryParams.set('phone_number', phone_number);
if (tags && tags.length > 0) {
tags.forEach((tagId) => queryParams.append('tags[]', tagId.toString()));
}
const queryString = queryParams.toString();
const path = `/calls/search${queryString ? `?${queryString}` : ''}`;
const response = await makeRequest(context.auth, HttpMethod.GET, path);
const { calls } = response as { calls: { id: number }[] };
return {
found: calls.length > 0,
data: calls.length > 0 ? calls[0] : {},
};
},
});

View File

@@ -0,0 +1,44 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
export const findContact = createAction({
auth: aircallAuth,
name: 'findContact',
displayName: 'Find Contact',
description: 'Finds contact based on phone or email.',
props: {
phone_number: Property.ShortText({
displayName: 'Phone Number',
description:
'Search by phone number (with country code, e.g., +1234567890).',
required: false,
}),
email: Property.ShortText({
displayName: 'Email',
description: 'Search by email address.',
required: false,
}),
},
async run(context) {
const { phone_number, email } = context.propsValue;
// Build query parameters
const queryParams = new URLSearchParams();
if (phone_number) queryParams.set('phone_number', phone_number);
if (email) queryParams.set('email', email);
const queryString = queryParams.toString();
const path = `/contacts/search${queryString ? `?${queryString}` : ''}`;
const response = await makeRequest(context.auth, HttpMethod.GET, path);
const { contacts } = response as { contacts: { id: number }[] };
return {
found: contacts.length > 0,
data: contacts.length > 0 ? contacts[0] : {},
};
},
});

View File

@@ -0,0 +1,31 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { callIdDropdown } from '../common/props';
export const getCall = createAction({
auth: aircallAuth,
name: 'getCall',
displayName: 'Get Call',
description: 'Retrieves details about a specific call.',
props: {
callId: callIdDropdown,
},
async run(context) {
const { callId } = context.propsValue;
// Build query parameters
const queryParams = new URLSearchParams();
queryParams.set('fetch_contact', 'true');
queryParams.set('fetch_short_urls', 'true');
queryParams.set('fetch_call_timeline', 'true');
const queryString = queryParams.toString();
const path = `/calls/${callId}${queryString ? `?${queryString}` : ''}`;
const response = await makeRequest(context.auth, HttpMethod.GET, path);
return response;
},
});

View File

@@ -0,0 +1,33 @@
import { createAction } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { callIdDropdown, tagIdDropdown } from '../common/props';
export const tagACall = createAction({
auth: aircallAuth,
name: 'tagACall',
displayName: 'Tag a Call',
description: 'Add tags to a specific call.',
props: {
callId: callIdDropdown,
tags: tagIdDropdown,
},
async run(context) {
const { callId, tags } = context.propsValue;
const response = await makeRequest(
context.auth,
HttpMethod.POST,
`/calls/${callId}/tags`,
{ tags }
);
return {
status: 'success',
message: `Tags added successfully to call ${callId}.`,
data: response,
};
},
});

View File

@@ -0,0 +1,53 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { contactIdDropdown } from '../common/props';
export const updateContact = createAction({
auth: aircallAuth,
name: 'updateContact',
displayName: 'Update Contact',
description: 'Update an existing contact.',
props: {
contactId: contactIdDropdown,
first_name: Property.ShortText({
displayName: 'First Name',
required: false,
}),
last_name: Property.ShortText({
displayName: 'Last Name',
description: 'Last name of the contact',
required: false,
}),
company_name: Property.ShortText({
displayName: 'Company Name',
required: false,
}),
information: Property.LongText({
displayName: 'Information',
description: 'Additional information about the contact',
required: false,
}),
},
async run(context) {
const { contactId, first_name, last_name, company_name, information } =
context.propsValue;
// Prepare request body with only provided fields
const requestBody: Record<string,any> = {};
if (first_name) requestBody['first_name'] = first_name;
if (last_name) requestBody['last_name'] = last_name;
if (company_name) requestBody['company_name'] = company_name;
if (information) requestBody['information'] = information;
const response = await makeRequest(
context.auth,
HttpMethod.POST,
`/contacts/${contactId}`,
requestBody
);
return response;
},
});

View File

@@ -0,0 +1,23 @@
import { PieceAuth } from '@activepieces/pieces-framework';
import { makeRequest } from './client';
import { HttpMethod } from '@activepieces/pieces-common';
export const aircallAuth = PieceAuth.BasicAuth({
description: `You can create API key by naviagting to **Integrations & API** menu.`,
required: true,
username: {
displayName: 'API ID',
},
password: {
displayName: 'API Token',
},
validate: async ({ auth }) => {
try {
await makeRequest(auth, HttpMethod.GET, '/ping');
return { valid: true };
} catch (error) {
return { valid: false, error: 'Invalid Credentials' };
}
},
});

View File

@@ -0,0 +1,75 @@
import { AuthenticationType, HttpMethod, httpClient } from '@activepieces/pieces-common';
export const BASE_URL = `https://api.aircall.io/v1`;
export async function makeRequest(
auth: { username: string; password: string },
method: HttpMethod,
path: string,
body?: unknown
) {
try {
const response = await httpClient.sendRequest({
method,
url: `${BASE_URL}${path}`,
authentication:{
type:AuthenticationType.BASIC,
username:auth.username,
password:auth.password
},
headers: {
'Content-Type': 'application/json',
},
body,
});
// Handle different status codes
if (response.status >= 200 && response.status < 300) {
return response.body;
}
// Handle specific error cases
switch (response.status) {
case 400:
throw new Error(
`Bad Request: The request could not be processed. Please check your input parameters.`
);
case 403:
throw new Error(
`Forbidden: Invalid authentication credentials or insufficient permissions.`
);
case 404:
throw new Error(
`Not Found: The requested resource could not be found.`
);
case 405:
throw new Error(
`Method Not Allowed: The HTTP method is not supported for this endpoint.`
);
case 500:
throw new Error(
`Internal Server Error: Aircall server encountered an unexpected condition.`
);
default:
throw new Error(
`HTTP ${response.status}: ${
response.body?.message || 'Unknown error occurred'
}`
);
}
} catch (error: any) {
// Re-throw if it's already our custom error
if (
error.message.includes('Bad Request') ||
error.message.includes('Forbidden') ||
error.message.includes('Not Found') ||
error.message.includes('Method Not Allowed') ||
error.message.includes('Internal Server Error')
) {
throw error;
}
// Handle network or other unexpected errors
throw new Error(`Request failed: ${error.message || String(error)}`);
}
}

View File

@@ -0,0 +1,161 @@
import { Property } from '@activepieces/pieces-framework';
import { makeRequest } from './client';
import { HttpMethod } from '@activepieces/pieces-common';
import { aircallAuth } from './auth';
export const callIdDropdown = Property.Dropdown<number,true,typeof aircallAuth>({
auth: aircallAuth,
displayName: 'Call',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your account first',
};
}
try {
const response = await makeRequest(
auth as { username: string; password: string },
HttpMethod.GET,
'/calls'
);
const {calls} = response as {calls:{id:number,raw_digits:string, direction:string}[]}
return {
disabled: false,
options: calls.map((call) => ({
label: `${call.raw_digits} - ${call.direction}`,
value: call.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading calls.',
};
}
},
});
export const numberIdDropdown = Property.Dropdown<string,true,typeof aircallAuth>({
auth: aircallAuth,
displayName: 'Number ID',
required: true,
refreshers: ['auth'],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your account first',
};
}
try {
const response = await makeRequest(
auth,
HttpMethod.GET,
'/numbers'
);
return {
disabled: false,
options: response.numbers.map((number: any) => ({
label: number.name,
value: number.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading numbers',
};
}
},
});
export const contactIdDropdown = Property.Dropdown<string,true,typeof aircallAuth>({
auth: aircallAuth,
displayName: 'Contact ID',
description: 'Select the contact to update',
required: true,
refreshers: ['auth'],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your account first',
};
}
try {
const response = await makeRequest(
auth,
HttpMethod.GET,
'/contacts'
);
const {contacts} = response as {contacts:{id:string,first_name:string,last_name:string}[]}
return {
disabled: false,
options: contacts.map((contact) => ({
label: `${contact.first_name || ""} ${contact.last_name || ""}` || contact.id,
value: contact.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading contacts',
};
}
},
});
export const tagIdDropdown = Property.MultiSelectDropdown<number,false,typeof aircallAuth>({
auth: aircallAuth,
displayName: 'Tags',
required: false,
refreshers: ['auth'],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your account first',
};
}
try {
const response = await makeRequest(
auth as { username: string; password: string },
HttpMethod.GET,
'/tags'
);
const {tags} = response as {tags:{id:number,name:string}[]}
return {
disabled: false,
options: tags.map((tag) => ({
label: tag.name,
value: tag.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading tags',
};
}
},
});

View File

@@ -0,0 +1,122 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
const TRIGGER_KEY = 'trigger_call-ended';
export const callEnded = createTrigger({
auth: aircallAuth,
name: 'callEnded',
displayName: 'Call Ended',
description: 'Triggers when a call ends.',
props: {},
sampleData: {
id: 12345,
direction: 'inbound',
status: 'answered',
started_at: '2023-07-31T10:30:00Z',
answered_at: '2023-07-31T10:30:05Z',
ended_at: '2023-07-31T10:35:00Z',
duration: 300,
from: '+1234567890',
to: '+0987654321',
via: '+0987654321',
recording: {
id: 456,
url: 'https://api.aircall.io/v1/calls/12345/recording',
filename: 'call_12345_recording.mp3',
},
comments: [
{
id: 789,
content: 'Customer inquiry resolved',
posted_at: '2023-07-31T10:36:00Z',
posted_by: {
id: 456,
name: 'John Smith',
email: 'john.smith@company.com',
},
},
],
tags: [
{
id: 101,
name: 'Customer Support',
color: '#ff0000',
},
],
contact: {
id: 456,
first_name: 'Jane',
last_name: 'Doe',
phone_numbers: [
{
id: 789,
label: 'Mobile',
value: '+1234567890',
},
],
},
user: {
id: 123,
name: 'Agent Smith',
email: 'agent@company.com',
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const webhookUrl = context.webhookUrl;
const response = await makeRequest(
context.auth,
HttpMethod.POST,
'/webhooks',
{
url: webhookUrl,
events: ['call.ended'],
}
);
const { webhook } = response as { webhook: { webhook_id: string } };
await context.store.put<string>(TRIGGER_KEY, webhook.webhook_id);
},
async onDisable(context) {
const webhookId = await context.store.get<string>(TRIGGER_KEY);
if (webhookId) {
await makeRequest(
context.auth,
HttpMethod.DELETE,
`/webhooks/${webhookId}`
);
}
},
async run(context) {
const payload = context.payload.body as {
event: string;
data: Record<string, any>;
};
if (payload.event === 'call.ended') {
return [payload.data];
}
return [];
},
async test(context) {
const response = await makeRequest(
context.auth,
HttpMethod.GET,
'/calls?order=desc&per_page=10'
);
const { calls } = response as { calls: { id: number }[] };
return calls;
},
});

View File

@@ -0,0 +1,99 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
const TRIGGER_KEY = 'trigger_new-contact'
export const newContact = createTrigger({
auth: aircallAuth,
name: 'newContact',
displayName: 'New Contact',
description: 'Triggers when a new contact is created.',
props: {},
sampleData: {
id: 456,
first_name: 'John',
last_name: 'Doe',
company_name: 'Acme Corp',
information: 'Important client contact',
is_shared: true,
created_at: '2023-07-31T10:30:00Z',
updated_at: '2023-07-31T10:30:00Z',
phone_numbers: [
{
id: 789,
label: 'Work',
value: '+1234567890'
},
{
id: 790,
label: 'Mobile',
value: '+1234567891'
}
],
emails: [
{
id: 123,
label: 'Office',
value: 'john.doe@acme.com'
}
]
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const webhookUrl = context.webhookUrl;
const response = await makeRequest(
context.auth,
HttpMethod.POST,
'/webhooks',
{
url: webhookUrl,
events: ['contact.created'],
}
);
const { webhook } = response as { webhook: { webhook_id: string } };
await context.store.put<string>(TRIGGER_KEY, webhook.webhook_id); },
async onDisable(context) {
const webhookId = await context.store.get<string>(TRIGGER_KEY);
if (webhookId) {
await makeRequest(
context.auth,
HttpMethod.DELETE,
`/webhooks/${webhookId}`
);
}
},
async run(context) {
const payload = context.payload.body as {
event: string;
data: Record<string, any>;
};
if (payload.event === 'contact.created') {
return [payload.data];
}
return [];
},
async test(context) {
const response = await makeRequest(
context.auth,
HttpMethod.GET,
'/contacts?order=desc&per_page=10'
);
const { contacts } = response as { contacts: { id: number }[] };
return contacts;
},
});

View File

@@ -0,0 +1,95 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
const TRIGGER_KEY = 'trigger_new-note';
export const newNote = createTrigger({
auth: aircallAuth,
name: 'newNote',
displayName: 'New Note',
description: 'Triggers when a new note is added to a call.',
props: {},
sampleData: {
id: 12345,
direction: 'inbound',
status: 'answered',
started_at: '2023-07-31T10:30:00Z',
answered_at: '2023-07-31T10:30:05Z',
ended_at: '2023-07-31T10:35:00Z',
duration: 300,
from: '+1234567890',
to: '+0987654321',
via: '+0987654321',
comments: [
{
id: 789,
content: 'Customer called about billing inquiry',
posted_at: '2023-07-31T10:36:00Z',
posted_by: {
id: 456,
name: 'John Smith',
email: 'john.smith@company.com',
},
},
],
contact: {
id: 456,
first_name: 'Jane',
last_name: 'Doe',
phone_numbers: [
{
id: 789,
label: 'Mobile',
value: '+1234567890',
},
],
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const webhookUrl = context.webhookUrl;
const response = await makeRequest(
context.auth,
HttpMethod.POST,
'/webhooks',
{
url: webhookUrl,
events: ['call.commented'],
}
);
const { webhook } = response as { webhook: { webhook_id: string } };
await context.store.put<string>(TRIGGER_KEY, webhook.webhook_id);
},
async onDisable(context) {
const webhookId = await context.store.get<string>(TRIGGER_KEY);
if (webhookId) {
await makeRequest(
context.auth,
HttpMethod.DELETE,
`/webhooks/${webhookId}`
);
}
},
async run(context) {
const payload = context.payload.body as {
event: string;
data: Record<string, any>;
};
// Verify this is a call commented event
if (payload.event === 'call.commented') {
return [payload.data];
}
return [];
},
});

View File

@@ -0,0 +1,74 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
const TRIGGER_KEY = 'trigger_new-number'
export const newNumberCreated = createTrigger({
auth: aircallAuth,
name: 'newNumberCreated',
displayName: 'New Number Created',
description: 'Triggers when a new number is created.',
props: {},
sampleData: {
id: 123,
name: 'Main Office Line',
digits: '+1234567890',
country: 'US',
time_zone: 'America/New_York',
created_at: '2023-07-31T10:30:00Z',
open: true,
priority: 1,
messages: {
welcome: 'Welcome to our company',
waiting: 'Please hold while we connect you',
voicemail: 'Please leave a message after the tone'
}
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const webhookUrl = context.webhookUrl;
const response = await makeRequest(
context.auth,
HttpMethod.POST,
'/webhooks',
{
url: webhookUrl,
events: ['number.created'],
}
);
const { webhook } = response as { webhook: { webhook_id: string } };
await context.store.put<string>(TRIGGER_KEY, webhook.webhook_id); },
async onDisable(context) {
const webhookId = await context.store?.get(TRIGGER_KEY);
if (webhookId) {
await makeRequest(
context.auth,
HttpMethod.DELETE,
`/webhooks/${webhookId}`
);
}
},
async run(context) {
const payload = context.payload.body as {
event: string;
data: Record<string, any>;
};
// Verify this is a number created event
if (payload.event === 'number.created') {
return [payload.data];
}
return [];
},
});

View File

@@ -0,0 +1,84 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { aircallAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
const TRIGGER_KEY = 'trigger_new-sms'
export const newSms = createTrigger({
auth: aircallAuth,
name: 'newSms',
displayName: 'New SMS',
description: 'Triggers when a new SMS message is received.',
props: {},
sampleData: {
id: 12345,
direction: 'inbound',
body: 'Hello, this is a test SMS message',
sent_at: '2023-07-31T10:30:00Z',
from: '+1234567890',
to: '+0987654321',
number: {
id: 123,
name: 'Main Number',
digits: '+0987654321',
},
contact: {
id: 456,
first_name: 'John',
last_name: 'Doe',
phone_numbers: [
{
id: 789,
label: 'Mobile',
value: '+1234567890',
},
],
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const webhookUrl = context.webhookUrl;
const response = await makeRequest(
context.auth,
HttpMethod.POST,
'/webhooks',
{
url: webhookUrl,
events: ['message.received'],
}
);
const { webhook } = response as { webhook: { webhook_id: string } };
await context.store.put<string>(TRIGGER_KEY, webhook.webhook_id); },
async onDisable(context) {
const webhookId = await context.store.get<string>(TRIGGER_KEY);
if (webhookId) {
await makeRequest(
context.auth,
HttpMethod.DELETE,
`/webhooks/${webhookId}`
);
}
},
async run(context) {
const payload = context.payload.body as {
event: string;
data: Record<string, any>;
};
if (payload.event === 'message.received') {
return [payload.data];
}
return [];
},
});

View File

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

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"]
}