AutomationFlowsWeb Scraping › Rodopi Dent - Calendar Create Event

Rodopi Dent - Calendar Create Event

Rodopi Dent - Calendar Create Event. Uses googleCalendar, httpRequest. Webhook trigger; 6 nodes.

Webhook trigger★★★★☆ complexity6 nodesGoogle CalendarHTTP Request
Web Scraping Trigger: Webhook Nodes: 6 Complexity: ★★★★☆ Added:

This workflow follows the Google Calendar → HTTP Request recipe pattern — see all workflows that pair these two integrations.

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 →

Download .json
{
  "name": "Rodopi Dent - Calendar Create Event",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "calendar-create",
        "responseMode": "responseNode",
        "options": {
          "allowedOrigins": "*"
        }
      },
      "id": "webhook",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Parse and validate input\nconst body = $input.first().json.body;\n\n// Support both patientName and title for blocking\nconst eventTitle = body.title || body.patientName;\n\n// Required fields\nif (!eventTitle) {\n  throw new Error('\u0418\u043c\u0435 \u043d\u0430 \u043f\u0430\u0446\u0438\u0435\u043d\u0442 \u0438\u043b\u0438 \u0437\u0430\u0433\u043b\u0430\u0432\u0438\u0435 \u0435 \u0437\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u043e');\n}\nif (!body.date) {\n  throw new Error('\u0414\u0430\u0442\u0430 \u0435 \u0437\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u0430');\n}\nif (!body.startTime) {\n  throw new Error('\u041d\u0430\u0447\u0430\u043b\u0435\u043d \u0447\u0430\u0441 \u0435 \u0437\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u0435\u043d');\n}\n\n// Calculate end time based on duration or endTime\nlet endTime;\nif (body.endTime) {\n  endTime = body.endTime;\n} else {\n  const duration = body.duration || 30; // Default 30 minutes\n  const [hours, minutes] = body.startTime.split(':').map(Number);\n  const startDate = new Date(`${body.date}T${body.startTime}:00`);\n  const endDate = new Date(startDate.getTime() + duration * 60 * 1000);\n  endTime = `${String(endDate.getHours()).padStart(2, '0')}:${String(endDate.getMinutes()).padStart(2, '0')}`;\n}\n\n// Appointment status handling\nconst statusVal = body.status || 'confirmed';\nconst statusLabels = { 'pending': '\u0427\u0430\u043a\u0430\u0449', 'confirmed': '\u041f\u043e\u0442\u0432\u044a\u0440\u0434\u0435\u043d', 'completed': '\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d' };\nconst statusLabel = statusLabels[statusVal] || '\u041f\u043e\u0442\u0432\u044a\u0440\u0434\u0435\u043d';\n\n// Build summary - add \u23f3 prefix for pending\nlet summary = eventTitle;\nif (statusVal === 'pending') {\n  summary = '\u23f3 ' + eventTitle;\n}\n\n// Build description with structured data\nlet description = '';\nif (body.patientPhone) {\n  description += `\ud83d\udcde \u0422\u0435\u043b: ${body.patientPhone}\\n`;\n}\nif (body.procedure) {\n  description += `\ud83e\uddb7 \u041f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430: ${body.procedure}\\n`;\n}\ndescription += `\ud83d\udccb \u0421\u0442\u0430\u0442\u0443\u0441: ${statusLabel}\\n`;\nif (body.notes) {\n  description += `\ud83d\udcdd \u0411\u0435\u043b\u0435\u0436\u043a\u0438: ${body.notes}\\n`;\n}\n\n// Map color names to Google Calendar colorId (1-11)\nconst colorMap = {\n  'green': '10',    // Basil (green)\n  'blue': '9',      // Blueberry (blue)\n  'red': '11',      // Tomato (red)\n  'yellow': '5',    // Banana (yellow)\n  'purple': '3',    // Grape (purple)\n  'orange': '6',    // Tangerine (orange)\n  'pink': '4',      // Flamingo (pink)\n  'gray': '8'       // Graphite (gray)\n};\n// Status-based default colors: pending=yellow, completed=gray, confirmed=green\nconst statusColorDefaults = { 'pending': 'yellow', 'completed': 'gray', 'confirmed': 'green' };\nconst effectiveColor = body.colorId || statusColorDefaults[statusVal] || 'green';\nconst googleColorId = colorMap[effectiveColor] || colorMap['green'];\n\nreturn [{\n  json: {\n    summary: summary,\n    description: description.trim(),\n    startDateTime: `${body.date}T${body.startTime}:00`,\n    endDateTime: `${body.date}T${endTime}:00`,\n    date: body.date,\n    duration: body.duration || 30,\n    patientName: body.patientName || eventTitle,\n    patientPhone: body.patientPhone || '',\n    procedure: body.procedure || '',\n    status: statusVal,\n    colorId: googleColorId\n  }\n}];"
      },
      "id": "prepare",
      "name": "Prepare Event Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "operation": "create",
        "calendar": {
          "__rl": true,
          "mode": "id",
          "value": "rodopi.dent@gmail.com"
        },
        "start": "={{ $json.startDateTime }}",
        "end": "={{ $json.endDateTime }}",
        "additionalFields": {
          "summary": "={{ $json.summary }}",
          "description": "={{ $json.description }}",
          "sendUpdates": "all",
          "colorId": "={{ $json.colorId || '' }}"
        }
      },
      "id": "create-event",
      "name": "Create Calendar Event",
      "type": "n8n-nodes-base.googleCalendar",
      "typeVersion": 1.2,
      "position": [
        440,
        0
      ],
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Get created event details\nconst event = $input.first().json;\nconst prevData = $('Prepare Event Data').first().json;\n\nreturn [{\n  json: {\n    id: event.id,\n    googleEventId: event.id,\n    title: event.summary,\n    patientName: prevData.patientName,\n    patientPhone: prevData.patientPhone,\n    procedure: prevData.procedure,\n    date: prevData.date,\n    duration: prevData.duration,\n    status: prevData.status || 'confirmed',\n    htmlLink: event.htmlLink,\n    created: event.created,\n    updated: event.updated\n  }\n}];"
      },
      "id": "format-response",
      "name": "Format Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, message: '\u0421\u044a\u0431\u0438\u0442\u0438\u0435\u0442\u043e \u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435\u043d\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e', event: $json }) }}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "id": "respond-success",
      "name": "Respond Success",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        880,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://n8n.simeontsvetanovn8nworkflows.site/webhook/patients-upsert",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"name\": \"{{ $('Prepare Event Data').first().json.patientName }}\",\n  \"phone\": \"{{ $('Prepare Event Data').first().json.patientPhone }}\"\n}",
        "options": {}
      },
      "id": "save-patient",
      "name": "Save Patient to Sheet",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        660,
        150
      ],
      "continueOnFail": true
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Prepare Event Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Event Data": {
      "main": [
        [
          {
            "node": "Create Calendar Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Calendar Event": {
      "main": [
        [
          {
            "node": "Format Response",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save Patient to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Response": {
      "main": [
        [
          {
            "node": "Respond Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "tags": [
    {
      "name": "Rodopi Dent"
    }
  ]
}

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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Rodopi Dent - Calendar Create Event. Uses googleCalendar, httpRequest. Webhook trigger; 6 nodes.

Source: https://github.com/Georgi-Piskov/RODOPI-DENT/blob/f071a84326ea5adf54e4eb20a2ba3e34aac5b728/n8n-workflows/12-calendar-create.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di

n8n, Execute Workflow Trigger, HTTP Request +1
Web Scraping

This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .

HTTP Request, Ssh
Web Scraping

This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c

HTTP Request
Web Scraping

Sign PDF documents with legally-compliant digital signatures using X.509 certificates. Supports multiple PAdES signature levels (B, T, LT, LTA) with optional visible stamps.

Execute Command, HTTP Request, Read Write File +1
Web Scraping

📡 This workflow serves as the central Alpha Vantage API fetcher for Tesla trading indicators, delivering cleaned 20-point JSON outputs for three timeframes: , , and . It is required by the following a

HTTP Request