The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Agendamiento Epoxy con Sugerencia y Confirmaci\u00f3n",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "agendar"
},
"id": "1",
"name": "Webhook (Agendar)",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
250,
300
]
},
{
"parameters": {
"functionCode": "const fecha = new Date($json[\"fecha\"]);\n\n// Horarios permitidos\nconst rangos = [\n { inicio: 10 * 60, fin: 12 * 60 + 50 },\n { inicio: 17 * 60, fin: 20 * 60 }\n];\n\nconst dia = fecha.getDay();\nconst minutos = fecha.getHours() * 60 + fecha.getMinutes();\n\nlet valido = false;\nif (dia >= 1 && dia <= 5) {\n for (const r of rangos) {\n if (minutos >= r.inicio && minutos <= r.fin) {\n valido = true;\n break;\n }\n }\n}\n\nreturn [{\n valido,\n fecha: fecha.toISOString(),\n servicio: $json.servicio,\n nombre: $json.nombre,\n email: $json.email,\n aceptar: $json.aceptar || false\n}];"
},
"id": "2",
"name": "Validar Horario",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
500,
300
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{$json[\"valido\"]}}"
}
]
}
},
"id": "3",
"name": "\u00bfHorario v\u00e1lido?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
750,
300
]
},
{
"parameters": {
"calendar": "primary",
"options": {
"timeMin": "={{$json[\"fecha\"]}}",
"timeMax": "={{$json[\"fecha\"]}}"
}
},
"id": "4",
"name": "Google Calendar - Check Disponibilidad",
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1,
"position": [
1000,
200
],
"credentials": {
"googleCalendarOAuth2Api": "<your credential>"
}
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{$json[\"items\"].length}}",
"operation": "equal",
"value2": "0"
}
]
}
},
"id": "5",
"name": "\u00bfDisponible?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1250,
200
]
},
{
"parameters": {
"calendar": "primary",
"start": "={{$json[\"fecha\"]}}",
"end": "={{$json[\"fecha\"]}}",
"summary": "Cita Epoxy - {{$json[\"servicio\"]}}",
"description": "Cliente: {{$json[\"nombre\"]}} - Email: {{$json[\"email\"]}}"
},
"id": "6",
"name": "Google Calendar - Crear Evento",
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1,
"position": [
1500,
100
],
"credentials": {
"googleCalendarOAuth2Api": "<your credential>"
}
},
{
"parameters": {
"statusCode": 200,
"responseBody": "={{{\"status\": \"ok\", \"mensaje\": \"Cita confirmada para el \" + $json[\"fecha\"]}}}"
},
"id": "7",
"name": "Responder OK",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1750,
100
]
},
{
"parameters": {
"functionCode": "function siguienteFranja(fecha) {\n const rangos = [\n { inicio: 10 * 60, fin: 12 * 60 + 50 },\n { inicio: 17 * 60, fin: 20 * 60 }\n ];\n\n let d = new Date(fecha);\n\n for (let i = 0; i < 30; i++) {\n const dia = d.getDay();\n if (dia >= 1 && dia <= 5) {\n for (const r of rangos) {\n const inicio = new Date(d);\n inicio.setHours(Math.floor(r.inicio/60), r.inicio%60, 0);\n if (inicio > fecha) {\n return inicio.toISOString();\n }\n }\n }\n d.setDate(d.getDate() + 1);\n d.setHours(10, 0, 0);\n }\n return null;\n}\n\nconst fecha = new Date($json[\"fecha\"]);\nconst sugerida = siguienteFranja(fecha);\n\nreturn [{\n fecha: $json[\"fecha\"],\n sugerida,\n servicio: $json[\"servicio\"],\n nombre: $json[\"nombre\"],\n email: $json[\"email\"],\n aceptar: $json[\"aceptar\"] || false\n}];"
},
"id": "8",
"name": "Calcular Siguiente Franja",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
1500,
300
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{$json[\"aceptar\"]}}"
}
]
}
},
"id": "9",
"name": "\u00bfAcepta sugerida?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1750,
300
]
},
{
"parameters": {
"calendar": "primary",
"start": "={{$json[\"sugerida\"]}}",
"end": "={{$json[\"sugerida\"]}}",
"summary": "Cita Epoxy - {{$json[\"servicio\"]}}",
"description": "Cliente: {{$json[\"nombre\"]}} - Email: {{$json[\"email\"]}}"
},
"id": "10",
"name": "Google Calendar - Crear Evento (Sugerida)",
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1,
"position": [
2000,
200
],
"credentials": {
"googleCalendarOAuth2Api": "<your credential>"
}
},
{
"parameters": {
"statusCode": 200,
"responseBody": "={{{\"status\": \"ok\", \"mensaje\": \"Cita confirmada en nueva fecha: \" + $json[\"sugerida\"]}}}"
},
"id": "11",
"name": "Responder OK (Sugerida)",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
2250,
200
]
},
{
"parameters": {
"statusCode": 409,
"responseBody": "={{{\"status\": \"ocupado\", \"mensaje\": \"La fecha no est\u00e1 disponible. Pr\u00f3xima sugerencia: \" + $json[\"sugerida\"], \"sugerida\": $json[\"sugerida\"]}}}"
},
"id": "12",
"name": "Responder con Sugerencia",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
2000,
400
]
},
{
"parameters": {
"statusCode": 400,
"responseBody": "={{{\"status\": \"invalido\", \"mensaje\": \"El horario solicitado no es v\u00e1lido. Debe ser Lunes-Viernes 10:00\u201312:50 o 17:00\u201320:00.\"}}}"
},
"id": "13",
"name": "Responder Horario Inv\u00e1lido",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1000,
400
]
}
],
"connections": {
"Webhook (Agendar)": {
"main": [
[
{
"node": "Validar Horario",
"type": "main",
"index": 0
}
]
]
},
"Validar Horario": {
"main": [
[
{
"node": "\u00bfHorario v\u00e1lido?",
"type": "main",
"index": 0
}
]
]
},
"\u00bfHorario v\u00e1lido?": {
"main": [
[
{
"node": "Google Calendar - Check Disponibilidad",
"type": "main",
"index": 0
}
],
[
{
"node": "Responder Horario Inv\u00e1lido",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar - Check Disponibilidad": {
"main": [
[
{
"node": "\u00bfDisponible?",
"type": "main",
"index": 0
}
]
]
},
"\u00bfDisponible?": {
"main": [
[
{
"node": "Google Calendar - Crear Evento",
"type": "main",
"index": 0
}
],
[
{
"node": "Calcular Siguiente Franja",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar - Crear Evento": {
"main": [
[
{
"node": "Responder OK",
"type": "main",
"index": 0
}
]
]
},
"Calcular Siguiente Franja": {
"main": [
[
{
"node": "\u00bfAcepta sugerida?",
"type": "main",
"index": 0
}
]
]
},
"\u00bfAcepta sugerida?": {
"main": [
[
{
"node": "Google Calendar - Crear Evento (Sugerida)",
"type": "main",
"index": 0
}
],
[
{
"node": "Responder con Sugerencia",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar - Crear Evento (Sugerida)": {
"main": [
[
{
"node": "Responder OK (Sugerida)",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleCalendarOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Agendamiento Epoxy con Sugerencia y Confirmación. Uses googleCalendar. Webhook trigger; 13 nodes.
Source: https://gist.github.com/beleiromeoasistencia-cloud/1c2d4541c227c6aadc30a0f384dea2c3 — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Blotato-Api. Uses @blotato/n8n-nodes-blotato. Webhook trigger; 53 nodes.
Community Node Disclaimer: This workflow uses KlickTipp community nodes.
Social Media Poster - Dual Trigger. Uses @blotato/n8n-nodes-blotato. Webhook trigger; 23 nodes.
Odoo Customers API – Export to JSON or Excel provides a simple way to fetch customer records from your Odoo database and get them back either as a structured JSON response or a downloadable Excel (.xl
Bridge the gap between Monday.com and Jira with this intelligent n8n automation template.