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

View File

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

View File

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

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Klicken Sie auf Ihr Profilsymbol oben rechts und navigieren Sie zu Einstellungen > Integrationen > Apps.\n 2. Suchen Sie den Abschnitt API-Zugriffstoken am oberen Rand der Seite.\n 3. Klicken Sie auf den Button **+ API-Token generieren**.\n 4. Wählen Sie folgende Bereiche aus:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Klicken Sie auf Token generieren, um den Prozess abzuschließen.\n ",
"Get Candidate": "Bewerber erhalten",
"Get Members": "Mitglieder erhalten",
"Get Job": "Job erhalten",
"Get Stages": "Stadien abrufen",
"Move Candidate": "Kandidat verschieben",
"Rate candidate": "Bewerte Kandidat",
"Custom API Call": "Eigener API-Aufruf",
"Gets candidate's information.": "Ruft die Informationen des Kandidaten ab.",
"Gets members of hiring team.": "Ruft Mitglieder des Einstellungsteams ein.",
"Gets specific job deatils.": "Liefert bestimmte Job-Deatilitäten.",
"Gets stages in your recruitment pipeline stages.": "Ruft Stufen in Ihren Rekrutierungsphasen ab.",
"Moves candidate to the specified stage.": "Bewegt den Kandidaten in die angegebene Phase.",
"Rates the candidate on workable.": "Bewertet den Kandidaten auf praktikabel.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Candidate's Id": "Id des Kandidaten",
"Limit": "Limit",
"Role": "Rolle",
"Shortcode": "Shortcode",
"Member's email": "E-Mail des Mitglieds",
"Member's name": "Name des Mitglieds",
"Member's Id": "Mitglieder-Id",
"Target stage name": "Name des Zielstadiums",
"Comment": "Kommentar",
"Rating scale": "Bewertungsmaßstab",
"Grade": "Note",
"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)",
"Default is 50": "Standard ist 50",
"Filter for member of specified role": "Filter nach Mitglied der angegebenen Rolle",
"Shortcode of specific job": "Kurzcode für einen bestimmten Job",
"Filter for specific member by email": "Nach bestimmten Mitgliedern per E-Mail filtern",
"Filter for members of specified name (Exact Match)": "Filter für Mitglieder des angegebenen Namens (Exact Match)",
"Id of candidate": "Id des Kandidaten",
"This person's Id is used to move the candidate to the next stage": "Die Id dieser Person wird verwendet, um den Kandidaten in die nächste Stufe zu verschieben",
"Slug of stage target should be moved to": "Slug des Stufenziels sollte verschoben werden",
"Id of member that is adding the rating": "Id des Mitglieds, das die Bewertung hinzufügt",
"Comment about the scoring of the candidate": "Kommentar zur Punktzahl des Kandidaten",
"Select scale to rate candidate on": "Wählen Sie eine Skala um den Kandidaten zu bewerten",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Thumbs Skala: 0-2, Sterne Skala: 0-4, Zahlen Skalierung: 0-9",
"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..",
"Thumbs": "Daumen",
"Stars": "Sterne",
"Numbers": "Nummern",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"New Candidate": "Neuer Kandidat",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "Auslöser wenn ein neuer Kandidat eine Bewerbung einreicht. Kann nach einem bestimmten Job gefiltert werden und/oder Pipelinebühne.",
"Stage Slug": "Stage Slug",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "Kurzcode für bestimmte Aufgaben. Leer lassen um für alle Jobs auszulösen.",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "Stage Slug zum Filtern nach spezifischer Einstellung Pipeline-Phase (z.B. 'applied', 'phone_screen', 'interview', 'offer'). Leer lassen um für alle Stufen auszulösen."
}

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ",
"Get Candidate": "Obtener Candidate",
"Get Members": "Obtener miembros",
"Get Job": "Obtener trabajo",
"Get Stages": "Obtener etapas",
"Move Candidate": "Mover Candidato",
"Rate candidate": "Calificar candidato",
"Custom API Call": "Llamada API personalizada",
"Gets candidate's information.": "Obtiene la información del candidato.",
"Gets members of hiring team.": "Obtiene miembros del equipo de contratación.",
"Gets specific job deatils.": "Obtiene deatils de trabajo específicos.",
"Gets stages in your recruitment pipeline stages.": "Obtiene etapas en las fases de reclutamiento de tuberías.",
"Moves candidate to the specified stage.": "Mueve el candidato a la etapa especificada.",
"Rates the candidate on workable.": "Califica al candidato en cuanto viable.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Candidate's Id": "Id de Candidato",
"Limit": "Límite",
"Role": "Rol",
"Shortcode": "Código corto",
"Member's email": "Email del miembro",
"Member's name": "Nombre del miembro",
"Member's Id": "Id del miembro",
"Target stage name": "Nombre de la etapa destino",
"Comment": "Comentario",
"Rating scale": "Escala de valoración",
"Grade": "Nota",
"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)",
"Default is 50": "Por defecto es 50",
"Filter for member of specified role": "Filtro para miembro del rol especificado",
"Shortcode of specific job": "Código corto del trabajo específico",
"Filter for specific member by email": "Filtrar para un miembro específico por correo electrónico",
"Filter for members of specified name (Exact Match)": "Filtro para miembros del nombre especificado (Coincidencia exacta)",
"Id of candidate": "Id del candidato",
"This person's Id is used to move the candidate to the next stage": "El Id de esta persona se utiliza para mover el candidato a la siguiente etapa",
"Slug of stage target should be moved to": "El objetivo de la etapa debe ser movido a",
"Id of member that is adding the rating": "Id del miembro que está añadiendo la calificación",
"Comment about the scoring of the candidate": "Comentario sobre la puntuación del candidato",
"Select scale to rate candidate on": "Seleccionar escala para calificar candidato en",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Escala de pulgas: 0-2, Escala de estrellas: 0-4, Escala de números: 0-9",
"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.",
"Thumbs": "Pulgares",
"Stars": "Estrellas",
"Numbers": "Números",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"New Candidate": "Nuevo comando",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "Dispara cuando el nuevo candidato presenta la solicitud. Puede ser filtrado por un trabajo específico y/o contratando tuberías etapas.",
"Stage Slug": "Fase de Slug",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "Código corto de trabajo específico. Dejar en blanco para activar todos los trabajos.",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "Fase de slug para filtrar por una etapa específica del tubo de contratación (por ejemplo, 'aplicado', 'pantalla_teléfono', 'entrevista', 'oferta'). Dejar vacío para activar todas las etapas."
}

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ",
"Get Candidate": "Obtenir un candidat",
"Get Members": "Obtenir des membres",
"Get Job": "Obtenir un emploi",
"Get Stages": "Obtenir des étapes",
"Move Candidate": "Déplacer le candidat",
"Rate candidate": "Noter le candidat",
"Custom API Call": "Appel d'API personnalisé",
"Gets candidate's information.": "Obtient les informations du candidat.",
"Gets members of hiring team.": "Obtient les membres de l'équipe d'embauche.",
"Gets specific job deatils.": "Obtient des déatils de travail spécifiques.",
"Gets stages in your recruitment pipeline stages.": "Obtient des étapes dans vos étapes de recrutement.",
"Moves candidate to the specified stage.": "Déplace le candidat à l'étape spécifiée.",
"Rates the candidate on workable.": "Évalue le candidat sur le faisable.",
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
"Candidate's Id": "Identifiant du candidat",
"Limit": "Limite",
"Role": "Rôle",
"Shortcode": "Shortcode",
"Member's email": "E-mail du membre",
"Member's name": "Nom du membre",
"Member's Id": "Identifiant du membre",
"Target stage name": "Nom de l'étape cible",
"Comment": "Commenter",
"Rating scale": "Échelle de notation",
"Grade": "Note",
"Method": "Méthode",
"Headers": "Headers",
"Query Parameters": "Paramètres de requête",
"Body": "Body",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'expiration (en secondes)",
"Default is 50": "La valeur par défaut est 50",
"Filter for member of specified role": "Filtrer pour le membre du rôle spécifié",
"Shortcode of specific job": "Raccourci de tâche spécifique",
"Filter for specific member by email": "Filtrer pour un membre spécifique par email",
"Filter for members of specified name (Exact Match)": "Filtrer pour les membres du nom spécifié (Exact Match)",
"Id of candidate": "Id du candidat",
"This person's Id is used to move the candidate to the next stage": "L'identifiant de cette personne est utilisé pour déplacer le candidat à l'étape suivante",
"Slug of stage target should be moved to": "Le périmètre de la cible de l'étape doit être déplacé vers",
"Id of member that is adding the rating": "Id du membre qui ajoute la note",
"Comment about the scoring of the candidate": "Commentaire sur le score du candidat",
"Select scale to rate candidate on": "Sélectionnez l'échelle pour noter le candidat sur",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Échelle des pouces : 0-2, Échelle des étoiles: 0-4, Échelle des nombres : 0-9",
"Authorization headers are injected automatically from your connection.": "Les Headers 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.",
"Thumbs": "Pouce",
"Stars": "Étoiles",
"Numbers": "Numéros",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Candidate": "Nouveau candidat",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "Déclenche lorsque le nouveau candidat soumet une candidature. Peut être filtré par un poste spécifique et/ou embauche l'étape de pipeline.",
"Stage Slug": "Limace de l'étape",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "Shortcode de la tâche spécifique. Laissez vide pour déclencher tous les travaux.",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "Stage slug pour filtrer par étape spécifique du pipeline d'embauche (par exemple, 'applied', 'phone_screen', 'interview', 'offer'). Laisser vide pour déclencher pour toutes les étapes."
}

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ",
"Get Candidate": "候補を取得",
"Get Members": "メンバーを取得",
"Get Job": "作業を取得",
"Get Stages": "ステージを取得",
"Move Candidate": "候補を移動",
"Rate candidate": "候補者を評価",
"Custom API Call": "カスタムAPI通話",
"Gets candidate's information.": "候補者の情報を取得します。",
"Gets members of hiring team.": "採用チームのメンバーを取得します。",
"Gets specific job deatils.": "特定のジョブdeatilsを取得します。",
"Gets stages in your recruitment pipeline stages.": "あなたの募集パイプラインの段階を取得します。",
"Moves candidate to the specified stage.": "候補を指定したステージに移動します。",
"Rates the candidate on workable.": "実行可能な候補を評価します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Candidate's Id": "候補者のID",
"Limit": "制限",
"Role": "ロール",
"Shortcode": "ショートカット",
"Member's email": "メンバーのメールアドレス",
"Member's name": "メンバーの名前",
"Member's Id": "メンバーID",
"Target stage name": "ターゲットステージ名",
"Comment": "コメント",
"Rating scale": "評価の大きさ",
"Grade": "成績",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Default is 50": "デフォルトは50です",
"Filter for member of specified role": "指定されたロールのメンバーのフィルター",
"Shortcode of specific job": "特定のジョブのショートカット",
"Filter for specific member by email": "電子メールで特定のメンバーのフィルター",
"Filter for members of specified name (Exact Match)": "指定された名前のメンバのフィルター (完全一致)",
"Id of candidate": "候補者ID",
"This person's Id is used to move the candidate to the next stage": "この人の Id は候補者を次のステージに移動するために使用されます",
"Slug of stage target should be moved to": "ステージターゲットのスラグを移動する必要があります",
"Id of member that is adding the rating": "評価を追加しているメンバーの Id",
"Comment about the scoring of the candidate": "候補者の得点に関するコメント",
"Select scale to rate candidate on": "候補者を評価するスケールを選択してください",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"Thumbs": "Thumbs",
"Stars": "星",
"Numbers": "数値",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"New Candidate": "新規候補",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "新しい候補者が申請を提出するときにトリガーします。特定のジョブおよび/またはパイプラインの段階を採用することでフィルタリングできます。",
"Stage Slug": "ステージスラグ",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "特定のジョブのショートコード。すべてのジョブをトリガーするには空のままにしてください。",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "特定の採用パイプラインステージによってフィルタリングするためのステージスラグ(例:「適用」、「電話」、「面接」、「提供」)。すべてのステージでトリガーするには空のままにしてください。"
}

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Klik op je profielpictogram rechtsboven en navigeer naar Instellingen > Integraties > Apps.\n 2. Zoek de API Tokens sectie naast de bovenkant van de pagina.\n 3. Klik op de knop **+ API token genereren**.\n 4. Selecteer de volgende toepassingsgebieden:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Klik op Token genereren om het proces te voltooien.\n ",
"Get Candidate": "Kandidaat ophalen",
"Get Members": "Leden ophalen",
"Get Job": "Taak krijgen",
"Get Stages": "Fases ophalen",
"Move Candidate": "Kandidaat verplaatsen",
"Rate candidate": "Kandidaat beoordelen",
"Custom API Call": "Custom API Call",
"Gets candidate's information.": "Haalt de informatie van de kandidaat op.",
"Gets members of hiring team.": "Krijgt leden van het inhurende team.",
"Gets specific job deatils.": "Krijgt specifieke job deatils.",
"Gets stages in your recruitment pipeline stages.": "Haalt fasen op in je wervingspijplijnfasen.",
"Moves candidate to the specified stage.": "Verplaatst kandidaat naar de opgegeven fase.",
"Rates the candidate on workable.": "Veroordeelt de kandidaat op werkbaar.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Candidate's Id": "ID Kandidaat",
"Limit": "Limiet",
"Role": "Functie",
"Shortcode": "Shortcode",
"Member's email": "Gebruiker zijn e-mail",
"Member's name": "Naam deelnemer",
"Member's Id": "Lid ID",
"Target stage name": "Naam doelstadium",
"Comment": "Opmerking",
"Rating scale": "Schaal waardering",
"Grade": "Beoordeling",
"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)",
"Default is 50": "Standaard is 50",
"Filter for member of specified role": "Filter voor lid van opgegeven rol",
"Shortcode of specific job": "Shortcode van specifieke taak",
"Filter for specific member by email": "Filter voor specifiek lid per e-mail",
"Filter for members of specified name (Exact Match)": "Filter voor leden van de opgegeven naam (Exact Match)",
"Id of candidate": "Id van kandidaat",
"This person's Id is used to move the candidate to the next stage": "Deze ID wordt gebruikt om de kandidaat naar de volgende fase te verplaatsen",
"Slug of stage target should be moved to": "Slug van podium doel moet worden verplaatst naar",
"Id of member that is adding the rating": "Id van het lid dat de beoordeling toevoegt",
"Comment about the scoring of the candidate": "Commentaar over de score van de kandidaat",
"Select scale to rate candidate on": "Selecteer schaal om kandidaat op te waarderen",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Duimen schaal: 0-2, sterren schaal: 0-4, Nummers schaal: 0-9",
"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..",
"Thumbs": "Duimen",
"Stars": "Sterren",
"Numbers": "Nummers",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"New Candidate": "Nieuwe kandidaat",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "Triggers wanneer nieuwe kandidaat de applicatie indient. Kan worden gefilterd op specifieke taken en/of het huren van een pijplijnstadium.",
"Stage Slug": "Fase slak",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "Kortcode van specifieke taak. Laat leeg voor trigger voor alle vacatures.",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "Fase slug om te filteren op specifieke hiring pipeline fase (bijv. 'toegepast', 'phone_screen', 'interview', 'offer'). Laat leeg om te activeren voor alle fases."
}

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ",
"Get Candidate": "Obter Candidato",
"Get Members": "Obter Membros",
"Get Job": "Obter trabalho",
"Get Stages": "Obter estágios",
"Move Candidate": "Mover Candidato",
"Rate candidate": "Avaliar candidato",
"Custom API Call": "Chamada de API personalizada",
"Gets candidate's information.": "Obtém informação do candidato.",
"Gets members of hiring team.": "Obtém membros da equipe de contratação.",
"Gets specific job deatils.": "Obtém deações de tarefas específicas.",
"Gets stages in your recruitment pipeline stages.": "Obtém estágios nas suas fases do pipeline de recrutamento.",
"Moves candidate to the specified stage.": "Move o candidato para a fase especificada.",
"Rates the candidate on workable.": "Tarifa o candidato praticável.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Candidate's Id": "Identificação do candidato",
"Limit": "Limitar",
"Role": "Funções",
"Shortcode": "Shortcode",
"Member's email": "E-mail do membro",
"Member's name": "Nome do membro",
"Member's Id": "ID do membro",
"Target stage name": "Nome destino do estágio",
"Comment": "Comentar",
"Rating scale": "Escala de classificação",
"Grade": "Avaliação",
"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)",
"Default is 50": "Padrão é 50",
"Filter for member of specified role": "Filtro para membro da função especificada",
"Shortcode of specific job": "Shortcode da tarefa específica",
"Filter for specific member by email": "Filtrar por email para um membro específico",
"Filter for members of specified name (Exact Match)": "Filtro para membros do nome especificado (Correspondência exata)",
"Id of candidate": "ID do candidato",
"This person's Id is used to move the candidate to the next stage": "O ID desta pessoa é usado para mover o candidato para a próxima etapa",
"Slug of stage target should be moved to": "Slug do alvo do estágio deve ser movido para",
"Id of member that is adding the rating": "ID do membro que está adicionando a classificação",
"Comment about the scoring of the candidate": "Comentário sobre o pontuação da candidata",
"Select scale to rate candidate on": "Selecione a escala para avaliar o candidato em",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Escala das miniaturas: 0-2, Escala das estrelas: 0-4, Escala dos números: 0-9",
"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..",
"Thumbs": "Miniaturas",
"Stars": "Favoritos",
"Numbers": "Números",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"New Candidate": "Novo Candidato",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "Dispara quando um novo candidato enviar uma aplicação. Pode ser filtrado por profissão e/ou estágio específico de contratação.",
"Stage Slug": "Slug da Fase",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "Código de atalho de uma tarefa específica. Deixe em branco para acionar todas as tarefas.",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "Slug do estágio para filtrar por estágio de contratação específica de pipeline (por exemplo, 'aplicado', 'phone_screen', 'entrevte', 'oferta'). Deixe em branco para acionar em todos os estágios."
}

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ",
"Get Candidate": "Get Candidate",
"Get Members": "Get Members",
"Get Job": "Get Job",
"Get Stages": "Get Stages",
"Move Candidate": "Move Candidate",
"Rate candidate": "Rate candidate",
"Custom API Call": "Custom API Call",
"Gets candidate's information.": "Gets candidate's information.",
"Gets members of hiring team.": "Gets members of hiring team.",
"Gets specific job deatils.": "Gets specific job deatils.",
"Gets stages in your recruitment pipeline stages.": "Gets stages in your recruitment pipeline stages.",
"Moves candidate to the specified stage.": "Moves candidate to the specified stage.",
"Rates the candidate on workable.": "Rates the candidate on workable.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Candidate's Id": "Candidate's Id",
"Limit": "Limit",
"Role": "Role",
"Shortcode": "Shortcode",
"Member's email": "Member's email",
"Member's name": "Member's name",
"Member's Id": "Member's Id",
"Target stage name": "Target stage name",
"Comment": "Comment",
"Rating scale": "Rating scale",
"Grade": "Grade",
"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)",
"Default is 50": "Default is 50",
"Filter for member of specified role": "Filter for member of specified role",
"Shortcode of specific job": "Shortcode of specific job",
"Filter for specific member by email": "Filter for specific member by email",
"Filter for members of specified name (Exact Match)": "Filter for members of specified name (Exact Match)",
"Id of candidate": "Id of candidate",
"This person's Id is used to move the candidate to the next stage": "This person's Id is used to move the candidate to the next stage",
"Slug of stage target should be moved to": "Slug of stage target should be moved to",
"Id of member that is adding the rating": "Id of member that is adding the rating",
"Comment about the scoring of the candidate": "Comment about the scoring of the candidate",
"Select scale to rate candidate on": "Select scale to rate candidate on",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9",
"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..",
"Thumbs": "Thumbs",
"Stars": "Stars",
"Numbers": "Numbers",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Candidate": "New Candidate",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.",
"Stage Slug": "Stage Slug",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "Shortcode of specific job. Leave empty to trigger for all jobs.",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages."
}

