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,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "Geben Sie Ihren OpenPhone-API-Schlüssel ein. Sie können einen über die API-Registerkarte in Ihren Arbeitsbereichseinstellungen generieren.",
"Send Message": "Nachricht senden",
"Create Contact": "Kontakt erstellen",
"Update Contact": "Kontakt aktualisieren",
"Get Call Summary": "Anrufübersicht erhalten",
"Send SMS/MMS from your OpenPhone number to a recipient": "SMS/MMS von Ihrer OpenPhone-Nummer an einen Empfänger senden",
"Create a new contact in your OpenPhone workspace": "Erstellen Sie einen neuen Kontakt in Ihrem OpenPhone-Arbeitsbereich",
"Update an existing contact in your OpenPhone workspace": "Aktualisiere einen bestehenden Kontakt in deinem OpenPhone-Arbeitsbereich",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "Abrufen einer von der KI generierten Zusammenfassung eines bestimmten Anrufs per ID. Anrufzusammenfassungen sind nur im OpenPhone Business Plan verfügbar.",
"Message Content": "Nachrichteninhalt",
"From Phone Number": "Von Telefonnummer",
"To Phone Numbers": "An Telefonnummern",
"User ID": "Benutzer-ID",
"Inbox Status": "Posteingang Status",
"First Name": "Vorname",
"Last Name": "Nachname",
"Company": "Firma",
"Role": "Rolle",
"Email Addresses": "E-Mail-Adressen",
"Phone Numbers": "Telefonnummern",
"Custom Fields": "Eigene Felder",
"Created By User ID": "Erstellt von Benutzer-ID",
"Source": "Quelle",
"Source URL": "Quell-URL",
"External ID": "Externe ID",
"Contact": "Kontakt",
"Phone Number": "Telefonnummer",
"Participant Phone Number": "Teilnehmer-Telefon",
"Call": "Anruf",
"The text content of the message to be sent (1-1600 characters)": "Der Text der zu sendenden Nachricht (1-1600 Zeichen)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "OpenPhone-Nummer, die gesendet werden soll (E.164-Format: +15555555555) oder Telefonnummer ID (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "Empfänger Telefonnummern im E.164 Format (z. B. +1555555555555)",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "Der eindeutige Identifikator des OpenPhone-Benutzers, der die Nachricht sendet. Falls nicht angegeben, wird standardmäßig der Besitzer der Telefonnummer verwendet.",
"Set the status of the related OpenPhone inbox conversation": "Legen Sie den Status der zugehörigen OpenPhone-Posteingangskonversation fest",
"The contact's first name": "Vorname des Kontakts",
"The contact's last name": "Nachname des Kontakts",
"The contact's company name": "Der Firmenname des Kontakts",
"The contact's role": "Die Rolle des Kontakts",
"List of email addresses for the contact": "Liste der E-Mail-Adressen für den Kontakt",
"List of phone numbers for the contact": "Liste der Telefonnummern für den Kontakt",
"Custom fields for the contact": "Benutzerdefinierte Felder für den Kontakt",
"The unique identifier of the user who created the contact (US123abc format)": "Der eindeutige Identifikator des Benutzers, der den Kontakt erstellt hat (US123abc Format)",
"The contact's source (defaults to \"public-api\")": "Die Quelle des Kontakts (standardmäßig \"public-api\")",
"A link to the contact in the source system": "Ein Link zum Kontakt im Quellsystem",
"A unique identifier from an external system": "Ein einzigartiger Bezeichner eines externen Systems",
"Select a contact": "Kontakt auswählen",
"List of email addresses for the contact (replaces existing emails)": "Liste der E-Mail-Adressen für den Kontakt (ersetzt bestehende E-Mails)",
"List of phone numbers for the contact (replaces existing phone numbers)": "Liste der Telefonnummern für den Kontakt (Ersetzt vorhandene Telefonnummern)",
"Update the contact's source": "Quelle des Kontakts aktualisieren",
"Update the link to the contact in the source system": "Link zum Kontakt im Quellsystem aktualisieren",
"Update the unique identifier from an external system": "Eindeutige Kennung eines externen Systems aktualisieren",
"Select a phone number to get calls from": "Wählen Sie eine Telefonnummer, um Anrufe zu erhalten",
"Select a participant phone number to filter calls": "Wählen Sie eine Teilnehmer-Telefonnummer, um Anrufe zu filtern",
"Select a call": "Anruf auswählen",
"Done": "Done",
"Call Recording Completed": "Anrufaufnahme abgeschlossen",
"Outgoing Message Delivered": "Ausgehende Nachricht geliefert",
"Outgoing Call Completed": "Ausgehender Anruf abgeschlossen",
"Incoming Call Completed": "Eingehender Anruf abgeschlossen",
"Incoming Message Received": "Eingehende Nachricht empfangen",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "Löst ab, wenn eine Anrufaufnahme beendet ist. Nützlich für Post-Transkription oder Archiv-Workflows.",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "Löscht ab, wenn eine ausgehende Nachricht erfolgreich gesendet wird. Nützlich für Workflows zur Nachrichtenbestätigung.",
"Fires when an outbound call ends. Useful for call logging.": "Feuert ab, wenn ein ausgehender Anruf endet. Nützlich für Anrufprotokollierung.",
"Fires when an incoming call is completed. Includes voicemail data if available.": "Löscht ab, wenn ein eingehender Anruf abgeschlossen ist. Enthält Sprachnachrichten falls verfügbar.",
"Fires when a new SMS/MMS message is received.": "Löscht ab, wenn eine neue SMS/MMS-Nachricht empfangen wird."
}

View File

@@ -0,0 +1,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "Introduzca su clave API de OpenPhone. Puede generar una desde la pestaña API en la configuración de su espacio de trabajo.",
"Send Message": "Enviar mensaje",
"Create Contact": "Crear contacto",
"Update Contact": "Actualizar contacto",
"Get Call Summary": "Obtener resumen de llamadas",
"Send SMS/MMS from your OpenPhone number to a recipient": "Enviar SMS/MMS desde su número OpenPhone a un destinatario",
"Create a new contact in your OpenPhone workspace": "Crear un nuevo contacto en su área de trabajo OpenPhone",
"Update an existing contact in your OpenPhone workspace": "Actualizar un contacto existente en su área de trabajo OpenPhone",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "Recuperar un resumen generado por la AIE de una llamada específica por el ID. Los resúmenes de llamadas sólo están disponibles en el plan de negocios de OpenPhone.",
"Message Content": "Contenido del mensaje",
"From Phone Number": "Desde el número de teléfono",
"To Phone Numbers": "A números de teléfono",
"User ID": "ID Usuario",
"Inbox Status": "Estado de la bandeja de entrada",
"First Name": "Nombre",
"Last Name": "Apellido",
"Company": "Empresa",
"Role": "Rol",
"Email Addresses": "Direcciones de email",
"Phone Numbers": "Números de teléfono",
"Custom Fields": "Campos personalizados",
"Created By User ID": "Creado por ID de usuario",
"Source": "Fuente",
"Source URL": "URL de origen",
"External ID": "ID Externo",
"Contact": "Contacto",
"Phone Number": "Número de teléfono",
"Participant Phone Number": "Número de teléfono del participante",
"Call": "Llamar",
"The text content of the message to be sent (1-1600 characters)": "El contenido de texto del mensaje a enviar (1-1600 caracteres)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "Número de OpenPhone a enviar desde (E.164 formato: +15555555555) o número de teléfono ID (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "Número de teléfono del destinatario en formato E.164 (por ejemplo, +15555555555)",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "El identificador único del usuario de OpenPhone que envía el mensaje. Si no se proporciona, por defecto al propietario del número de teléfono.",
"Set the status of the related OpenPhone inbox conversation": "Establecer el estado de la conversación relacionada con OpenPhone",
"The contact's first name": "Nombre del contacto",
"The contact's last name": "Apellido del contacto",
"The contact's company name": "Nombre de empresa del contacto",
"The contact's role": "El rol del contacto",
"List of email addresses for the contact": "Lista de direcciones de correo electrónico para el contacto",
"List of phone numbers for the contact": "Lista de números de teléfono para el contacto",
"Custom fields for the contact": "Campos personalizados para el contacto",
"The unique identifier of the user who created the contact (US123abc format)": "El identificador único del usuario que creó el contacto (formato US123abc)",
"The contact's source (defaults to \"public-api\")": "La fuente del contacto (por defecto es \"public-api\")",
"A link to the contact in the source system": "Un enlace al contacto en el sistema fuente",
"A unique identifier from an external system": "Un identificador único de un sistema externo",
"Select a contact": "Seleccione un contacto",
"List of email addresses for the contact (replaces existing emails)": "Lista de direcciones de correo electrónico para el contacto (sustituye los correos ya existentes)",
"List of phone numbers for the contact (replaces existing phone numbers)": "Lista de números de teléfono para el contacto (reemplaza los números de teléfono existentes)",
"Update the contact's source": "Actualizar la fuente del contacto",
"Update the link to the contact in the source system": "Actualizar el enlace al contacto en el sistema fuente",
"Update the unique identifier from an external system": "Actualizar el identificador único desde un sistema externo",
"Select a phone number to get calls from": "Seleccione un número de teléfono del que recibir llamadas",
"Select a participant phone number to filter calls": "Seleccione un número de teléfono del participante para filtrar llamadas",
"Select a call": "Seleccione una llamada",
"Done": "Hecho",
"Call Recording Completed": "Grabación de llamada completada",
"Outgoing Message Delivered": "Mensaje saliente entregado",
"Outgoing Call Completed": "Llamada saliente completada",
"Incoming Call Completed": "Llamada entrante completada",
"Incoming Message Received": "Mensaje recibido",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "Dispara cuando termina una grabación de llamadas. Útil para flujos de trabajo posttranscripción o archivo.",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "Dispara cuando un mensaje saliente se entrega con éxito. Útil para los flujos de trabajo de confirmación de mensajes.",
"Fires when an outbound call ends. Useful for call logging.": "Dispara cuando termina una llamada saliente. Útil para registrar llamadas.",
"Fires when an incoming call is completed. Includes voicemail data if available.": "Dispara cuando una llamada entrante se completa. Incluye datos del buzón de voz si está disponible.",
"Fires when a new SMS/MMS message is received.": "Dispara cuando un nuevo mensaje SMS/MMS es recibido."
}

