The following blog post is a continuation from the connecting to the Zoom API via OAuth one here (please familiarise yourself with it before proceeding). In addition to this post for getting your Zoom meeting settings via the API.
We have already demonstrated successfully getting an Access Token for authentication from Zoom OAuth and then getting our Zoom meeting settings. Now that we have those items we can go ahead and create a Zoom meeting, as we will do here. You may find this page on creating a meeting via the API useful.
Zoom meeting details in a Google Sheet |
Again we have a Google Sheet with the Apps Script linked to it. We have various details of the meeting that can be entered into the Sheet as well as some of the meeting settings we captured in the last blog post. The Apps Script is configured to pick-up these individual pieces of information to help show how they are being used.
One of the more difficult pieces of information to handle is the start date/time which needs to be formatted as ISO 8601 Extended format: yyyy-mm-ddThh:mm:ss.000
// get and format the Start date/time
var startDate_Time = ss.getRange(4, 2).getValue();
var startDate = new Date(startDate_Time);
var startHour = startDate.getUTCHours();
var startMin = startDate.getUTCMinutes();
var formattedStartDate = Utilities.formatDate(startDate, timeZone, "yyyy-MM-dd");
// recombine above parts to created suitably formatted date
var startTime = formattedStartDate + 'T' + startHour + ':' + startMin + ':' + '00' + '.000';
Where boolean values are required ('true', 'false') we need to convert them from text on the Google Sheet:
// get the Host video setting and convert to Boolean
var hostVideo = ss.getRange(7, 2).getValue();
if (hostVideo == "True") {
hostVideo = true;
}
else {
hostVideo = false;
}
Next we combine all of the values into a payload for the API:
var payload = {
"topic": topic,
"type": 2,
"start_time": startTime,
"timezone": timeZone,
"duration": duration,
"agenda": agenda,
"password": password,
"settings": {
"host_video": hostVideo,
"participant_video": participantsVideo,
"join_before_host": beforeHost,
"mute_upon_entry": entryMute,
"waiting_room": waitingRoom
}
};
We can then set the HTTP headers and include the Access Token as we get ready to make the API call:
// set the HTTP headers and include the Access Token for authentication
var options = {
'method': "post",
'contentType': "application/json",
'headers': {
"Authorization": "Bearer " + accessToken
},
'payload': JSON.stringify(payload)
};
Now we can make the call to the User Meetings API as specified by the Zoom documentation:
// make Zoom API call
var response = UrlFetchApp.fetch("https://api.zoom.us/v2/users/me/meetings", options);
Lots of information is returned so this script both puts all of that into the Google Sheet so you can see what details are available for accessing and specifically extracts the meeting ID and join URL:
// gather data from response
var resultText = response.getContentText();
var resultObj = JSON.parse(resultText);
// specifically get meeting ID and join URL
var meetingID = resultObj['id'];
saveIntoSheet(joinURL, 14);
File Download
Download the Create a Zoom meeting via the API here. Please use 'File' > 'Make a copy' for your own version. This is a Google Sheet with the Apps Script bound to it. You will need to deploy it as a Web App and create your own Zoom OAuth App.
/* | |
Function to connect to Zoom API via OAuth. | |
*/ | |
function doGet(e) { | |
// get authorisation code from returned Url | |
var authCode = JSON.stringify(e.parameter.code); | |
// remove quotes around the code | |
var authCodeClean = authCode.replace(/['"]+/g, ''); | |
// run Function to add to Spreadsheet | |
saveIntoSheet(authCodeClean, 1) | |
// run Function to get Token from AuthCode | |
var accessToken = getToken(authCodeClean); | |
// check status of Access Token and run subsequent Function | |
if (accessToken) { | |
// run Function to create a Zoom meeting via the API | |
createZoomMeeting(accessToken); | |
// return message to webpage to inform user | |
return HtmlService.createHtmlOutput('Success! You can close this tab.'); | |
} | |
else { | |
// there was a problem getting Authentication Code | |
// return message to webpage to inform user | |
return HtmlService.createHtmlOutput('Failed. You can close this tab'); | |
} | |
} | |
// use Authorisation Code to get a Token | |
function getToken(authCodeClean) { | |
// set authentication and get OAuthKeys | |
var clientID = "ENTER YOUR APP ID HERE"; | |
var clientSecret = "ENTER YOUR APP SECRET HERE"; | |
var encodedKeys = Utilities.base64Encode(clientID + ":" + clientSecret); | |
// set the HTTP headers | |
var options = { | |
'method': "post", | |
'headers': {"Authorization": "Basic " + encodedKeys}, | |
}; | |
// Web App URL linked to Zoom OAuth App | |
var returnUrl = "ENTER YOUR WEB APP URL HERE"; | |
// make Zoom OAuth call | |
var response = UrlFetchApp.fetch("https://zoom.us/oauth/token?grant_type=authorization_code&code=" + authCodeClean + "&redirect_uri=" + returnUrl, options); | |
// run Function to add Access Token to Spreadsheet | |
var resultText = response.getContentText(); | |
var resultObj = JSON.parse(resultText); | |
var accessToken = resultObj['access_token']; | |
saveIntoSheet(accessToken, 2); | |
// return the Access Token value to the Parent Function | |
return accessToken; | |
} | |
// Function to copy values into the Google Sheet. | |
function saveIntoSheet(value, row) { | |
var ss = SpreadsheetApp.getActiveSheet(); | |
var cell = ss.getRange(row, 2); | |
cell.setValue(value); | |
return; | |
} | |
/* | |
Function to create a Zoom meeting via the API, using values | |
from the Google Sheet. | |
*/ | |
function createZoomMeeting(accessToken) { | |
// get the Google Sheet so we can then get the values from it | |
var ss = SpreadsheetApp.getActiveSheet(); | |
// get the Topic | |
var topic = ss.getRange(3, 2).getValue(); | |
// get the TimeZone | |
var timeZone = SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(); | |
// get and format the Start date/time | |
var startDate_Time = ss.getRange(4, 2).getValue(); | |
var startDate = new Date(startDate_Time); | |
var startHour = startDate.getUTCHours(); | |
var startMin = startDate.getUTCMinutes(); | |
var formattedStartDate = Utilities.formatDate(startDate, timeZone, "yyyy-MM-dd"); | |
// recombine above parts to created suitably formatted date | |
var startTime = formattedStartDate + 'T' + startHour + ':' + startMin + ':' + '00' + '.000'; | |
// get the Duration | |
var duration = ss.getRange(5, 2).getValue(); | |
// get the Agenda (Description) | |
var agenda = ss.getRange(6, 2).getValue(); | |
// generate a random string to use for password | |
var uniqueValue = Utilities.getUuid(); | |
var password = uniqueValue.slice(0, 8); // get first 8 characters | |
// get the Host video setting and convert to Boolean | |
var hostVideo = ss.getRange(7, 2).getValue(); | |
if (hostVideo == "True") { | |
hostVideo = true; | |
} | |
else { | |
hostVideo = false; | |
} | |
// get the Participants video setting and convert to Boolean | |
var participantsVideo = ss.getRange(8, 2).getValue(); | |
if (participantsVideo == "True") { | |
participantsVideo = true; | |
} | |
else { | |
participantsVideo = false; | |
} | |
// get the Join before host setting and convert to Boolean | |
var beforeHost = ss.getRange(9, 2).getValue(); | |
if (beforeHost == "True") { | |
beforeHost = true; | |
} | |
else { | |
beforeHost = false; | |
} | |
// get the Mute upon entry setting and convert to Boolean | |
var entryMute = ss.getRange(10, 2).getValue(); | |
if (entryMute == "True") { | |
entryMute = true; | |
} | |
else { | |
entryMute = false; | |
} | |
// get the Waiting Room setting and convert to Boolean | |
var waitingRoom = ss.getRange(11, 2).getValue(); | |
if (waitingRoom == "True") { | |
waitingRoom = true; | |
} | |
else { | |
waitingRoom = false; | |
} | |
// put together the meeting data | |
var payload = { | |
"topic": topic, | |
"type": 2, | |
"start_time": startTime, | |
"timezone": timeZone, | |
"duration": duration, | |
"agenda": agenda, | |
"password": password, | |
"settings": { | |
"host_video": hostVideo, | |
"participant_video": participantsVideo, | |
"join_before_host": beforeHost, | |
"mute_upon_entry": entryMute, | |
"waiting_room": waitingRoom | |
} | |
}; | |
// set the HTTP headers and include the Access Token for authentication | |
var options = { | |
'method': "post", | |
'contentType': "application/json", | |
'headers': { | |
"Authorization": "Bearer " + accessToken | |
}, | |
'payload': JSON.stringify(payload) | |
}; | |
// make Zoom API call | |
var response = UrlFetchApp.fetch("https://api.zoom.us/v2/users/me/meetings", options); | |
// gather data from response | |
var resultText = response.getContentText(); | |
var resultObj = JSON.parse(resultText); | |
// run Function to copy all returned data into Google Sheet | |
saveIntoSheet(resultObj,12); | |
// gather some relevant meeting details and log in Google Sheet ***************** | |
var meetingID = resultObj['id']; | |
saveIntoSheet(meetingID, 13); | |
var joinURL = resultObj['join_url']; | |
saveIntoSheet(joinURL, 14); | |
// gather some relevant meeting details and log in Google Sheet ***************** | |
return; | |
} |
Hello, Mr. Bainbridge.
ReplyDeleteGreat blog and article.
I'm new to the apps-script world so thanks in advance and i'll keep going :). just one thing, in the first paragraph the link to the 'connecting to the Zoom API via OAuth one here' leads to blogger.com so after using the search tool i've found the other article. Thanks again. :)
Hi
DeleteThank you for your feedback and for highlighting that broken link - I have now fixed it.
Kind regards
Phil
Thanks for the examples. I worked thought the last Oauth post, and got it working.
ReplyDeleteThese scripts are bound a particular sheet. To attach to a new sheet, as I understand it, I would have to copy/paste the code into a new sheet.
I guess what I want is an add-on that would have access to the sheet (for meeting info) and to Zoom to create the meetings.
But it's unclear how an add-on could also be deployed as an WebApp to allow for the OAuth flow to complete.
Hi Bob
DeleteGlad you got it working.
Yes these are bound scripts. An alternative is to make a copy of the Google Sheet itself and the Apps Script code will come along with it.
I have been exploring Add-ons last week but I'm yet to figure a way to overcome the 30 second execution time-out/limit with Functions that use the Card Service. Which means for bulk processes such as this it is not possible.
Kind regards
Phil