View File

@@ -0,0 +1,63 @@
{
"\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ": "\n 1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.\n 2. Locate the API Access Tokens section near the top of the page.\n 3. Click the button **+ Generate API token**.\n 4. Select the following scopes:\n - r_jobs\n - r_candidates\n - w_candidates\n 5. Click Generate token to complete the process.\n ",
"Get Candidate": "Get Candidate",
"Get Members": "Get Members",
"Get Job": "Get Job",
"Get Stages": "Get Stages",
"Move Candidate": "Move Candidate",
"Rate candidate": "Rate candidate",
"Custom API Call": "自定义 API 呼叫",
"Gets candidate's information.": "Gets candidate's information.",
"Gets members of hiring team.": "Gets members of hiring team.",
"Gets specific job deatils.": "Gets specific job deatils.",
"Gets stages in your recruitment pipeline stages.": "Gets stages in your recruitment pipeline stages.",
"Moves candidate to the specified stage.": "Moves candidate to the specified stage.",
"Rates the candidate on workable.": "Rates the candidate on workable.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Candidate's Id": "Candidate's Id",
"Limit": "Limit",
"Role": "作用",
"Shortcode": "Shortcode",
"Member's email": "Member's email",
"Member's name": "Member's name",
"Member's Id": "Member's Id",
"Target stage name": "Target stage name",
"Comment": "Comment",
"Rating scale": "Rating scale",
"Grade": "Grade",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Default is 50": "Default is 50",
"Filter for member of specified role": "Filter for member of specified role",
"Shortcode of specific job": "Shortcode of specific job",
"Filter for specific member by email": "Filter for specific member by email",
"Filter for members of specified name (Exact Match)": "Filter for members of specified name (Exact Match)",
"Id of candidate": "Id of candidate",
"This person's Id is used to move the candidate to the next stage": "This person's Id is used to move the candidate to the next stage",
"Slug of stage target should be moved to": "Slug of stage target should be moved to",
"Id of member that is adding the rating": "Id of member that is adding the rating",
"Comment about the scoring of the candidate": "Comment about the scoring of the candidate",
"Select scale to rate candidate on": "Select scale to rate candidate on",
"Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9": "Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"Thumbs": "Thumbs",
"Stars": "Stars",
"Numbers": "Numbers",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"New Candidate": "New Candidate",
"Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.": "Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.",
"Stage Slug": "Stage Slug",
"Shortcode of specific job. Leave empty to trigger for all jobs.": "Shortcode of specific job. Leave empty to trigger for all jobs.",
"Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.": "Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages."
}