View File

@@ -0,0 +1,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "Entrez votre clé API OpenPhone. Vous pouvez en générer une depuis l'onglet API dans les paramètres de votre espace de travail.",
"Send Message": "Envoyer un message",
"Create Contact": "Créer un contact",
"Update Contact": "Mettre à jour le contact",
"Get Call Summary": "Obtenir le résumé de l'appel",
"Send SMS/MMS from your OpenPhone number to a recipient": "Envoyer des SMS/MMS depuis votre numéro OpenPhone à un destinataire",
"Create a new contact in your OpenPhone workspace": "Créer un nouveau contact dans votre espace de travail OpenPhone",
"Update an existing contact in your OpenPhone workspace": "Mettre à jour un contact existant dans votre espace de travail OpenPhone",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "Récupérez un résumé généré par l'AI d'un appel spécifique par ID. Les résumés d'appels ne sont disponibles que sur le plan OpenPhone Business.",
"Message Content": "Contenu du message",
"From Phone Number": "À partir du numéro de téléphone",
"To Phone Numbers": "Vers les numéros de téléphone",
"User ID": "Identifiant de l'utilisateur",
"Inbox Status": "État de la boîte de réception",
"First Name": "First Name",
"Last Name": "Last Name",
"Company": "Entreprise",
"Role": "Rôle",
"Email Addresses": "Adresses e-mail",
"Phone Numbers": "Numéros de téléphone",
"Custom Fields": "Champs personnalisés",
"Created By User ID": "Créé par ID d'utilisateur",
"Source": "Source",
"Source URL": "URL de la source",
"External ID": "ID externe",
"Contact": "Contacter",
"Phone Number": "Numéro de téléphone",
"Participant Phone Number": "Numéro de téléphone du participant",
"Call": "Appel",
"The text content of the message to be sent (1-1600 characters)": "Le contenu du message à envoyer (1-1600 caractères)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "Numéro OpenPhone à envoyer du format (E.164 : +1555555555555) ou numéro de téléphone (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "Numéro de téléphone du destinataire au format E.164 (par exemple, +15555555555)",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "L'identifiant unique de l'utilisateur OpenPhone envoyant le message. Si non fourni, le propriétaire du numéro de téléphone par défaut.",
"Set the status of the related OpenPhone inbox conversation": "Définir le statut de la conversation OpenPhone associée",
"The contact's first name": "Prénom du contact",
"The contact's last name": "Nom du contact",
"The contact's company name": "Le nom de la société du contact",
"The contact's role": "Rôle du contact",
"List of email addresses for the contact": "Liste des adresses e-mail pour le contact",
"List of phone numbers for the contact": "Liste des numéros de téléphone du contact",
"Custom fields for the contact": "Champs personnalisés pour le contact",
"The unique identifier of the user who created the contact (US123abc format)": "L'identifiant unique de l'utilisateur qui a créé le contact (format US123abc)",
"The contact's source (defaults to \"public-api\")": "Source du contact (par défaut \"public-api\")",
"A link to the contact in the source system": "Un lien vers le contact dans le système source",
"A unique identifier from an external system": "Un identifiant unique à partir d'un système externe",
"Select a contact": "Sélectionnez un contact",
"List of email addresses for the contact (replaces existing emails)": "Liste des adresses e-mail du contact (remplace les e-mails existants)",
"List of phone numbers for the contact (replaces existing phone numbers)": "Liste des numéros de téléphone du contact (remplace les numéros de téléphone existants)",
"Update the contact's source": "Mettre à jour la source du contact",
"Update the link to the contact in the source system": "Mettre à jour le lien vers le contact dans le système source",
"Update the unique identifier from an external system": "Mettre à jour l'identifiant unique d'un système externe",
"Select a phone number to get calls from": "Sélectionnez un numéro de téléphone pour recevoir des appels de",
"Select a participant phone number to filter calls": "Sélectionnez un numéro de téléphone pour filtrer les appels",
"Select a call": "Sélectionnez un appel",
"Done": "Terminé",
"Call Recording Completed": "Enregistrement de l'appel terminé",
"Outgoing Message Delivered": "Message sortant délivré",
"Outgoing Call Completed": "Appel sortant terminé",
"Incoming Call Completed": "Appel entrant terminé",
"Incoming Message Received": "Message entrant reçu",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "Tire lorsquun enregistrement dappel se termine. Utile pour les flux de travail après transcription ou archives.",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "Déclenche lorsqu'un message sortant est envoyé avec succès. Utile pour les flux de travail de confirmation de message.",
"Fires when an outbound call ends. Useful for call logging.": "Tire quand un appel sortant se termine. Utile pour l'enregistrement des appels.",
"Fires when an incoming call is completed. Includes voicemail data if available.": "Se déclenche lorsqu'un appel entrant est terminé. Inclure les données de messagerie vocale si disponible.",
"Fires when a new SMS/MMS message is received.": "Déclenche lorsqu'un nouveau message SMS/MMS est reçu."
}

View File

@@ -0,0 +1,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "OpenPhone API キーを入力します。ワークスペース設定の API タブから生成できます。",
"Send Message": "メッセージを送信",
"Create Contact": "連絡先を作成",
"Update Contact": "連絡先を更新",
"Get Call Summary": "通話サマリーの取得",
"Send SMS/MMS from your OpenPhone number to a recipient": "OpenPhoneの番号から受信者にSMS/MMSを送信",
"Create a new contact in your OpenPhone workspace": "OpenPhone ワークスペースに新しい連絡先を作成します",
"Update an existing contact in your OpenPhone workspace": "OpenPhone ワークスペースの既存の連絡先を更新",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "IDによる特定の通話のAI生成サマリーを取得します。通話サマリーはOpenPhone Businessプランでのみ利用できます。",
"Message Content": "メッセージの内容",
"From Phone Number": "電話番号",
"To Phone Numbers": "電話番号へ",
"User ID": "ユーザー ID",
"Inbox Status": "受信トレイの状態",
"First Name": "名",
"Last Name": "Last Name",
"Company": "会社名",
"Role": "ロール",
"Email Addresses": "メールアドレス",
"Phone Numbers": "電話番号",
"Custom Fields": "カスタムフィールド",
"Created By User ID": "作成者ユーザーID",
"Source": "ソース",
"Source URL": "ソースURL",
"External ID": "外部 ID",
"Contact": "お問い合わせ",
"Phone Number": "電話番号",
"Participant Phone Number": "参加者電話番号",
"Call": "電話",
"The text content of the message to be sent (1-1600 characters)": "送信されるメッセージのテキストの内容 (1-1600 文字)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "発信元のOpenPhone番号 (E.164形式: +15555555) または電話番号ID (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "E.164形式の受信者の電話番号(例:+1555555",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "メッセージを送信している OpenPhone ユーザーの一意の識別子。指定されていない場合は、既定の電話番号の所有者になります。",
"Set the status of the related OpenPhone inbox conversation": "関連する OpenPhone 受信トレイの会話の状態を設定します",
"The contact's first name": "連絡先の名",
"The contact's last name": "連絡先の姓",
"The contact's company name": "連絡先の会社名",
"The contact's role": "連絡先の役割",
"List of email addresses for the contact": "連絡先のメールアドレス一覧",
"List of phone numbers for the contact": "連絡先の電話番号一覧",
"Custom fields for the contact": "連絡先のカスタムフィールド",
"The unique identifier of the user who created the contact (US123abc format)": "コンタクトを作成したユーザーの一意の識別子 (US123abc フォーマット)",
"The contact's source (defaults to \"public-api\")": "連絡先のソース (デフォルトは \"public-api\")",
"A link to the contact in the source system": "ソースシステム内の連絡先へのリンク",
"A unique identifier from an external system": "外部システムからの一意の識別子",
"Select a contact": "連絡先を選択",
"List of email addresses for the contact (replaces existing emails)": "連絡先のメールアドレスの一覧 (既存のメールを置き換えます)",
"List of phone numbers for the contact (replaces existing phone numbers)": "連絡先の電話番号の一覧 (既存の電話番号を置き換えます)",
"Update the contact's source": "連絡先のソースを更新",
"Update the link to the contact in the source system": "ソースシステムの連絡先へのリンクを更新する",
"Update the unique identifier from an external system": "外部システムから一意の識別子を更新する",
"Select a phone number to get calls from": "電話番号を選択してから通話を受ける",
"Select a participant phone number to filter calls": "参加者の電話番号を選択して通話をフィルターする",
"Select a call": "通話を選択",
"Done": "完了",
"Call Recording Completed": "通話記録完了",
"Outgoing Message Delivered": "送信メッセージを送信しました",
"Outgoing Call Completed": "発信完了",
"Incoming Call Completed": "着信が完了しました",
"Incoming Message Received": "受信したメッセージ",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "通話記録が終了すると発火します。転写後やアーカイブのワークフローに便利です。",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "送信メッセージが正常に配信されたときに発生します。メッセージの確認ワークフローに役立ちます。",
"Fires when an outbound call ends. Useful for call logging.": "アウトバウンドコールが終了したときに発生します。コールログに便利です。",
"Fires when an incoming call is completed. Includes voicemail data if available.": "着信が完了したときに発生します。利用可能な場合はボイスメールデータが含まれます。",
"Fires when a new SMS/MMS message is received.": "新しいSMS/MMSメッセージを受信したときに発生します。"
}

