3

I am trying to create a new calendar in my Google account using Javascript (through the Google Apps Script editor).

First, to make sure my Oauth2 is working with the Calendar API, I make a GET request to get my primary calendar:

var email = 'me@mydomain.com';

var fetchArgs = {};
fetchArgs.headers = {'Authorization': 'Bearer '+ calendarOauth2Service.getAccessToken() };
fetchArgs.method = 'GET';
fetchArgs.muteHttpExceptions = true;

var url = 'https://www.googleapis.com/calendar/v3/calendars/' + email;

var response = UrlFetchApp.fetch(url, fetchArgs);

The request is successful and returns this response:

{
 "kind": "calendar#calendar",
 "etag": "\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"",
 "id": "me@mydomain.com",
 "summary": "me@mydomain.com",
 "timeZone": "America/New_York"
}

Now I want to use the insert method to add a calendar to my account:

var calendarResource = {
       "summary": "test calendar title"
      };

var fetchArgs = {};
fetchArgs.headers = {'Authorization': 'Bearer '+ calendarOauth2Service.getAccessToken() };
fetchArgs.method = "POST";
fetchArgs.data = calendarResource;
fetchArgs.muteHttpExceptions = true;

var url = 'https://www.googleapis.com/calendar/v3/calendars';

var response = UrlFetchApp.fetch(url, fetchArgs);

The calendar is not created, and this is the response:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "required",
    "message": "Missing title."
   }
  ],
  "code": 400,
  "message": "Missing title."
 }
}

I've been working on this for almost 20 hours straight now (not an exaggeration) and I can't figure it out. I've tried the following things:

  1. Changing fetchArgs.data = calendarResource; to fetchArgs.body = calendarResource;
  2. Changing fetchArgs.data = calendarResource; to fetchArgs.resource = calendarResource;
  3. Changing fetchArgs.data = calendarResource; to fetchArgs.payload = calendarResource;
  4. Changing fetchArgs.data = calendarResource; to fetchArgs.summary = calendarResource;
  5. Changing fetchArgs.data = calendarResource; to fetchArgs.title = calendarResource;
  6. Moving fetchArgs.data = calendarResource; in to the fetchArgs.header object
  7. Moving fetchArgs.method = "POST"; in to the fetchArgs.header object
  8. Adding fetchArgs.contentType = 'application/json; to both the fetchArgs object and the fetchArgs.header object
  9. And many other things, can't think of them all right now

There aren't that many questions related to this on SO. These are the ones I've been trying things from:

Google Calendar REST API errors

Google Calendar.Insert API returning 400 'required'

Here is my original question in which I was trying to do this for another calendar on my Google Apps domain, but since I wasn't able to get that to work, I decided to create this question to remove the domain-wide delegation issue from the equation and just focus on the API call.

Also, one more thing worth mentioning: I am able to successfully create the calendars using the APIs Explorer on the Google Calendar API Calendars: insert documentation page.

It shows me that the request was this:

POST https://www.googleapis.com/calendar/v3/calendars
{
 "summary": "test calendar title"
}

And the response was this:

200 OK
- HIDE HEADERS -
cache-control:  no-cache, no-store, max-age=0, must-revalidate
content-encoding:  gzip
content-length:  193
content-type:  application/json; charset=UTF-8
date:  Sat, 22 Aug 2015 14:34:05 GMT
etag:  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
expires:  Fri, 01 Jan 1990 00:00:00 GMT
pragma:  no-cache
server:  GSE
vary:  Origin, X-Origin
{

 "kind": "calendar#calendar",
 "etag": "\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"",
 "id": "mydomain.com_xxxxxxxxxxxxxxxxxxxxx@group.calendar.google.com",
 "summary": "test calendar title"
}

Any ideas?

Update with the working code based on luc's answer below:

The resource needs to be stringified (the Google Apps Script debugger was showing that it is an object, not a string).

var calendarResource = {
       "summary": "test calendar title"
      };

var fetchArgs = {};
fetchArgs.headers = {'Authorization': 'Bearer '+ calendarOauth2Service.getAccessToken() };
fetchArgs.method = "POST";
fetchArgs.payload = JSON.stringify(calendarResource);
fetchArgs.muteHttpExceptions = true;

var url = 'https://www.googleapis.com/calendar/v3/calendars';

var response = UrlFetchApp.fetch(url, fetchArgs);
Community
  • 1
  • 1
Employee
  • 2,231
  • 3
  • 33
  • 60

1 Answers1

4

First of all, I suspect you should be setting the payload, not data. Second of all the passed in object won't be interpreted as JSON unless you tell it to (JSON.stringify(calendarResource)).


For users working with JavaScript in a Browser environment:

When debugging you should try printing the request that ends up sent (or look at it in the browser through the developer tools) and compare it to the one from the explorer.

Also using the JavaScript client library could save you some troubles. Have you seen this tutorial? https://developers.google.com/google-apps/calendar/quickstart/js

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
luc
  • 3,642
  • 1
  • 18
  • 21
  • luc, you are my hero. Setting the resource property to be called `payload`, using `JSON.stringify` on the resource value, and including the property `contentType: 'application/json'` worked! I will update my question now to include the complete code. Also, I took a look at the [Javascript Client Library](https://goo.gl/Enb90) but I'm not sure if it's possible to be used in the sandboxed Google Apps Script editor. I'll test it out. – Employee Aug 23 '15 at 13:48
  • Also, just want to mention that at one point while pulling my hair out I think I basically tried stringifying the resource myself like so: `var calendarResource = '{"summary": "test calendar title"}';`, which might have worked if the contentType and resource property were correct. JSON.strigify is awesome though. – Employee Aug 23 '15 at 14:08