View File

@@ -0,0 +1,54 @@
import { createPiece, PieceAuth } from "@activepieces/pieces-framework";
import { getCandidate } from "./lib/actions/get-candidate";
import { getMembers } from "./lib/actions/get-members";
import { getJob } from "./lib/actions/get-job";
import { getStages } from "./lib/actions/get-stages";
import { moveCandidate } from "./lib/actions/move-candidate";
import { rateCandidate } from "./lib/actions/rate-candidate";
import { newCandidate } from "./lib/triggers/new-candidate";
import { createCustomApiCallAction } from "@activepieces/pieces-common";
import { PieceCategory } from "@activepieces/shared";
export const workableAuth = PieceAuth.SecretText({
displayName: "API Access Token",
description: `
1. Click your profile icon in the upper right and navigate to Settings > Integrations > Apps.
2. Locate the API Access Tokens section near the top of the page.
3. Click the button **+ Generate API token**.
4. Select the following scopes:
- r_jobs
- r_candidates
- w_candidates
5. Click Generate token to complete the process.
`,
required: true
})
export const workable = createPiece({
displayName: "Workable",
auth: workableAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: "https://cdn.activepieces.com/pieces/workable.png",
categories:[PieceCategory.HUMAN_RESOURCES],
authors: ['Cloudieunnie'],
actions: [
getCandidate,
getMembers,
getJob,
getStages,
moveCandidate,
rateCandidate,
createCustomApiCallAction({
baseUrl: () => `https://workable.com/spi/v3/`,
auth: workableAuth,
authMapping: async (auth) => ({
Authorization: `Bearer ${auth.secret_text}`,
Accept: 'application/json'
})
})
],
triggers: [
newCandidate
],
});