View File

@@ -0,0 +1,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "Voer uw OpenPhone API-sleutel in. U kunt er een aanmaken via het API-tabblad in uw workspace instellingen.",
"Send Message": "Verstuur bericht",
"Create Contact": "Contactpersoon aanmaken",
"Update Contact": "Contactpersoon bijwerken",
"Get Call Summary": "Oproep samenvatting ophalen",
"Send SMS/MMS from your OpenPhone number to a recipient": "SMS/MMS verzenden van uw OpenPhone nummer naar een ontvanger",
"Create a new contact in your OpenPhone workspace": "Maak een nieuw contact aan in uw OpenPhone workspace",
"Update an existing contact in your OpenPhone workspace": "Een bestaand contact in uw OpenPhone workspace bijwerken",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "Haal een AI-gegenereerde samenvatting op van een specifieke oproep met ID. Oproepsamenvattingen zijn alleen beschikbaar op OpenPhone Business Plan.",
"Message Content": "Bericht inhoud",
"From Phone Number": "Van Telefoonnummer",
"To Phone Numbers": "Naar telefoonnummers",
"User ID": "Gebruiker ID",
"Inbox Status": "Status inbox",
"First Name": "Voornaam",
"Last Name": "Achternaam",
"Company": "Bedrijfsnaam",
"Role": "Functie",
"Email Addresses": "E-mail adressen",
"Phone Numbers": "Telefoon nummers",
"Custom Fields": "Aangepaste velden",
"Created By User ID": "Aangemaakt door gebruikers-ID",
"Source": "Bron",
"Source URL": "Bron URL",
"External ID": "Extern ID",
"Contact": "Contactpersoon",
"Phone Number": "Telefoon nummer",
"Participant Phone Number": "Telefoonnummer deelnemer",
"Call": "Oproepen",
"The text content of the message to be sent (1-1600 characters)": "De tekst inhoud van het bericht dat verzonden wordt (1-1600 tekens)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "OpenPhone nummer te verzenden vanaf (E.164 formaat: +155555555) of telefoonnummer ID (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "Geadresseerde telefoonnummers in E.164-formaat (bijv. +15555555555)",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "De unieke id van de OpenPhone gebruiker die het bericht verstuurt. Indien niet opgegeven, standaard de eigenaar van het telefoonnummer.",
"Set the status of the related OpenPhone inbox conversation": "Stel de status in van het gerelateerde OpenPhone inbox gesprek",
"The contact's first name": "Voornaam van de contactpersoon",
"The contact's last name": "Achternaam van de contactpersoon",
"The contact's company name": "Bedrijfsnaam van de contactpersoon",
"The contact's role": "Rol van de contactpersoon",
"List of email addresses for the contact": "Lijst met e-mailadressen voor de contactpersoon",
"List of phone numbers for the contact": "Lijst van telefoonnummers voor de contactpersoon",
"Custom fields for the contact": "Aangepaste velden voor de contactpersoon",
"The unique identifier of the user who created the contact (US123abc format)": "De unieke id van de gebruiker die de contactpersoon heeft gemaakt (US123abc formaat)",
"The contact's source (defaults to \"public-api\")": "Bron van het contact (standaard \"Publiek-api\")",
"A link to the contact in the source system": "Een link naar het contact in het bronsysteem",
"A unique identifier from an external system": "Een unieke id van een extern systeem",
"Select a contact": "Selecteer een contactpersoon",
"List of email addresses for the contact (replaces existing emails)": "Lijst met e-mailadressen voor de contactpersoon (vervangt bestaande e-mails)",
"List of phone numbers for the contact (replaces existing phone numbers)": "Lijst van telefoonnummers voor de contactpersoon (vervangt bestaande telefoonnummers)",
"Update the contact's source": "Update de bron van de contactpersoon",
"Update the link to the contact in the source system": "Werk de link naar de contactpersoon in het bronsysteem bij",
"Update the unique identifier from an external system": "Update de unieke id van een extern systeem",
"Select a phone number to get calls from": "Selecteer een telefoonnummer om oproepen van op te halen",
"Select a participant phone number to filter calls": "Selecteer een deelnemer telefoonnummer om oproepen te filteren",
"Select a call": "Selecteer een oproep",
"Done": "Voltooid",
"Call Recording Completed": "Oproep opnemen voltooid",
"Outgoing Message Delivered": "Uitgaande bericht afgeleverd",
"Outgoing Call Completed": "Uitgaande oproep voltooid",
"Incoming Call Completed": "Inkomende oproep voltooid",
"Incoming Message Received": "Inkomend bericht ontvangen",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "Vuurt wanneer een oproepopname klaar is. Nuttig voor transcriptie of archivering workflows.",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "Vuurt wanneer een uitgaande bericht succesvol wordt afgeleverd. Nuttig voor de bevestigingsworkflows.",
"Fires when an outbound call ends. Useful for call logging.": "Vuurt wanneer een uitgaande oproep eindigt. Nuttig voor oproeplog.",
"Fires when an incoming call is completed. Includes voicemail data if available.": "Vuurt wanneer een inkomende oproep is voltooid. Inclusief voicemailgegevens indien beschikbaar.",
"Fires when a new SMS/MMS message is received.": "Schiet wanneer een nieuw SMS/MMS bericht is ontvangen."
}

View File

@@ -0,0 +1,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "Digite sua chave da API do OpenPhone. Você pode gerar uma na guia API nas configurações do seu espaço de trabalho.",
"Send Message": "Enviar mensagem",
"Create Contact": "Criar contato",
"Update Contact": "Atualizar contato",
"Get Call Summary": "Obter Resumo da Ligação",
"Send SMS/MMS from your OpenPhone number to a recipient": "Enviar SMS/MMS do seu número OpenPhone para um destinatário",
"Create a new contact in your OpenPhone workspace": "Criar um novo contato em seu espaço de trabalho OpenPhone",
"Update an existing contact in your OpenPhone workspace": "Atualizar um contato existente no seu espaço de trabalho OpenPhone",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "Obter um resumo gerado pela IA de uma chamada específica por ID. Os resumos de chamadas estão disponíveis apenas no plano OpenPhone Business.",
"Message Content": "Conteúdo da Mensagem",
"From Phone Number": "De número de telefone",
"To Phone Numbers": "Para números de telefone",
"User ID": "ID de usuário",
"Inbox Status": "Status da Caixa de Entrada",
"First Name": "Nome",
"Last Name": "Sobrenome",
"Company": "Empresas",
"Role": "Funções",
"Email Addresses": "Endereços de e-mail",
"Phone Numbers": "Números de telefone",
"Custom Fields": "Campos Personalizados",
"Created By User ID": "Criado pelo ID do Usuário",
"Source": "fonte",
"Source URL": "URL de origem",
"External ID": "ID Externo",
"Contact": "contato",
"Phone Number": "Número de telefone",
"Participant Phone Number": "Telefone do participante",
"Call": "Chamada",
"The text content of the message to be sent (1-1600 characters)": "O conteúdo da mensagem a ser enviada (1-1600 caracteres)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "Número OpenPhone para enviar do formato (E.164: +15555555555) ou ID do telefone (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "Números de telefone do beneficiário no formato E.164 (por exemplo, +1555555555555)",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "O identificador exclusivo do usuário OpenPhone enviando a mensagem. Se não for fornecido, o padrão é o proprietário do número de telefone.",
"Set the status of the related OpenPhone inbox conversation": "Definir o status da conversa relacionada com o OpenPhone",
"The contact's first name": "Primeiro nome do contato",
"The contact's last name": "Sobrenome do contato",
"The contact's company name": "O nome do contato da empresa",
"The contact's role": "Função do contato",
"List of email addresses for the contact": "Lista de endereços de e-mail para o contato",
"List of phone numbers for the contact": "Lista de números de telefone para o contato",
"Custom fields for the contact": "Campos personalizados para o contato",
"The unique identifier of the user who created the contact (US123abc format)": "O identificador exclusivo do usuário que criou o contato (formato US123abc)",
"The contact's source (defaults to \"public-api\")": "A fonte do contato (o padrão é \"public-api\")",
"A link to the contact in the source system": "Um link para o contato no sistema de origem",
"A unique identifier from an external system": "Um identificador exclusivo de um sistema externo",
"Select a contact": "Selecione um contato",
"List of email addresses for the contact (replaces existing emails)": "Lista de endereços de e-mail para o contato (substituir e-mails existentes)",
"List of phone numbers for the contact (replaces existing phone numbers)": "Lista de números de telefone para o contato (substitui os números de telefone existentes)",
"Update the contact's source": "Atualizar fonte do contato",
"Update the link to the contact in the source system": "Atualizar o link para o contato no sistema de origem",
"Update the unique identifier from an external system": "Atualizar o identificador exclusivo de um sistema externo",
"Select a phone number to get calls from": "Selecione um número de telefone de onde quer receber chamadas",
"Select a participant phone number to filter calls": "Selecione um número de telefone do usuário para filtrar chamadas",
"Select a call": "Selecione uma chamada",
"Done": "Concluído",
"Call Recording Completed": "Gravação de chamada concluída",
"Outgoing Message Delivered": "Mensagem de saída entregue",
"Outgoing Call Completed": "Chamada de saída concluída",
"Incoming Call Completed": "Chamada recebida concluída",
"Incoming Message Received": "Mensagem de entrada recebida",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "Atira quando termina a gravação de chamada. Útil para fluxos de trabalho pós-transcrição ou arquivamento.",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "Atira quando uma mensagem de saída é entregue com sucesso. Útil para fluxos de trabalho de confirmação de mensagem.",
"Fires when an outbound call ends. Useful for call logging.": "Atira quando uma chamada de saída termina. Útil para registro de chamadas.",
"Fires when an incoming call is completed. Includes voicemail data if available.": "Efetua quando uma chamada recebida é concluída. Inclui dados de correio de voz se disponível.",
"Fires when a new SMS/MMS message is received.": "Efetua quando uma nova mensagem de SMS/MMS é recebida."
}

