How to build a Calendly clone using Airkit's low code platform
Tags: webdev, lowcode, tutorial, productivity
Published: 2022-10-17 21:54:21

I use  [Calendly](https://calendly.com/)  a lot in my day to day to book meetings that fit within my schedule, and as I continued to use it, I wanted to see if I could build the core functionality of the tool in Airkit. There were a few things I wanted to make sure we could do in Airkit, which is connect to both google calendar and zoom, be able to programmatically get all of the free slots on my calendar in 30 minute increments, and programmatically generate zoom links attached to calendar invites.

With that in mind, this tutorial will walk through the steps on how to build a Calendly clone, integrated with Google Calendar and Zoom. 

{% embed https://youtu.be/ot9mhYDm4Jk %}

## Application Overview
When a user visits the application, they will see a calendar with an availability list of 30 minute appointment slots where they can choose and confirm an appointment time of their choice.

![This image has an empty alt attribute; its file name is Calendly-Application-Overview-1.png](https://test-airkit.pantheonsite.io/app/uploads/2022/09/Calendly-Application-Overview-1.png)

Once the user selects the time slot. They will be presented with a form where they enter details about themselves (name and email address), add additional guests, and a message for the meeting. When they click on Schedule Event, Airkit will then create an appointment, send out meeting invitations to all participants along with a Zoom Meeting link.

You can check the application out here:  [https://app.airkit.com/calendly](https://app.airkit.com/calendly)

### Prerequisites

To build along with this tutorial, you will need a few things to get started:

-   Access to Airkit Studio
-   [A Google Developer account](https://developers.google.com/)
-   [A Zoom Developer account](https://developers.zoom.us/)

## Creating APIs for the Google Calendar and Zoom Meetings

Let’s start with the Google Calendar API. One of the first things you will need to do to get started is create a project in the Google Developer Console. You will need to create a new project called Calendly Airkit and then select it. Next add the Google Calendar API.

![This image has an empty alt attribute; its file name is MvuuRfsXFwe6eyrx1LSCS-5_aPrx9JMCfVewvs5A5R0gZFLRzzFvHgrOocYr1xye_JOqMbQMACZXfALK57vVqSvJJtzENlIeNJuRhhL9s5iQ5F14O95OQiNKAZQkUGwDqqz7hc6nHMGygnkmo45wzOJuLthEtZ7-aXp2LBJh20E62aOLuPi1VQMlYQ](https://lh6.googleusercontent.com/MvuuRfsXFwe6eyrx1LSCS-5_aPrx9JMCfVewvs5A5R0gZFLRzzFvHgrOocYr1xye_JOqMbQMACZXfALK57vVqSvJJtzENlIeNJuRhhL9s5iQ5F14O95OQiNKAZQkUGwDqqz7hc6nHMGygnkmo45wzOJuLthEtZ7-aXp2LBJh20E62aOLuPi1VQMlYQ)

After enabling the Google Calendar API, you will need to configure the Credentials with an OAuth client id.

![This image has an empty alt attribute; its file name is W4jKyNXZM5NY52GJ-MqpohrPPpjYf8kPtHWuU2cwF2DanW-EO-V8GxLFjreTvZa9PYMo2yX9wkESQRWlRcG7krs2bradoZaanw5yaPnHIu5uou2CmTRb36Rzs8a6ztg3xRJhF4Zohnf8UVmEPwJHUzLwSuGF7axT7QW3UOVVdJglLkpa3GXnV43E-Q](https://lh3.googleusercontent.com/W4jKyNXZM5NY52GJ-MqpohrPPpjYf8kPtHWuU2cwF2DanW-EO-V8GxLFjreTvZa9PYMo2yX9wkESQRWlRcG7krs2bradoZaanw5yaPnHIu5uou2CmTRb36Rzs8a6ztg3xRJhF4Zohnf8UVmEPwJHUzLwSuGF7axT7QW3UOVVdJglLkpa3GXnV43E-Q)

Provide the OAuth consent screen with the appropriate information and then you will need configure any scopes which are necessary for the Google Calendar API to work with this newly established Project:

-   Google Calendar API – `/auth/calendar`
-   Google Calendar API – `/auth/calendar.readonly`
-   Google Calendar API – `/auth/calendar.events`

![This image has an empty alt attribute; its file name is 3zOMPQiEKrc3Ichm1AAiCW9rqslGpshTv31kKKZApaRLloboTsfN04_dlKKiKHSWIjidDdHgFldjkdFA1PASO9V_YMfh-08OyVmPMAXxBd1TFO0XnVzoHxOIiQRUkaasrdHl2ky7YB5o2YsLstutQo9gsB6l6LJ4zYgfcn9jHNj6E8pEYLKhC0YWPQ](https://lh4.googleusercontent.com/3zOMPQiEKrc3Ichm1AAiCW9rqslGpshTv31kKKZApaRLloboTsfN04_dlKKiKHSWIjidDdHgFldjkdFA1PASO9V_YMfh-08OyVmPMAXxBd1TFO0XnVzoHxOIiQRUkaasrdHl2ky7YB5o2YsLstutQo9gsB6l6LJ4zYgfcn9jHNj6E8pEYLKhC0YWPQ)

Now are you able to create the OAuth Credential. You will need the redirect URI which can be found in this  [doc](https://support.airkit.com/reference/custom-integrations). Because my organization is in the US region, I use the below redirect URI.


“`

[https://us.api.prod.airkit.com/internal/sessions/v1/auth/callback](https://us.api.prod.airkit.com/internal/sessions/v1/auth/callback)

“`

Next let’s configure the Zoom Developer API. Like Google, you will need a Zoom Developer account. You will be creating an OAuth app type. The app will be an account level application.

![This image has an empty alt attribute; its file name is DrJpawWYxghsFxHTzriIfxsCsvBNILv64Oj0_FS3eDhTbpHIFMpuKM_uy3kfSyx5aYsmaDz1gtmnYv5vVa0ZxULT_xroI0FaOJxaeiMMCbDuv3XYa73Jztdr0IPpEVxMxe4Ys19yyIUcclpguhvmolnXZ7ZJxx9p6XlBwsni4wzgXyvsd0B4Oz29IA](https://lh4.googleusercontent.com/DrJpawWYxghsFxHTzriIfxsCsvBNILv64Oj0_FS3eDhTbpHIFMpuKM_uy3kfSyx5aYsmaDz1gtmnYv5vVa0ZxULT_xroI0FaOJxaeiMMCbDuv3XYa73Jztdr0IPpEVxMxe4Ys19yyIUcclpguhvmolnXZ7ZJxx9p6XlBwsni4wzgXyvsd0B4Oz29IA)

You will be using the information from the App credentials later. Like before refer to the Custom Integrations documentation for the URL information for Redirect URL and Allow List. Now you are able to create the application. Finally you will need to add Scopes:

-   View and manage all user meetings

![This image has an empty alt attribute; its file name is D22kKxY2B6qWVaIgrkNUtyxDkxqQ9WQU99cSb4s-d1vnWWpQRGYEjz1uqfQDr5SOCP6KnTdZJfoInb-d4jQF6HHOQUg_6FBLL0_hQpF6qITlep5XZs0aVUM5LBygQMbgIzluO-52JrhuqAD3sPgSSN22Vn2zInENq7ABRvrjkYiH8_6N6b6GMPYxmg](https://lh6.googleusercontent.com/D22kKxY2B6qWVaIgrkNUtyxDkxqQ9WQU99cSb4s-d1vnWWpQRGYEjz1uqfQDr5SOCP6KnTdZJfoInb-d4jQF6HHOQUg_6FBLL0_hQpF6qITlep5XZs0aVUM5LBygQMbgIzluO-52JrhuqAD3sPgSSN22Vn2zInENq7ABRvrjkYiH8_6N6b6GMPYxmg)

All of our integrations setup on Google Cloud and Zoom are done and ready to to be integrated into Airkit.

## Creating the Integration

Now that you have the API integrations setup with Zoom and Google Calendar, it’s time to create the custom integration within our Airkit application. In the Airkit Console, go to the Integration tab. We will be creating two custom integrations. First, we will create a custom integration with Zoom and then will create a connected account to our application there. Next, we will repeat this process again with Google Calendar .

### Zoom Integration

Create a new Custom Integration, with a name and key that you indicate an integration with Zoom. The authentication type we are going to use is OAuth 2.0. The Integration Parameters are `client_id` and `client_secret`.

![This image has an empty alt attribute; its file name is InilW5GmtBDphFyBbjogAa2_KHhUaQuR-Ft5OfZ94JL3LY9yP5wPMVTKlfWYat4PPGN83bQY4WJwl-YaklLYRsmYZMg_VtJLecIfznGiIcm7lvI0J8T3ZoeuJ2iaHf8XmJxFP6b4eP9DZCxWPLSMvcGe6P4AKRIahWuT7T83qKZp7-FlV9rAIATrKQ](https://lh5.googleusercontent.com/InilW5GmtBDphFyBbjogAa2_KHhUaQuR-Ft5OfZ94JL3LY9yP5wPMVTKlfWYat4PPGN83bQY4WJwl-YaklLYRsmYZMg_VtJLecIfznGiIcm7lvI0J8T3ZoeuJ2iaHf8XmJxFP6b4eP9DZCxWPLSMvcGe6P4AKRIahWuT7T83qKZp7-FlV9rAIATrKQ)

The OAuth2 Configuration will be using the following configuration parameters listed below and shown in the sample:

-   Authorization Grant Type: Authorization Code
-   Access Endpoint: “https://zoom.us/oauth/token”
-   Access Token Verb: POST
-   Authorization Endpoint: “https://zoom.us/oauth/authorize”
-   OAuth Scope: meeting:write:admin
-   Client ID: `{client_id}`
-   Client Secret: `{client_secret}`

![This image has an empty alt attribute; its file name is sMBqPdFGDmyYUgxoeEzY6vZqkRu6X2u6LwqqA5LL4dGBsaTkV5QI9-rYiIz0cZuQw-HkpzGiZOQ8rTQXwP61syllBQSs8ca_E466hv9-hbVy0VJI0eYYl8oR8oPp2aNm4PVYcPbPyjwie4WfcZlVBVpDrpaj1aX_8X6rPUgfKgUgHk-NklhOf1CZ4Q](https://lh6.googleusercontent.com/sMBqPdFGDmyYUgxoeEzY6vZqkRu6X2u6LwqqA5LL4dGBsaTkV5QI9-rYiIz0cZuQw-HkpzGiZOQ8rTQXwP61syllBQSs8ca_E466hv9-hbVy0VJI0eYYl8oR8oPp2aNm4PVYcPbPyjwie4WfcZlVBVpDrpaj1aX_8X6rPUgfKgUgHk-NklhOf1CZ4Q)

The Auth token configuration will be the following configurations:

-   Token Parameter: Header
-   Token Parameter Name: Authorization
-   Token Parameter Value Template: Bearer {token}

![This image has an empty alt attribute; its file name is ZUYoYaT1EE6r9N3vxn8M-mEjAVo_aFvvXyyHAxBh0LsBhIAfuyKd5f20hSnFgpzJGd8XLh-d9Jk9r0jLx5qffRa_wcdjAkfzW8bYf4TwhyE398g3WGjilRMCXTFce_vX4mB-LryTSO9Ym4V98NBO7I-qPPPBX8E0wYWJEWstbTimZgPZkIVpAUTJGQ](https://lh6.googleusercontent.com/ZUYoYaT1EE6r9N3vxn8M-mEjAVo_aFvvXyyHAxBh0LsBhIAfuyKd5f20hSnFgpzJGd8XLh-d9Jk9r0jLx5qffRa_wcdjAkfzW8bYf4TwhyE398g3WGjilRMCXTFce_vX4mB-LryTSO9Ym4V98NBO7I-qPPPBX8E0wYWJEWstbTimZgPZkIVpAUTJGQ)

### Google Calendar Integration

Create a new Custom Integration, with a name and key that you indicate an integration with Google Calendar. We will follow similar steps as done for the Zoom Integration. The authentication type we are going to use is OAuth 2.0. The Integration Parameters are `client_id` and `client_secret`.

![This image has an empty alt attribute; its file name is FYUNjcXQqua-C2NRcuCYxm3SDC9JJ7cOWd4BL6EkLiYLHtf1Hxevix1malnLK5MM8qvm6VDCdOe45g1LqjocDo3lwUxcQXDpp6zR_VAd797jKhAIkv_JxI0On_6yNn6lC3nCPMfxsD3EPpVOS18A9PeQwJKxUAciOk8qIKWpRHEKBbb_jr4toy8c5g](https://lh5.googleusercontent.com/FYUNjcXQqua-C2NRcuCYxm3SDC9JJ7cOWd4BL6EkLiYLHtf1Hxevix1malnLK5MM8qvm6VDCdOe45g1LqjocDo3lwUxcQXDpp6zR_VAd797jKhAIkv_JxI0On_6yNn6lC3nCPMfxsD3EPpVOS18A9PeQwJKxUAciOk8qIKWpRHEKBbb_jr4toy8c5g)

The OAuth2 Configuration will be using the following configuration parameters listed below and shown in the sample:

-   Authorization Grant Type: Authorization Code
-   Access Endpoint: “https://oauth2.googleapis.com/token”
-   Access Token Verb: POST
-   Authorization Endpoint: “https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent”
-   OAuth Scope:
    -   “https://www.googleapis.com/auth/calendar”
    -   “https://www.googleapis.com/auth/calendar.readonly”
    -   “https://www.googleapis.com/auth/calendar.events”
-   Client ID: `{client_id}`
-   Client Secret: `{client_secret}`

![This image has an empty alt attribute; its file name is 9_zmMt2G8vx36tgCacb3wP8EN9CGcE-iuXbL92tJMx_KmiWSU3Hv7j3nTyayNYL-5bVSZBqWHBVs7FiCCO3LEiVBzSHaLhGPZAwgqdHoWaRmaNxDcVd7C2LZQdi91Ke3lePDTUT_N4t24bMfx0idF6lu5WckEPAWlfT-EVjdCGfBLnXdZ_9BWFqZMQ](https://lh4.googleusercontent.com/9_zmMt2G8vx36tgCacb3wP8EN9CGcE-iuXbL92tJMx_KmiWSU3Hv7j3nTyayNYL-5bVSZBqWHBVs7FiCCO3LEiVBzSHaLhGPZAwgqdHoWaRmaNxDcVd7C2LZQdi91Ke3lePDTUT_N4t24bMfx0idF6lu5WckEPAWlfT-EVjdCGfBLnXdZ_9BWFqZMQ)

The Auth token configuration will be the following configurations:

-   Token Parameter is Header
-   Token Parameter Name is Authorization
-   Token Parameter Value Template is Bearer {token}

![This image has an empty alt attribute; its file name is 4Lt7iptIQjU-Tls8e82NDiwLyHfCn_Hy6g8s7b8yL71HdQ_vSIOs0TZqdl_lfXeUg_u-bT6oCXwFvSZV9MK-RJyMkliS9wwQZfbRB6T0w0xBGrdnalb16KEILV0mKhGtikUWvcTzNWXIj9siVLRiEX7OvCHvYPTYpF4y5ptOwtaPxvvKEeUbPSVE5A](https://lh4.googleusercontent.com/4Lt7iptIQjU-Tls8e82NDiwLyHfCn_Hy6g8s7b8yL71HdQ_vSIOs0TZqdl_lfXeUg_u-bT6oCXwFvSZV9MK-RJyMkliS9wwQZfbRB6T0w0xBGrdnalb16KEILV0mKhGtikUWvcTzNWXIj9siVLRiEX7OvCHvYPTYpF4y5ptOwtaPxvvKEeUbPSVE5A)

Refer to  [this snippet of the video](https://www.youtube.com/watch?v=ot9mhYDm4Jk&t=1710s)  on how to pair the connected accounts for Zoom and Google Calendar API or refer to  [this document on Connected accounts](https://support.airkit.com/reference/custom-integrations#integration-parameters).

## Functionality through Data Flows

Now we have the integrations ready for use in the Airkit Application, next we will need to build out six Data Flows for the application for self-service appointment scheduling. Refer to the YouTube Video for complete details on how to create all these Data Flows.

First, we will create three Data Flows for finding all the available time slots on a particular day. The main Data Flow will be called  **“Get Free Slots”** and then we will create two additional supporting Data Flows called  **“Merge Objects”**  and  **“Generate 30 Min Slots”**.

![This image has an empty alt attribute; its file name is XM3bqx3IbEY4UQrrCPe0d6yO0xV7Pum98icKlIKCKM3NMV2GGoVdSNLz2txcl2wabi75AizGu3f8K8jwb2HnWyPZhFMTbhx85GehNLoOfJL86ECVYlughYBi1pzLBcSVpEPX-Yd_TUugUKi7qpteN2N0sMay-D7FRCpGIvbSuQSslSmOKF0lrFFRIg](https://lh3.googleusercontent.com/XM3bqx3IbEY4UQrrCPe0d6yO0xV7Pum98icKlIKCKM3NMV2GGoVdSNLz2txcl2wabi75AizGu3f8K8jwb2HnWyPZhFMTbhx85GehNLoOfJL86ECVYlughYBi1pzLBcSVpEPX-Yd_TUugUKi7qpteN2N0sMay-D7FRCpGIvbSuQSslSmOKF0lrFFRIg)

**Get Free Slots Data Flow:** We will be setting the appointment window starting time and ending time, finding the existing appointments via the Google Calendar API, and creating a list of 30 minute available time slots.

Google Calendar API expects the date to be in RFC 3339 format. We will need to use the following Airscript function: `FORMAT_DATETIME` in order to format the date into RFC 3339.

![This image has an empty alt attribute; its file name is WMN7r3x_ACrSTfKP_wgFPrpMt5L7X3Rqygd48mH7m-Wff7LR0ofo4_FYCURIe7dbpT1sVuzEURCVdsmbxYtqirY0YXBAOcyXck30CVfU7WiKL2XBZbej0lxBbb6I5BrY3TADPT2aVwUgIb-roat_zF1oR59MT1T319A3kspZ36MKoAK5iYMrv7xoZg](https://lh6.googleusercontent.com/WMN7r3x_ACrSTfKP_wgFPrpMt5L7X3Rqygd48mH7m-Wff7LR0ofo4_FYCURIe7dbpT1sVuzEURCVdsmbxYtqirY0YXBAOcyXck30CVfU7WiKL2XBZbej0lxBbb6I5BrY3TADPT2aVwUgIb-roat_zF1oR59MT1T319A3kspZ36MKoAK5iYMrv7xoZg)

We can use this `FORMAT_DATE` Airscript in a Transform Function for both the Start of the Day and End of the Day Variable.

<[https://support.airkit.com/reference/format_datetime](https://support.airkit.com/reference/format_datetime)>

Now we will need information from Google Calendar API to find the busy times so we will leverage the integration we set up already. In order to make this request, we will use HTTP Request Data operation and use the following settings:

-   Service: Google Calendar API
-   Method: POST
-   URL: “[https://www.googleapis.com/calendar/v3/freeBusy](https://www.googleapis.com/calendar/v3/freeBusy)“
-   Content Type: “application/json”
-   Body will use results from previous Data Operations show in the screen shot below

![This image has an empty alt attribute; its file name is gd9SkwiM7Zk4e4jZ6Ae0Ee8P6BgT5QDay0_W4fIGkfuWt1SnYn9icP-GodPaKWSKaPO7DV_G6xEBOhb4jiaD_PB3JRxFOohIb9TNFaizssta1sVFx4VRtGw4nAFT3rNa1Enc-cVLDWd1ygByPBFBuX2gsSjnwJfwrlea8zqFtTExogt434INe9mIaQ](https://lh3.googleusercontent.com/gd9SkwiM7Zk4e4jZ6Ae0Ee8P6BgT5QDay0_W4fIGkfuWt1SnYn9icP-GodPaKWSKaPO7DV_G6xEBOhb4jiaD_PB3JRxFOohIb9TNFaizssta1sVFx4VRtGw4nAFT3rNa1Enc-cVLDWd1ygByPBFBuX2gsSjnwJfwrlea8zqFtTExogt434INe9mIaQ)

The resulting busy time slots will look like the following:

![This image has an empty alt attribute; its file name is X-Cl7pDhqPONvC1rYEXVW0HzFiT8VnM6ABjuKaFlsGOtaHcNyQlNYfCwRwD9CrOi5D4uTGW7IeSKp5kvcU-aDWyPv_dff2GUF8gNZmPlPEUuy3NEQ7KwzT4hbHrttRZZ5rmIrXk4rbICYfroHaI1xuPlnL1DNSjgNENE5wQZocLXMmYat8IkHkS2IA](https://lh5.googleusercontent.com/X-Cl7pDhqPONvC1rYEXVW0HzFiT8VnM6ABjuKaFlsGOtaHcNyQlNYfCwRwD9CrOi5D4uTGW7IeSKp5kvcU-aDWyPv_dff2GUF8gNZmPlPEUuy3NEQ7KwzT4hbHrttRZZ5rmIrXk4rbICYfroHaI1xuPlnL1DNSjgNENE5wQZocLXMmYat8IkHkS2IA)

**Merge Objects Data Flow:** Since we have a few time slot objects, we will need to bring some different object data together and we will create and use another Data Flow called Merge Objects. This Data Flow will use the Airscript Function `[MERGE_OBJECT](https://support.airkit.com/reference/merge_objects)`. Refer to the YouTube Video for more details on this Data Flow.

Additionally there will be some additional time formatting needed to produce a list of 30 minute available time slots. Key Airscript functions will be  [`TIME_FROM_FORMAT`](https://support.airkit.com/reference/time_from_format),  [`UPDATE_TIMEZONE`](https://support.airkit.com/reference/update_timezone), and  [`DATETIME_FROM_FORMAT`](https://support.airkit.com/reference/datetime_from_format)  refer to the documentation to learn more about these functions.

**Generate 30 min Slots Data Flow:** To generate a list of available time slots, we will create another supporting Data Flow called “Generate 30 min slots”. This Data Flow will take two inputs of start_time and end_time and create an object with a list of slots in 30 minute increments. In order to accomplish the list, use a  [Query Expression](https://support.airkit.com/docs/filtering-data-using-query-expression)  to create the list.

![This image has an empty alt attribute; its file name is s6EIGdrgA5O0Yq9Ga_J85OUNWNI0tjhrL03BQgnJQNgGnevHYum0DQ5C2L3b_O2_WRDR-iDHA8vWznPN6CfUFtK6eHgOeIcz_bE5dRi1K2ydH-Y8-8tvGPpU62YFub7_ty8Rv1sOD5WMM_xgjHdiBm93RIulQ4_weFitWr3qH-WRlioZeMDJni6kjg](https://lh4.googleusercontent.com/s6EIGdrgA5O0Yq9Ga_J85OUNWNI0tjhrL03BQgnJQNgGnevHYum0DQ5C2L3b_O2_WRDR-iDHA8vWznPN6CfUFtK6eHgOeIcz_bE5dRi1K2ydH-Y8-8tvGPpU62YFub7_ty8Rv1sOD5WMM_xgjHdiBm93RIulQ4_weFitWr3qH-WRlioZeMDJni6kjg)

The list of time slots will be used later when we build the Airkit application.

Now we will create the last three Data Flows which will schedule the Calendar event and create a Zoom Meeting. We will create another main Data Flow called “**Schedule Event**” and two supporting Data Flows: “**Create Zoom Meeting**” and “**Create Google Calendar Event**”.

![This image has an empty alt attribute; its file name is qbs9Usdpx-W-pfDkMXW6jQo9LQKPxTneAPxGBI4Im1AWeszuY7qkmmNcv42qRWK2BVq86g1_IcYd8rooNsrKyTeG6FlQgdexVHWASyspDcmephqU2Hz7r7AIiv5Sg3kz4fyDnJMBhZo-akZ2tTbyY_6NOCOAoc6tyqFrbcWmf_mXgkwg34XWr49naA](https://lh5.googleusercontent.com/qbs9Usdpx-W-pfDkMXW6jQo9LQKPxTneAPxGBI4Im1AWeszuY7qkmmNcv42qRWK2BVq86g1_IcYd8rooNsrKyTeG6FlQgdexVHWASyspDcmephqU2Hz7r7AIiv5Sg3kz4fyDnJMBhZo-akZ2tTbyY_6NOCOAoc6tyqFrbcWmf_mXgkwg34XWr49naA)

**Create Zoom Meeting Data Flow:** Let’s build this Data Flow! This Data Flow takes an input of starting time and a list of emails and then makes a HTTP request to Zoom for the meeting information.

We will use the Zoom API integration we configured before and will use the HTTP Request Data operation with the following settings:

-   Service: Zoom OAuth API
-   Method: POST
-   URL: “https://api.zoom.us/v2/users/me/meetings”
-   Content type: “application/json”
-   Body will need the following parameters modified:
    -   “`schedule_for`” : <enter in email address for hosting party>
    -   “`Meeting_invitees`” : Use a query expression to all the emails to send invites to
        -   FROM email IN `list_of_emails` SELECT `{ “email”: email }`
    -   “`start_time`” : Use the start time and format appropriately for Zoom
        -   `“{{FORMAT_DATETIME(start_time, “yyyy-MM-ddTHH:mm:ss”)}}”`

![This image has an empty alt attribute; its file name is JLXFzwVHVbY1LySZr0FhSqlrE18smYx4SQSMQBp0jNx5DQksNCHZSoLh9q3tM4a7Bu_bJqIMHm1HPwYykk6Zn8VMKCbdrdmunqSAbdSJEatx510lbSgDwY72Uw03fgsmgyEqVHgaGVJNCu7XGaGkWEKCIKCt6iWzBXi5AZd9UYcZJ0GkmmCce55UZw](https://lh6.googleusercontent.com/JLXFzwVHVbY1LySZr0FhSqlrE18smYx4SQSMQBp0jNx5DQksNCHZSoLh9q3tM4a7Bu_bJqIMHm1HPwYykk6Zn8VMKCbdrdmunqSAbdSJEatx510lbSgDwY72Uw03fgsmgyEqVHgaGVJNCu7XGaGkWEKCIKCt6iWzBXi5AZd9UYcZJ0GkmmCce55UZw)

The result can be customized accordingly with a Transform operation and then sent back to the  **“Schedule Event”**  Data Flow to be used in the “**Create Google Calendar Event**” Data Flow.

**Create Google Calendar Event Data Flow:** Let’s build it! This Data Flow takes the input of the following variables: `summary`, `start_time`, `end_time`, `list_of_emails`, and a `description`. And then makes a HTTP request to Google Calendar API to create a Google Calendar Meeting.

We will use the Google Calendar API integration we configured before and will use the HTTP Request Data operation with the following settings:

-   Service: Google Calendar API
-   Method: POST
-   URL: “[https://www.googleapis.com/calendar/v3/calendars/primary/events?conferenceDataVersion=1″](https://www.googleapis.com/calendar/v3/calendars/primary/events?conferenceDataVersion=1%22)“
-   Content type: “application/json”
-   Body:

    { “summary”: summary,
    
    “start”: { “dateTime”: FORMAT_DATETIME(start_time) },
    
    “end”: { “dateTime”: FORMAT_DATETIME(end_time) },
    
    “attendees”: FROM a IN emails SELECT { “email”: a },
    
    “description”: description}

![This image has an empty alt attribute; its file name is wpYX9i2OvY8PNAL2Fg9z7i1VuHc5nghzU0xhKwXopfs0pLTlc6b-IfZBFSJvQRZHt2YkvRJfK_SZWLo2cxd81qNtPUgjHX299b5T3IgWOAYCQU15bZsyW44GEL8ufPmn3zTL4t_sf-zL53Kl8s7TLNLI5DAyKCbAhv0Nj6CfzI7-X0VBXNjgSz_q7Q](https://lh3.googleusercontent.com/wpYX9i2OvY8PNAL2Fg9z7i1VuHc5nghzU0xhKwXopfs0pLTlc6b-IfZBFSJvQRZHt2YkvRJfK_SZWLo2cxd81qNtPUgjHX299b5T3IgWOAYCQU15bZsyW44GEL8ufPmn3zTL4t_sf-zL53Kl8s7TLNLI5DAyKCbAhv0Nj6CfzI7-X0VBXNjgSz_q7Q)

**Schedule Event Data Flow:** Let’s build it now! This is the main Data Flow which brings all the necessary data together to create the Google Calendar Event. The Input data variables are the following: selected_time, name, email, list_guest_email, and preparation notes which all will come from a web page form built later in the Building Airkit Application section. See the screenshot below to see how the Data Flows are configured or continue to watch the Youtube Video to see how this app is built.

![This image has an empty alt attribute; its file name is MqIMYHw6YjACVFUNbf8nRUXVqF_r8iieVlZkfBoz26TVpZsCHbKWXMFbqN7zfaePkSkcnGmhzv4v0tZp1eLCxV-1DkpHXRa4IPVQNbJVuJuWXot5Ukgkc-4p5CiVivdBJ42_NmBy-8pcljiSmxtEHnQKAvAg354teidAsEErhwMFyzJoExoEAqdREw](https://lh5.googleusercontent.com/MqIMYHw6YjACVFUNbf8nRUXVqF_r8iieVlZkfBoz26TVpZsCHbKWXMFbqN7zfaePkSkcnGmhzv4v0tZp1eLCxV-1DkpHXRa4IPVQNbJVuJuWXot5Ukgkc-4p5CiVivdBJ42_NmBy-8pcljiSmxtEHnQKAvAg354teidAsEErhwMFyzJoExoEAqdREw)

![This image has an empty alt attribute; its file name is SatVBT50r4QkrnlwaPXVbmu4J-y5DWaxg9Gm48Hs60LL2G_jlq9YNZhGyagl2w4w2HhR67TcATg_BWG55-nnbuAoNTYwbX0Sd9ftDNuUhvr_X9-zRZZ6dE-qWk81Iw-jBd2XSzG-zRaxRUyMRPpaIs6z9Oh1pm0XAtw9_WJ7GHCstAWSjRSg1-bObQ](https://lh3.googleusercontent.com/SatVBT50r4QkrnlwaPXVbmu4J-y5DWaxg9Gm48Hs60LL2G_jlq9YNZhGyagl2w4w2HhR67TcATg_BWG55-nnbuAoNTYwbX0Sd9ftDNuUhvr_X9-zRZZ6dE-qWk81Iw-jBd2XSzG-zRaxRUyMRPpaIs6z9Oh1pm0XAtw9_WJ7GHCstAWSjRSg1-bObQ)

## Building the Airkit Application

Now we have the integrations and Data Flows ready for use in Airkit Application, next we will need to build out the application for self-service appointment scheduling.
In Journey Builder, add a Visit a Link Trigger to start the application, and add a webflow in the first Journey step. Then in Web Builder, we will make three Web Pages. On the first page, a self-service appointment scheduler, we will add the following key controls: Label, Container, Date Picker and Container List with two Buttons. Make sure you label all the controls appropriately.

The Web Page Tree should look like the following example:

![This image has an empty alt attribute; its file name is GxfMkubV1mZA_gZIqc7iIX77EavUIepp071Jy_GFn52sP_YxbKgMCY41zq6lSDuE8fRR8YA3ZCoBdhhkq5j5WotjN7_A2BwG5FKGZwMSzGWfVEzH79ImK0Ob6WpmghmZpmZIv2eplGoEU7wpQKwvaYiwAexU3s0Nu-UE2OzYVhfS01RDTHU7RIzZ7Q](https://lh6.googleusercontent.com/GxfMkubV1mZA_gZIqc7iIX77EavUIepp071Jy_GFn52sP_YxbKgMCY41zq6lSDuE8fRR8YA3ZCoBdhhkq5j5WotjN7_A2BwG5FKGZwMSzGWfVEzH79ImK0Ob6WpmghmZpmZIv2eplGoEU7wpQKwvaYiwAexU3s0Nu-UE2OzYVhfS01RDTHU7RIzZ7Q)

After you add these controls you can configure labels appropriately similar to what is shown in the Youtube Video or the screenshot below:

![This image has an empty alt attribute; its file name is uOyG4rpdFpkQp5CxLg82fbamTW9WdknjD2VnzFCKepskXzrhzxria7Wiwh0Z9XX7kXWEBJQh3lnzaWPu-YqJ_bOdwv1FoFhD4AHLM5TY8G-goyG0GH0JS5mqzjtc8DEdWMIVxnMPruYz4X6Cm32_wiJ-Ef8htrVdDXB2lZrt1xKNvz3oqS_z5cXteA](https://lh3.googleusercontent.com/uOyG4rpdFpkQp5CxLg82fbamTW9WdknjD2VnzFCKepskXzrhzxria7Wiwh0Z9XX7kXWEBJQh3lnzaWPu-YqJ_bOdwv1FoFhD4AHLM5TY8G-goyG0GH0JS5mqzjtc8DEdWMIVxnMPruYz4X6Cm32_wiJ-Ef8htrVdDXB2lZrt1xKNvz3oqS_z5cXteA)

Next, we will configure the controls for the Date and Time Slot Selection. First we will configure the Date Picker control. You will configure the Control Properties as shown below to get a one month layout.

![This image has an empty alt attribute; its file name is vlFqoLIIafApCu6VJ5Zj3MSMTlUFCQh92VLBVqgdIRdBjJjDjS7967D_J1GOkTtOeanMUFs09_ESeeqJsf1eKJh9oafL4wzKWJr6HZvQgjrHRMsMae8BOw1m7V5HbO-31I8Iwnc3ItJpl3Y_D63PR9lQZSAg5bVLVUiIQkyt2j8Iwd9n6mqd2x3bnw](https://lh5.googleusercontent.com/vlFqoLIIafApCu6VJ5Zj3MSMTlUFCQh92VLBVqgdIRdBjJjDjS7967D_J1GOkTtOeanMUFs09_ESeeqJsf1eKJh9oafL4wzKWJr6HZvQgjrHRMsMae8BOw1m7V5HbO-31I8Iwnc3ItJpl3Y_D63PR9lQZSAg5bVLVUiIQkyt2j8Iwd9n6mqd2x3bnw)

The selection of the date has a concurrent action of calling a Data Flow which gets all available time slots for that particular day. We use the “**Get Free Slots”**  Data Flow, which will extract information from Google Calendar. See the screenshot for the variables to update.

![This image has an empty alt attribute; its file name is Q47wTOYqyjrsU-fyXXekJ45C7Q_9svVBU_mXOzDAXjtzK1vDGniK838Mc7bjWd8mBvzZXCSQuX9gMKKs9DbjIF9N39q-AvM0Ic_iIdBbdQvJpMVS-UgbtcZBL0xszwql1d8qPGtkMsNA8FRzf9r7a4ov1Ra83pf4KgUgpmOoKfXUXN0ZFQFEy0hkqw](https://lh6.googleusercontent.com/Q47wTOYqyjrsU-fyXXekJ45C7Q_9svVBU_mXOzDAXjtzK1vDGniK838Mc7bjWd8mBvzZXCSQuX9gMKKs9DbjIF9N39q-AvM0Ic_iIdBbdQvJpMVS-UgbtcZBL0xszwql1d8qPGtkMsNA8FRzf9r7a4ov1Ra83pf4KgUgpmOoKfXUXN0ZFQFEy0hkqw)

The variable `session.availability` will have all the time slot data which will populate the buttons in the Container List control. The application will show a list of buttons with the available time slots.

Once a time slot is selected and confirmed via the Confirm Button control, the application will move to the next Web Page “Enter Details and Confirm”.

On the second page, “Enter Details and Confirm”, we will create a scheduled event form where a user can create a meeting, add guests to the email guest list, add any notes to the meeting and then schedule the appointment. We will be adding another set of controls: Container, Label, Text Input, Text Area Input and Button. Make sure you label all the controls appropriately.

![This image has an empty alt attribute; its file name is tsdcEYQHaylXYaqmxi3NTHFPNUKGkAEGTU3DOuQhFycW4so5zBG9dpltdb07AHH80TFUkyHC6R-yhycXBSegg8XNJhlq-m9anZPhieYj6wevL2Se1nCsspSYRVmGVbfvB8JHV12-RtO1zPBvfMHAlJ8tZ7hPZAPdZ_xZLCFhyk8aawGh7GUKa3wBNQ](https://lh3.googleusercontent.com/tsdcEYQHaylXYaqmxi3NTHFPNUKGkAEGTU3DOuQhFycW4so5zBG9dpltdb07AHH80TFUkyHC6R-yhycXBSegg8XNJhlq-m9anZPhieYj6wevL2Se1nCsspSYRVmGVbfvB8JHV12-RtO1zPBvfMHAlJ8tZ7hPZAPdZ_xZLCFhyk8aawGh7GUKa3wBNQ)

The Schedule Event button action unifies all the inputs from the initial page and current page via the “Schedule Event Data Flow” in order to create a Google Calendar Event with a Zoom Meeting. See the screenshot below:

![This image has an empty alt attribute; its file name is yhvNr8BYCMtG-Ej0KYal3JEQWCS40885UsMAm4cpMLK53Ss4uTovNA4hJ1UuNGusBvy-_KfjUwyEjSs0yH9Ec3ZP5wNt7YD1LZqqLm1i3UznUZT6Vv2051IGlNgIrScezGTAlgRXp3Iu_el271znYmUof79ExB2diGV5FCwi7yH5xghRc8G0b4uWBA](https://lh4.googleusercontent.com/yhvNr8BYCMtG-Ej0KYal3JEQWCS40885UsMAm4cpMLK53Ss4uTovNA4hJ1UuNGusBvy-_KfjUwyEjSs0yH9Ec3ZP5wNt7YD1LZqqLm1i3UznUZT6Vv2051IGlNgIrScezGTAlgRXp3Iu_el271znYmUof79ExB2diGV5FCwi7yH5xghRc8G0b4uWBA)

After the event is scheduled, the user is sent to the Thank You page.

On the final page, a Thank you page, add a label which thanks the user for scheduling an appointment.

![This image has an empty alt attribute; its file name is 1Drc1ohl9WX_JxYxHR1ngelBocIyK8Uzsz9RG4pf-aZFmwHq21fOPlnLCIp0ysxOGqPYISJ6savcNjyzB0dUUPl9SFmFYl4YULNPcXFQea9kFh41RWSiUsAztVYpo4vTaMM-P6QpkBKuwXEXTF-3BTyTB7B_5nmelIsv2uYw5fDQfE8-L14GJZGSSg](https://lh3.googleusercontent.com/1Drc1ohl9WX_JxYxHR1ngelBocIyK8Uzsz9RG4pf-aZFmwHq21fOPlnLCIp0ysxOGqPYISJ6savcNjyzB0dUUPl9SFmFYl4YULNPcXFQea9kFh41RWSiUsAztVYpo4vTaMM-P6QpkBKuwXEXTF-3BTyTB7B_5nmelIsv2uYw5fDQfE8-L14GJZGSSg)

## Wrap Up

Hopefully this walkthrough has been a helpful guide on how to create a calendly clone on your own.

Even this build has room to add additional functionality! You could upload additional documents for the meeting to the calendar invite via the File Upload control. You could change the video conference link by creating a new API integration with Microsoft Teams or any other video conferencing service. Try adding new features of your own and let us know what you build!