View File

@@ -0,0 +1,35 @@
import { workableAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { getAccountSubdomain } from '../common/get-subdomain';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
export const getCandidate = createAction({
auth: workableAuth,
name: 'getCandidate',
displayName: 'Get Candidate',
description: "Gets candidate's information.",
props: {
id: Property.ShortText({
displayName: "Candidate's Id",
required: true
})
},
async run(context) {
// Action logic here
const candidateId = context.propsValue.id;
const accessToken = context.auth.secret_text;
const account = await getAccountSubdomain(accessToken);
//get candidate information
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: `https://${account}.workable.com/spi/v3/candidates/${candidateId}`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
},
});
return response.body;
},
});

View File

@@ -0,0 +1,39 @@
import { workableAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { getAccountSubdomain } from '../common/get-subdomain';
export const getJob = createAction({
auth: workableAuth,
name: 'getJob',
displayName: 'Get Job',
description: 'Gets specific job deatils.',
props: {
shortcode: Property.ShortText({
displayName: "Shortcode",
description: "Shortcode of specific job",
required: true
})
},
async run(context) {
// Action logic here
const shortcode = context.propsValue?.shortcode;
const accessToken = context.auth.secret_text;
// get account subdomain
const account = await getAccountSubdomain(accessToken);
const url = `https://${account}.workable.com/spi/v3/jobs/${shortcode}`;
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: url,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
},
});
return response.body;
},
});

