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

View File

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

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-paperform",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/paperform/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/paperform",
"tsConfig": "packages/pieces/community/paperform/tsconfig.lib.json",
"packageJson": "packages/pieces/community/paperform/package.json",
"main": "packages/pieces/community/paperform/src/index.ts",
"assets": [
"packages/pieces/community/paperform/*.md",
{
"input": "packages/pieces/community/paperform/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/paperform",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Ihr Papierform-API-Schlüssel. Diesen finden Sie in Ihrem Papierform-Dashboard unter Einstellungen > Entwickler.",
"Delete Form Submission": "Formulareinreichung löschen",
"Delete Partial Form Submission": "Teilweise Formulareinreichung löschen",
"Create Form Coupon": "Formulargutschein erstellen",
"Update Form Coupon": "Gutschein aktualisieren",
"Delete Form Coupon": "Formulargutschein löschen",
"Create Form Product": "Formularprodukt erstellen",
"Update Form Product": "Formularprodukt aktualisieren",
"Delete Form Product": "Formularprodukt löschen",
"Create Space": "Raum erstellen",
"Update Space": "Raum aktualisieren",
"Find Form Product": "Formularprodukt finden",
"Find Form": "Formular suchen",
"Find Space": "Raum finden",
"Custom API Call": "Eigener API-Aufruf",
"Deletes a completed submission by its ID.": "Löscht eine abgeschlossene Einreichung durch seine ID.",
"Deletes a partial/in-progress submission by its ID.": "Löscht eine teilweise/laufende Einreichung durch seine ID.",
"Creates a new discount coupon to a specified form.": "Erstellt einen neuen Rabattgutschein in einem bestimmten Formular.",
"Updates an existing form coupon.": "Aktualisiert einen vorhandenen Formulargutschein.",
"Deletes a coupon from a form.": "Löscht einen Gutschein aus einem Formular.",
"Creates a form product.": "Erstellt ein Formularprodukt.",
"Updates an existing form product.": "Aktualisiert ein bestehendes Formularprodukt.",
"Deletes an existing form product.": "Löscht ein bestehendes Formularprodukt.",
"Creates a new space.": "Erstellt einen neuen Raum.",
"Updates an existing space.": "Aktualisiert einen existierenden Bereich.",
"Finds a form product by name.": "Findet ein Formularprodukt nach Namen.",
"Finds a form by title.": "Findet ein Formular nach Titel.",
"Finds a space by name.": "Findet ein Leerzeichen nach Namen.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Form": "Formular",
"Form Submission ID": "Formulareinreichungs-ID",
"Partial Submission ID": "Teilnahme-ID",
"Coupon Code": "Gutscheincode",
"Enabled": "Aktiviert",
"Target": "Target",
"Discount Type": "Rabattart",
"Discount Amount": "Rabattbetrag",
"Discount Percentage": "Rabatt Prozentsatz",
"Expires At": "Gültig bis",
"Coupon": "Gutschein",
"Product Field": "Produktfeld",
"Product Name": "Produktname",
"Product SKU": "Produkt-SKU",
"Product Price": "Produktpreis",
"Quantity": "Menge",
"Minimum Quantity": "Mindestmenge",
"Maximum Quantity": "Maximale Menge",
"Discountable ?": "Discountable ?",
"Image URL": "Bild-URL",
"Image Width": "Bildbreite",
"Image Height": "Bildhöhe",
"Product": "Produkt",
"Space Name": "Raumname",
"Space": "Raum",
"Form Product Name": "Produktname des Formulars",
"Form Title": "Formulartitel",
"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)",
"Whether the coupon is enabled or not.": "Ob der Gutschein aktiviert ist oder nicht.",
"The target of the coupon.": "Das Ziel des Gutscheins.",
"Choose between amount or percentage discount.": "Wählen Sie zwischen Betrag oder prozentualem Rabatt.",
"The date and time when the coupon expires.": "Das Datum und die Uhrzeit, an der der Gutschein abläuft.",
"Whether the coupon is enabled or not": "Ob der Gutschein aktiviert ist oder nicht",
"Product quantity": "Produktmenge",
"URL of the product image": "URL des Produktbildes",
"Width of the product image in pixels": "Breite des Produktbildes in Pixeln",
"Height of the product image in pixels (optional)": "Höhe des Produktbildes in Pixeln (optional)",
"Width of the product image in pixels.": "Breite des Produktbildes in Pixel.",
"Height of the product image in pixels (optional).": "Höhe des Produktbildes in Pixeln (optional).",
"Select the form to search products in": "Wählen Sie das Formular um Produkte zu suchen",
"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..",
"Price": "Preis",
"Subscription": "Abonnements",
"Amount": "Betrag",
"Percentage": "Prozentsatz",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"New Form Submission": "Neue Formulareinreichung",
"New Partial Form Submission": "Neue Teilformulareinreichung",
"Triggers when a completed form submission is received.": "Wird ausgelöst, wenn eine abgeschlossene Formularabgabe empfangen wird.",
"Triggers when a partial/in-progress submission is received.": "Wird ausgelöst, wenn eine teilweise/laufende Einreichung empfangen wird."
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Tu clave API de Paperform. Puedes encontrar esto en tu panel de Paperform en Ajustes > Desarrollador.",
"Delete Form Submission": "Eliminar Envío de Formulario",
"Delete Partial Form Submission": "Eliminar envío parcial del formulario",
"Create Form Coupon": "Crear cupón de formulario",
"Update Form Coupon": "Actualizar cupón de formulario",
"Delete Form Coupon": "Eliminar cupón de formulario",
"Create Form Product": "Crear artículo de formulario",
"Update Form Product": "Actualizar artículo de formulario",
"Delete Form Product": "Eliminar producto de formulario",
"Create Space": "Crear espacio",
"Update Space": "Actualizar espacio",
"Find Form Product": "Buscar artículo de formulario",
"Find Form": "Buscar formulario",
"Find Space": "Buscar espacio",
"Custom API Call": "Llamada API personalizada",
"Deletes a completed submission by its ID.": "Elimina un envío completado por su ID.",
"Deletes a partial/in-progress submission by its ID.": "Elimina un envío parcial/en progreso por su ID.",
"Creates a new discount coupon to a specified form.": "Crea un nuevo cupón de descuento a un formulario especificado.",
"Updates an existing form coupon.": "Actualiza un cupón de formulario existente.",
"Deletes a coupon from a form.": "Elimina un cupón de un formulario.",
"Creates a form product.": "Crea un producto de formulario.",
"Updates an existing form product.": "Actualiza un producto de formulario existente.",
"Deletes an existing form product.": "Elimina un producto de formulario existente.",
"Creates a new space.": "Crea un nuevo espacio.",
"Updates an existing space.": "Actualiza un espacio existente.",
"Finds a form product by name.": "Encuentra un producto de formulario por nombre.",
"Finds a form by title.": "Encuentra un formulario por título.",
"Finds a space by name.": "Encuentra un espacio por nombre.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Form": "Forma",
"Form Submission ID": "ID del formulario de envío",
"Partial Submission ID": "ID de envío parcial",
"Coupon Code": "Código de cupón",
"Enabled": "Activado",
"Target": "Target",
"Discount Type": "Tipo de descuento",
"Discount Amount": "Importe del descuento",
"Discount Percentage": "Porcentaje de descuento",
"Expires At": "Caduca el",
"Coupon": "Cupón",
"Product Field": "Campo de producto",
"Product Name": "Producto",
"Product SKU": "SKU del producto",
"Product Price": "Precio del producto",
"Quantity": "Cantidad",
"Minimum Quantity": "Cantidad mínima",
"Maximum Quantity": "Cantidad máxima",
"Discountable ?": "¿Descontable?",
"Image URL": "URL de imagen",
"Image Width": "Ancho de imagen",
"Image Height": "Altura de imagen",
"Product": "Producto",
"Space Name": "Nombre del espacio",
"Space": "Espacio",
"Form Product Name": "Nombre del formulario de producto",
"Form Title": "Título del formulario",
"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)",
"Whether the coupon is enabled or not.": "Si el cupón está habilitado o no.",
"The target of the coupon.": "El objetivo del cupón.",
"Choose between amount or percentage discount.": "Elija entre la cantidad o porcentaje de descuento.",
"The date and time when the coupon expires.": "La fecha y hora en que el cupón caduca.",
"Whether the coupon is enabled or not": "Si el cupón está habilitado o no",
"Product quantity": "Cantidad de producto",
"URL of the product image": "URL de la imagen del producto",
"Width of the product image in pixels": "Ancho de la imagen del producto en píxeles",
"Height of the product image in pixels (optional)": "Altura de la imagen del producto en píxeles (opcional)",
"Width of the product image in pixels.": "Ancho de la imagen del producto en píxeles.",
"Height of the product image in pixels (optional).": "Altura de la imagen del producto en píxeles (opcional).",
"Select the form to search products in": "Seleccione el formulario en el que buscar productos",
"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.",
"Price": "Precio",
"Subscription": "Subscripción",
"Amount": "Cantidad",
"Percentage": "Porcentaje",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"New Form Submission": "Nuevo envío de formulario",
"New Partial Form Submission": "Nuevo envío parcial del formulario",
"Triggers when a completed form submission is received.": "Se activa cuando se recibe un envío de formulario completo.",
"Triggers when a partial/in-progress submission is received.": "Dispara cuando un envío parcial/en curso es recibido."
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Votre clé API Paperform. Vous pouvez la trouver dans votre tableau de bord Paperform dans Paramètres > Développeur.",
"Delete Form Submission": "Supprimer la remise du formulaire",
"Delete Partial Form Submission": "Supprimer la soumission partielle du formulaire",
"Create Form Coupon": "Créer un coupon de formulaire",
"Update Form Coupon": "Mettre à jour le bon de réduction du formulaire",
"Delete Form Coupon": "Supprimer le coupon de formulaire",
"Create Form Product": "Créer un produit de formulaire",
"Update Form Product": "Mettre à jour le produit du formulaire",
"Delete Form Product": "Supprimer le produit du formulaire",
"Create Space": "Créer un espace",
"Update Space": "Mettre à jour l'espace",
"Find Form Product": "Trouver un produit de formulaire",
"Find Form": "Formulaire de recherche",
"Find Space": "Trouver un espace",
"Custom API Call": "Appel API personnalisé",
"Deletes a completed submission by its ID.": "Supprime une soumission complétée par son ID.",
"Deletes a partial/in-progress submission by its ID.": "Supprime une soumission partielle/en cours par son ID.",
"Creates a new discount coupon to a specified form.": "Crée un nouveau coupon de réduction sur un formulaire spécifié.",
"Updates an existing form coupon.": "Met à jour un coupon de formulaire existant.",
"Deletes a coupon from a form.": "Supprime un coupon d'un formulaire.",
"Creates a form product.": "Crée un produit de formulaire.",
"Updates an existing form product.": "Met à jour un produit de formulaire existant.",
"Deletes an existing form product.": "Supprime un produit de formulaire existant.",
"Creates a new space.": "Crée un nouvel espace.",
"Updates an existing space.": "Met à jour un espace existant.",
"Finds a form product by name.": "Trouve un produit de formulaire par nom.",
"Finds a form by title.": "Trouve un formulaire par titre.",
"Finds a space by name.": "Trouve un espace par nom.",
"Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un point de terminaison spécifique",
"Form": "Forme",
"Form Submission ID": "ID de la remise du formulaire",
"Partial Submission ID": "ID de la soumission partielle",
"Coupon Code": "Code promo",
"Enabled": "Activé",
"Target": "Target",
"Discount Type": "Type de réduction",
"Discount Amount": "Montant de la remise",
"Discount Percentage": "Pourcentage de réduction",
"Expires At": "Expire à",
"Coupon": "Bon de réduction",
"Product Field": "Champ produit",
"Product Name": "Nom du produit",
"Product SKU": "REF du produit",
"Product Price": "Prix du produit",
"Quantity": "Quantité",
"Minimum Quantity": "Quantité minimale",
"Maximum Quantity": "Quantité maximale",
"Discountable ?": "Remise ?",
"Image URL": "URL de l'image",
"Image Width": "Largeur de l'image",
"Image Height": "Hauteur de l'image",
"Product": "Produit",
"Space Name": "Nom de l'espace",
"Space": "Espace libre",
"Form Product Name": "Nom du produit du formulaire",
"Form Title": "Titre du formulaire",
"Method": "Méthode",
"Headers": "En-têtes",
"Query Parameters": "Paramètres de requête",
"Body": "Corps",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'attente (en secondes)",
"Whether the coupon is enabled or not.": "Si le coupon est activé ou non.",
"The target of the coupon.": "La cible du coupon.",
"Choose between amount or percentage discount.": "Choisissez entre le montant ou le pourcentage.",
"The date and time when the coupon expires.": "La date et l'heure à laquelle le coupon expire.",
"Whether the coupon is enabled or not": "Si le coupon est activé ou non",
"Product quantity": "Quantité de produit",
"URL of the product image": "URL de l'image du produit",
"Width of the product image in pixels": "Largeur de l'image du produit en pixels",
"Height of the product image in pixels (optional)": "Hauteur de l'image du produit en pixels (facultatif)",
"Width of the product image in pixels.": "Largeur de l'image du produit en pixels.",
"Height of the product image in pixels (optional).": "Hauteur de l'image du produit en pixels (optionnel).",
"Select the form to search products in": "Sélectionnez le formulaire de recherche des produits dans",
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
"Price": "Prix",
"Subscription": "Abonnement",
"Amount": "Montant",
"Percentage": "Pourcentage",
"GET": "OBTENIR",
"POST": "POSTER",
"PATCH": "PATCH",
"PUT": "EFFACER",
"DELETE": "SUPPRIMER",
"HEAD": "TÊTE",
"New Form Submission": "Nouvelle soumission de formulaire",
"New Partial Form Submission": "Nouvelle soumission partielle de formulaire",
"Triggers when a completed form submission is received.": "Déclenche quand un formulaire rempli est reçu.",
"Triggers when a partial/in-progress submission is received.": "Déclenche quand une soumission partielle/en cours est reçue."
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Paperform API キー。これは Paperform ダッシュボードの設定 > 開発者 から確認できます。",
"Delete Form Submission": "フォームの提出物を削除",
"Delete Partial Form Submission": "部分フォームの提出物を削除",
"Create Form Coupon": "フォームクーポンを作成",
"Update Form Coupon": "フォームクーポンを更新",
"Delete Form Coupon": "フォームクーポンを削除",
"Create Form Product": "フォーム製品を作成",
"Update Form Product": "フォーム商品を更新",
"Delete Form Product": "フォーム商品を削除",
"Create Space": "スペースを作成",
"Update Space": "スペースを更新",
"Find Form Product": "フォーム商品を検索",
"Find Form": "フォームを検索",
"Find Space": "スペースを検索",
"Custom API Call": "カスタムAPI通話",
"Deletes a completed submission by its ID.": "IDで完了した提出物を削除します。",
"Deletes a partial/in-progress submission by its ID.": "IDによって部分的/進行中の提出物を削除します。",
"Creates a new discount coupon to a specified form.": "指定されたフォームに新しい割引クーポンを作成します。",
"Updates an existing form coupon.": "既存のフォーム クーポンを更新します。",
"Deletes a coupon from a form.": "フォームからクーポンを削除します。",
"Creates a form product.": "フォーム製品を作成します。",
"Updates an existing form product.": "既存のフォーム製品を更新します。",
"Deletes an existing form product.": "既存のフォーム製品を削除します。",
"Creates a new space.": "新しいスペースを作成します。",
"Updates an existing space.": "既存のスペースを更新します。",
"Finds a form product by name.": "名前でフォーム製品を検索します。",
"Finds a form by title.": "タイトルでフォームを検索します。",
"Finds a space by name.": "名前でスペースを検索します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Form": "フォーム",
"Form Submission ID": "フォーム送信ID",
"Partial Submission ID": "部分提出 ID",
"Coupon Code": "クーポンコード",
"Enabled": "有効",
"Target": "Target",
"Discount Type": "割引の種類",
"Discount Amount": "割引額",
"Discount Percentage": "割引率",
"Expires At": "有効期限",
"Coupon": "クーポン",
"Product Field": "商品フィールド",
"Product Name": "商品名",
"Product SKU": "商品SKU",
"Product Price": "商品価格",
"Quantity": "数量",
"Minimum Quantity": "最小数量",
"Maximum Quantity": "最大数量",
"Discountable ?": "割引可能?",
"Image URL": "画像URL",
"Image Width": "画像の幅",
"Image Height": "画像の高さ",
"Product": "商品",
"Space Name": "スペース名",
"Space": "スペース",
"Form Product Name": "フォーム商品名",
"Form Title": "フォームタイトル",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Whether the coupon is enabled or not.": "クーポンが有効になっているかどうか。",
"The target of the coupon.": "クーポンのターゲット。",
"Choose between amount or percentage discount.": "金額またはパーセント割引のいずれかを選択します。",
"The date and time when the coupon expires.": "クーポンの有効期限が切れる日時。",
"Whether the coupon is enabled or not": "クーポンが有効になっているかどうか",
"Product quantity": "製品数量",
"URL of the product image": "製品画像の URL",
"Width of the product image in pixels": "商品画像の幅 (ピクセル)",
"Height of the product image in pixels (optional)": "製品画像の高さ(オプション)",
"Width of the product image in pixels.": "商品画像の幅をピクセルで指定します。",
"Height of the product image in pixels (optional).": "製品画像の高さ(任意)",
"Select the form to search products in": "検索対象のフォームを選択してください",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"Price": "価格",
"Subscription": "サブスクリプション",
"Amount": "金額",
"Percentage": "割合",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"New Form Submission": "新しいフォーム提出",
"New Partial Form Submission": "新しい部分フォームの提出",
"Triggers when a completed form submission is received.": "完了したフォームの送信を受信したときにトリガーします。",
"Triggers when a partial/in-progress submission is received.": "部分的/進行中の提出物を受信したときにトリガーします。"
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Jouw Paperform API-sleutel. Je vindt dit in je Paperform dashboard onder Instellingen > Ontwikkelaar.",
"Delete Form Submission": "Formulier inzending verwijderen",
"Delete Partial Form Submission": "Gedeeltelijke formulier inzending verwijderen",
"Create Form Coupon": "Maak formulierkortingsbon",
"Update Form Coupon": "Update formulierkortingscode",
"Delete Form Coupon": "Verwijder formulierkortingscode",
"Create Form Product": "Formulier product maken",
"Update Form Product": "Formulier product bijwerken",
"Delete Form Product": "Formulierproduct verwijderen",
"Create Space": "Ruimte creëren",
"Update Space": "Ruimte bijwerken",
"Find Form Product": "Formulier product zoeken",
"Find Form": "Formulier zoeken",
"Find Space": "Ruimte zoeken",
"Custom API Call": "Custom API Call",
"Deletes a completed submission by its ID.": "Verwijdert een voltooide uitwerking met de ID.",
"Deletes a partial/in-progress submission by its ID.": "Verwijdert een gedeeltelijke / in-progress indiening via het ID.",
"Creates a new discount coupon to a specified form.": "Maakt een nieuwe kortingscoupon aan op een opgegeven formulier.",
"Updates an existing form coupon.": "Werkt een bestaande kortingscode bij.",
"Deletes a coupon from a form.": "Verwijdert een coupon uit een formulier.",
"Creates a form product.": "Maakt een formulierproduct aan.",
"Updates an existing form product.": "Werkt een bestaand formulierproduct bij.",
"Deletes an existing form product.": "Verwijdert een bestaand formulierproduct.",
"Creates a new space.": "Maakt een nieuwe ruimte.",
"Updates an existing space.": "Werkt een bestaande ruimte bij.",
"Finds a form product by name.": "Vindt een formulierproduct op naam.",
"Finds a form by title.": "Vindt een formulier op titel.",
"Finds a space by name.": "Vindt een spatie op naam.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Form": "Vorm",
"Form Submission ID": "ID formulier inzending",
"Partial Submission ID": "Gedeeltelijke indiening ID",
"Coupon Code": "Kortingsbon code",
"Enabled": "Ingeschakeld",
"Target": "Target",
"Discount Type": "Type korting",
"Discount Amount": "Korting hoeveelheid",
"Discount Percentage": "Kortingspercentage",
"Expires At": "Verloopt op",
"Coupon": "Kortingsbon",
"Product Field": "Product Veld",
"Product Name": "Product Naam",
"Product SKU": "Product Art.nr.",
"Product Price": "Product Prijs",
"Quantity": "Aantal",
"Minimum Quantity": "Minimale hoeveelheid",
"Maximum Quantity": "Maximale hoeveelheid",
"Discountable ?": "Korting ?",
"Image URL": "Afbeelding URL",
"Image Width": "Afbeelding breedte",
"Image Height": "Afbeelding hoogte",
"Product": "product",
"Space Name": "Ruimte Naam",
"Space": "Spatiebalk",
"Form Product Name": "Formulier product naam",
"Form Title": "Formulier titel",
"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)",
"Whether the coupon is enabled or not.": "Of de coupon is ingeschakeld of niet.",
"The target of the coupon.": "Het doel van de coupon.",
"Choose between amount or percentage discount.": "Kies tussen bedrag of percentage korting.",
"The date and time when the coupon expires.": "De datum en tijd wanneer de coupon afloopt.",
"Whether the coupon is enabled or not": "Of de kortingsbon is ingeschakeld of niet",
"Product quantity": "Aantal producten",
"URL of the product image": "URL van de productafbeelding",
"Width of the product image in pixels": "Breedte van de productafbeelding in pixels",
"Height of the product image in pixels (optional)": "Hoogte van de productafbeelding in pixels (optioneel)",
"Width of the product image in pixels.": "Breedte van de productafbeelding in pixels.",
"Height of the product image in pixels (optional).": "Hoogte van de productafbeelding in pixels (optioneel).",
"Select the form to search products in": "Selecteer het formulier om producten in te zoeken",
"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..",
"Price": "Prijs",
"Subscription": "Abbonnement",
"Amount": "Hoeveelheid",
"Percentage": "Percentage",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"New Form Submission": "Nieuw formulier indienen",
"New Partial Form Submission": "Nieuwe gedeeltelijke formulier inzending",
"Triggers when a completed form submission is received.": "Triggert wanneer een ingevulde formulier wordt ingediend.",
"Triggers when a partial/in-progress submission is received.": "Triggert wanneer een partiële / in-progress uitwerking wordt ontvangen."
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Sua chave API do Paperform. Você pode encontrá-la no painel do Paperform em Configurações > Desenvolvedor.",
"Delete Form Submission": "Excluir Envio de Formulário",
"Delete Partial Form Submission": "Excluir Envio Parcial de Formulário",
"Create Form Coupon": "Criar formulário de cupom",
"Update Form Coupon": "Atualizar Cupom de Formulário",
"Delete Form Coupon": "Excluir cupom de formulário",
"Create Form Product": "Criar produto de formulário",
"Update Form Product": "Atualizar Formulário de Produto",
"Delete Form Product": "Excluir Produto Formulário",
"Create Space": "Criar espaço",
"Update Space": "Atualizar Espaço",
"Find Form Product": "Encontrar produto de formulário",
"Find Form": "Encontrar Formulário",
"Find Space": "Encontrar espaço",
"Custom API Call": "Chamada de API personalizada",
"Deletes a completed submission by its ID.": "Exclui uma submissão completa por seu ID. (Automatic Translation)",
"Deletes a partial/in-progress submission by its ID.": "Exclui um envio parcial/em progresso pelo seu ID.",
"Creates a new discount coupon to a specified form.": "Cria um novo cupom de desconto para um formulário especificado.",
"Updates an existing form coupon.": "Atualiza um cupom existente",
"Deletes a coupon from a form.": "Exclui um cupom de um formulário.",
"Creates a form product.": "Cria um produto de formulário.",
"Updates an existing form product.": "Atualizar um produto de formulário existente.",
"Deletes an existing form product.": "Exclui um produto de formulário existente.",
"Creates a new space.": "Cria um novo espaço.",
"Updates an existing space.": "Atualiza um espaço existente.",
"Finds a form product by name.": "Localiza um produto de formulário pelo nome.",
"Finds a form by title.": "Localiza um formulário por título.",
"Finds a space by name.": "Localiza um espaço por nome.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Form": "Formulário",
"Form Submission ID": "ID da Submissão de Formulário",
"Partial Submission ID": "ID da Submissão Parcial",
"Coupon Code": "Código do cupom",
"Enabled": "Ativado",
"Target": "Target",
"Discount Type": "Tipo de desconto",
"Discount Amount": "Valor do desconto",
"Discount Percentage": "Porcentagem de Desconto",
"Expires At": "Expira em",
"Coupon": "Cupom",
"Product Field": "Campo de Produto",
"Product Name": "Nome do Produto",
"Product SKU": "SKU do produto",
"Product Price": "Preço do Produto",
"Quantity": "Quantidade",
"Minimum Quantity": "Quantidade mínima",
"Maximum Quantity": "Quantidade máxima",
"Discountable ?": "Descontável ?",
"Image URL": "URL da imagem",
"Image Width": "Largura da imagem",
"Image Height": "Altura da Imagem",
"Product": "Produto:",
"Space Name": "Nome do Espaço",
"Space": "Sala",
"Form Product Name": "Nome do Formulário Produto",
"Form Title": "Título do formulário",
"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)",
"Whether the coupon is enabled or not.": "Se o cupom está habilitado ou não.",
"The target of the coupon.": "O objetivo do cupom.",
"Choose between amount or percentage discount.": "Escolha entre o valor ou porcentagem de desconto.",
"The date and time when the coupon expires.": "A data e a hora em que o cupom expira.",
"Whether the coupon is enabled or not": "Se o cupom está habilitado ou não",
"Product quantity": "Quantidade de produtos",
"URL of the product image": "URL da imagem do produto",
"Width of the product image in pixels": "Largura da imagem do produto em pixels",
"Height of the product image in pixels (optional)": "Altura da imagem do produto em pixels (opcional)",
"Width of the product image in pixels.": "Largura da imagem do produto em pixels.",
"Height of the product image in pixels (optional).": "Altura da imagem do produto em pixels (opcional).",
"Select the form to search products in": "Selecione o formulário em que os produtos serão pesquisados",
"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..",
"Price": "Quantidade",
"Subscription": "Assinatura",
"Amount": "Quantidade",
"Percentage": "Porcentagem",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"New Form Submission": "Nova Submissão de Formulário",
"New Partial Form Submission": "Nova Submissão Parcial do Formulário",
"Triggers when a completed form submission is received.": "Dispara quando uma submissão completa do formulário for recebida.",
"Triggers when a partial/in-progress submission is received.": "Dispara quando uma submissão parcial/em andamento for recebida."
}

View File

@@ -0,0 +1,92 @@
{
"Paperform": "Бумажная форма",
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Ваш ключ API Paperform. Вы можете найти это в панели управления Paperform в Settings > Developer.",
"Delete Form Submission": "Удалить форму отправки",
"Delete Partial Form Submission": "Удалить частичную форму отправки",
"Create Form Coupon": "Создать купон на форму",
"Update Form Coupon": "Обновить купон формы",
"Delete Form Coupon": "Удалить купон формы",
"Create Form Product": "Создать продукт формы",
"Update Form Product": "Обновить продукт формы",
"Delete Form Product": "Удалить продукт формы",
"Create Space": "Создать область",
"Update Space": "Обновить пространство",
"Find Form Product": "Найти продукт формы",
"Find Form": "Найти форму",
"Find Space": "Найти область",
"Custom API Call": "Пользовательский вызов API",
"Deletes a completed submission by its ID.": "Удаляет завершённое задание по его ID.",
"Deletes a partial/in-progress submission by its ID.": "Удаляет частичное/незавершенное представление по его ID.",
"Creates a new discount coupon to a specified form.": "Создает новый купон на скидку в указанную форму.",
"Updates an existing form coupon.": "Обновляет существующий купон формы.",
"Deletes a coupon from a form.": "Удаляет купон из формы.",
"Creates a form product.": "Создает продукт формы.",
"Updates an existing form product.": "Обновляет существующий продукт формы.",
"Deletes an existing form product.": "Удаляет существующий продукт формы.",
"Creates a new space.": "Создает новую область.",
"Updates an existing space.": "Обновляет существующее пространство.",
"Finds a form product by name.": "Находит продукт формы по имени.",
"Finds a form by title.": "Поиск формы по названию.",
"Finds a space by name.": "Находит пробел по имени.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Form": "Форма",
"Form Submission ID": "ID отправки формы",
"Partial Submission ID": "ID частичной справки",
"Coupon Code": "Код купона",
"Enabled": "Включено",
"Target": "Target",
"Discount Type": "Тип скидки",
"Discount Amount": "Сумма скидки",
"Discount Percentage": "Процент скидки",
"Expires At": "Истекает",
"Coupon": "Купон",
"Product Field": "Поле товара",
"Product Name": "Название товара",
"Product SKU": "Артикул товара",
"Product Price": "Цена товара",
"Quantity": "Количество",
"Minimum Quantity": "Минимальное количество",
"Maximum Quantity": "Максимальное количество",
"Discountable ?": "Скидка ?",
"Image URL": "URL изображения",
"Image Width": "Ширина изображения",
"Image Height": "Высота изображения",
"Product": "Товар",
"Space Name": "Название области",
"Space": "Пространство",
"Form Product Name": "Название продукта формы",
"Form Title": "Заголовок формы",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Whether the coupon is enabled or not.": "Включен ли купон или нет.",
"The target of the coupon.": "Цель купона.",
"Choose between amount or percentage discount.": "Выберите между суммой или процентной скидкой.",
"The date and time when the coupon expires.": "Дата и время окончания действия купона.",
"Whether the coupon is enabled or not": "Включен ли купон или нет",
"Product quantity": "Количество товара",
"URL of the product image": "URL изображения товара",
"Width of the product image in pixels": "Ширина изображения товара в пикселях",
"Height of the product image in pixels (optional)": "Высота изображения товара в пикселях (опционально)",
"Width of the product image in pixels.": "Ширина изображения товара в пикселях.",
"Height of the product image in pixels (optional).": "Высота изображения товара в пикселях (опционально).",
"Select the form to search products in": "Выберите форму для поиска товаров в",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"Price": "Цена",
"Subscription": "Подписка",
"Amount": "Сумма",
"Percentage": "Процент",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"New Form Submission": "Новая форма отправки",
"New Partial Form Submission": "Новое частичное представление формы",
"Triggers when a completed form submission is received.": "Триггеры при получении заполненной формы.",
"Triggers when a partial/in-progress submission is received.": "Триггеры при частичной/незавершенной отправке."
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.",
"Delete Form Submission": "Delete Form Submission",
"Delete Partial Form Submission": "Delete Partial Form Submission",
"Create Form Coupon": "Create Form Coupon",
"Update Form Coupon": "Update Form Coupon",
"Delete Form Coupon": "Delete Form Coupon",
"Create Form Product": "Create Form Product",
"Update Form Product": "Update Form Product",
"Delete Form Product": "Delete Form Product",
"Create Space": "Create Space",
"Update Space": "Update Space",
"Find Form Product": "Find Form Product",
"Find Form": "Find Form",
"Find Space": "Find Space",
"Custom API Call": "Custom API Call",
"Deletes a completed submission by its ID.": "Deletes a completed submission by its ID.",
"Deletes a partial/in-progress submission by its ID.": "Deletes a partial/in-progress submission by its ID.",
"Creates a new discount coupon to a specified form.": "Creates a new discount coupon to a specified form.",
"Updates an existing form coupon.": "Updates an existing form coupon.",
"Deletes a coupon from a form.": "Deletes a coupon from a form.",
"Creates a form product.": "Creates a form product.",
"Updates an existing form product.": "Updates an existing form product.",
"Deletes an existing form product.": "Deletes an existing form product.",
"Creates a new space.": "Creates a new space.",
"Updates an existing space.": "Updates an existing space.",
"Finds a form product by name.": "Finds a form product by name.",
"Finds a form by title.": "Finds a form by title.",
"Finds a space by name.": "Finds a space by name.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Form": "Form",
"Form Submission ID": "Form Submission ID",
"Partial Submission ID": "Partial Submission ID",
"Coupon Code": "Coupon Code",
"Enabled": "Enabled",
"Target": "Target",
"Discount Type": "Discount Type",
"Discount Amount": "Discount Amount",
"Discount Percentage": "Discount Percentage",
"Expires At": "Expires At",
"Coupon": "Coupon",
"Product Field": "Product Field",
"Product Name": "Product Name",
"Product SKU": "Product SKU",
"Product Price": "Product Price",
"Quantity": "Quantity",
"Minimum Quantity": "Minimum Quantity",
"Maximum Quantity": "Maximum Quantity",
"Discountable ?": "Discountable ?",
"Image URL": "Image URL",
"Image Width": "Image Width",
"Image Height": "Image Height",
"Product": "Product",
"Space Name": "Space Name",
"Space": "Space",
"Form Product Name": "Form Product Name",
"Form Title": "Form Title",
"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)",
"Whether the coupon is enabled or not.": "Whether the coupon is enabled or not.",
"The target of the coupon.": "The target of the coupon.",
"Choose between amount or percentage discount.": "Choose between amount or percentage discount.",
"The date and time when the coupon expires.": "The date and time when the coupon expires.",
"Whether the coupon is enabled or not": "Whether the coupon is enabled or not",
"Product quantity": "Product quantity",
"URL of the product image": "URL of the product image",
"Width of the product image in pixels": "Width of the product image in pixels",
"Height of the product image in pixels (optional)": "Height of the product image in pixels (optional)",
"Width of the product image in pixels.": "Width of the product image in pixels.",
"Height of the product image in pixels (optional).": "Height of the product image in pixels (optional).",
"Select the form to search products in": "Select the form to search products in",
"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..",
"Price": "Price",
"Subscription": "Subscription",
"Amount": "Amount",
"Percentage": "Percentage",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Form Submission": "New Form Submission",
"New Partial Form Submission": "New Partial Form Submission",
"Triggers when a completed form submission is received.": "Triggers when a completed form submission is received.",
"Triggers when a partial/in-progress submission is received.": "Triggers when a partial/in-progress submission is received."
}

View File

@@ -0,0 +1,92 @@
{
"Paperform": "Paperform",
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.",
"Delete Form Submission": "Delete Form Submission",
"Delete Partial Form Submission": "Delete Partial Form Submission",
"Create Form Coupon": "Create Form Coupon",
"Update Form Coupon": "Update Form Coupon",
"Delete Form Coupon": "Delete Form Coupon",
"Create Form Product": "Create Form Product",
"Update Form Product": "Update Form Product",
"Delete Form Product": "Delete Form Product",
"Create Space": "Create Space",
"Update Space": "Update Space",
"Find Form Product": "Find Form Product",
"Find Form": "Find Form",
"Find Space": "Find Space",
"Custom API Call": "Custom API Call",
"Deletes a completed submission by its ID.": "Deletes a completed submission by its ID.",
"Deletes a partial/in-progress submission by its ID.": "Deletes a partial/in-progress submission by its ID.",
"Creates a new discount coupon to a specified form.": "Creates a new discount coupon to a specified form.",
"Updates an existing form coupon.": "Updates an existing form coupon.",
"Deletes a coupon from a form.": "Deletes a coupon from a form.",
"Creates a form product.": "Creates a form product.",
"Updates an existing form product.": "Updates an existing form product.",
"Deletes an existing form product.": "Deletes an existing form product.",
"Creates a new space.": "Creates a new space.",
"Updates an existing space.": "Updates an existing space.",
"Finds a form product by name.": "Finds a form product by name.",
"Finds a form by title.": "Finds a form by title.",
"Finds a space by name.": "Finds a space by name.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Form": "Form",
"Form Submission ID": "Form Submission ID",
"Partial Submission ID": "Partial Submission ID",
"Coupon Code": "Coupon Code",
"Enabled": "Enabled",
"Target": "Target",
"Discount Type": "Discount Type",
"Discount Amount": "Discount Amount",
"Discount Percentage": "Discount Percentage",
"Expires At": "Expires At",
"Coupon": "Coupon",
"Product Field": "Product Field",
"Product Name": "Product Name",
"Product SKU": "Product SKU",
"Product Price": "Product Price",
"Quantity": "Quantity",
"Minimum Quantity": "Minimum Quantity",
"Maximum Quantity": "Maximum Quantity",
"Discountable ?": "Discountable ?",
"Image URL": "Image URL",
"Image Width": "Image Width",
"Image Height": "Image Height",
"Product": "Product",
"Space Name": "Space Name",
"Space": "Space",
"Form Product Name": "Form Product Name",
"Form Title": "Form Title",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Whether the coupon is enabled or not.": "Whether the coupon is enabled or not.",
"The target of the coupon.": "The target of the coupon.",
"Choose between amount or percentage discount.": "Choose between amount or percentage discount.",
"The date and time when the coupon expires.": "The date and time when the coupon expires.",
"Whether the coupon is enabled or not": "Whether the coupon is enabled or not",
"Product quantity": "Product quantity",
"URL of the product image": "URL of the product image",
"Width of the product image in pixels": "Width of the product image in pixels",
"Height of the product image in pixels (optional)": "Height of the product image in pixels (optional)",
"Width of the product image in pixels.": "Width of the product image in pixels.",
"Height of the product image in pixels (optional).": "Height of the product image in pixels (optional).",
"Select the form to search products in": "Select the form to search products in",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"Price": "Price",
"Subscription": "Đăng ký",
"Amount": "Amount",
"Percentage": "Percentage",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Form Submission": "New Form Submission",
"New Partial Form Submission": "New Partial Form Submission",
"Triggers when a completed form submission is received.": "Triggers when a completed form submission is received.",
"Triggers when a partial/in-progress submission is received.": "Triggers when a partial/in-progress submission is received."
}

View File

@@ -0,0 +1,93 @@
{
"Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.": "Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.",
"Delete Form Submission": "Delete Form Submission",
"Delete Partial Form Submission": "Delete Partial Form Submission",
"Create Form Coupon": "Create Form Coupon",
"Update Form Coupon": "Update Form Coupon",
"Delete Form Coupon": "Delete Form Coupon",
"Create Form Product": "Create Form Product",
"Update Form Product": "Update Form Product",
"Delete Form Product": "Delete Form Product",
"Create Space": "Create Space",
"Update Space": "Update Space",
"Find Form Product": "Find Form Product",
"Find Form": "Find Form",
"Find Space": "Find Space",
"Custom API Call": "自定义 API 呼叫",
"Deletes a completed submission by its ID.": "Deletes a completed submission by its ID.",
"Deletes a partial/in-progress submission by its ID.": "Deletes a partial/in-progress submission by its ID.",
"Creates a new discount coupon to a specified form.": "Creates a new discount coupon to a specified form.",
"Updates an existing form coupon.": "Updates an existing form coupon.",
"Deletes a coupon from a form.": "Deletes a coupon from a form.",
"Creates a form product.": "Creates a form product.",
"Updates an existing form product.": "Updates an existing form product.",
"Deletes an existing form product.": "Deletes an existing form product.",
"Creates a new space.": "Creates a new space.",
"Updates an existing space.": "Updates an existing space.",
"Finds a form product by name.": "Finds a form product by name.",
"Finds a form by title.": "Finds a form by title.",
"Finds a space by name.": "Finds a space by name.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Form": "Form",
"Form Submission ID": "Form Submission ID",
"Partial Submission ID": "Partial Submission ID",
"Coupon Code": "Coupon Code",
"Enabled": "已启用",
"Target": "Target",
"Discount Type": "Discount Type",
"Discount Amount": "Discount Amount",
"Discount Percentage": "Discount Percentage",
"Expires At": "Expires At",
"Coupon": "Coupon",
"Product Field": "Product Field",
"Product Name": "Product Name",
"Product SKU": "Product SKU",
"Product Price": "Product Price",
"Quantity": "Quantity",
"Minimum Quantity": "Minimum Quantity",
"Maximum Quantity": "Maximum Quantity",
"Discountable ?": "Discountable ?",
"Image URL": "Image URL",
"Image Width": "Image Width",
"Image Height": "Image Height",
"Product": "Product",
"Space Name": "Space Name",
"Space": "Space",
"Form Product Name": "Form Product Name",
"Form Title": "Form Title",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Whether the coupon is enabled or not.": "Whether the coupon is enabled or not.",
"The target of the coupon.": "The target of the coupon.",
"Choose between amount or percentage discount.": "Choose between amount or percentage discount.",
"The date and time when the coupon expires.": "The date and time when the coupon expires.",
"Whether the coupon is enabled or not": "Whether the coupon is enabled or not",
"Product quantity": "Product quantity",
"URL of the product image": "URL of the product image",
"Width of the product image in pixels": "Width of the product image in pixels",
"Height of the product image in pixels (optional)": "Height of the product image in pixels (optional)",
"Width of the product image in pixels.": "Width of the product image in pixels.",
"Height of the product image in pixels (optional).": "Height of the product image in pixels (optional).",
"Select the form to search products in": "Select the form to search products in",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"Price": "Price",
"Subscription": "订阅",
"Amount": "Amount",
"Percentage": "Percentage",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"New Form Submission": "New Form Submission",
"New Partial Form Submission": "New Partial Form Submission",
"Triggers when a completed form submission is received.": "Triggers when a completed form submission is received.",
"Triggers when a partial/in-progress submission is received.": "Triggers when a partial/in-progress submission is received."
}

View File

@@ -0,0 +1,57 @@
import { createPiece } from "@activepieces/pieces-framework"
import { paperformAuth } from "./lib/common/auth"
import { newPartialFormSubmission } from './lib/triggers/new-partial-form-submission';
import { newFormSubmission } from './lib/triggers/new-form-submission-';
import { deleteFormSubmission } from './lib/actions/delete-form-submission';
import { deletePartialFormSubmission } from './lib/actions/delete-partial-form-submission';
import { createFormCoupon } from './lib/actions/create-form-coupon';
import { updateFormCoupon } from './lib/actions/update-form-coupon';
import { deleteFormCoupon } from './lib/actions/delete-form-coupon';
import { createFormProduct } from './lib/actions/create-form-product-';
import { updateFormProduct } from './lib/actions/update-form-product';
import { deleteFormProduct } from './lib/actions/delete-form-product';
import { createSpace } from './lib/actions/create-space';
import { updateSpace } from './lib/actions/update-space';
import { findFormProduct } from './lib/actions/find-form-product';
import { findForm } from './lib/actions/find-form';
import { findSpace } from './lib/actions/find-space';
import { createCustomApiCallAction } from "@activepieces/pieces-common";
import { paperformCommon } from "./lib/common/client";
import { PieceCategory } from "@activepieces/shared";
export const paperform = createPiece({
displayName: "Paperform",
auth: paperformAuth,
categories:[PieceCategory.FORMS_AND_SURVEYS],
minimumSupportedRelease: '0.36.1',
logoUrl: "https://cdn.activepieces.com/pieces/paperform.png",
authors: ['nuvex-dev'],
actions: [
deleteFormSubmission,
deletePartialFormSubmission,
createFormCoupon,
updateFormCoupon,
deleteFormCoupon,
createFormProduct,
updateFormProduct,
deleteFormProduct,
createSpace,
updateSpace,
findFormProduct,
findForm,
findSpace,
createCustomApiCallAction({
auth:paperformAuth,
baseUrl:()=>paperformCommon.baseUrl,
authMapping:async (auth)=>{
return{
Authorization:`Bearer ${auth.secret_text}`
}
}
})
],
triggers: [newFormSubmission, newPartialFormSubmission],
});

View File

@@ -0,0 +1,127 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { paperformCommonProps } from '../common/props';
import { PaperformCreateCouponResponse } from '../common/types';
export const createFormCoupon = createAction({
auth: paperformAuth,
name: 'createFormCoupon',
displayName: 'Create Form Coupon',
description: 'Creates a new discount coupon to a specified form.',
props: {
formId: paperformCommonProps.formId,
code: Property.ShortText({
displayName: 'Coupon Code',
required: true,
}),
enabled: Property.Checkbox({
displayName: 'Enabled',
description: 'Whether the coupon is enabled or not.',
required: false,
defaultValue: true,
}),
target: Property.StaticDropdown({
displayName: 'Target',
description: 'The target of the coupon.',
required: false,
options: {
disabled: false,
options: [
{ label: 'Price', value: 'price' },
{ label: 'Subscription', value: 'subscription' },
],
},
}),
discountType: Property.StaticDropdown({
displayName: 'Discount Type',
description: 'Choose between amount or percentage discount.',
required: true,
options: {
disabled: false,
options: [
{ label: 'Amount', value: 'amount' },
{ label: 'Percentage', value: 'percentage' },
],
},
}),
discountAmount: Property.Number({
displayName: 'Discount Amount',
required: false,
}),
discountPercentage: Property.Number({
displayName: 'Discount Percentage',
required: false,
}),
expiresAt: Property.DateTime({
displayName: 'Expires At',
description: 'The date and time when the coupon expires.',
required: false,
}),
},
async run({ auth, propsValue }) {
const {
formId,
code,
enabled,
target,
discountType,
discountAmount,
discountPercentage,
expiresAt,
} = propsValue;
if (discountType === 'amount' && (!discountAmount || discountAmount < 0)) {
throw new Error(
'Discount amount is required and must be ≥ 0 when discount type is amount'
);
}
if (
discountType === 'percentage' &&
(!discountPercentage ||
discountPercentage < 0 ||
discountPercentage > 100)
) {
throw new Error(
'Discount percentage is required and must be between 0 and 100 when discount type is percentage'
);
}
const requestBody: any = {
code,
enabled: enabled ?? true,
};
if (target) {
requestBody.target = target;
}
if (discountType === 'amount' && discountAmount) {
requestBody.discountAmount = discountAmount;
}
if (discountType === 'percentage' && discountPercentage) {
requestBody.discountPercentage = discountPercentage;
}
if (expiresAt) {
requestBody.expiresAt = expiresAt;
}
try {
const response =
await paperformCommon.apiCall<PaperformCreateCouponResponse>({
method: HttpMethod.POST,
url: `/forms/${formId}/coupons`,
body: requestBody,
auth: auth.secret_text,
});
return response.results.coupon;
} catch (error: any) {
throw new Error(`Failed to create coupon: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,154 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { PaperformCreateProductResponse, PaperformField } from '../common/types';
import { paperformCommonProps } from '../common/props';
import { isNil } from '@activepieces/shared';
export const createFormProduct = createAction({
auth: paperformAuth,
name: 'createFormProduct',
displayName: 'Create Form Product',
description: 'Creates a form product.',
props: {
formId:paperformCommonProps.formId,
productFieldKey: paperformCommonProps.productFieldKey,
name: Property.ShortText({
displayName: 'Product Name',
required: true,
}),
sku: Property.ShortText({
displayName: 'Product SKU',
required: true,
}),
price: Property.Number({
displayName: 'Product Price',
required: true,
}),
quantity: Property.Number({
displayName: 'Quantity',
description: 'Product quantity',
required: false,
}),
minimum: Property.Number({
displayName: 'Minimum Quantity',
required: false,
}),
maximum: Property.Number({
displayName: 'Maximum Quantity',
required: false,
}),
discountable: Property.Checkbox({
displayName: 'Discountable ?',
required: false,
defaultValue: false,
}),
imageUrl: Property.ShortText({
displayName: 'Image URL',
description: 'URL of the product image',
required: false,
}),
imageWidth: Property.Number({
displayName: 'Image Width',
description: 'Width of the product image in pixels',
required: false,
}),
imageHeight: Property.Number({
displayName: 'Image Height',
description: 'Height of the product image in pixels (optional)',
required: false,
}),
},
async run({ auth, propsValue }) {
const {
formId,
productFieldKey,
name,
sku,
price,
quantity,
minimum,
maximum,
discountable,
imageUrl,
imageWidth,
imageHeight
} = propsValue;
if (!price || price < 0) {
throw new Error('Product price is required and must be ≥ 0');
}
if (quantity !== undefined && quantity < 0) {
throw new Error('Quantity must be ≥ 0');
}
if (minimum !== undefined && minimum < 0) {
throw new Error('Minimum quantity must be ≥ 0');
}
if (maximum !== undefined && maximum < 0) {
throw new Error('Maximum quantity must be ≥ 0');
}
if (minimum !== undefined && maximum !== undefined && minimum > maximum) {
throw new Error('Minimum quantity cannot be greater than maximum quantity');
}
if(imageUrl && isNil(imageWidth))
{
throw new Error('Provide Image Width.');
}
const requestBody: any = {
product_field_key: productFieldKey,
name,
price,
SKU: sku,
};
if (quantity !== undefined) {
requestBody.quantity = quantity;
}
if (minimum !== undefined) {
requestBody.minimum = minimum;
}
if (maximum !== undefined) {
requestBody.maximum = maximum;
}
if (discountable !== undefined) {
requestBody.discountable = discountable;
}
if (imageUrl && imageWidth) {
const image: any = {
url: imageUrl,
width: imageWidth,
};
if (imageHeight) {
image.height = imageHeight;
}
requestBody.images = [image];
}
try {
const response = await paperformCommon.apiCall<PaperformCreateProductResponse>({
method: HttpMethod.POST,
url: `/forms/${formId}/products`,
body: requestBody,
auth: auth.secret_text,
});
return response.results.product;
} catch (error: any) {
throw new Error(`Failed to create product: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,36 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { PaperformCreateSpaceResponse } from '../common/types';
export const createSpace = createAction({
auth: paperformAuth,
name: 'createSpace',
displayName: 'Create Space',
description: 'Creates a new space.',
props: {
name: Property.ShortText({
displayName: 'Space Name',
required: true,
}),
},
async run({ auth, propsValue }) {
const { name } = propsValue;
try {
const response = await paperformCommon.apiCall<PaperformCreateSpaceResponse>({
method: HttpMethod.POST,
url: '/spaces',
body: {
name,
},
auth: auth.secret_text,
});
return response.results.space;
} catch (error: any) {
throw new Error(`Failed to create space: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,34 @@
import { createAction } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { paperformCommonProps } from '../common/props';
export const deleteFormCoupon = createAction({
auth: paperformAuth,
name: 'deleteFormCoupon',
displayName: 'Delete Form Coupon',
description: 'Deletes a coupon from a form.',
props: {
formId: paperformCommonProps.formId,
couponCode:paperformCommonProps.couponCode,
},
async run({ auth, propsValue }) {
const { formId, couponCode } = propsValue;
try {
await paperformCommon.apiCall({
method: HttpMethod.DELETE,
url: `/forms/${formId}/coupons/${couponCode}`,
auth: auth.secret_text,
});
return {
success: true,
message: `Coupon "${couponCode}" has been successfully deleted.`,
};
} catch (error: any) {
throw new Error(`Failed to delete coupon: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { paperformCommonProps } from '../common/props';
export const deleteFormProduct = createAction({
auth: paperformAuth,
name: 'deleteFormProduct',
displayName: 'Delete Form Product',
description: 'Deletes an existing form product.',
props: {
formId: paperformCommonProps.formId,
productSku: paperformCommonProps.productSku,
},
async run({ auth, propsValue }) {
const { formId, productSku } = propsValue;
try {
await paperformCommon.apiCall({
method: HttpMethod.DELETE,
url: `/forms/${formId}/products/${productSku}`,
auth: auth.secret_text,
});
return {
success: true,
message: `Product "${productSku}" has been successfully deleted.`,
};
} catch (error: any) {
throw new Error(`Failed to delete product: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,37 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { paperformCommonProps } from '../common/props';
export const deleteFormSubmission = createAction({
auth: paperformAuth,
name: 'deleteFormSubmission',
displayName: 'Delete Form Submission',
description: 'Deletes a completed submission by its ID.',
props: {
formId: paperformCommonProps.formId,
submissionId: Property.ShortText({
displayName: 'Form Submission ID',
required: true,
}),
},
async run({ auth, propsValue }) {
const { submissionId } = propsValue;
try {
await paperformCommon.apiCall({
method: HttpMethod.DELETE,
url: `/submissions/${submissionId}`,
auth: auth.secret_text,
});
return {
success: true,
message: `Submission with ID ${submissionId} has been successfully deleted.`,
};
} catch (error: any) {
throw new Error(`Failed to delete submission: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,71 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { PaperformPartialSubmission } from '../common/types';
import { paperformCommonProps } from '../common/props';
export const deletePartialFormSubmission = createAction({
auth: paperformAuth,
name: 'deletePartialFormSubmission',
displayName: 'Delete Partial Form Submission',
description: 'Deletes a partial/in-progress submission by its ID.',
props: {
formId: paperformCommonProps.formId,
partialSubmissionId: Property.Dropdown({
auth: paperformAuth,
displayName: 'Partial Submission ID',
required: true,
refreshers: ['auth', 'formId'],
options: async ({ auth, formId }) => {
if (!auth || !formId) {
return {
disabled: true,
placeholder: 'Please select a form first',
options: [],
};
}
try {
const partialSubmissions = await paperformCommon.getPartialSubmissions({
formSlugOrId: formId as string,
auth: auth.secret_text,
limit: 100,
});
return {
disabled: false,
options: partialSubmissions.results["partial-submissions"].map((partialSubmission: PaperformPartialSubmission) => ({
label: `${partialSubmission.id}`,
value: partialSubmission.id,
})),
};
} catch (error) {
return {
disabled: true,
placeholder: 'Error loading partial submissions',
options: [],
};
}
},
}),
},
async run({ auth, propsValue }) {
const { partialSubmissionId } = propsValue;
try {
await paperformCommon.apiCall({
method: HttpMethod.DELETE,
url: `/partial-submissions/${partialSubmissionId}`,
auth: auth.secret_text,
});
return {
success: true,
message: `Partial submission with ID ${partialSubmissionId} has been successfully deleted.`,
};
} catch (error: any) {
throw new Error(`Failed to delete partial submission: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,72 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
export const findFormProduct = createAction({
auth: paperformAuth,
name: 'findFormProduct',
displayName: 'Find Form Product',
description: 'Finds a form product by name.',
props: {
formId: Property.Dropdown({
auth: paperformAuth,
displayName: 'Form',
description: 'Select the form to search products in',
required: true,
refreshers: ['auth'],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your account first',
options: [],
};
}
try {
const forms = await paperformCommon.getForms({
auth: auth.secret_text,
limit: 100,
});
return {
disabled: false,
options: forms.results.forms.map((form) => ({
label: form.title,
value: form.id,
})),
};
} catch (error) {
return {
disabled: true,
placeholder: 'Error loading forms',
options: [],
};
}
},
}),
search: Property.ShortText({
displayName: 'Form Product Name',
required: true,
}),
},
async run({ auth, propsValue }) {
const { formId, search } = propsValue;
try {
const response = await paperformCommon.getProducts({
formSlugOrId: formId as string,
auth: auth.secret_text,
search: search as string,
limit: 100,
});
return {
found: response.results.products.length > 0,
data: response.results.products,
};
} catch (error: any) {
throw new Error(`Failed to find products: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
export const findForm = createAction({
auth: paperformAuth,
name: 'findForm',
displayName: 'Find Form',
description: 'Finds a form by title.',
props: {
search: Property.ShortText({
displayName: 'Form Title',
required: true,
}),
},
async run({ auth, propsValue }) {
const { search } = propsValue;
try {
const response = await paperformCommon.getForms({
auth: auth.secret_text,
search: search as string,
limit: 100,
});
return {
found: response.results.forms.length > 0,
data: response.results.forms,
};
} catch (error: any) {
throw new Error(`Failed to find forms: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
export const findSpace = createAction({
auth: paperformAuth,
name: 'findSpace',
displayName: 'Find Space',
description: 'Finds a space by name.',
props: {
search: Property.ShortText({
displayName: 'Space Name',
required: true,
}),
},
async run({ auth, propsValue }) {
const { search } = propsValue;
try {
const response = await paperformCommon.getSpaces({
auth: auth.secret_text,
search: search as string,
limit: 100,
});
return {
found: response.results.spaces.length > 0,
data: response.results.spaces,
};
} catch (error: any) {
throw new Error(`Failed to find spaces: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,127 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { PaperformCreateCouponResponse } from '../common/types';
import { paperformCommonProps } from '../common/props';
export const updateFormCoupon = createAction({
auth: paperformAuth,
name: 'updateFormCoupon',
displayName: 'Update Form Coupon',
description:'Updates an existing form coupon.',
props: {
formId: paperformCommonProps.formId,
couponCode: paperformCommonProps.couponCode,
enabled: Property.Checkbox({
displayName: 'Enabled',
description: 'Whether the coupon is enabled or not',
required: false,
}),
target: Property.StaticDropdown({
displayName: 'Target',
description: 'The target of the coupon.',
required: false,
options: {
disabled: false,
options: [
{ label: 'Price', value: 'price' },
{ label: 'Subscription', value: 'subscription' },
],
},
}),
discountType: Property.StaticDropdown({
displayName: 'Discount Type',
description: 'Choose between amount or percentage discount.',
required: false,
options: {
disabled: false,
options: [
{ label: 'Amount', value: 'amount' },
{ label: 'Percentage', value: 'percentage' },
],
},
}),
discountAmount: Property.Number({
displayName: 'Discount Amount',
required: false,
}),
discountPercentage: Property.Number({
displayName: 'Discount Percentage',
required: false,
}),
expiresAt: Property.DateTime({
displayName: 'Expires At',
description: 'The date and time when the coupon expires.',
required: false,
}),
},
async run({ auth, propsValue }) {
const {
formId,
couponCode,
enabled,
target,
discountType,
discountAmount,
discountPercentage,
expiresAt,
} = propsValue;
if (
discountType === 'amount' &&
discountAmount !== undefined &&
discountAmount < 0
) {
throw new Error(
'Discount amount must be ≥ 0 when discount type is amount'
);
}
if (
discountType === 'percentage' &&
discountPercentage !== undefined &&
(discountPercentage < 0 || discountPercentage > 100)
) {
throw new Error(
'Discount percentage must be between 0 and 100 when discount type is percentage'
);
}
const requestBody: any = {};
if (enabled !== undefined) {
requestBody.enabled = enabled;
}
if (target) {
requestBody.target = target;
}
if (discountType === 'amount' && discountAmount !== undefined) {
requestBody.discountAmount = discountAmount;
}
if (discountType === 'percentage' && discountPercentage !== undefined) {
requestBody.discountPercentage = discountPercentage;
}
if (expiresAt) {
requestBody.expiresAt = expiresAt;
}
try {
const response =
await paperformCommon.apiCall<PaperformCreateCouponResponse>({
method: HttpMethod.PUT,
url: `/forms/${formId}/coupons/${couponCode}`,
body: requestBody,
auth: auth.secret_text,
});
return response.results.coupon;
} catch (error: any) {
throw new Error(`Failed to update coupon: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,152 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { PaperformCreateProductResponse } from '../common/types';
import { paperformCommonProps } from '../common/props';
import { isNil } from '@activepieces/shared';
export const updateFormProduct = createAction({
auth: paperformAuth,
name: 'updateFormProduct',
displayName: 'Update Form Product',
description: 'Updates an existing form product.',
props: {
formId: paperformCommonProps.formId,
productSku: paperformCommonProps.productSku,
name: Property.ShortText({
displayName: 'Product Name',
required: false,
}),
price: Property.Number({
displayName: 'Product Price',
required: false,
}),
quantity: Property.Number({
displayName: 'Quantity',
description: 'Product quantity',
required: false,
}),
minimum: Property.Number({
displayName: 'Minimum Quantity',
required: false,
}),
maximum: Property.Number({
displayName: 'Maximum Quantity',
required: false,
}),
discountable: Property.Checkbox({
displayName: 'Discountable ?',
required: false,
}),
imageUrl: Property.ShortText({
displayName: 'Image URL',
description: 'URL of the product image',
required: false,
}),
imageWidth: Property.Number({
displayName: 'Image Width',
description: 'Width of the product image in pixels.',
required: false,
}),
imageHeight: Property.Number({
displayName: 'Image Height',
description: 'Height of the product image in pixels (optional).',
required: false,
}),
},
async run({ auth, propsValue }) {
const {
formId,
productSku,
name,
price,
quantity,
minimum,
maximum,
discountable,
imageUrl,
imageWidth,
imageHeight
} = propsValue;
if (price !== undefined && price < 0) {
throw new Error('Product price must be ≥ 0');
}
if (quantity !== undefined && quantity < 0) {
throw new Error('Quantity must be ≥ 0');
}
if (minimum !== undefined && minimum < 0) {
throw new Error('Minimum quantity must be ≥ 0');
}
if (maximum !== undefined && maximum < 0) {
throw new Error('Maximum quantity must be ≥ 0');
}
if (minimum !== undefined && maximum !== undefined && minimum > maximum) {
throw new Error('Minimum quantity cannot be greater than maximum quantity');
}
if(imageUrl && isNil(imageWidth))
{
throw new Error('Provide Image Width.');
}
const requestBody: any = {};
if (name !== undefined) {
requestBody.name = name;
}
if (price !== undefined) {
requestBody.price = price;
}
if (quantity !== undefined) {
requestBody.quantity = quantity;
}
if (minimum !== undefined) {
requestBody.minimum = minimum;
}
if (maximum !== undefined) {
requestBody.maximum = maximum;
}
if (discountable !== undefined) {
requestBody.discountable = discountable;
}
// Add image if provided
if (imageUrl && imageWidth) {
const image: any = {
url: imageUrl,
width: imageWidth,
};
if (imageHeight) {
image.height = imageHeight;
}
requestBody.images = [image];
}
try {
const response = await paperformCommon.apiCall<PaperformCreateProductResponse>({
method: HttpMethod.PUT,
url: `/forms/${formId}/products/${productSku}`,
body: requestBody,
auth: auth.secret_text,
});
return response.results.product;
} catch (error: any) {
throw new Error(`Failed to update product: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,39 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { HttpMethod } from '@activepieces/pieces-common';
import { PaperformSpace, PaperformUpdateSpaceResponse } from '../common/types';
import { paperformCommonProps } from '../common/props';
export const updateSpace = createAction({
auth: paperformAuth,
name: 'updateSpace',
displayName: 'Update Space',
description: 'Updates an existing space.',
props: {
spaceId: paperformCommonProps.spaceId,
name: Property.ShortText({
displayName: 'Space Name',
required: true,
}),
},
async run({ auth, propsValue }) {
const { spaceId, name } = propsValue;
try {
const response =
await paperformCommon.apiCall<PaperformUpdateSpaceResponse>({
method: HttpMethod.PUT,
url: `/spaces/${spaceId}`,
body: {
name,
},
auth: auth.secret_text,
});
return response.results.space;
} catch (error: any) {
throw new Error(`Failed to update space: ${error.message}`);
}
},
});

View File

@@ -0,0 +1,34 @@
import { PieceAuth } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { paperformCommon } from './client'
export const paperformAuth = PieceAuth.SecretText({
displayName: 'API Key',
description: 'Your Paperform API key. You can find this in your Paperform dashboard under Settings > Developer.',
required: true,
validate: async ({ auth }) => {
try {
await paperformCommon.apiCall({
method: HttpMethod.GET,
url: '/forms',
auth: { apiKey: auth as string },
});
return {
valid: true,
};
} catch (error: any) {
if (error.message.includes('401') || error.message.includes('403')) {
return {
valid: false,
error: 'Invalid API key. Please check your API key and try again.',
};
}
return {
valid: false,
error: `Authentication failed: ${error.message}. Please verify your API key is correct.`,
};
}
},
});

View File

@@ -0,0 +1,323 @@
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { PaperformFormsResponse, PaperformWebhookResponse, PaperformSubmissionsResponse, PaperformPartialSubmissionsResponse, PaperformCouponsResponse, PaperformFieldsResponse, PaperformProductsResponse, PaperformSpacesResponse, PaperformField, PaperformSubmission } from './types';
export const paperformCommon = {
baseUrl: 'https://api.paperform.co/v1',
async apiCall<T>({
method,
url,
body,
auth,
headers,
}: {
method: HttpMethod;
url: string;
body?: any;
auth: string | { apiKey: string };
headers?: Record<string, string>;
}): Promise<T> {
const apiKey = typeof auth === 'string' ? auth : auth.apiKey;
const response = await httpClient.sendRequest<T>({
method,
url: `${this.baseUrl}${url}`,
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
...headers,
},
body,
});
if (response.status >= 400) {
throw new Error(`Paperform API error: ${response.status}`);
}
return response.body;
},
async getSpaces({
auth,
search,
limit = 20,
skip = 0,
afterId,
beforeId,
beforeDate,
afterDate,
sort = 'DESC',
}: {
auth: string | { apiKey: string };
search?: string;
limit?: number;
skip?: number;
afterId?: string;
beforeId?: string;
beforeDate?: string;
afterDate?: string;
sort?: string;
}) {
const params = new URLSearchParams();
if (search) params.append('search', search);
if (limit) params.append('limit', limit.toString());
if (skip) params.append('skip', skip.toString());
if (afterId) params.append('after_id', afterId);
if (beforeId) params.append('before_id', beforeId);
if (beforeDate) params.append('before_date', beforeDate);
if (afterDate) params.append('after_date', afterDate);
if (sort) params.append('sort', sort);
return this.apiCall<PaperformSpacesResponse>({
method: HttpMethod.GET,
url: `/spaces?${params.toString()}`,
auth,
});
},
async getForms({
auth,
search,
limit = 20,
skip = 0,
afterId,
beforeId,
beforeDate,
afterDate,
sort = 'DESC',
}: {
auth: string | { apiKey: string };
search?: string;
limit?: number;
skip?: number;
afterId?: string;
beforeId?: string;
beforeDate?: string;
afterDate?: string;
sort?: string;
}) {
const params = new URLSearchParams();
if (search) params.append('search', search);
if (limit) params.append('limit', limit.toString());
if (skip) params.append('skip', skip.toString());
if (afterId) params.append('after_id', afterId);
if (beforeId) params.append('before_id', beforeId);
if (beforeDate) params.append('before_date', beforeDate);
if (afterDate) params.append('after_date', afterDate);
if (sort) params.append('sort', sort);
return this.apiCall<PaperformFormsResponse>({
method: HttpMethod.GET,
url: `/forms?${params.toString()}`,
auth,
});
},
async getForm({
formId,
auth,
}: {
formId: string;
auth: string | { apiKey: string };
}) {
return this.apiCall({
method: HttpMethod.GET,
url: `/forms/${formId}`,
auth,
});
},
async getFormFields({
formSlugOrId,
auth,
search,
}: {
formSlugOrId: string;
auth: string | { apiKey: string };
search?: string;
}) {
const params = new URLSearchParams();
if (search) params.append('search', search);
return this.apiCall<PaperformFieldsResponse>({
method: HttpMethod.GET,
url: `/forms/${formSlugOrId}/fields?${params.toString()}`,
auth,
});
},
async getSubmissions({
formId,
auth,
limit = 50,
skip = 0,
}: {
formId: string;
auth: string | { apiKey: string };
limit?: number;
skip?: number;
}) {
const params = new URLSearchParams();
if (limit) params.append('limit', limit.toString());
if (skip) params.append('skip', skip.toString());
return this.apiCall<PaperformSubmissionsResponse>({
method: HttpMethod.GET,
url: `/forms/${formId}/submissions?${params.toString()}`,
auth,
});
},
async getPartialSubmissions({
formSlugOrId,
auth,
limit = 50,
skip = 0,
}: {
formSlugOrId: string;
auth: string | { apiKey: string };
limit?: number;
skip?: number;
}) {
const params = new URLSearchParams();
if (limit) params.append('limit', limit.toString());
if (skip) params.append('skip', skip.toString());
return this.apiCall<PaperformPartialSubmissionsResponse>({
method: HttpMethod.GET,
url: `/forms/${formSlugOrId}/partial-submissions?${params.toString()}`,
auth,
});
},
async getCoupons({
formSlugOrId,
auth,
limit = 50,
skip = 0,
}: {
formSlugOrId: string;
auth: string | { apiKey: string };
limit?: number;
skip?: number;
}) {
const params = new URLSearchParams();
if (limit) params.append('limit', limit.toString());
if (skip) params.append('skip', skip.toString());
return this.apiCall<PaperformCouponsResponse>({
method: HttpMethod.GET,
url: `/forms/${formSlugOrId}/coupons?${params.toString()}`,
auth,
});
},
async getProducts({
formSlugOrId,
auth,
search,
limit = 50,
skip = 0,
}: {
formSlugOrId: string;
auth: string | { apiKey: string };
search?: string;
limit?: number;
skip?: number;
}) {
const params = new URLSearchParams();
if (search) params.append('search', search);
if (limit) params.append('limit', limit.toString());
if (skip) params.append('skip', skip.toString());
return this.apiCall<PaperformProductsResponse>({
method: HttpMethod.GET,
url: `/forms/${formSlugOrId}/products?${params.toString()}`,
auth,
});
},
async getSubmission({
submissionId,
auth,
}: {
submissionId: string;
auth: string | { apiKey: string };
}) {
return this.apiCall<{results:{submission:PaperformSubmission}}>({
method: HttpMethod.GET,
url: `/submissions/${submissionId}`,
auth,
});
},
async getPartialSubmission({
submissionId,
auth,
}: {
submissionId: string;
auth: string | { apiKey: string };
}) {
return this.apiCall<{results:{'partial-submission':PaperformSubmission}}>({
method: HttpMethod.GET,
url: `/partial-submissions/${submissionId}`,
auth,
});
},
async createWebhook({
formId,
webhookUrl,
auth,
eventType,
}: {
formId: string;
webhookUrl: string;
auth: string | { apiKey: string };
eventType: string;
}) {
return this.apiCall<PaperformWebhookResponse>({
method: HttpMethod.POST,
url: `/forms/${formId}/webhooks`,
body: {
target_url: webhookUrl,
triggers: [eventType],
},
auth,
});
},
async deleteWebhook({
webhookId,
auth,
}: {
webhookId: string;
auth: string | { apiKey: string };
}) {
return this.apiCall({
method: HttpMethod.DELETE,
url: `/webhooks/${webhookId}`,
auth,
});
},
transformSubmissionData(
formFields:PaperformField[],
submissionFields:Record<string,any>
):Record<string,any>{
const fieldMap: Record<string, string> = formFields.reduce((acc, field) => {
acc[field.key] = field.title;
return acc;
}, {} as Record<string, string>);
const transformedFields: Record<string, any> = {};
for (const [key, value] of Object.entries(submissionFields)) {
const label = fieldMap[key] ?? key;
transformedFields[label] = value;
}
return transformedFields;
}
};

View File

@@ -0,0 +1,214 @@
import { Property } from '@activepieces/pieces-framework';
import { paperformCommon } from './client';
import {
PaperformCoupon,
PaperformField,
PaperformProduct,
PaperformSpace,
} from './types';
import { isNil } from '@activepieces/shared';
import { paperformAuth } from './auth';
export const paperformCommonProps = {
spaceId: Property.Dropdown({
auth: paperformAuth,
displayName: 'Space',
required: true,
refreshers: ['auth'],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your account first.',
options: [],
};
}
try {
const spaces = await paperformCommon.getSpaces({
auth: auth.secret_text,
limit: 100,
});
return {
disabled: false,
options: spaces.results.spaces.map((space: PaperformSpace) => ({
label: space.name,
value: space.id,
})),
};
} catch (error) {
return {
disabled: true,
placeholder: 'Error loading spaces.',
options: [],
};
}
},
}),
formId: Property.Dropdown({
auth: paperformAuth,
displayName: 'Form',
required: true,
refreshers: ['auth'],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your account first.',
options: [],
};
}
try {
const forms = await paperformCommon.getForms({
auth: auth.secret_text,
limit: 100,
});
return {
disabled: false,
options: forms.results.forms.map((form) => ({
label: form.title,
value: form.id,
})),
};
} catch (error) {
return {
disabled: true,
placeholder: 'Error loading forms.',
options: [],
};
}
},
}),
productFieldKey: Property.Dropdown({
auth: paperformAuth,
displayName: 'Product Field',
required: true,
refreshers: ['auth', 'formId'],
options: async ({ auth, formId }) => {
if (!auth || !formId) {
return {
disabled: true,
placeholder: 'Please select a form first',
options: [],
};
}
try {
const fields = await paperformCommon.getFormFields({
formSlugOrId: formId as string,
auth: auth.secret_text,
});
const productFields = fields.results.fields.filter(
(field: PaperformField) => field.type === 'products'
);
if (productFields.length === 0) {
return {
disabled: true,
placeholder: 'No product fields found on this form',
options: [],
};
}
return {
disabled: false,
options: productFields.map((field: PaperformField) => ({
label: `${field.title} (${field.key})`,
value: field.key,
})),
};
} catch (error) {
return {
disabled: true,
placeholder: 'Error loading form fields',
options: [],
};
}
},
}),
productSku: Property.Dropdown({
auth: paperformAuth,
displayName: 'Product',
required: true,
refreshers: ['auth', 'formId'],
options: async ({ auth, formId }) => {
if (!auth || !formId) {
return {
disabled: true,
placeholder: 'Please select a form first.',
options: [],
};
}
try {
const products = await paperformCommon.getProducts({
formSlugOrId: formId as string,
auth: auth.secret_text,
limit: 100,
});
return {
disabled: false,
options: products.results.products.map(
(product: PaperformProduct) => ({
label:
isNil(product.name) || product.name === ''
? product.SKU
: product.name,
value: product.SKU,
})
),
};
} catch (error) {
return {
disabled: true,
placeholder: 'Error loading products.',
options: [],
};
}
},
}),
couponCode: Property.Dropdown({
auth: paperformAuth,
displayName: 'Coupon',
required: true,
refreshers: ['auth', 'formId'],
options: async ({ auth, formId }) => {
if (!auth || !formId) {
return {
disabled: true,
placeholder: 'Please select a form first',
options: [],
};
}
try {
const coupons = await paperformCommon.getCoupons({
formSlugOrId: formId as string,
auth: auth.secret_text,
limit: 100,
});
return {
disabled: false,
options: coupons.results.coupons.map((coupon: PaperformCoupon) => ({
label: `${coupon.code} - ${
coupon.enabled ? 'Enabled' : 'Disabled'
}`,
value: coupon.code,
})),
};
} catch (error) {
return {
disabled: true,
placeholder: 'Error loading coupons',
options: [],
};
}
},
}),
};

View File

@@ -0,0 +1,228 @@
export interface PaperformForm {
id: string;
slug: string;
custom_slug?: string;
space_id: string;
title: string;
description?: string;
cover_image_url?: string;
url: string;
additional_urls?: string[];
live: boolean;
tags?: string[];
submission_count: number;
created_at: string;
updated_at: string;
account_timezone: string;
created_at_utc: string;
updated_at_utc: string;
}
export interface PaperformSubmission {
id: string;
form_id: string;
created_at: string;
updated_at: string;
data: Record<string, any>;
}
export interface PaperformPartialSubmission {
id: string;
form_id: string;
data: Record<string, any>;
last_answered: string;
submitted_at: string;
updated_at: string;
created_at: string;
account_timezone: string;
submitted_at_utc: string;
created_at_utc: string;
updated_at_utc: string;
}
export interface PaperformCoupon {
code: string;
enabled: boolean;
target?: string;
discountAmount?: number;
discountPercentage?: number;
expiresAt?: string | null;
}
export interface PaperformProductImage {
url: string;
width: number;
height?: number;
}
export interface PaperformProduct {
name: string;
quantity?: number;
price: number;
minimum?: number;
maximum?: number;
discountable?: boolean;
images?: PaperformProductImage[];
SKU: string;
}
export interface PaperformField {
key: string;
title: string;
description?: string;
required: boolean;
type: string;
custom_key?: string;
placeholder?: string;
options?: string[];
}
export interface PaperformSpace {
id: string;
name: string;
created_at: string;
updated_at: string;
account_timezone: string;
created_at_utc: string;
updated_at_utc: string;
}
export interface PaperformFormsResponse {
status: string;
results: {
forms: PaperformForm[];
};
total: number;
has_more: boolean;
limit: number;
skip: number;
}
export interface PaperformSubmissionsResponse {
status: string;
results: {
submissions: PaperformSubmission[];
};
total: number;
has_more: boolean;
limit: number;
skip: number;
}
export interface PaperformPartialSubmissionsResponse {
status: string;
results: {
"partial-submissions": PaperformPartialSubmission[];
};
total: number;
has_more: boolean;
limit: number;
skip: number;
}
export interface PaperformCouponsResponse {
status: string;
results: {
coupons: PaperformCoupon[];
};
total: number;
has_more: boolean;
limit: number;
skip: number;
}
export interface PaperformProductsResponse {
status: string;
results: {
products: PaperformProduct[];
};
total: number;
has_more: boolean;
limit: number;
skip: number;
}
export interface PaperformSpacesResponse {
status: string;
results: {
spaces: PaperformSpace[];
};
total: number;
has_more: boolean;
limit: number;
skip: number;
}
export interface PaperformFieldsResponse {
status: string;
results: {
fields: PaperformField[];
};
}
export interface PaperformProductResponse {
status: string;
results: {
product: PaperformProduct;
};
}
export interface PaperformCouponResponse {
status: string;
results: {
coupon: PaperformCoupon;
};
}
export interface PaperformWebhook {
id: string;
target_url: string;
triggers: string[];
created_at: string;
updated_at: string;
account_timezone: string;
created_at_utc: string;
updated_at_utc: string;
}
export interface PaperformWebhookResponse {
status: string;
results: {
webhook: PaperformWebhook;
};
}
export interface PaperformCreateSpaceResponse{
results:{
space:{
id:number,
name:string
}
}
}
export interface PaperformUpdateSpaceResponse{
results:{
space:{
id:number,
name:string
}
}
}
export interface PaperformCreateProductResponse{
results:{
product:{
name:string
}
}
}
export interface PaperformCreateCouponResponse{
results:{
coupon:{
code:string
}
}
}

View File

@@ -0,0 +1,100 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { paperformCommonProps } from '../common/props';
import { PaperformSubmission } from '../common/types';
const TRIGGER_KEY = 'new_form_submission';
export const newFormSubmission = createTrigger({
auth: paperformAuth,
name: 'new_form_submission',
displayName: 'New Form Submission',
description: 'Triggers when a completed form submission is received.',
props: {
formId: paperformCommonProps.formId,
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const formId = context.propsValue.formId;
const response = await paperformCommon.createWebhook({
formId,
webhookUrl: context.webhookUrl,
auth: context.auth.secret_text,
eventType: 'submission',
});
await context.store.put(TRIGGER_KEY, response.results.webhook.id);
},
async onDisable(context) {
const webhookId = await context.store.get<string>(TRIGGER_KEY);
if (webhookId) {
await paperformCommon.deleteWebhook({
webhookId,
auth: context.auth.secret_text,
});
}
},
async run(context) {
const { formId } = context.propsValue;
const payload = context.payload.body as Payload;
const response = await paperformCommon.getSubmission({
submissionId: payload.submission_id,
auth: context.auth.secret_text,
});
const submission = response.results.submission;
const fields = await paperformCommon.getFormFields({
formSlugOrId: formId as string,
auth: context.auth.secret_text,
});
const transformedFields = paperformCommon.transformSubmissionData(
fields.results.fields,
submission.data
);
return [
{
...submission,
data: transformedFields,
},
];
},
async test(context) {
const { formId } = context.propsValue;
const response = await paperformCommon.getSubmissions({
formId,
auth: context.auth.secret_text,
limit: 10,
});
if (response.results.submissions.length === 0) return [];
const fields = await paperformCommon.getFormFields({
formSlugOrId: formId as string,
auth: context.auth.secret_text,
});
return response.results.submissions.map((submission) => {
const transformedFields = paperformCommon.transformSubmissionData(
fields.results.fields,
submission.data
);
return {
...submission,
data: transformedFields,
};
});
},
sampleData: {},
});
interface Payload {
submission_id: string;
form_id: string;
}

View File

@@ -0,0 +1,109 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { paperformAuth } from '../common/auth';
import { paperformCommon } from '../common/client';
import { paperformCommonProps } from '../common/props';
const TRIGGER_KEY = 'new_partial_form_submission';
export const newPartialFormSubmission = createTrigger({
auth: paperformAuth,
name: 'new_partial_form_submission',
displayName: 'New Partial Form Submission',
description: 'Triggers when a partial/in-progress submission is received.',
props: {
formId: paperformCommonProps.formId,
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const formId = context.propsValue.formId;
const response = await paperformCommon.createWebhook({
formId,
webhookUrl: context.webhookUrl,
auth: context.auth.secret_text,
eventType: 'partial_submission',
});
await context.store.put(TRIGGER_KEY, response.results.webhook.id);
},
async onDisable(context) {
const webhookId = await context.store.get<string>(TRIGGER_KEY);
if (webhookId) {
await paperformCommon.deleteWebhook({
webhookId,
auth: context.auth.secret_text,
});
}
},
async run(context) {
const { formId } = context.propsValue;
const payload = context.payload.body as Payload;
const response = await paperformCommon.getPartialSubmission({
submissionId: payload.submission_id,
auth: context.auth.secret_text,
});
const submission = response.results['partial-submission'];
const fields = await paperformCommon.getFormFields({
formSlugOrId: formId as string,
auth: context.auth.secret_text,
});
const transformedFields =
Array.isArray(submission.data) && submission.data.length === 0
? {}
: paperformCommon.transformSubmissionData(
fields.results.fields,
submission.data
);
return [
{
...submission,
data: transformedFields,
},
];
},
async test(context) {
const { formId } = context.propsValue;
const response = await paperformCommon.getPartialSubmissions({
formSlugOrId: formId,
auth: context.auth.secret_text,
limit: 10,
});
if (response.results['partial-submissions'].length === 0) return [];
const fields = await paperformCommon.getFormFields({
formSlugOrId: formId as string,
auth: context.auth.secret_text,
});
return response.results['partial-submissions'].map((submission) => {
if (Array.isArray(submission.data) && submission.data.length === 0) {
return {
...submission,
data: {},
};
}
const transformedFields = paperformCommon.transformSubmissionData(
fields.results.fields,
submission.data
);
return {
...submission,
data: transformedFields,
};
});
},
sampleData: {},
});
interface Payload {
submission_id: string;
form_id: string;
}

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"]
}