{
  "id": "W2i8H6M2VChQVAOJ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Book Appointment open-source-01",
  "tags": [
    {
      "id": "oufe6ROEtWIl02g4",
      "name": "open-source-01",
      "createdAt": "2026-06-25T18:55:08.441Z",
      "updatedAt": "2026-06-25T18:55:08.441Z"
    }
  ],
  "nodes": [
    {
      "id": "65ab2398-c878-450c-85a4-99d64db98ed6",
      "name": "When Executed by Another Workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        1904,
        1648
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "name"
            },
            {
              "name": "service_type"
            },
            {
              "name": "preferred_date"
            },
            {
              "name": "preferred_time"
            },
            {
              "name": "phone"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8059396b-5183-48e5-a8b2-1f55de956ac8",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2528,
        1280
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 272,
        "content": "## Create calendar event\n\nBuilds the appointment start and end values, then creates the booking in Google Calendar when the slot is available."
      },
      "typeVersion": 1
    },
    {
      "id": "c5be18b9-8a75-47c4-a00d-46126e7e0947",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3184,
        1104
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 336,
        "content": "## Success and background tasks\n\nTop-right output cluster that starts a background workflow after booking and prepares the successful booked response with appointment details."
      },
      "typeVersion": 1
    },
    {
      "id": "82bec1ca-a37d-49ee-bd1a-971ae08fe0a1",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3200,
        1712
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 384,
        "content": "## Booking error handling\n\nRight-side error cluster that invokes an error workflow and prepares an error response if event creation fails or needs exception handling."
      },
      "typeVersion": 1
    },
    {
      "id": "84a212e6-5108-4f0d-ac29-857a4197f415",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        928,
        1216
      ],
      "parameters": {
        "color": 4,
        "width": 832,
        "height": 816,
        "content": "## Book Appointment \n\n### How it works\n\nThis workflow is called by another workflow to book an appointment. It checks whether the requested slot is available, returns an unavailable response if not, and otherwise creates the Google Calendar event. After event creation, it emits success details, can start a background workflow, and routes errors to dedicated error responses or an error workflow.\n\n### Setup steps\n\n- Configure the Execute Workflow Trigger so the parent workflow sends the required appointment fields, such as name, service type, preferred date, and slot details.\n- Set up the referenced sub-workflows: \"Check Slot Availability\", \"Background Workflow\", and \"Error Workflow\".\n- Connect Google Calendar credentials in the \"Create an event\" node and select the target calendar.\n- Verify the Set nodes map the expected output fields for booked status, appointment metadata, and error messages.\n\n### Customization\n\nAdjust the slot start/end calculation, calendar event fields, and returned success or error payloads to match your booking rules and client-facing response format."
      },
      "typeVersion": 1
    },
    {
      "id": "ae9342d4-7fa2-4f09-96d3-3344774389f0",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1792,
        1392
      ],
      "parameters": {
        "color": 7,
        "width": 688,
        "height": 240,
        "content": "## Receive and check slot\n\nEntry cluster that receives execution from another workflow, calls the slot-availability sub-workflow, and evaluates the availability result."
      },
      "typeVersion": 1
    },
    {
      "id": "3abcb585-d5bb-4a0d-b16b-1bf76707e486",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2640,
        1920
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 272,
        "content": "## Unavailable slot response\n\nReturns a booked=false style response with an error when the requested appointment slot is not available."
      },
      "typeVersion": 1
    },
    {
      "id": "2378d322-0ab3-447f-8612-321dc1b07476",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3600,
        1216
      ],
      "parameters": {
        "width": 944,
        "height": 880,
        "content": "## See it in action\n\nThis workflow powers appointment booking inside Aria, a live AI \nvoice receptionist that books, reschedules, and cancels real \nappointments by phone. Watch the full call below.\n\n@[youtube](OF-5d0pQ7Zo)\n\nNote: this is one of 5 sub-workflows in the Aria system \u2014 \nbooking, canceling, rescheduling, checking availability, and \nfinding alternate slots each run as a separate workflow, called \nvia MCP tools. Build each one to match your own calendar/CRM \nsetup \u2014 or watch the video to see the full pattern working end \nto end."
      },
      "typeVersion": 1
    },
    {
      "id": "5b7e0160-2625-448d-8b11-ed2e39fb0819",
      "name": "Check Slot Availability",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        2128,
        1648
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "AQhWv6s3ouxoTLPI",
          "cachedResultUrl": "/workflow/AQhWv6s3ouxoTLPI",
          "cachedResultName": "Check Slot Availability"
        },
        "workflowInputs": {
          "value": {
            "name": "={{ $json.name }}",
            "service_type": "={{ $json.service_type }}",
            "preferred_date": "={{ $json.preferred_date }}",
            "preferred_time": "={{ $json.preferred_time }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "name",
              "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
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "76cdb1d4-ba60-4de1-9149-e1433fbcacc9",
      "name": "Run Background Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "disabled": true,
      "position": [
        3024,
        1264
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "hEOycKblp9Yg7ath",
          "cachedResultUrl": "/workflow/hEOycKblp9Yg7ath",
          "cachedResultName": "Background Workflow"
        },
        "workflowInputs": {
          "value": {
            "name": "={{ $('When Executed by Another Workflow').item.json.name }}",
            "phone": "={{ $('When Executed by Another Workflow').item.json.phone }}",
            "event_id": "={{ $json.id }}",
            "action_type": "Book",
            "service_type": "={{ $('When Executed by Another Workflow').item.json.service_type }}",
            "preferred_date": "={{ $('When Executed by Another Workflow').item.json.preferred_date }}",
            "preferred_time": "={{ $('When Executed by Another Workflow').item.json.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": "81cda2b4-bde5-43a1-bb77-c22b14d54e84",
      "name": "Execute Error Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "disabled": true,
      "position": [
        3024,
        1648
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "bQdno8qQgpKWbiDE",
          "cachedResultUrl": "/workflow/bQdno8qQgpKWbiDE",
          "cachedResultName": "Error Workflow"
        },
        "workflowInputs": {
          "value": {
            "resolved": "No",
            "node_name": "={{ $json.error }}",
            "timestamp": "={{ $now.toISO() }}",
            "error_type": "={{ $json.error }}",
            "execution_id": "={{ $execution.id }}",
            "patient_name": "={{ $('When Executed by Another Workflow').item.json.name }}",
            "service_type": "={{ $('When Executed by Another Workflow').item.json.service_type }}",
            "patient_phone": "={{ $('When Executed by Another Workflow').item.json.phone }}",
            "workflow_name": "={{ $workflow.name }}",
            "preferred_date": "={{ $('When Executed by Another Workflow').item.json.preferred_date }}",
            "preferred_time": "={{ $('When Executed by Another Workflow').item.json.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": "timestamp",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "timestamp",
              "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
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "e71209b7-ae6a-49ea-9ecd-531b81fc101f",
      "name": "Check Slot Availability Status",
      "type": "n8n-nodes-base.if",
      "position": [
        2352,
        1648
      ],
      "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": "d1eefcfb-acc0-4cab-b451-d06db5cf6a61",
      "name": "Set Slot Start and End",
      "type": "n8n-nodes-base.set",
      "position": [
        2576,
        1552
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fd936412-e8ed-45b2-9842-9fccc73da593",
              "name": "start",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json.preferred_date }}T{{ $('When Executed by Another Workflow').item.json.preferred_time }}"
            },
            {
              "id": "3cda2a1b-6a47-452e-9840-93fffbda80f3",
              "name": "end",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json.preferred_date }}T{{\nDateTime\n  .fromFormat(\n    $('When Executed by Another Workflow').first().json.preferred_time,\n    'HH:mm'\n  )\n  .plus({ minutes: 30 })\n  .toFormat('HH:mm')\n}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ab5e9c27-765e-4259-99d4-5ed4cdd57c85",
      "name": "Set Availability Error",
      "type": "n8n-nodes-base.set",
      "position": [
        2576,
        1744
      ],
      "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": "df6033a0-ee17-480e-a3ff-362c1f4a10d3",
      "name": "Create Google Calendar Event",
      "type": "n8n-nodes-base.googleCalendar",
      "onError": "continueErrorOutput",
      "position": [
        2800,
        1552
      ],
      "parameters": {
        "end": "={{ $json.end }}",
        "start": "={{ $json.start }}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "user@example.com",
          "cachedResultName": "user@example.com"
        },
        "additionalFields": {
          "summary": "={{ $('When Executed by Another Workflow').item.json.service_type }} - {{ $('When Executed by Another Workflow').item.json.name }}",
          "attendees": [],
          "description": "={{ $('When Executed by Another Workflow').item.json.phone }}"
        }
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1.3,
      "waitBetweenTries": 1000
    },
    {
      "id": "a4120312-e7a5-49bf-a2cc-d02df82c4d60",
      "name": "Set Booking Details",
      "type": "n8n-nodes-base.set",
      "position": [
        3024,
        1456
      ],
      "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": "={{ $('When Executed by Another Workflow').item.json.name }}"
            },
            {
              "id": "67c137ed-cda6-468a-b072-65b032c3214e",
              "name": "service_type",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json.service_type }}"
            },
            {
              "id": "3a7717f0-f49f-477d-a331-015c08c0c4b3",
              "name": "preferred_date",
              "type": "string",
              "value": "={{\nDateTime\n  .fromISO($('When Executed by Another Workflow').item.json.preferred_date)\n  .toFormat('dd LLL yyyy')\n}}"
            },
            {
              "id": "d7fc5978-8bd3-4941-9bf2-2e4d5508c08c",
              "name": "preferred_time",
              "type": "string",
              "value": "={{ DateTime   .fromFormat($('When Executed by Another Workflow').item.json.preferred_time, 'HH:mm')   .toFormat('hh:mm a') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2029ef6b-d15a-414e-98f5-ba6dc92f7d69",
      "name": "Set Error Details",
      "type": "n8n-nodes-base.set",
      "position": [
        3024,
        1840
      ],
      "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": "calendar_unavailable"
            }
          ]
        }
      },
      "typeVersion": 3.4
    }
  ],
  "active": false,
  "settings": {
    "timezone": "America/Chicago",
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "bQdno8qQgpKWbiDE",
    "timeSavedMode": "fixed",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "8b16fb2f-13a9-46c5-b82c-637af760ffda",
  "connections": {
    "Set Slot Start and End": {
      "main": [
        [
          {
            "node": "Create Google Calendar Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Slot Availability": {
      "main": [
        [
          {
            "node": "Check Slot Availability Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Google Calendar Event": {
      "main": [
        [
          {
            "node": "Set Booking Details",
            "type": "main",
            "index": 0
          },
          {
            "node": "Run Background Workflow",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set Error Details",
            "type": "main",
            "index": 0
          },
          {
            "node": "Execute Error Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Slot Availability Status": {
      "main": [
        [
          {
            "node": "Set Slot Start and End",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set Availability Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Check Slot Availability",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}