View File

@@ -0,0 +1,79 @@
import { workableAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { getAccountSubdomain } from '../common/get-subdomain';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
export const getMembers = createAction({
auth: workableAuth,
name: 'getMembers',
displayName: 'Get Members',
description: 'Gets members of hiring team.',
props: {
limit: Property.Number({
displayName: "Limit",
description: "Default is 50",
required: false
}),
role: Property.ShortText({
displayName: "Role",
description: "Filter for member of specified role",
required: false
}),
shortcode: Property.ShortText({
displayName: "Shortcode",
description: "Shortcode of specific job",
required: false
}),
email: Property.ShortText({
displayName: "Member's email",
description: "Filter for specific member by email",
required: false
}),
name: Property.ShortText({
displayName: "Member's name",
description: "Filter for members of specified name (Exact Match)",
required: false
}),
},
async run(context) {
// Action logic here
const limit = context.propsValue['limit'];
const role = context.propsValue['role'];
const shortcode = context.propsValue['shortcode'];
const email = context.propsValue['email'];
const name = context.propsValue['name'];
const accessToken = context.auth.secret_text;
const queryParams: Record<string, any> = {};
if(limit !== undefined && limit !== null) {
queryParams["limit"] = limit;
}
if(role && role.trim() !== ''){
queryParams["role"] = role;
}
if(shortcode && shortcode.trim() !== ""){
queryParams["shortcode"] = shortcode;
}
if(email && email.trim() !== ""){
queryParams["email"] = email;
}
if(name && name.trim() !== ''){
queryParams["name"] = name;
}
const subdomain = await getAccountSubdomain(accessToken);
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: `https://${subdomain}.workable.com/spi/v3/members`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
},
queryParams
})
return response.body;
},
});

