{
  "id": "npJArGmuihVd7HKd",
  "name": "Appointment Booking workflow with GHL integration",
  "tags": [
    {
      "id": "oufe6ROEtWIl02g4",
      "name": "open-source",
      "createdAt": "2026-06-25T18:55:08.441Z",
      "updatedAt": "2026-07-13T19:25:56.333Z"
    }
  ],
  "nodes": [
    {
      "id": "a94b2944-edd4-437d-ac54-11f754efa256",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -528,
        464
      ],
      "parameters": {
        "width": 480,
        "height": 896,
        "content": "## \n\n### How it works\n\nThis workflow receives an appointment booking request by webhook, checks whether the requested slot is available, and stops with an unavailable response if it is not. If the slot is free, it prepares the start/end times, creates or updates the contact in GoHighLevel, books the appointment, then finds or creates the related opportunity. It updates opportunity custom fields, returns a booked response, triggers a background workflow, and routes operational failures to a dedicated error workflow.\n\n### Setup steps\n\n- Configure the Webhook node URL in the calling system that sends booking requests.\n- Set up GoHighLevel/LeadConnector credentials for the HighLevel nodes that create contacts, book appointments, search opportunities, and update opportunity stages.\n- Configure the HTTP request authentication and endpoint details for updating opportunity custom fields on services.leadconnectorhq.com.\n- Ensure the sub-workflows named \"Ray - Check Slot Availability\", \"Ray - Background Workflow\", and \"Ray - Error Workflow\" exist and are callable from this workflow.\n- Verify field mappings for contact details, appointment start/end times, service type, preferred date, pipeline/stage IDs, and opportunity custom fields.\n\n### Customization\n\nAdjust the availability rules in the check-slot sub-workflow, the appointment duration used to create start/end times, and the opportunity stage or custom field mappings to match different booking processes."
      },
      "typeVersion": 1
    },
    {
      "id": "cc4f86f4-8f98-4cca-abdb-d6f9d65a10c8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        1008
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 336,
        "content": "## Receive and check slot\n\nEntry cluster that receives the booking request, calls the slot-availability sub-workflow, and branches based on whether the requested time can be booked."
      },
      "typeVersion": 1
    },
    {
      "id": "f676a947-c383-4c4a-a300-f4bb5ee89209",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        672
      ],
      "parameters": {
        "color": 7,
        "height": 672,
        "content": "## Prepare availability result\n\nNearby branch outputs from the availability decision: one prepares start and end values for an available slot, while the other returns a booked/error response when the slot is unavailable."
      },
      "typeVersion": 1
    },
    {
      "id": "4f36ffad-c8c0-44c9-b721-610bf44f66d4",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 528,
        "content": "## Create contact appointment\n\nCreates or updates the contact in GoHighLevel and then books the appointment for the prepared time slot."
      },
      "typeVersion": 1
    },
    {
      "id": "12e264cc-3c04-440e-b43c-ef54dbd1df0d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1408,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 528,
        "content": "## Find matching opportunity\n\nSearches GoHighLevel opportunities after the appointment is booked and decides whether an existing opportunity should be updated or a new one should be created."
      },
      "typeVersion": 1
    },
    {
      "id": "b69837ab-902e-4db9-8cc6-0d3cf75d93c4",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 624,
        "content": "## Update opportunity details\n\nHandles the opportunity write path by either moving an existing opportunity to the booked stage or creating a new opportunity, then applying the required custom fields through the LeadConnector API."
      },
      "typeVersion": 1
    },
    {
      "id": "f3a69a50-c26c-490a-9ea6-462a99b100cc",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2304,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 656,
        "content": "## Return success follow-up\n\nFinal success cluster that marks the appointment as booked for the response and starts the separate background workflow for any asynchronous follow-up tasks."
      },
      "typeVersion": 1
    },
    {
      "id": "ae92a1e0-87f9-486f-bff2-1f510e7f789c",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2336,
        576
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 592,
        "content": "## Central error handling (Optional)\n\nFar-right error handling cluster that records a generic booked/error response and invokes the dedicated Ray error workflow when upstream GoHighLevel or HTTP operations fail."
      },
      "typeVersion": 1
    },
    {
      "id": "5874b78e-1c38-45e7-b6a8-87b1aed4b169",
      "name": "Set Slot Start & End Times",
      "type": "n8n-nodes-base.set",
      "position": [
        736,
        976
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fd936412-e8ed-45b2-9842-9fccc73da593",
              "name": "start",
              "type": "string",
              "value": "={{ $('Receive Appointment Request').item.json.body.preferred_date }}T{{ $('Receive Appointment Request').item.json.body.preferred_time }}"
            },
            {
              "id": "3cda2a1b-6a47-452e-9840-93fffbda80f3",
              "name": "end",
              "type": "string",
              "value": "={{ $('Receive Appointment Request').item.json.body.preferred_date }}T{{\nDateTime\n  .fromFormat(\n    $('Receive Appointment Request').first().json.body.preferred_time,\n    'HH:mm'\n  )\n  .plus({ minutes: 30 })\n  .toFormat('HH:mm')\n}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9d5ad015-f769-456b-b2ff-b85802349685",
      "name": "Run Background Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "disabled": true,
      "position": [
        2352,
        144
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "NN2GGNgkR3wTT408",
          "cachedResultUrl": "/workflow/NN2GGNgkR3wTT408",
          "cachedResultName": "Ray - Background Workflow"
        },
        "workflowInputs": {
          "value": {
            "name": "={{ $('Receive Appointment Request').item.json.body.name }}",
            "phone": "={{ $('Receive Appointment Request').item.json.body.phone }}",
            "event_id": "={{ $('Schedule Appointment in GHL').item.json.id }}",
            "action_type": "Book",
            "service_type": "={{ $('Receive Appointment Request').item.json.body.service_type }}",
            "preferred_date": "={{ $('Receive Appointment Request').item.json.body.preferred_date }}",
            "preferred_time": "={{ $('Receive Appointment Request').item.json.body.preferred_time }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "service_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "service_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "preferred_date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "preferred_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "preferred_time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "preferred_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "event_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "event_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "action_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "action_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "ceec5ca7-1680-4c2b-a485-f0460bae1462",
      "name": "Receive Appointment Request",
      "type": "n8n-nodes-base.webhook",
      "position": [
        64,
        1168
      ],
      "parameters": {
        "path": "ray/book-appointment",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "e2f539ab-7bf5-4f73-9b9f-eb83d6d1652b",
      "name": "Execute Error Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "disabled": true,
      "position": [
        2384,
        816
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "QRDMcC4sl0wOL9XN",
          "cachedResultUrl": "/workflow/QRDMcC4sl0wOL9XN",
          "cachedResultName": "Ray - Error Workflow"
        },
        "workflowInputs": {
          "value": {
            "resolved": "No",
            "node_name": "GHL",
            "error_type": "GHL node unavailable",
            "workflow_id": "={{ $workflow.id }}",
            "execution_id": "={{ $execution.id }}",
            "patient_name": "={{ $('Receive Appointment Request').item.json.body.name }}",
            "service_type": "={{ $('Receive Appointment Request').item.json.body.service_type }}",
            "patient_phone": "={{ $('Receive Appointment Request').item.json.body.phone }}",
            "workflow_name": "={{ $workflow.name }}",
            "preferred_date": "={{ $('Receive Appointment Request').item.json.body.preferred_date }}",
            "preferred_time": "={{ $('Receive Appointment Request').item.json.body.preferred_time }}"
          },
          "schema": [
            {
              "id": "workflow_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "workflow_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "node_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "node_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "error_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "error_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "patient_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "patient_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "patient_phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "patient_phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "service_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "service_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "preferred_date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "preferred_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "preferred_time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "preferred_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "execution_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "execution_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "resolved",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "resolved",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "workflow_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "workflow_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "fc963dc8-b470-4076-95a9-b518c2799671",
      "name": "Execute Slot Availability Check",
      "type": "n8n-nodes-base.executeWorkflow",
      "disabled": true,
      "position": [
        288,
        1168
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "b8Gcq5Lx1ZBZ7k7w",
          "cachedResultUrl": "/workflow/b8Gcq5Lx1ZBZ7k7w",
          "cachedResultName": "Ray - Check Slot Availability"
        },
        "workflowInputs": {
          "value": {
            "preferred_date": "={{ $json.body.preferred_date }}",
            "preferred_time": "={{ $json.body.preferred_time }}"
          },
          "schema": [
            {
              "id": "preferred_date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "preferred_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "preferred_time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "preferred_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "e5e8ed7b-5c16-45f5-89fa-a9f5d042a1de",
      "name": "Sync Contact in GHL",
      "type": "n8n-nodes-base.highLevel",
      "onError": "continueErrorOutput",
      "position": [
        1008,
        976
      ],
      "parameters": {
        "email": "={{ $('Receive Appointment Request').item.json.body.phone.replace(/[^0-9]/g, '') }}@example.com",
        "phone": "={{ $('Receive Appointment Request').item.json.body.phone }}",
        "requestOptions": {},
        "additionalFields": {
          "name": "={{ $('Receive Appointment Request').item.json.body.name }}",
          "address1": "={{ $('Receive Appointment Request').item.json.body.address }}"
        }
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2
    },
    {
      "id": "2f141040-adb3-40c7-b544-3b36e4cb0009",
      "name": "Schedule Appointment in GHL",
      "type": "n8n-nodes-base.highLevel",
      "onError": "continueErrorOutput",
      "position": [
        1232,
        768
      ],
      "parameters": {
        "resource": "calendar",
        "contactId": "={{ $json.id }}",
        "startTime": "={{ DateTime.fromISO($('Set Slot Start & End Times').item.json.start, { zone: 'America/Chicago' }).toISO() }}",
        "calendarId": "calendarId",
        "locationId": "locationId",
        "requestOptions": {},
        "additionalFields": {
          "title": "={{ $('Receive Appointment Request').item.json.body.service_type }} - {{ $('Receive Appointment Request').item.json.body.name }}",
          "address": "={{ $('Receive Appointment Request').item.json.body.address }}",
          "endTime": "={{ DateTime.fromISO($('Set Slot Start & End Times').item.json.end, { zone: 'America/Chicago' }).toISO() }}"
        }
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2
    },
    {
      "id": "2d72aaeb-8480-48b4-a6d7-5ce2f17f52de",
      "name": "Add New Opportunity in GHL",
      "type": "n8n-nodes-base.highLevel",
      "onError": "continueErrorOutput",
      "position": [
        1920,
        480
      ],
      "parameters": {
        "name": "={{ $('Receive Appointment Request').item.json.body.service_type }} - {{ $('Receive Appointment Request').item.json.body.name }}",
        "resource": "opportunity",
        "contactId": "={{ $('Sync Contact in GHL').item.json.id }}",
        "pipelineId": "=pipelineId",
        "requestOptions": {},
        "additionalFields": {
          "stageId": "=stageId"
        }
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2
    },
    {
      "id": "f1736624-326e-4ca0-b7d8-5999dc3d40e2",
      "name": "Customize Opportunity Fields",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        2128,
        240
      ],
      "parameters": {
        "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunity.id }}",
        "method": "PUT",
        "options": {},
        "jsonBody": "={{ JSON.stringify({\n  customFields: [\n    {\n      id: \"YOUR_SERVICE_TYPE_FIELD_ID\",\n      field_value: $('Receive Appointment Request').item.json.body.service_type\n    },\n    {\n      id: \"YOUR_PREFERRED_DATE_FIELD_ID\",\n      field_value: $('Receive Appointment Request').item.json.body.preferred_date\n    },\n    {\n      id: \"YOUR_PREFERRED_TIME_FIELD_ID\",\n      field_value: $('Receive Appointment Request').item.json.body.preferred_time\n    },\n    {\n      id: \"YOUR_EVENT_ID_FIELD_ID\",\n      field_value: $('Schedule Appointment in GHL').item.json.id\n    }\n  ]\n}) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "nodeCredentialType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.2
    },
    {
      "id": "f2e37226-fbda-4a84-93ce-422c5c043a35",
      "name": "Check Slot Availability",
      "type": "n8n-nodes-base.if",
      "position": [
        512,
        1168
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7c9e95fb-6367-444f-8c8b-6a0acd096dff",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.available === true }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "00bdd6dd-bf20-42b5-9021-09460cb792a2",
      "name": "Handle Unavailable Slot",
      "type": "n8n-nodes-base.set",
      "position": [
        736,
        1168
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a978fa3a-1de7-4149-8740-736df1b7f1a6",
              "name": "booked",
              "type": "boolean",
              "value": false
            },
            {
              "id": "0916d5f0-3c63-411a-953b-ac888d3c316a",
              "name": "error",
              "type": "string",
              "value": "slot_unavailable"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "1b3f7beb-bcbd-4a3c-a3b5-44e088a65001",
      "name": "Report Booking Error",
      "type": "n8n-nodes-base.set",
      "position": [
        2384,
        1008
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a978fa3a-1de7-4149-8740-736df1b7f1a6",
              "name": "booked",
              "type": "boolean",
              "value": false
            },
            {
              "id": "0916d5f0-3c63-411a-953b-ac888d3c316a",
              "name": "error",
              "type": "string",
              "value": "=GHL Not Available"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "3fd55b61-9a7a-436b-9d66-c4d790662363",
      "name": "Find Opportunities in GHL",
      "type": "n8n-nodes-base.highLevel",
      "onError": "continueErrorOutput",
      "position": [
        1456,
        544
      ],
      "parameters": {
        "filters": {
          "query": "={{ $('Receive Appointment Request').item.json.body.phone || $('Sync Contact in GHL').item.json.phone }}",
          "pipelineId": "pipelineId"
        },
        "resource": "opportunity",
        "operation": "getAll",
        "returnAll": true,
        "requestOptions": {}
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "ef440faf-3d1d-4f38-8827-934b8fd7e68e",
      "name": "Verify Opportunity Existence",
      "type": "n8n-nodes-base.if",
      "position": [
        1680,
        368
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a032d2b7-bed4-44af-9d62-7652125ec608",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{$json.id}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d9bf63bb-ab8e-4ec3-a491-aa46e12eab84",
      "name": "Advance Opportunity to Booked",
      "type": "n8n-nodes-base.highLevel",
      "position": [
        1904,
        240
      ],
      "parameters": {
        "resource": "opportunity",
        "operation": "update",
        "updateFields": {
          "stageId": "=stageId",
          "pipelineId": "=pipelineId"
        },
        "opportunityId": "={{ $('Find Opportunities in GHL').item.json.id }}",
        "requestOptions": {}
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b7f680a2-87e5-4809-bcbf-ff31f66d7fc6",
      "name": "Confirm Appointment Details",
      "type": "n8n-nodes-base.set",
      "position": [
        2352,
        336
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "320ac51e-c6c0-491e-af7c-690ca9e9ebad",
              "name": "booked",
              "type": "boolean",
              "value": true
            },
            {
              "id": "be46c811-6817-49ec-b91d-9595cc592c8f",
              "name": "name",
              "type": "string",
              "value": "={{ $('Receive Appointment Request').item.json.body.name }}"
            },
            {
              "id": "67c137ed-cda6-468a-b072-65b032c3214e",
              "name": "service_type",
              "type": "string",
              "value": "={{ $('Receive Appointment Request').item.json.body.service_type }}"
            },
            {
              "id": "3a7717f0-f49f-477d-a331-015c08c0c4b3",
              "name": "preferred_date",
              "type": "string",
              "value": "={{\nDateTime\n  .fromISO($('Receive Appointment Request').item.json.body.preferred_date)\n  .toFormat('dd LLL yyyy')\n}}"
            },
            {
              "id": "d7fc5978-8bd3-4941-9bf2-2e4d5508c08c",
              "name": "preferred_time",
              "type": "string",
              "value": "={{ DateTime   .fromFormat($('Receive Appointment Request').item.json.body.preferred_time, 'HH:mm')   .toFormat('hh:mm a') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fe9d40aa-7758-4f33-ac49-2778b3c153e5",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2768,
        288
      ],
      "parameters": {
        "color": 4,
        "width": 560,
        "height": 800,
        "content": "## Ray - Book Appointment\n\n### See it in action\n\nThis workflow handles real appointment booking by webhook. It checks whether the requested slot is available, creates or updates the contact in GoHighLevel, books the appointment, then updates or creates the related opportunity and custom fields.\n\nIt also triggers separate sub-workflows for background processing and error handling.\n\n@[youtube](BUoYWR61YwQ)\n\nNote: the workflow uses separate sub-workflows for availability checks, background tasks, and error handling. Adapt the contact, calendar, pipeline, and custom field IDs to match your own GoHighLevel setup."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "6a530160-d2cf-41f2-a8b4-7d3385fe55e8",
  "nodeGroups": [],
  "connections": {
    "Sync Contact in GHL": {
      "main": [
        [
          {
            "node": "Schedule Appointment in GHL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report Booking Error",
            "type": "main",
            "index": 0
          },
          {
            "node": "Execute Error Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Slot Availability": {
      "main": [
        [
          {
            "node": "Set Slot Start & End Times",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Unavailable Slot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Opportunities in GHL": {
      "main": [
        [
          {
            "node": "Verify Opportunity Existence",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Execute Error Workflow",
            "type": "main",
            "index": 0
          },
          {
            "node": "Report Booking Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add New Opportunity in GHL": {
      "main": [
        [
          {
            "node": "Customize Opportunity Fields",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report Booking Error",
            "type": "main",
            "index": 0
          },
          {
            "node": "Execute Error Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Slot Start & End Times": {
      "main": [
        [
          {
            "node": "Sync Contact in GHL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Appointment Request": {
      "main": [
        [
          {
            "node": "Execute Slot Availability Check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Appointment in GHL": {
      "main": [
        [
          {
            "node": "Find Opportunities in GHL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report Booking Error",
            "type": "main",
            "index": 0
          },
          {
            "node": "Execute Error Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Customize Opportunity Fields": {
      "main": [
        [
          {
            "node": "Confirm Appointment Details",
            "type": "main",
            "index": 0
          },
          {
            "node": "Run Background Workflow",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report Booking Error",
            "type": "main",
            "index": 0
          },
          {
            "node": "Execute Error Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Opportunity Existence": {
      "main": [
        [
          {
            "node": "Advance Opportunity to Booked",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Add New Opportunity in GHL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Advance Opportunity to Booked": {
      "main": [
        [
          {
            "node": "Customize Opportunity Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Slot Availability Check": {
      "main": [
        [
          {
            "node": "Check Slot Availability",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}