Sincronización de tiempo de vacaciones de Everhour
Este es unHRflujo de automatización del dominio deautomatización que contiene 23 nodos.Utiliza principalmente nodos como If, Set, Code, HttpRequest, GoogleCalendar. Sincronización automática de tiempo de vacaciones de Everhour a eventos de todo el día en Google Calendar
- •Pueden requerirse credenciales de autenticación para la API de destino
Nodos utilizados (23)
Categoría
{
"id": "atCSLFdL7AyLdjJD",
"meta": {
"instanceId": "ed54b493f1b983b9b64b327a27338be1695af08f90b0f5fff3b6d18c570c4fc2"
},
"name": "Everhour Time Off",
"tags": [],
"nodes": [
{
"id": "fe08e8fe-779b-4428-8060-08da88a61118",
"name": "Disparador Programado",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1856,
384
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "8082b4f8-5ff0-4af3-ac3f-268cdd8bee97",
"name": "Construir Grupos de Asignación",
"type": "n8n-nodes-base.code",
"position": [
-656,
576
],
"parameters": {
"jsCode": "// Input: per-day items from Edit Fields (each has externalKey, startDate, endDateExclusive)\n// Output: one item per assignmentId with the set of current keys and a search window\n\nconst groups = {}; // { [assignmentId]: { currentKeys:Set, minDate, maxDate } }\n\nfor (const it of items) {\n const j = it.json;\n const parts = (j.externalKey || '').split(':'); // [\"everhour\", \"<id>\", \"<date>\"]\n const assignmentId = parts[1];\n if (!assignmentId) continue;\n\n if (!groups[assignmentId]) {\n groups[assignmentId] = {\n assignmentId,\n currentKeys: new Set(),\n minDate: j.startDate,\n maxDate: j.endDateExclusive\n };\n }\n groups[assignmentId].currentKeys.add(j.externalKey);\n if (j.startDate < groups[assignmentId].minDate) groups[assignmentId].minDate = j.startDate;\n if (j.endDateExclusive > groups[assignmentId].maxDate) groups[assignmentId].maxDate = j.endDateExclusive;\n}\n\n// Emit one item per assignment, with a small buffer on the search window (optional)\nconst out = [];\nfor (const id of Object.keys(groups)) {\n const g = groups[id];\n out.push({\n json: {\n assignmentId: id,\n currentKeys: Array.from(g.currentKeys),\n searchTimeMin: g.minDate + 'T00:00:00',\n searchTimeMax: g.maxDate + 'T23:59:59'\n }\n });\n}\nreturn out;\n"
},
"typeVersion": 2
},
{
"id": "f210fb86-0d78-4140-adff-0573566b23ac",
"name": "Construir Conjunto de Claves Global",
"type": "n8n-nodes-base.code",
"position": [
-656,
768
],
"parameters": {
"jsCode": "// Build the set of keys we SHOULD have right now\nlet minDate = null, maxDate = null;\nconst keys = new Set();\n\nfor (const it of items) {\n const j = it.json;\n if (j.externalKey) keys.add(j.externalKey);\n if (j.startDate && (!minDate || j.startDate < minDate)) minDate = j.startDate;\n if (j.endDateExclusive && (!maxDate || j.endDateExclusive > maxDate)) maxDate = j.endDateExclusive;\n}\n\n// Reasonable window (optional). Broaden if you want.\nif (!minDate) minDate = new Date().toISOString().slice(0,10);\nif (!maxDate) {\n const d = new Date(); d.setFullYear(d.getFullYear() + 1);\n maxDate = d.toISOString().slice(0,10);\n}\n\nreturn [{\n json: {\n currentKeys: Array.from(keys),\n searchTimeMin: minDate + 'T00:00:00',\n searchTimeMax: maxDate + 'T23:59:59'\n }\n}];\n"
},
"typeVersion": 2
},
{
"id": "c76c87dc-876c-46f0-ac7e-a4a15ac3661c",
"name": "Everhour - Obtener Tiempo Libre",
"type": "n8n-nodes-base.httpRequest",
"notes": "Uses Header Auth credential (add `X-Api-Key`). No hardcoded keys.",
"position": [
-1568,
384
],
"parameters": {
"url": "https://api.everhour.com/resource-planner/assignments",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"notesInFlow": true,
"typeVersion": 4.2
},
{
"id": "92a16e7c-bb00-439f-b819-6b7557ff5017",
"name": "Filtrar Tiempo Libre Aprobado",
"type": "n8n-nodes-base.if",
"position": [
-1344,
384
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9e28789f-61a6-4fcb-b132-294825f6ea39",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "approved"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "c20edb41-1400-4f8d-a90e-c61bda0295c7",
"name": "Construir Carga Útil de Calendario",
"type": "n8n-nodes-base.set",
"position": [
-896,
384
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a7cb20ad-8a14-4252-9bb2-499db02852cd",
"name": "=searchQuery",
"type": "string",
"value": "={{ $json.externalKey }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "5fe3aab5-3136-4619-8857-96e53578adbd",
"name": "Preparar Elementos de Tiempo Libre",
"type": "n8n-nodes-base.code",
"position": [
-1120,
384
],
"parameters": {
"jsCode": "// All time-off (including half-day) → keep creating as ALL-DAY events,\n// but also expose `isAllDay` based on Everhour's original period.\n\nfunction* eachDateInclusive(startStr, endStr, includeWeekends) {\n const start = new Date(startStr + 'T00:00:00');\n const end = new Date(endStr + 'T00:00:00');\n for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {\n const dow = d.getDay(); // 0=Sun .. 6=Sat\n if (!includeWeekends && (dow === 0 || dow === 6)) continue;\n yield new Date(d);\n }\n}\nfunction fmtDate(d){ return d.toISOString().slice(0,10); }\n\nconst out = [];\nfor (const item of items) {\n const r = item.json;\n if ((r.status || '').toLowerCase() !== 'approved') continue;\n if (r.type !== 'time-off') continue;\n\n const userName = r.user?.name || 'Unknown';\n const userEmail = r.user?.email || '';\n const startDate = r.startDate;\n const endDate = r.endDate || r.startDate;\n const includeWeekends = !!r.includeWeekends;\n const period = r.timeOffPeriod || 'full-day'; // 'full-day' | 'half-of-day'\n const type = r.timeOffType?.name || 'Time Off';\n const note = r.note || '';\n const id = r.id;\n\n // Derive the original \"isAllDay\" from Everhour's period (without changing mapping)\n const isAllDayOriginal = (period !== 'half-of-day');\n\n // Expand per-day; skip weekends if flag=false\n for (const d of eachDateInclusive(startDate, endDate, includeWeekends)) {\n const day = fmtDate(d);\n\n // All-day mapping (end date exclusive)\n const endObj = new Date(d);\n endObj.setDate(endObj.getDate() + 1);\n const endExclusive = fmtDate(endObj);\n\n out.push({\n json: {\n // You are still creating ALL-DAY events\n isAllDay: isAllDayOriginal, // <-- added (reflects original Everhour period)\n startDate: day,\n endDateExclusive: endExclusive,\n\n employeeName: userName,\n employeeEmail: userEmail,\n type,\n note,\n status: r.status,\n\n // unique key per assignment-day\n externalKey: `everhour:${id}:${day}`,\n\n // keep for debugging/visibility\n originalPeriod: period\n }\n });\n }\n}\nreturn out;\n"
},
"typeVersion": 2
},
{
"id": "11e26f03-b016-445a-99b1-72b9e5b8c0c3",
"name": "Buscar Evento Existente por Clave Externa",
"type": "n8n-nodes-base.httpRequest",
"position": [
-672,
96
],
"parameters": {
"url": "={{ 'https://www.googleapis.com/calendar/v3/calendars/' + $items(\"Config\")[0].json.calendarId + '/events' }}",
"options": {},
"sendQuery": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "singleEvents",
"value": "true"
},
{
"name": "maxResults",
"value": "1"
},
{
"name": "=q",
"value": "={{ $json.externalKey }}"
}
]
},
"nodeCredentialType": "googleApi"
},
"typeVersion": 4.2
},
{
"id": "929dc366-f019-435e-88ed-9d1807ac70da",
"name": "Adjuntar ID de Evento Encontrado",
"type": "n8n-nodes-base.code",
"position": [
-448,
96
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// This Function is in \"Run Once for Each Item\" mode.\n// $json here is the HTTP search response for THIS PTO item.\n\nconst ev = Array.isArray($json.items) ? $json.items[0] : null;\n\n// IMPORTANT: use the current index, not 0\nconst i = $itemIndex;\nconst src = $items(\"Build Calendar Payload\")[i].json;\n\nreturn {\n json: {\n ...src, // keep your PTO fields for THIS item\n existingEventId: ev ? ev.id : null, // id if found\n found: !!ev // boolean for IF node\n }\n};\n"
},
"typeVersion": 2
},
{
"id": "b05c97db-3810-4847-8a24-b81a824894ab",
"name": "Verificar si el Evento Existe",
"type": "n8n-nodes-base.if",
"position": [
-224,
96
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "59967d64-2b86-4c86-a653-45adec8fba72",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.found }}",
"rightValue": "true"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "1c3a725d-775e-452b-9567-b00f2a3181b2",
"name": "Actualizar Evento de Día Completo",
"type": "n8n-nodes-base.googleCalendar",
"notes": "Calendar ID pulled from the Config node: `$items(\"Config\")[0].json.calendarId`.",
"position": [
0,
0
],
"parameters": {
"eventId": "={{ $json.existingEventId }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "={{ $items(\"Config\")[0].json.calendarId }}"
},
"operation": "update",
"updateFields": {
"end": "={{ $json.endDateExclusive }}",
"start": "={{ $json.startDate }}",
"allday": "yes",
"summary": "={{ $json.employeeName }} - {{ $json.type }}",
"description": "=Everhour PTO\nKey: {{$json.externalKey}}\nType: {{$json.type}}\nStatus: {{$json.status}}\nNote: {{$json.note}}\n"
}
},
"notesInFlow": true,
"typeVersion": 1.3
},
{
"id": "ba91bdf7-b56a-4f61-adc3-ef1a016ebde6",
"name": "Crear Evento de Día Completo",
"type": "n8n-nodes-base.googleCalendar",
"notes": "Calendar ID pulled from the Config node: `$items(\"Config\")[0].json.calendarId`.",
"position": [
0,
192
],
"parameters": {
"end": "={{ $json.endDateExclusive }}",
"start": "={{ $json.startDate }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "={{ $items(\"Config\")[0].json.calendarId }}"
},
"additionalFields": {
"allday": "yes",
"summary": "={{ $json.employeeName }} - {{ $json.type }}",
"description": "=Everhour PTO\nKey: {{$json.externalKey}}\nType: {{$json.type}}\nStatus: {{$json.status}}\nNote: {{$json.note}}\n"
}
},
"notesInFlow": true,
"typeVersion": 1.3
},
{
"id": "2d4aeb2e-742d-499c-9e94-8a8be2c5c9d6",
"name": "Listar Eventos de Asignación",
"type": "n8n-nodes-base.httpRequest",
"notes": "Calendar ID pulled from the Config node: `$items(\"Config\")[0].json.calendarId`.",
"position": [
-432,
576
],
"parameters": {
"url": "={{ 'https://www.googleapis.com/calendar/v3/calendars/' + $items(\"Config\")[0].json.calendarId + '/events' }}",
"options": {},
"sendQuery": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "singleEvents",
"value": "true"
},
{
"name": "maxResults",
"value": "2500"
},
{
"name": "orderBy",
"value": "startTime"
},
{
"name": "q",
"value": "={{ 'everhour:' + $json.assignmentId + ':' }}"
}
]
},
"nodeCredentialType": "googleApi"
},
"notesInFlow": true,
"typeVersion": 4.2
},
{
"id": "cca57225-aef9-4426-9d21-816e8a882ab9",
"name": "Buscar Eventos Obsoletos (por asignación)",
"type": "n8n-nodes-base.code",
"position": [
-208,
576
],
"parameters": {
"jsCode": "// Run Once for ALL Items\n// Pair each HTTP Request2 result (events for an assignment) with the matching group from Code2\n\nconst groups = $items(\"Build Assignment Groups\").map(it => it.json); // <-- node name must match exactly\nconst out = [];\n\nfor (let i = 0; i < items.length; i++) {\n const group = groups[i];\n if (!group) continue;\n\n const current = new Set(group.currentKeys);\n const apiItems = Array.isArray(items[i].json.items) ? items[i].json.items : [];\n\n for (const ev of apiItems) {\n const desc = ev.description || \"\";\n const m = desc.match(/Key:\\s*(everhour:[^\\s]+)/i); // \"Key: everhour:<id>:<date>\"\n if (!m) continue;\n const key = m[1];\n\n if (!current.has(key)) {\n out.push({\n json: { eventId: ev.id, key, assignmentId: group.assignmentId }\n });\n }\n }\n}\n\nreturn out; // one item per stale event to delete\n"
},
"typeVersion": 2
},
{
"id": "acf5aa87-0784-4633-a127-0cae6a069bf8",
"name": "Eliminar Evento de Calendario",
"type": "n8n-nodes-base.googleCalendar",
"notes": "Calendar ID pulled from the Config node: `$items(\"Config\")[0].json.calendarId`.",
"position": [
16,
672
],
"parameters": {
"eventId": "={{ $json.eventId }}",
"options": {
"sendUpdates": "none"
},
"calendar": {
"__rl": true,
"mode": "list",
"value": "={{ $items(\"Config\")[0].json.calendarId }}"
},
"operation": "delete"
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 1.3
},
{
"id": "6c4c4f1e-7772-41f7-9ef9-22936167b523",
"name": "Listar Todos los Eventos de Everhour",
"type": "n8n-nodes-base.httpRequest",
"notes": "Calendar ID pulled from the Config node: `$items(\"Config\")[0].json.calendarId`.",
"position": [
-432,
768
],
"parameters": {
"url": "={{ 'https://www.googleapis.com/calendar/v3/calendars/' + $items(\"Config\")[0].json.calendarId + '/events' }}",
"options": {},
"sendQuery": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "singleEvents",
"value": "true"
},
{
"name": "maxResults",
"value": "2500"
},
{
"name": "orderBy",
"value": "startTime"
},
{
"name": "q",
"value": "everhour:"
}
]
},
"nodeCredentialType": "googleApi"
},
"notesInFlow": true,
"typeVersion": 4.2
},
{
"id": "6651bc72-0b3d-4fe3-99cd-e1ff5a092da0",
"name": "Buscar Eventos Obsoletos (global)",
"type": "n8n-nodes-base.code",
"position": [
-208,
768
],
"parameters": {
"jsCode": "// Run Once for ALL Items\n// Compare calendar events (items[0].json.items) vs currentKeys from \"Build global key set\"\n\nconst current = new Set($items(\"Build Global Key Set\")[0].json.currentKeys);\nconst evs = Array.isArray(items[0].json.items) ? items[0].json.items : [];\nconst out = [];\n\nfor (const ev of evs) {\n const desc = ev.description || \"\";\n const m = desc.match(/Key:\\s*(everhour:[^\\s]+)/i); // extracts \"everhour:<id>:<date>\"\n if (!m) continue;\n const key = m[1];\n if (!current.has(key)) {\n out.push({ json: { eventId: ev.id, key }});\n }\n}\nreturn out; // one item per stale event to delete\n"
},
"typeVersion": 2
},
{
"id": "ac73d08e-3e0b-416f-8ec9-89b11e4c3a25",
"name": "Configuración",
"type": "n8n-nodes-base.set",
"notes": "Set your Google Calendar ID here. Example: team-calendar@group.calendar.google.com",
"position": [
-1856,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "0b59d6f6-4e28-4f6d-a4ad-0cb253b9a65f",
"name": "calendarId",
"type": "string",
"value": "REPLACE_WITH_YOUR_CALENDAR_ID@group.calendar.google.com"
}
]
},
"includeOtherFields": true
},
"notesInFlow": true,
"typeVersion": 3.4,
"alwaysOutputData": true
},
{
"id": "9bde197a-7009-41d3-ac7e-6b86ccdd2863",
"name": "🗒️ Descripción de Plantilla (Léame)",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2960,
160
],
"parameters": {
"color": null,
"width": 1024,
"height": 736,
"content": "## Everhour time-off sync to Google Calendar\n\n### Who’s it for\nTeams using **Everhour** for time tracking and **Google Calendar** for visibility.\n\n### What it does\n- Fetches **approved time-off** from Everhour\n- Creates/updates **all-day events** per day of absence\n- Deletes **stale events** if requests change or are canceled\n\n### How it works\n1. **Schedule Trigger** runs on an interval.\n2. Fetch Everhour assignments via API (Header Auth — set your Everhour API key in n8n credentials).\n3. Filter to **approved** time-off.\n4. Create/update events keyed by `everhour:<assignmentId>:<YYYY-MM-DD>`.\n5. Remove obsolete calendar events by comparing current keys with what’s on the calendar.\n\n### Setup\n- Create Everhour **Header Auth** credential: `X-Api-Key: <YOUR_EVERHOUR_API_KEY>`.\n- Add your **Google Calendar** OAuth credential to Calendar nodes.\n- In the **Config** node, set `calendarId` (e.g., `team@group.calendar.google.com`).\n\n### Customize\n- Change schedule cadence.\n- Filter by users/time-off types.\n- Adjust event title/description template.\n"
},
"typeVersion": 1
},
{
"id": "3dbeed2f-b8db-493e-ac9f-32b393008668",
"name": "Nota: Obtener Everhour",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
240
],
"parameters": {
"color": 7,
"height": 336,
"content": "## **Fetch Everhour**\n\nFetch approved time-off from Everhour using Header Auth (no keys in node)."
},
"typeVersion": 1
},
{
"id": "a595b36f-b23f-4356-85ce-2da5a0758d03",
"name": "Nota: Construir Claves",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1168,
256
],
"parameters": {
"color": 7,
"width": 416,
"height": 336,
"content": "## **Build Keys**\n\nGenerate per-day `externalKey` like `everhour:<id>:<date>`."
},
"typeVersion": 1
},
{
"id": "b028f58c-bb85-4894-a274-a099a4ea92ec",
"name": "Nota: Upsertar Eventos",
"type": "n8n-nodes-base.stickyNote",
"position": [
-720,
-112
],
"parameters": {
"color": 7,
"width": 976,
"height": 512,
"content": "## **Upsert Events**\n\nSearch by key → update if found, otherwise create all-day event."
},
"typeVersion": 1
},
{
"id": "921f878d-1014-4018-995c-bac11224961a",
"name": "Nota: Limpieza",
"type": "n8n-nodes-base.stickyNote",
"position": [
-704,
432
],
"parameters": {
"color": 7,
"width": 960,
"height": 528,
"content": "## **Cleanup**\n\nList events and delete those not present in current keys."
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "13a31a87-6b2e-4e1d-9f14-0f8a350b0d78",
"connections": {
"fe08e8fe-779b-4428-8060-08da88a61118": {
"main": [
[
{
"node": "c76c87dc-876c-46f0-ac7e-a4a15ac3661c",
"type": "main",
"index": 0
},
{
"node": "ac73d08e-3e0b-416f-8ec9-89b11e4c3a25",
"type": "main",
"index": 0
}
]
]
},
"f210fb86-0d78-4140-adff-0573566b23ac": {
"main": [
[
{
"node": "6c4c4f1e-7772-41f7-9ef9-22936167b523",
"type": "main",
"index": 0
}
]
]
},
"929dc366-f019-435e-88ed-9d1807ac70da": {
"main": [
[
{
"node": "b05c97db-3810-4847-8a24-b81a824894ab",
"type": "main",
"index": 0
}
]
]
},
"b05c97db-3810-4847-8a24-b81a824894ab": {
"main": [
[
{
"node": "1c3a725d-775e-452b-9567-b00f2a3181b2",
"type": "main",
"index": 0
}
],
[
{
"node": "ba91bdf7-b56a-4f61-adc3-ef1a016ebde6",
"type": "main",
"index": 0
}
]
]
},
"c20edb41-1400-4f8d-a90e-c61bda0295c7": {
"main": [
[
{
"node": "11e26f03-b016-445a-99b1-72b9e5b8c0c3",
"type": "main",
"index": 0
},
{
"node": "8082b4f8-5ff0-4af3-ac3f-268cdd8bee97",
"type": "main",
"index": 0
},
{
"node": "f210fb86-0d78-4140-adff-0573566b23ac",
"type": "main",
"index": 0
}
]
]
},
"2d4aeb2e-742d-499c-9e94-8a8be2c5c9d6": {
"main": [
[
{
"node": "cca57225-aef9-4426-9d21-816e8a882ab9",
"type": "main",
"index": 0
}
]
]
},
"5fe3aab5-3136-4619-8857-96e53578adbd": {
"main": [
[
{
"node": "c20edb41-1400-4f8d-a90e-c61bda0295c7",
"type": "main",
"index": 0
}
]
]
},
"8082b4f8-5ff0-4af3-ac3f-268cdd8bee97": {
"main": [
[
{
"node": "2d4aeb2e-742d-499c-9e94-8a8be2c5c9d6",
"type": "main",
"index": 0
}
]
]
},
"92a16e7c-bb00-439f-b819-6b7557ff5017": {
"main": [
[
{
"node": "5fe3aab5-3136-4619-8857-96e53578adbd",
"type": "main",
"index": 0
}
]
]
},
"6c4c4f1e-7772-41f7-9ef9-22936167b523": {
"main": [
[
{
"node": "6651bc72-0b3d-4fe3-99cd-e1ff5a092da0",
"type": "main",
"index": 0
}
]
]
},
"c76c87dc-876c-46f0-ac7e-a4a15ac3661c": {
"main": [
[
{
"node": "92a16e7c-bb00-439f-b819-6b7557ff5017",
"type": "main",
"index": 0
}
]
]
},
"6651bc72-0b3d-4fe3-99cd-e1ff5a092da0": {
"main": [
[
{
"node": "acf5aa87-0784-4633-a127-0cae6a069bf8",
"type": "main",
"index": 0
}
]
]
},
"11e26f03-b016-445a-99b1-72b9e5b8c0c3": {
"main": [
[
{
"node": "929dc366-f019-435e-88ed-9d1807ac70da",
"type": "main",
"index": 0
}
]
]
},
"cca57225-aef9-4426-9d21-816e8a882ab9": {
"main": [
[
{
"node": "acf5aa87-0784-4633-a127-0cae6a069bf8",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Avanzado - Recursos Humanos
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
Compartir este flujo de trabajo