View File

@@ -0,0 +1,35 @@
import { workableAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { getAccountSubdomain } from '../common/get-subdomain';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
export const getStages = createAction({
auth: workableAuth,
name: 'getStages',
displayName: 'Get Stages',
description: 'Gets stages in your recruitment pipeline stages.',
props: {
shortcode: Property.ShortText({
displayName: "Shortcode",
description: "Shortcode of specific job",
required: true
})
},
async run(context) {
// Action logic here
const shortcode = context.propsValue.shortcode;
const accessToken = context.auth.secret_text;
const account = await getAccountSubdomain(accessToken);
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: `https://${account}.workable.com/spi/v3/jobs/${shortcode}/stages`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
}
});
return response.body;
},
});

View File

@@ -0,0 +1,54 @@
import { workableAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { getAccountSubdomain } from '../common/get-subdomain';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
export const moveCandidate = createAction({
auth: workableAuth,
name: 'moveCandidate',
displayName: 'Move Candidate',
description: 'Moves candidate to the specified stage.',
props: {
id: Property.ShortText({
displayName: "Candidate's Id",
description: "Id of candidate",
required: true
}),
member_id: Property.ShortText({
displayName: "Member's Id",
description: "This person's Id is used to move the candidate to the next stage",
required: true
}),
target_stage: Property.ShortText({
displayName: "Target stage name",
description: "Slug of stage target should be moved to",
required: true
})
},
async run(context) {
// Action logic here
const id = context.propsValue.id;
const member_id = context.propsValue.member_id;
const target_stage = context.propsValue.target_stage;
const accessToken = context.auth.secret_text;
const subdomain = await getAccountSubdomain(accessToken);
const payload: Record<string, any> = {
member_id: member_id,
target_stage: target_stage
}
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `https://${subdomain}.workable.com/spi/v3/candidates/${id}/move`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
},
body: payload
})
return response;
},
});