View File

@@ -0,0 +1,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.",
"Send Message": "Send Message",
"Create Contact": "Create Contact",
"Update Contact": "Update Contact",
"Get Call Summary": "Get Call Summary",
"Send SMS/MMS from your OpenPhone number to a recipient": "Send SMS/MMS from your OpenPhone number to a recipient",
"Create a new contact in your OpenPhone workspace": "Create a new contact in your OpenPhone workspace",
"Update an existing contact in your OpenPhone workspace": "Update an existing contact in your OpenPhone workspace",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.",
"Message Content": "Message Content",
"From Phone Number": "From Phone Number",
"To Phone Numbers": "To Phone Numbers",
"User ID": "User ID",
"Inbox Status": "Inbox Status",
"First Name": "First Name",
"Last Name": "Last Name",
"Company": "Company",
"Role": "Role",
"Email Addresses": "Email Addresses",
"Phone Numbers": "Phone Numbers",
"Custom Fields": "Custom Fields",
"Created By User ID": "Created By User ID",
"Source": "Source",
"Source URL": "Source URL",
"External ID": "External ID",
"Contact": "Contact",
"Phone Number": "Phone Number",
"Participant Phone Number": "Participant Phone Number",
"Call": "Call",
"The text content of the message to be sent (1-1600 characters)": "The text content of the message to be sent (1-1600 characters)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "Recipient phone numbers in E.164 format (e.g., +15555555555)",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.",
"Set the status of the related OpenPhone inbox conversation": "Set the status of the related OpenPhone inbox conversation",
"The contact's first name": "The contact's first name",
"The contact's last name": "The contact's last name",
"The contact's company name": "The contact's company name",
"The contact's role": "The contact's role",
"List of email addresses for the contact": "List of email addresses for the contact",
"List of phone numbers for the contact": "List of phone numbers for the contact",
"Custom fields for the contact": "Custom fields for the contact",
"The unique identifier of the user who created the contact (US123abc format)": "The unique identifier of the user who created the contact (US123abc format)",
"The contact's source (defaults to \"public-api\")": "The contact's source (defaults to \"public-api\")",
"A link to the contact in the source system": "A link to the contact in the source system",
"A unique identifier from an external system": "A unique identifier from an external system",
"Select a contact": "Select a contact",
"List of email addresses for the contact (replaces existing emails)": "List of email addresses for the contact (replaces existing emails)",
"List of phone numbers for the contact (replaces existing phone numbers)": "List of phone numbers for the contact (replaces existing phone numbers)",
"Update the contact's source": "Update the contact's source",
"Update the link to the contact in the source system": "Update the link to the contact in the source system",
"Update the unique identifier from an external system": "Update the unique identifier from an external system",
"Select a phone number to get calls from": "Select a phone number to get calls from",
"Select a participant phone number to filter calls": "Select a participant phone number to filter calls",
"Select a call": "Select a call",
"Done": "Done",
"Call Recording Completed": "Call Recording Completed",
"Outgoing Message Delivered": "Outgoing Message Delivered",
"Outgoing Call Completed": "Outgoing Call Completed",
"Incoming Call Completed": "Incoming Call Completed",
"Incoming Message Received": "Incoming Message Received",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "Fires when a call recording finishes. Useful for post-transcription or archival workflows.",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.",
"Fires when an outbound call ends. Useful for call logging.": "Fires when an outbound call ends. Useful for call logging.",
"Fires when an incoming call is completed. Includes voicemail data if available.": "Fires when an incoming call is completed. Includes voicemail data if available.",
"Fires when a new SMS/MMS message is received.": "Fires when a new SMS/MMS message is received."
}

View File

@@ -0,0 +1,67 @@
{
"Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.": "Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.",
"Send Message": "Send Message",
"Create Contact": "Create Contact",
"Update Contact": "Update Contact",
"Get Call Summary": "Get Call Summary",
"Send SMS/MMS from your OpenPhone number to a recipient": "Send SMS/MMS from your OpenPhone number to a recipient",
"Create a new contact in your OpenPhone workspace": "Create a new contact in your OpenPhone workspace",
"Update an existing contact in your OpenPhone workspace": "Update an existing contact in your OpenPhone workspace",
"Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.": "Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.",
"Message Content": "Message Content",
"From Phone Number": "From Phone Number",
"To Phone Numbers": "To Phone Numbers",
"User ID": "User ID",
"Inbox Status": "Inbox Status",
"First Name": "First Name",
"Last Name": "名字",
"Company": "Company",
"Role": "作用",
"Email Addresses": "Email Addresses",
"Phone Numbers": "Phone Numbers",
"Custom Fields": "Custom Fields",
"Created By User ID": "Created By User ID",
"Source": "来源",
"Source URL": "Source URL",
"External ID": "外部ID",
"Contact": "Contact",
"Phone Number": "Phone Number",
"Participant Phone Number": "Participant Phone Number",
"Call": "Call",
"The text content of the message to be sent (1-1600 characters)": "The text content of the message to be sent (1-1600 characters)",
"OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)": "OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)",
"Recipient phone numbers in E.164 format (e.g., +15555555555)": "Recipient phone numbers in E.164 format (e.g., +15555555555)",
"The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.": "The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.",
"Set the status of the related OpenPhone inbox conversation": "Set the status of the related OpenPhone inbox conversation",
"The contact's first name": "The contact's first name",
"The contact's last name": "The contact's last name",
"The contact's company name": "The contact's company name",
"The contact's role": "The contact's role",
"List of email addresses for the contact": "List of email addresses for the contact",
"List of phone numbers for the contact": "List of phone numbers for the contact",
"Custom fields for the contact": "Custom fields for the contact",
"The unique identifier of the user who created the contact (US123abc format)": "The unique identifier of the user who created the contact (US123abc format)",
"The contact's source (defaults to \"public-api\")": "The contact's source (defaults to \"public-api\")",
"A link to the contact in the source system": "A link to the contact in the source system",
"A unique identifier from an external system": "A unique identifier from an external system",
"Select a contact": "Select a contact",
"List of email addresses for the contact (replaces existing emails)": "List of email addresses for the contact (replaces existing emails)",
"List of phone numbers for the contact (replaces existing phone numbers)": "List of phone numbers for the contact (replaces existing phone numbers)",
"Update the contact's source": "Update the contact's source",
"Update the link to the contact in the source system": "Update the link to the contact in the source system",
"Update the unique identifier from an external system": "Update the unique identifier from an external system",
"Select a phone number to get calls from": "Select a phone number to get calls from",
"Select a participant phone number to filter calls": "Select a participant phone number to filter calls",
"Select a call": "Select a call",
"Done": "完成",
"Call Recording Completed": "Call Recording Completed",
"Outgoing Message Delivered": "Outgoing Message Delivered",
"Outgoing Call Completed": "Outgoing Call Completed",
"Incoming Call Completed": "Incoming Call Completed",
"Incoming Message Received": "Incoming Message Received",
"Fires when a call recording finishes. Useful for post-transcription or archival workflows.": "Fires when a call recording finishes. Useful for post-transcription or archival workflows.",
"Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.": "Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.",
"Fires when an outbound call ends. Useful for call logging.": "Fires when an outbound call ends. Useful for call logging.",
"Fires when an incoming call is completed. Includes voicemail data if available.": "Fires when an incoming call is completed. Includes voicemail data if available.",
"Fires when a new SMS/MMS message is received.": "Fires when a new SMS/MMS message is received."
}

View File

@@ -0,0 +1,33 @@
import { createPiece, PieceAuth } from '@activepieces/pieces-framework';
import { sendMessage } from './lib/actions/send-message';
import { createContact } from './lib/actions/create-contact';
import { updateContact } from './lib/actions/update-contact';
import { getCallSummary } from './lib/actions/get-call-summary';
import { callRecordingCompleted } from './lib/triggers/call-recording-completed';
import { outgoingMessageDelivered } from './lib/triggers/outgoing-message-delivered';
import { outgoingCallCompleted } from './lib/triggers/outgoing-call-completed';
import { incomingCallCompleted } from './lib/triggers/incoming-call-completed';
import { incomingMessageReceived } from './lib/triggers/incoming-message-received';
export const openPhoneAuth = PieceAuth.SecretText({
displayName: 'API Key',
required: true,
description:
'Enter your OpenPhone API key. You can generate one from the API tab in your workspace settings.',
});
export const openPhone = createPiece({
displayName: 'OpenPhone',
auth: openPhoneAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: 'https://cdn.activepieces.com/pieces/open-phone.png',
authors: ['Ani-4x', 'onyedikachi-david'],
actions: [sendMessage, createContact, updateContact, getCallSummary],
triggers: [
callRecordingCompleted,
outgoingMessageDelivered,
outgoingCallCompleted,
incomingCallCompleted,
incomingMessageReceived,
],
});

View File

