AutomationFlowsAI & RAG › Book Appointments with Voice Using Vapi & Cal.com

Book Appointments with Voice Using Vapi & Cal.com

ByNabin Bhandari @knabinbhandari on n8n.io

This template uses VAPI and Cal.com to book appointments through a voice conversation. It detects whether the user wants to check availability or book an appointment, then responds naturally with real-time scheduling options.

Webhook trigger★★★★☆ complexity18 nodesHTTP Request
AI & RAG Trigger: Webhook Nodes: 18 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #6895 — we link there as the canonical source.

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
{
  "id": "uPrkBTcWYNleMzSM",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Appointment Booking Voice Agent",
  "tags": [],
  "nodes": [
    {
      "id": "6adc4f2f-867e-49dd-9179-cf55f0a3f56d",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "disabled": true,
      "position": [
        -1408,
        96
      ],
      "parameters": {
        "path": "308f0eec-8459-4e6c-bf25-5cd9b2c31ad6",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "322ff7ac-9c2c-49e9-a429-ab91d9b9f2bb",
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        -592,
        96
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Check Availability",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "813e4843-4769-4ed8-89d4-4a3969913d51",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Webhook').item.json.body.message.toolCalls[0].function.name }}",
                    "rightValue": "check-availability"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Book Appointment",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "ecb56d1d-336f-4504-b69b-ad635d1a6b24",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Webhook').item.json.body.message.toolWithToolCallList[0].function.name }}",
                    "rightValue": "book-appointment"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "ee168a09-1bb7-4080-b96e-8b20fc24b86c",
      "name": "Set Variables",
      "type": "n8n-nodes-base.set",
      "position": [
        -1184,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d9554d41-2307-4f97-967b-ca8b72c181bb",
              "name": "username",
              "type": "string",
              "value": "nabin-bhandari11"
            },
            {
              "id": "c6a7eb17-72bc-419a-a96b-232c3b00b3b8",
              "name": "eventTypeSlug",
              "type": "string",
              "value": "30 min"
            },
            {
              "id": "d1af9905-60e7-4f64-a235-867222d088c7",
              "name": "eventTypeId",
              "type": "string",
              "value": "2964463"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "bfbdc15f-2718-410c-8a48-90c861c5836f",
      "name": "Check Availability",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        0,
        -16
      ],
      "parameters": {
        "url": "https://api.cal.com/v2/slots",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "start",
              "value": "={{ $json[' start'] }}"
            },
            {
              "name": "end",
              "value": "={{ $json[' end'] }}"
            },
            {
              "name": "eventTypeId",
              "value": "={{ $('Set Variables').item.json.eventTypeId }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "cal-api-version",
              "value": "2024-09-04"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "0b1e3986-7b05-4ca4-aa10-976a7b0ba64c",
      "name": "Book Appointment",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -112,
        240
      ],
      "parameters": {
        "url": "https://api.cal.com/v2/bookings",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"attendee\": {\n    \"language\": \"en\",\n    \"name\": \"{{ $json.body.message.toolCalls[0].function.arguments.Name }}\",\n    \"timeZone\": \"{{ $json.body.message.toolCalls[0].function.arguments.callerTimeZone }}\",\n    \"email\": \"{{ $json.body.message.toolCalls[0].function.arguments.Email }}\"\n  },\n  \"start\": \"{{ $json.body.message.toolCallList[0].function.arguments.requestedappointmentdate }}\",\n  \"eventTypeId\": {{ $('Set Variables').item.json.eventTypeId }}\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "cal-api-version",
              "value": "2024-08-13"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "8728b814-432a-498f-8077-2f2f806143d7",
      "name": "Booking SuccessFul",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        160,
        240
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"results\": [\n    {\n      \"toolCallId\": \"{{ $('Webhook').item.json.body.message.toolCallList[0].id }}\",\n      \"result\": \"Booking Successful\"\n    }\n  ]\n}\n"
      },
      "typeVersion": 1.4
    },
    {
      "id": "7dced770-52a8-4f81-a0c8-83b1454fa475",
      "name": "Check Availability successful",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        224,
        -16
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"results\": [\n    {\n      \"toolCallId\": \"{{ $('Webhook').item.json.body.message.toolCallList[0].id }}\",\n      \"result\": \"{{ $json.data }}\"\n    }\n  ]\n}\n"
      },
      "typeVersion": 1.4
    },
    {
      "id": "d131814d-35ef-459b-8ba9-99ffe67539dd",
      "name": "Prepare Payload Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        -928,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9a6f391b-9dc9-4642-accf-be687dceb56e",
              "name": "body",
              "type": "object",
              "value": "={{ $('Webhook').item.json.body }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "30b16423-9253-4fa8-b20c-3ffd86ae1c95",
      "name": "Extract Start & End Time",
      "type": "n8n-nodes-base.set",
      "position": [
        -224,
        -16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "872ef0bf-8111-44e5-8c8d-fbaa0c982519",
              "name": " start",
              "type": "string",
              "value": "={{ $('Webhook').item.json.body.message.toolCalls[0].function.arguments.requestedappointment }}"
            },
            {
              "id": "57e9ef02-8748-4ab9-9dc3-39ee2f8c08d5",
              "name": " end",
              "type": "string",
              "value": "={{ $('Webhook').item.json.body.message.toolCalls[0].function.arguments.requestedappointment.toDateTime().plus(1, 'days') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "14dc0f51-6ac4-4058-8618-f8d7915bfc5d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1488,
        -32
      ],
      "parameters": {
        "height": 336,
        "content": "Entry point from VAPI. This webhook receives user intent and entities from the voice agent in a structured format (e.g. action = \"book\" or \"check\")."
      },
      "typeVersion": 1
    },
    {
      "id": "917a9fd1-a235-44c9-b810-c1efbae640a7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1232,
        -16
      ],
      "parameters": {
        "color": 4,
        "height": 320,
        "content": "Extracts variables like eventtypeid, eventtypeslug and username."
      },
      "typeVersion": 1
    },
    {
      "id": "8a4ef30e-6572-4746-942e-5ceaf95a91e7",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        -16
      ],
      "parameters": {
        "color": 2,
        "height": 320,
        "content": "Extracts the body from the webhook"
      },
      "typeVersion": 1
    },
    {
      "id": "e0f0ebd4-4a21-4d54-8cb8-fd076f1a082e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -672,
        -112
      ],
      "parameters": {
        "color": 5,
        "height": 416,
        "content": "Routes the voice intent:\n\nIf the user said \"Check availability\", go to the check flow.\n\nIf the user said \"Book appointment\", go to the booking flow."
      },
      "typeVersion": 1
    },
    {
      "id": "93c9caf4-e617-4d3e-9cb5-3a6973a84d60",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        -160
      ],
      "parameters": {
        "height": 304,
        "content": "Parses and formats spoken date/time info from the voice assistant to match Cal.com API's time range requirements."
      },
      "typeVersion": 1
    },
    {
      "id": "35d3230c-09ad-4176-9bef-24b4825dfa47",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        -160
      ],
      "parameters": {
        "color": 7,
        "height": 304,
        "content": "Sends a GET request to Cal.com to fetch available time slots for the specified date range from the voice input."
      },
      "typeVersion": 1
    },
    {
      "id": "d212d1a3-3471-4557-a96a-50dd311089ba",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        192,
        -160
      ],
      "parameters": {
        "color": 3,
        "height": 320,
        "content": "Returns a voice-ready response to VAPI (e.g. \"There\u2019s availability at 3 PM and 4 PM. Would you like to book?\")."
      },
      "typeVersion": 1
    },
    {
      "id": "59935070-d52a-4120-bd60-0f694eb538fe",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        144
      ],
      "parameters": {
        "color": 4,
        "height": 272,
        "content": "Sends a POST request to Cal.com to book the appointment using parsed info from the voice conversation."
      },
      "typeVersion": 1
    },
    {
      "id": "a4182a3e-4501-405c-9088-95a1b9dd8d81",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        160
      ],
      "parameters": {
        "color": 6,
        "width": 272,
        "height": 240,
        "content": "Returns a spoken confirmation via VAPI (e.g. \"Your appointment is confirmed for 3 PM on Tuesday\")"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "e483040f-c8c3-4cab-ae02-7008cf6a993c",
  "connections": {
    "Switch": {
      "main": [
        [
          {
            "node": "Extract Start & End Time",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Book Appointment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Set Variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Variables": {
      "main": [
        [
          {
            "node": "Prepare Payload Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Book Appointment": {
      "main": [
        [
          {
            "node": "Booking SuccessFul",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Availability": {
      "main": [
        [
          {
            "node": "Check Availability successful",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Payload Fields": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Start & End Time": {
      "main": [
        [
          {
            "node": "Check Availability",
            "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.

Pro

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

About this workflow

This template uses VAPI and Cal.com to book appointments through a voice conversation. It detects whether the user wants to check availability or book an appointment, then responds naturally with real-time scheduling options.

Source: https://n8n.io/workflows/6895/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

Jigsaw API key for image processing, I use this as a gatekeeper/second pair of eyes. LINK to their website https://jigsawstack.com/ SECOND A postgress DATABASE (I use Supabase) LlamaCloud for the pars

HTTP Request, Postgres, Stop And Error +2
AI & RAG

Whatsapp Multi Agent System optimized copy 2.0. Uses airtable, httpRequest, errorTrigger. Webhook trigger; 44 nodes.

Airtable, HTTP Request, Error Trigger
AI & RAG

Invoice Agent. Uses httpRequest, emailSend. Webhook trigger; 29 nodes.

HTTP Request, Email Send
AI & RAG

Reputation Engine — SEO QA Agent. Uses httpRequest. Webhook trigger; 28 nodes.

HTTP Request
AI & RAG

This workflow handles incoming voice calls or audio messages, transcribes them using Whisper (OpenAI) or ElevenLabs, extracts booking intent and preferred time slots using AI, checks availability on C

HTTP Request