View File

@@ -0,0 +1,76 @@
import { workableAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { getAccountSubdomain } from '../common/get-subdomain';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
export const rateCandidate = createAction({
auth: workableAuth,
name: 'rateCandidate',
displayName: 'Rate candidate',
description: 'Rates the candidate on workable.',
props: {
id: Property.ShortText({
displayName: "Candidate's Id",
description: "Id of candidate",
required: true
}),
member_id: Property.ShortText({
displayName: "Member's Id",
description: "Id of member that is adding the rating",
required: true
}),
comment: Property.LongText({
displayName: "Comment",
description: "Comment about the scoring of the candidate",
required: true
}),
scale: Property.StaticDropdown({
displayName: "Rating scale",
description: "Select scale to rate candidate on",
required: true,
options: {
options: [
{label: "Thumbs", value: "thumbs"},
{label: "Stars", value: "stars"},
{label: "Numbers", value: "numbers"}
]
}
}),
grade: Property.Number({
displayName: "Grade",
description: "Thumbs scale: 0-2, Stars scale: 0-4, Numbers scale: 0-9",
required: true
})
},
async run(context) {
// Action logic here
const id = context.propsValue.id;
const member_id = context.propsValue.member_id;
const comment = context.propsValue.comment;
const scale = context.propsValue.scale;
const grade = context.propsValue.grade;
const accessToken = context.auth.secret_text;
const subdomain = await getAccountSubdomain(accessToken);
const body: Record<string, any> = {
comment,
scale,
member_id,
grade
};
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `https://${subdomain}.workable.com/spi/v3/candidates/${id}/ratings`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
},
body: body
})
return response;
},
});

View File