@@ -0,0 +1,248 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import {
openPhoneCommon,
OpenPhoneContactResponse,
CreateOpenPhoneContactRequest,
OpenPhoneEmail,
OpenPhonePhoneNumber,
OpenPhoneCustomField,
} from '../common';
export const createContact = createAction({
auth: openPhoneAuth,
name: 'create_contact',
displayName: 'Create Contact',
description: 'Create a new contact in your OpenPhone workspace',
props: {
firstName: Property.ShortText({
displayName: 'First Name',
description: "The contact's first name",
required: true,
}),
lastName: Property.ShortText({
displayName: 'Last Name',
description: "The contact's last name",
required: false,
}),
company: Property.ShortText({
displayName: 'Company',
description: "The contact's company name",
required: false,
}),
role: Property.ShortText({
displayName: 'Role',
description: "The contact's role",
required: false,
}),
emails: Property.Array({
displayName: 'Email Addresses',
description: 'List of email addresses for the contact',
required: false,
properties: {
name: Property.ShortText({
displayName: 'Email Label',
description:
'Label for this email address (e.g., "work", "personal")',
required: true,
}),
value: Property.ShortText({
displayName: 'Email Address',
description: 'The email address',
required: true,
}),
},
}),
phoneNumbers: Property.Array({
displayName: 'Phone Numbers',
description: 'List of phone numbers for the contact',
required: false,
properties: {
name: Property.ShortText({
displayName: 'Phone Label',
description: 'Label for this phone number (e.g., "mobile", "work")',
required: true,
}),
value: Property.ShortText({
displayName: 'Phone Number',
description: 'The phone number (preferably in E.164 format)',
required: true,
}),
},
}),
customFields: Property.Array({
displayName: 'Custom Fields',
description: 'Custom fields for the contact',
required: false,
properties: {
key: Property.ShortText({
displayName: 'Field Key',
description: 'The identifying key for the custom field',
required: true,
}),
value: Property.ShortText({
displayName: 'Field Value',
description: 'The value for the custom field',
required: true,
}),
},
}),
createdByUserId: Property.ShortText({
displayName: 'Created By User ID',
description:
'The unique identifier of the user who created the contact (US123abc format)',
required: false,
}),
source: Property.ShortText({
displayName: 'Source',
description: 'The contact\'s source (defaults to "public-api")',
required: false,
defaultValue: 'public-api',
}),
sourceUrl: Property.ShortText({
displayName: 'Source URL',
description: 'A link to the contact in the source system',
required: false,
}),
externalId: Property.ShortText({
displayName: 'External ID',
description: 'A unique identifier from an external system',
required: false,
}),
},
async run(context) {
const {
firstName,
lastName,
company,
role,
emails,
phoneNumbers,
customFields,
createdByUserId,
source,
sourceUrl,
externalId,
} = context.propsValue;
const auth = context.auth;
if (!firstName || firstName.trim() === '') {
throw new Error('First name is required and cannot be empty');
}
if (emails && Array.isArray(emails)) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
for (const email of emails as Array<{ name: string; value: string }>) {
if (email.value && !emailRegex.test(email.value)) {
throw new Error(`Invalid email format: ${email.value}`);
}
}
}
if (source && (source.length < 1 || source.length > 72)) {
throw new Error('Source must be between 1 and 72 characters');
}
if (sourceUrl) {
try {
new URL(sourceUrl);
} catch {
throw new Error('Invalid source URL format');
}
if (sourceUrl.length < 1 || sourceUrl.length > 200) {
throw new Error('Source URL must be between 1 and 200 characters');
}
}
if (externalId && (externalId.length < 1 || externalId.length > 75)) {
throw new Error('External ID must be between 1 and 75 characters');
}
if (createdByUserId && !/^US(.*)$/.test(createdByUserId)) {
throw new Error(
'Created by user ID must start with "US" (e.g., US123abc)'
);
}
const requestBody: CreateOpenPhoneContactRequest = {
defaultFields: {
firstName: firstName.trim(),
lastName: lastName ? lastName.trim() : null,
company: company ? company.trim() : null,
role: role ? role.trim() : null,
},
};
if (emails && Array.isArray(emails) && emails.length > 0) {
requestBody.defaultFields.emails = (
emails as Array<{ name: string; value: string }>
).map(
(email): OpenPhoneEmail => ({
name: email.name.trim(),
value: email.value ? email.value.trim() : null,
})
);
}
if (
phoneNumbers &&
Array.isArray(phoneNumbers) &&
phoneNumbers.length > 0
) {
requestBody.defaultFields.phoneNumbers = (
phoneNumbers as Array<{ name: string; value: string }>
).map(
(phone): OpenPhonePhoneNumber => ({
name: phone.name.trim(),
value: phone.value ? phone.value.trim() : null,
})
);
}
if (
customFields &&
Array.isArray(customFields) &&
customFields.length > 0
) {
requestBody.customFields = (
customFields as Array<{ key: string; value: string }>
).map(
(field): OpenPhoneCustomField => ({
key: field.key.trim(),
value: field.value ? field.value.trim() : null,
})
);
}
if (createdByUserId) {
requestBody.createdByUserId = createdByUserId.trim();
}
if (source) {
requestBody.source = source.trim();
}
if (sourceUrl) {
requestBody.sourceUrl = sourceUrl.trim();
}
if (externalId) {
requestBody.externalId = externalId.trim();
}
try {
const response: OpenPhoneContactResponse =
await openPhoneCommon.makeRequest<OpenPhoneContactResponse>(
HttpMethod.POST,
'/v1/contacts',
auth,
requestBody
);
return response;
} catch (error) {
throw new Error(`Failed to create contact: ${error}`);
}
},
});

View File

@@ -0,0 +1,51 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import { openPhoneCommon, OpenPhoneCallSummaryResponse } from '../common';
import {
phoneNumberDropdown,
participantDropdown,
callDropdown,
} from '../common/props';
export const getCallSummary = createAction({
auth: openPhoneAuth,
name: 'get_call_summary',
displayName: 'Get Call Summary',
description:
'Retrieve an AI-generated summary of a specific call by ID. Call summaries are only available on OpenPhone Business plan.',
props: {
phoneNumberId: phoneNumberDropdown,
participantNumber: participantDropdown,
callId: callDropdown,
},
async run(context) {
const { callId } = context.propsValue;
const auth = context.auth;
if (!callId || callId === 'manual' || callId === '') {
throw new Error(
'Please provide a valid Call ID in the format AC... or select a call from the dropdown'
);
}
if (!callId.match(/^AC[a-zA-Z0-9]+$/)) {
throw new Error(
'Invalid call ID format. Call ID should start with "AC" followed by alphanumeric characters.'
);
}
try {
const response: OpenPhoneCallSummaryResponse =
await openPhoneCommon.makeRequest<OpenPhoneCallSummaryResponse>(
HttpMethod.GET,
`/v1/call-summaries/${callId}`,
auth
);
return response;
} catch (error) {
throw new Error(`Failed to get call summary: ${error}`);
}
},
});

View File

@@ -0,0 +1,115 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import { openPhoneCommon, OpenPhoneMessageResponse } from '../common';
export const sendMessage = createAction({
auth: openPhoneAuth,
name: 'send_message',
displayName: 'Send Message',
description: 'Send SMS/MMS from your OpenPhone number to a recipient',
props: {
content: Property.LongText({
displayName: 'Message Content',
description:
'The text content of the message to be sent (1-1600 characters)',
required: true,
}),
from: Property.ShortText({
displayName: 'From Phone Number',
description:
'OpenPhone number to send from (E.164 format: +15555555555) or phone number ID (PN123abc)',
required: true,
}),
to: Property.Array({
displayName: 'To Phone Numbers',
description:
'Recipient phone numbers in E.164 format (e.g., +15555555555)',
required: true,
properties: {
phoneNumber: Property.ShortText({
displayName: 'Phone Number',
description: 'Phone number in E.164 format',
required: true,
}),
},
}),
userId: Property.ShortText({
displayName: 'User ID',
description:
'The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.',
required: false,
}),
setInboxStatus: Property.StaticDropdown({
displayName: 'Inbox Status',
description: 'Set the status of the related OpenPhone inbox conversation',
required: false,
options: {
options: [
{
label: 'Done',
value: 'done',
},
],
},
}),
},
async run(context) {
const { content, from, to, userId, setInboxStatus } = context.propsValue;
const auth = context.auth;
const phoneRegex = /^\+[1-9]\d{1,14}$/;
if (!to || !Array.isArray(to) || to.length === 0) {
throw new Error('At least one phone number is required');
}
if (to.length > 1) {
throw new Error('Currently only one recipient phone number is supported');
}
const toPhoneNumbers = to as Array<{ phoneNumber: string }>;
for (const phone of toPhoneNumbers) {
if (!phoneRegex.test(phone.phoneNumber)) {
throw new Error(
`Invalid phone number format: ${phone.phoneNumber}. Use E.164 format (e.g., +15555555555)`
);
}
}
if (!content || !content.trim()) {
throw new Error(
'Message content cannot be empty or contain only whitespace'
);
}
if (content.length > 1600) {
throw new Error('Message content cannot exceed 1600 characters');
}
const requestBody: any = {
content: content,
from: from,
to: toPhoneNumbers.map((phone) => phone.phoneNumber),
};
if (userId) {
requestBody.userId = userId;
}
if (setInboxStatus) {
requestBody.setInboxStatus = setInboxStatus;
}
try {
const response: OpenPhoneMessageResponse =
await openPhoneCommon.makeRequest<OpenPhoneMessageResponse>(
HttpMethod.POST,
'/v1/messages',
auth,
requestBody
);
return response;
} catch (error) {
throw new Error(`Failed to send message: ${error}`);
}
},
});

View File