@@ -0,0 +1,15 @@
import { httpClient, HttpMethod } from "@activepieces/pieces-common";
export async function getAccountSubdomain(accessToken: string){
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: "https://workable.com/spi/v3/accounts",
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json'
}
});
console.log("this is response" + response.body.accounts[0].subdomain);
return response.body.accounts[0]?.subdomain;
}

View File

@@ -0,0 +1,45 @@
import { HttpMethod, httpClient, HttpRequest} from '@activepieces/pieces-common';
export const workableCommon = {
subscribeWebhook: async (
subdomain: string,
accessToken: string,
webhookUrl: string,
event: string,
args: Record<string, any> = {}
) => {
const request: HttpRequest = {
method: HttpMethod.POST,
url: `https://${subdomain}.workable.com/spi/v3/subscriptions`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
},
body: {
target: webhookUrl,
event,
args,
}
};
const response = await httpClient.sendRequest<{id: string}>(request);
return response.body;
},
unsubscribeWebhook: async (
subdomain: string,
accessToken: string,
subscriptionId: string
) => {
const request: HttpRequest = {
method: HttpMethod.DELETE,
url: `https://${subdomain}.workable.com/spi/v3/subscriptions/${subscriptionId}`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json'
}
}
return await httpClient.sendRequest(request);
}
}

View File

@@ -0,0 +1,125 @@
import { workableAuth } from '../../index';
import { createTrigger, Property, TriggerStrategy, WebhookResponse } from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { getAccountSubdomain } from '../common/get-subdomain';
import { workableCommon } from '../common/webhooks';
interface WebhookInformation {
webhookId: string;
}
interface WorkableWebhookPayload {
data: any;
event_type: string;
fired_at: string;
id: string;
resource_type: string;
}
export const newCandidate = createTrigger({
auth: workableAuth,
name: 'newCandidate',
displayName: 'New Candidate',
description: 'Triggers when new candidate submits application. Can be filtered by specific job and/or hiring pipeline stage.',
props: {
shortcode: Property.ShortText({
displayName: "Shortcode",
description: "Shortcode of specific job. Leave empty to trigger for all jobs.",
required: false
}),
stage_slug: Property.ShortText({
displayName: "Stage Slug",
description: "Stage slug to filter by specific hiring pipeline stage (e.g., 'applied', 'phone_screen', 'interview', 'offer'). Leave empty to trigger for all stages.",
required: false
})
},
sampleData: {
id: '123',
name: 'John Doe',
firstname: 'John',
lastname: 'Doe',
headline: 'Software Engineer',
account: {
subdomain: 'example',
name: 'Example Inc.'
},
job: {
shortcode: 'ENG123',
title: 'Software Engineer'
},
stage: 'applied',
disqualified: false,
disqualification_reason: '',
sourced: false,
profile_url: 'https://example.workable.com/candidates/123',
email: 'john.doe@example.com',
domain: 'example.com',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context){
const accessToken = context.auth.secret_text;
const subdomain = await getAccountSubdomain(accessToken);
const shortcode = context.propsValue.shortcode || '';
const stageSlug = context.propsValue.stage_slug || '';
const webhookUrl = context.webhookUrl;
const event = "candidate_created";
const subscription = await workableCommon.subscribeWebhook(
subdomain,
accessToken,
webhookUrl,
event,
{job_shortcode: shortcode, stage_slug: stageSlug}
);
await context.store?.put<WebhookInformation>('_new_candidate_created', {
webhookId: subscription.id,
})
},
async onDisable(context){
// implement webhook deletion logic
const accessToken = context.auth.secret_text;
const webhookInfo = await context.store.get<WebhookInformation>('_new_candidate_created');
if(webhookInfo?.webhookId) {
const subdomain = await getAccountSubdomain(accessToken);
await workableCommon.unsubscribeWebhook(subdomain, accessToken, webhookInfo.webhookId);
}
},
async test(context){
const accessToken = context.auth.secret_text;
const subdomain = await getAccountSubdomain(accessToken);
const shortcode = context.propsValue.shortcode || '';
const stageSlug = context.propsValue.stage_slug || '';
const queryParams: any = {};
if (shortcode) {
queryParams.shortcode = shortcode;
}
if (stageSlug) {
queryParams.stage = stageSlug;
}
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: `https://${subdomain}.workable.com/spi/v3/candidates/`,
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
},
queryParams: queryParams
});
const candidates = response.body.candidates?.slice(0, 3) ?? [];
return candidates;
},
async run(context){
const payload = context.payload.body as WorkableWebhookPayload;
return [payload.data]
}
})

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