@@ -0,0 +1,291 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import {
openPhoneCommon,
OpenPhoneContactResponse,
UpdateOpenPhoneContactRequest,
OpenPhoneEmail,
OpenPhonePhoneNumber,
} from '../common';
import { contactDropdown } from '../common/props';
export const updateContact = createAction({
auth: openPhoneAuth,
name: 'update_contact',
displayName: 'Update Contact',
description: 'Update an existing contact in your OpenPhone workspace',
props: {
contactId: contactDropdown,
firstName: Property.ShortText({
displayName: 'First Name',
description: "The contact's first name",
required: false,
}),
lastName: Property.ShortText({
displayName: 'Last Name',
description: "The contact's last name",
required: false,
}),
company: Property.ShortText({
displayName: 'Company',
description: "The contact's company name",
required: false,
}),
role: Property.ShortText({
displayName: 'Role',
description: "The contact's role",
required: false,
}),
emails: Property.Array({
displayName: 'Email Addresses',
description:
'List of email addresses for the contact (replaces existing emails)',
required: false,
properties: {
name: Property.ShortText({
displayName: 'Email Label',
description:
'Label for this email address (e.g., "work", "personal")',
required: true,
}),
value: Property.ShortText({
displayName: 'Email Address',
description: 'The email address (set to empty to remove)',
required: false,
}),
id: Property.ShortText({
displayName: 'Email ID',
description:
'The unique identifier for existing email field (required for updates)',
required: false,
}),
},
}),
phoneNumbers: Property.Array({
displayName: 'Phone Numbers',
description:
'List of phone numbers for the contact (replaces existing phone numbers)',
required: false,
properties: {
name: Property.ShortText({
displayName: 'Phone Label',
description: 'Label for this phone number (e.g., "mobile", "work")',
required: true,
}),
value: Property.ShortText({
displayName: 'Phone Number',
description:
'The phone number (set to empty to remove, preferably in E.164 format)',
required: false,
}),
id: Property.ShortText({
displayName: 'Phone ID',
description:
'The unique identifier for existing phone number field (required for updates)',
required: false,
}),
},
}),
customFields: Property.Array({
displayName: 'Custom Fields',
description: 'Custom fields for the contact',
required: false,
properties: {
key: Property.ShortText({
displayName: 'Field Key',
description: 'The identifying key for the custom field',
required: true,
}),
value: Property.ShortText({
displayName: 'Field Value',
description:
'The value for the custom field (set to empty to remove)',
required: false,
}),
id: Property.ShortText({
displayName: 'Field ID',
description:
'The unique identifier for the custom field (required for updates)',
required: false,
}),
},
}),
source: Property.ShortText({
displayName: 'Source',
description: "Update the contact's source",
required: false,
}),
sourceUrl: Property.ShortText({
displayName: 'Source URL',
description: 'Update the link to the contact in the source system',
required: false,
}),
externalId: Property.ShortText({
displayName: 'External ID',
description: 'Update the unique identifier from an external system',
required: false,
}),
},
async run(context) {
const {
contactId,
firstName,
lastName,
company,
role,
emails,
phoneNumbers,
customFields,
source,
sourceUrl,
externalId,
} = context.propsValue;
const auth = context.auth;
if (!contactId) {
throw new Error('Contact ID is required');
}
if (emails && Array.isArray(emails)) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
for (const email of emails as Array<{
name: string;
value?: string;
id?: string;
}>) {
if (
email.value &&
email.value.trim() &&
!emailRegex.test(email.value)
) {
throw new Error(`Invalid email format: ${email.value}`);
}
}
}
if (source && (source.length < 1 || source.length > 72)) {
throw new Error('Source must be between 1 and 72 characters');
}
if (sourceUrl) {
if (sourceUrl.trim()) {
try {
new URL(sourceUrl);
} catch {
throw new Error('Invalid source URL format');
}
if (sourceUrl.length < 1 || sourceUrl.length > 200) {
throw new Error('Source URL must be between 1 and 200 characters');
}
}
}
if (
externalId &&
externalId.trim() &&
(externalId.length < 1 || externalId.length > 75)
) {
throw new Error('External ID must be between 1 and 75 characters');
}
const requestBody: UpdateOpenPhoneContactRequest = {};
const hasDefaultFields =
firstName || lastName || company || role || emails || phoneNumbers;
if (hasDefaultFields) {
requestBody.defaultFields = {};
if (firstName !== undefined) {
requestBody.defaultFields.firstName = firstName
? firstName.trim()
: null;
}
if (lastName !== undefined) {
requestBody.defaultFields.lastName = lastName ? lastName.trim() : null;
}
if (company !== undefined) {
requestBody.defaultFields.company = company ? company.trim() : null;
}
if (role !== undefined) {
requestBody.defaultFields.role = role ? role.trim() : null;
}
if (emails && Array.isArray(emails) && emails.length > 0) {
requestBody.defaultFields.emails = (
emails as Array<{ name: string; value?: string; id?: string }>
).map(
(email): OpenPhoneEmail => ({
name: email.name.trim(),
value:
email.value && email.value.trim() ? email.value.trim() : null,
...(email.id && { id: email.id.trim() }),
})
);
}
if (
phoneNumbers &&
Array.isArray(phoneNumbers) &&
phoneNumbers.length > 0
) {
requestBody.defaultFields.phoneNumbers = (
phoneNumbers as Array<{ name: string; value?: string; id?: string }>
).map(
(phone): OpenPhonePhoneNumber => ({
name: phone.name.trim(),
value:
phone.value && phone.value.trim() ? phone.value.trim() : null,
...(phone.id && { id: phone.id.trim() }),
})
);
}
}
if (
customFields &&
Array.isArray(customFields) &&
customFields.length > 0
) {
requestBody.customFields = (
customFields as Array<{ key: string; value?: string; id?: string }>
).map((field) => ({
key: field.key.trim(),
value: field.value && field.value.trim() ? field.value.trim() : null,
...(field.id && { id: field.id.trim() }),
}));
}
if (source !== undefined) {
requestBody.source = source ? source.trim() : null;
}
if (sourceUrl !== undefined) {
requestBody.sourceUrl =
sourceUrl && sourceUrl.trim() ? sourceUrl.trim() : null;
}
if (externalId !== undefined) {
requestBody.externalId =
externalId && externalId.trim() ? externalId.trim() : null;
}
if (Object.keys(requestBody).length === 0) {
throw new Error('At least one field must be provided to update');
}
try {
const response: OpenPhoneContactResponse =
await openPhoneCommon.makeRequest<OpenPhoneContactResponse>(
HttpMethod.PATCH,
`/v1/contacts/${contactId}`,
auth,
requestBody
);
return response;
} catch (error) {
throw new Error(`Failed to update contact: ${error}`);
}
},
});

View File

@@ -0,0 +1,302 @@
import {
httpClient,
HttpMethod,
AuthenticationType,
} from '@activepieces/pieces-common';
import { AppConnectionValueForAuthProperty } from '@activepieces/pieces-framework';
import { openPhoneAuth } from '../..';
export interface OpenPhoneMessage {
id: string;
to: string[];
from: string;
text: string;
phoneNumberId: string | null;
direction: 'incoming' | 'outgoing';
userId: string;
status: 'queued' | 'sent' | 'delivered' | 'undelivered';
createdAt: string;
updatedAt: string;
}
export interface OpenPhoneMessageResponse {
data: OpenPhoneMessage;
}
export interface OpenPhoneErrorResponse {
message: string;
code: string;
status: number;
docs: string;
title: string;
trace?: string;
errors?: Array<{
path: string;
message: string;
value: any;
schema: {
type: string;
};
}>;
description?: string;
}
export const openPhoneCommon = {
baseUrl: 'https://api.openphone.com',
async makeRequest<T>(
method: HttpMethod,
endpoint: string,
auth: AppConnectionValueForAuthProperty<typeof openPhoneAuth>,
body?: any
): Promise<T> {
const response = await httpClient.sendRequest<T>({
method,
url: `${this.baseUrl}${endpoint}`,
headers: {
Authorization: auth.secret_text,
},
body: body,
});
return response.body;
},
};
export interface OpenPhoneEmail {
name: string;
value: string | null;
id?: string;
}
export interface OpenPhonePhoneNumber {
name: string;
value: string | null;
id?: string;
}
export interface OpenPhoneDefaultFields {
company?: string | null;
emails?: OpenPhoneEmail[];
firstName: string | null;
lastName?: string | null;
phoneNumbers?: OpenPhonePhoneNumber[];
role?: string | null;
}
export interface OpenPhoneCustomField {
key: string;
value: string | string[] | boolean | number | null;
}
export interface OpenPhoneContact {
id: string;
externalId: string | null;
source: string | null;
sourceUrl: string | null;
defaultFields: OpenPhoneDefaultFields;
customFields: Array<{
name: string;
key: string;
id: string;
type:
| 'multi-select'
| 'address'
| 'string'
| 'url'
| 'boolean'
| 'date'
| 'number';
value: string | string[] | boolean | number | null;
}>;
createdAt: string;
updatedAt: string;
createdByUserId: string;
}
export interface OpenPhoneContactResponse {
data: OpenPhoneContact;
}
export interface CreateOpenPhoneContactRequest {
defaultFields: OpenPhoneDefaultFields;
customFields?: OpenPhoneCustomField[];
createdByUserId?: string;
source?: string;
sourceUrl?: string;
externalId?: string | null;
}
export interface UpdateOpenPhoneContactRequest {
defaultFields?: Partial<OpenPhoneDefaultFields>;
customFields?: Array<{
key: string;
id?: string;
value: string | string[] | boolean | number | null;
}>;
source?: string | null;
sourceUrl?: string | null;
externalId?: string | null;
}
export interface OpenPhoneContactsListResponse {
data: OpenPhoneContact[];
totalItems: number;
nextPageToken: string | null;
}
export interface OpenPhoneCall {
answeredAt: string | null;
answeredBy: string | null;
initiatedBy: string | null;
direction: 'incoming' | 'outgoing';
status:
| 'queued'
| 'initiated'
| 'ringing'
| 'in-progress'
| 'completed'
| 'busy'
| 'failed'
| 'no-answer'
| 'canceled'
| 'missed'
| 'answered'
| 'forwarded'
| 'abandoned';
completedAt: string | null;
createdAt: string;
duration: number;
forwardedFrom: string | null;
forwardedTo: string | null;
id: string;
phoneNumberId: string;
participants: string[];
updatedAt: string | null;
userId: string;
}
export interface OpenPhoneCallsListResponse {
data: OpenPhoneCall[];
totalItems: number;
nextPageToken: string | null;
}
export interface OpenPhoneCallSummaryJob {
icon: string;
name: string;
result: {
data: Array<{
name: string;
value: string | number | boolean;
}>;
};
}
export interface OpenPhoneCallSummary {
callId: string;
nextSteps: string[] | null;
status: 'absent' | 'in-progress' | 'completed' | 'failed';
summary: string[] | null;
jobs?: OpenPhoneCallSummaryJob[] | null;
}
export interface OpenPhoneCallSummaryResponse {
data: OpenPhoneCallSummary;
}
export interface OpenPhoneUser {
email: string;
firstName: string | null;
groupId: string;
id: string;
lastName: string | null;
role: string;
}
export interface OpenPhoneNumber {
id: string;
groupId: string;
createdAt: string;
updatedAt: string;
name: string;
number: string;
formattedNumber: string | null;
forward: string | null;
portRequestId: string | null;
portingStatus: string | null;
symbol: string | null;
users: OpenPhoneUser[];
restrictions: {
messaging: {
CA: 'restricted' | 'unrestricted';
US: 'restricted' | 'unrestricted';
Intl: 'restricted' | 'unrestricted';
};
calling: {
CA: 'restricted' | 'unrestricted';
US: 'restricted' | 'unrestricted';
Intl: 'restricted' | 'unrestricted';
};
};
}
export interface OpenPhoneNumbersListResponse {
data: OpenPhoneNumber[];
}
export interface OpenPhoneWebhook {
id: string;
userId: string;
orgId: string;
label: string | null;
status: 'enabled' | 'disabled';
url: string;
key: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
events: ('call.completed' | 'call.ringing' | 'call.recording.completed')[];
resourceIds: string[];
}
export interface OpenPhoneWebhookResponse {
data: OpenPhoneWebhook;
}
export interface CreateOpenPhoneWebhookRequest {
url: string;
events: ('call.completed' | 'call.ringing' | 'call.recording.completed')[];
resourceIds?: string[];
userId?: string;
label?: string;
status?: 'enabled' | 'disabled';
}
export interface OpenPhoneMessageWebhook {
id: string;
userId: string;
orgId: string;
label: string | null;
status: 'enabled' | 'disabled';
url: string;
key: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
events: ('message.received' | 'message.delivered')[];
resourceIds: string[];
}
export interface OpenPhoneMessageWebhookResponse {
data: OpenPhoneMessageWebhook;
}
export interface CreateOpenPhoneMessageWebhookRequest {
url: string;
events: ('message.received' | 'message.delivered')[];
resourceIds?: string[];
userId?: string;
label?: string;
status?: 'enabled' | 'disabled';
}

View File

@@ -0,0 +1,282 @@
import { Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import {
openPhoneCommon,
OpenPhoneContactsListResponse,
OpenPhoneCallsListResponse,
OpenPhoneNumbersListResponse,
} from './index';
import { openPhoneAuth } from '../..';
export const contactDropdown = Property.Dropdown({
auth: openPhoneAuth,
displayName: 'Contact',
description: 'Select a contact',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your OpenPhone account first',
};
}
try {
const response: OpenPhoneContactsListResponse =
await openPhoneCommon.makeRequest<OpenPhoneContactsListResponse>(
HttpMethod.GET,
'/v1/contacts?maxResults=50',
auth
);
const options = response.data.map((contact) => {
const displayName =
[contact.defaultFields.firstName, contact.defaultFields.lastName]
.filter(Boolean)
.join(' ') || 'Unnamed Contact';
const company = contact.defaultFields.company;
const label = company ? `${displayName} (${company})` : displayName;
return {
label,
value: contact.id,
};
});
return {
disabled: false,
options: options.sort((a, b) => a.label.localeCompare(b.label)),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: `Error loading contacts: ${error}`,
};
}
},
});
export const phoneNumberDropdown = Property.Dropdown({
auth: openPhoneAuth,
displayName: 'Phone Number',
description: 'Select a phone number to get calls from',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your OpenPhone account first',
};
}
try {
const phoneNumbersResponse: OpenPhoneNumbersListResponse =
await openPhoneCommon.makeRequest<OpenPhoneNumbersListResponse>(
HttpMethod.GET,
'/v1/phone-numbers',
auth
);
if (
!phoneNumbersResponse.data ||
phoneNumbersResponse.data.length === 0
) {
return {
disabled: true,
options: [],
placeholder: 'No phone numbers found',
};
}
const options = phoneNumbersResponse.data.map((phoneNumber) => {
const displayName =
phoneNumber.name || phoneNumber.formattedNumber || phoneNumber.number;
const numberInfo = phoneNumber.formattedNumber || phoneNumber.number;
const label = phoneNumber.name
? `${displayName} (${numberInfo})`
: displayName;
return {
label,
value: phoneNumber.id,
};
});
return {
disabled: false,
options: options.sort((a, b) => a.label.localeCompare(b.label)),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: `Error loading phone numbers: ${error}`,
};
}
},
});
export const participantDropdown = Property.Dropdown({
auth: openPhoneAuth,
displayName: 'Participant Phone Number',
description: 'Select a participant phone number to filter calls',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your OpenPhone account first',
};
}
try {
const contactsResponse: OpenPhoneContactsListResponse =
await openPhoneCommon.makeRequest<OpenPhoneContactsListResponse>(
HttpMethod.GET,
'/v1/contacts?maxResults=50',
auth
);
const phoneNumbers = new Set<string>();
contactsResponse.data.forEach((contact) => {
if (contact.defaultFields.phoneNumbers) {
contact.defaultFields.phoneNumbers.forEach((phone) => {
if (phone.value) {
phoneNumbers.add(phone.value);
}
});
}
});
if (phoneNumbers.size === 0) {
return {
disabled: false,
options: [
{
label: 'Enter phone number manually (+1234567890)',
value: 'manual',
},
],
placeholder: 'No contact phone numbers found',
};
}
const options = Array.from(phoneNumbers).map((phoneNumber) => ({
label: phoneNumber,
value: phoneNumber,
}));
return {
disabled: false,
options: options.sort((a, b) => a.label.localeCompare(b.label)),
};
} catch (error) {
return {
disabled: false,
options: [
{
label: 'Enter phone number manually (+1234567890)',
value: 'manual',
},
],
placeholder: `Error loading participants: ${error}`,
};
}
},
});
export const callDropdown = Property.Dropdown({
auth: openPhoneAuth,
displayName: 'Call',
description: 'Select a call',
required: true,
refreshers: ['phoneNumberId', 'participantNumber'],
options: async ({ auth, phoneNumberId, participantNumber }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your OpenPhone account first',
};
}
if (!phoneNumberId) {
return {
disabled: true,
options: [],
placeholder: 'Please select a phone number first',
};
}
if (!participantNumber || participantNumber === 'manual') {
return {
disabled: true,
options: [],
placeholder: 'Please select a participant phone number first',
};
}
try {
const encodedParticipant = encodeURIComponent(
participantNumber as string
);
const callsResponse: OpenPhoneCallsListResponse =
await openPhoneCommon.makeRequest<OpenPhoneCallsListResponse>(
HttpMethod.GET,
`/v1/calls?phoneNumberId=${phoneNumberId}&participants=${encodedParticipant}&maxResults=50`,
auth
);
if (!callsResponse.data || callsResponse.data.length === 0) {
return {
disabled: false,
options: [
{
label: 'No calls found - Enter Call ID manually',
value: 'manual',
},
],
placeholder: 'No calls available for selection',
};
}
const options = callsResponse.data.map((call) => {
const statusInfo = call.status ? ` - ${call.status}` : '';
const durationInfo = call.duration ? ` (${call.duration}s)` : '';
const dateInfo = new Date(call.createdAt).toLocaleDateString();
const directionInfo = call.direction === 'incoming' ? '↓' : '↑';
return {
label: `${directionInfo} ${call.id}${statusInfo}${durationInfo} - ${dateInfo}`,
value: call.id,
};
});
return {
disabled: false,
options: options.sort((a, b) => b.label.localeCompare(a.label)),
};
} catch (error) {
return {
disabled: false,
options: [
{
label: 'Enter Call ID manually (AC...)',
value: 'manual',
},
],
placeholder: `Error loading calls: ${error}`,
};
}
},
});

View File

@@ -0,0 +1,83 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import {
openPhoneCommon,
OpenPhoneWebhookResponse,
CreateOpenPhoneWebhookRequest,
} from '../common';
import { phoneNumberDropdown } from '../common/props';
export const callRecordingCompleted = createTrigger({
auth: openPhoneAuth,
name: 'call_recording_completed',
displayName: 'Call Recording Completed',
description:
'Fires when a call recording finishes. Useful for post-transcription or archival workflows.',
props: {
phoneNumbers: phoneNumberDropdown,
},
sampleData: {
event: 'call.recording.completed',
data: {
id: 'AC123abc',
phoneNumberId: 'PN123abc',
userId: 'US123abc',
direction: 'incoming',
status: 'completed',
participants: ['+15555555555'],
duration: 120,
recordingUrl: 'https://example.com/recording.mp3',
createdAt: '2022-01-01T00:00:00Z',
completedAt: '2022-01-01T00:02:00Z',
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const { phoneNumbers } = context.propsValue;
const auth = context.auth;
const webhookRequest: CreateOpenPhoneWebhookRequest = {
url: context.webhookUrl,
events: ['call.recording.completed'],
resourceIds: phoneNumbers ? [phoneNumbers as string] : ['*'],
label: 'Activepieces Call Recording Completed Trigger',
status: 'enabled',
};
try {
const response: OpenPhoneWebhookResponse =
await openPhoneCommon.makeRequest<OpenPhoneWebhookResponse>(
HttpMethod.POST,
'/v1/webhooks/calls',
auth,
webhookRequest
);
await context.store.put('webhookId', response.data.id);
} catch (error) {
throw new Error(`Failed to create webhook: ${error}`);
}
},
async onDisable(context) {
const auth = context.auth;
const webhookId = await context.store.get('webhookId');
if (!webhookId) {
return;
}
try {
await openPhoneCommon.makeRequest(
HttpMethod.DELETE,
`/v1/webhooks/calls/${webhookId}`,
auth
);
} catch (error) {
throw new Error(`Failed to delete webhook: ${error}`);
}
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,91 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import {
openPhoneCommon,
OpenPhoneWebhookResponse,
CreateOpenPhoneWebhookRequest,
} from '../common';
import { phoneNumberDropdown } from '../common/props';
export const incomingCallCompleted = createTrigger({
auth: openPhoneAuth,
name: 'incoming_call_completed',
displayName: 'Incoming Call Completed',
description:
'Fires when an incoming call is completed. Includes voicemail data if available.',
props: {
phoneNumbers: phoneNumberDropdown,
},
sampleData: {
event: 'call.completed',
data: {
id: 'AC123abc',
phoneNumberId: 'PN123abc',
userId: 'US123abc',
direction: 'incoming',
status: 'completed',
participants: ['+15555555555'],
duration: 120,
answeredBy: 'US123abc',
answeredAt: '2022-01-01T00:00:30Z',
completedAt: '2022-01-01T00:02:30Z',
createdAt: '2022-01-01T00:00:00Z',
updatedAt: '2022-01-01T00:02:30Z',
voicemailUrl: 'https://example.com/voicemail.mp3',
voicemailDuration: 15,
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const { phoneNumbers } = context.propsValue;
const auth = context.auth;
const webhookRequest: CreateOpenPhoneWebhookRequest = {
url: context.webhookUrl,
events: ['call.completed'],
resourceIds: phoneNumbers ? [phoneNumbers as string] : ['*'],
label: 'Activepieces Incoming Call Completed Trigger',
status: 'enabled',
};
try {
const response: OpenPhoneWebhookResponse =
await openPhoneCommon.makeRequest<OpenPhoneWebhookResponse>(
HttpMethod.POST,
'/v1/webhooks/calls',
auth,
webhookRequest
);
await context.store.put('webhookId', response.data.id);
} catch (error) {
throw new Error(`Failed to create webhook: ${error}`);
}
},
async onDisable(context) {
const auth = context.auth;
const webhookId = await context.store.get('webhookId');
if (!webhookId) {
return;
}
try {
await openPhoneCommon.makeRequest(
HttpMethod.DELETE,
`/v1/webhooks/calls/${webhookId}`,
auth
);
} catch (error) {
throw new Error(`Failed to delete webhook: ${error}`);
}
},
async run(context) {
const payload = context.payload.body as any;
if (payload?.data && payload.data.direction === 'incoming') {
return [payload];
}
return [];
},
});

View File

@@ -0,0 +1,86 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import {
openPhoneCommon,
OpenPhoneMessageWebhookResponse,
CreateOpenPhoneMessageWebhookRequest,
} from '../common';
import { phoneNumberDropdown } from '../common/props';
export const incomingMessageReceived = createTrigger({
auth: openPhoneAuth,
name: 'incoming_message_received',
displayName: 'Incoming Message Received',
description: 'Fires when a new SMS/MMS message is received.',
props: {
phoneNumbers: phoneNumberDropdown,
},
sampleData: {
event: 'message.received',
data: {
id: 'AC123abc',
to: ['+15551234567'],
from: '+15555555555',
text: 'Hello, this is an incoming message',
phoneNumberId: 'PN123abc',
direction: 'incoming',
userId: 'US123abc',
status: 'received',
createdAt: '2022-01-01T00:00:00Z',
updatedAt: '2022-01-01T00:00:00Z',
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const { phoneNumbers } = context.propsValue;
const auth = context.auth;
const webhookRequest: CreateOpenPhoneMessageWebhookRequest = {
url: context.webhookUrl,
events: ['message.received'],
resourceIds: phoneNumbers ? [phoneNumbers as string] : ['*'],
label: 'Activepieces Incoming Message Received Trigger',
status: 'enabled',
};
try {
const response: OpenPhoneMessageWebhookResponse =
await openPhoneCommon.makeRequest<OpenPhoneMessageWebhookResponse>(
HttpMethod.POST,
'/v1/webhooks/messages',
auth,
webhookRequest
);
await context.store.put('webhookId', response.data.id);
} catch (error) {
throw new Error(`Failed to create webhook: ${error}`);
}
},
async onDisable(context) {
const auth = context.auth;
const webhookId = await context.store.get('webhookId');
if (!webhookId) {
return;
}
try {
await openPhoneCommon.makeRequest(
HttpMethod.DELETE,
`/v1/webhooks/messages/${webhookId}`,
auth
);
} catch (error) {
throw new Error(`Failed to delete webhook: ${error}`);
}
},
async run(context) {
const payload = context.payload.body as any;
if (payload?.data && payload.data.direction === 'incoming') {
return [payload];
}
return [];
},
});

View File

@@ -0,0 +1,88 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import {
openPhoneCommon,
OpenPhoneWebhookResponse,
CreateOpenPhoneWebhookRequest,
} from '../common';
import { phoneNumberDropdown } from '../common/props';
export const outgoingCallCompleted = createTrigger({
auth: openPhoneAuth,
name: 'outgoing_call_completed',
displayName: 'Outgoing Call Completed',
description: 'Fires when an outbound call ends. Useful for call logging.',
props: {
phoneNumbers: phoneNumberDropdown,
},
sampleData: {
event: 'call.completed',
data: {
id: 'AC123abc',
phoneNumberId: 'PN123abc',
userId: 'US123abc',
direction: 'outgoing',
status: 'completed',
participants: ['+15555555555'],
duration: 120,
initiatedBy: 'US123abc',
answeredAt: '2022-01-01T00:00:30Z',
completedAt: '2022-01-01T00:02:30Z',
createdAt: '2022-01-01T00:00:00Z',
updatedAt: '2022-01-01T00:02:30Z',
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const { phoneNumbers } = context.propsValue;
const auth = context.auth;
const webhookRequest: CreateOpenPhoneWebhookRequest = {
url: context.webhookUrl,
events: ['call.completed'],
resourceIds: phoneNumbers ? [phoneNumbers as string] : ['*'],
label: 'Activepieces Outgoing Call Completed Trigger',
status: 'enabled',
};
try {
const response: OpenPhoneWebhookResponse =
await openPhoneCommon.makeRequest<OpenPhoneWebhookResponse>(
HttpMethod.POST,
'/v1/webhooks/calls',
auth,
webhookRequest
);
await context.store.put('webhookId', response.data.id);
} catch (error) {
throw new Error(`Failed to create webhook: ${error}`);
}
},
async onDisable(context) {
const auth = context.auth;
const webhookId = await context.store.get('webhookId');
if (!webhookId) {
return;
}
try {
await openPhoneCommon.makeRequest(
HttpMethod.DELETE,
`/v1/webhooks/calls/${webhookId}`,
auth
);
} catch (error) {
throw new Error(`Failed to delete webhook: ${error}`);
}
},
async run(context) {
const payload = context.payload.body as any;
if (payload?.data && payload.data.direction === 'outgoing') {
return [payload];
}
return [];
},
});

View File

@@ -0,0 +1,83 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { openPhoneAuth } from '../../index';
import {
openPhoneCommon,
OpenPhoneMessageWebhookResponse,
CreateOpenPhoneMessageWebhookRequest,
} from '../common';
import { phoneNumberDropdown } from '../common/props';
export const outgoingMessageDelivered = createTrigger({
auth: openPhoneAuth,
name: 'outgoing_message_delivered',
displayName: 'Outgoing Message Delivered',
description:
'Fires when an outbound message is delivered successfully. Useful for message confirmation workflows.',
props: {
phoneNumbers: phoneNumberDropdown,
},
sampleData: {
event: 'message.delivered',
data: {
id: 'AC123abc',
to: ['+15555555555'],
from: '+15551234567',
text: 'Hello, this is a test message',
phoneNumberId: 'PN123abc',
direction: 'outgoing',
userId: 'US123abc',
status: 'delivered',
createdAt: '2022-01-01T00:00:00Z',
updatedAt: '2022-01-01T00:00:30Z',
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const { phoneNumbers } = context.propsValue;
const auth = context.auth;
const webhookRequest: CreateOpenPhoneMessageWebhookRequest = {
url: context.webhookUrl,
events: ['message.delivered'],
resourceIds: phoneNumbers ? [phoneNumbers as string] : ['*'],
label: 'Activepieces Outgoing Message Delivered Trigger',
status: 'enabled',
};
try {
const response: OpenPhoneMessageWebhookResponse =
await openPhoneCommon.makeRequest<OpenPhoneMessageWebhookResponse>(
HttpMethod.POST,
'/v1/webhooks/messages',
auth,
webhookRequest
);
await context.store.put('webhookId', response.data.id);
} catch (error) {
throw new Error(`Failed to create webhook: ${error}`);
}
},
async onDisable(context) {
const auth = context.auth;
const webhookId = await context.store.get('webhookId');
if (!webhookId) {
return;
}
try {
await openPhoneCommon.makeRequest(
HttpMethod.DELETE,
`/v1/webhooks/messages/${webhookId}`,
auth
);
} catch (error) {
throw new Error(`Failed to delete webhook: ${error}`);
}
},
async run(context) {
return [context.payload.body];
},
});