title: Google Apps Script create calendar event from sheet forbidden?
body: <p>In a document-bound Google Appscript in one of our company spreadsheets, I've created a script that turns spreadsheet lines into Google calendar appointments. The function works fine for me, but not for my coworker, even though we both have permissions to edit the calendar and change sharing permissions, and my coworker proved he can create appointments on the calendar from calendar.google.com.</p>
  
  <p>He gets the following error message when he runs the script:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>{"message":"Forbidden","name":"GoogleJsonResponseException","fileName":"SCHEDULER","lineNumber":204,"stack":"\tat SCHEDULER:204 (createAppointments)\n"}</code></pre>
  </div>
  </div>
  </p>
  
  <p>Line 204 corresponds to the command:</p>
  
  <pre><code> Calendar.Events.insert(event, CAL, {sendNotifications: true, supportsAttachments:true});
  </code></pre>
  
  <p>If he has edit rights to the calendar, why is this forbidden? Is there a problem with the Calendar service in Google Apps Script? What is more, I changed the CAL variable to a calendar I personally created and shared out to him with the same permissions. He can edit that calendar just fine.</p>
  
  <p>Here is the psuedocode for the function</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>function createAppointments() {
      
     var CAL = 'companyname.com_1v033gttnxe2r3eakd8t9sduqg@group.calendar.google.com';
    
      for(/*each row in spreadsheet*/) 
      { 
        if(/*needs appointment*/)
        { 
          var object = {/*...STUFF...*/};
          var coworker = 'coworker@companyname.com';
          var timeArgs = {start: /*UTC Formatted time*/, end: /*UTC Formatted time*/}
          
          if(/*All the data checks out*/{
            var summary = 'Name of appointment'
            var notes = 'Stuff to put in the body of the calendar appointment';
            var location = '123 Happy Trail, Monterrey, TX 12345'
            
            //BUILD GOOGLE CALENDAR OBJECT
            var event = {
              "summary": summary,
              "description": notes,
              "start": {
                "dateTime": timeArgs.start,
                "timeZone": TZ
              },
              "end": {
                "dateTime": timeArgs.end,
                "timeZone": TZ
              },
              "guestsCanInviteOthers": true,
              "reminders": {
                "useDefault": true
              },
              "location": location
              //,"attendees": []
            };
            event.attendees = [{coworker@companyname.com, displayName: 'coworker name'}];
            
            //CREATE CALENDAR IN GOOGLE CALENDAR OF CONST CAL
            Calendar.Events.insert(event, CAL, {sendNotifications: true, supportsAttachments:true});
          
        } else{/*Tell user to fix data*/}
      }  
    }</code></pre>
  </div>
  </div>
  </p>
  
  <p>Thank you very much!</p>
  
  <hr>
  
  <p><b>Update 12/29/2017:</b></p>
  
  <p>I've Tried adjusting the app according to Jason Allshorn and Crazy Ivan. Thank you for your help, so far! Interestingly, I have run into the same response using both the Advanced Calendar Service and the CalendarApp.</p>
  
  <p>The error is, as shown below:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;head&gt;&lt;link rel="shortcut icon" href="//ssl.gstatic.com/docs/script/images/favicon.ico"&gt;&lt;title&gt;Error&lt;/title&gt;&lt;style type="text/css"&gt;body {background-color: #fff; margin: 0; padding: 0;}.errorMessage {font-family: Arial,sans-serif; font-size: 12pt; font-weight: bold; line-height: 150%; padding-top: 25px;}&lt;/style&gt;&lt;/head&gt;&lt;body style="margin:20px"&gt;&lt;div&gt;&lt;img alt="Google Apps Script" src="//ssl.gstatic.com/docs/script/images/logo.png"&gt;&lt;/div&gt;&lt;div style="text-align:center;font-family:monospace;margin:50px auto 0;max-width:600px"&gt;Object does not allow properties to be added or changed.&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Or, after parsing that through an html editor:</p>
  
  <p><a href="https://i.stack.imgur.com/1oqAD.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/1oqAD.png" alt="enter image description here"></a></p>
  
  <p>What does that even mean? I have the advanced service enabled, and the script is enabled to run from anyone. Any ideas?</p>
  
  <p>I have confirmed after testing what the error comes back after trying to run the calendarApp/Advanced Calendar event creation command.</p>
  
  <p>Here is my code that caused me to get this far:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>function convertURItoObject(url){  
        url = url.replace(/\+/g,' ')
        url = decodeURIComponent(url)
        var parts = url.split("&amp;");
        var paramsObj = {};
        parts.forEach(function(item){
           var keyAndValue = item.split("=");
           paramsObj[keyAndValue[0]] = keyAndValue[1]
        })  
       return paramsObj; // here's your object
      }
  
  
  function doPost(e) { 
    var data = e.postData.contents;
    data = convertURItoObject(data);
    
    var CAL = data.cal;
    var event = JSON.parse(data.event);
    var key = data.key;
    
    var start = new Date(event.start.dateTime);
    
    if(ACCEPTEDPROJECTS.indexOf(key) &gt; -1)
    {
      try{
      var calendar = CalendarApp.getCalendarById(CAL);
      calendar.createEvent(event.summary, new Date(event.start.dateTime), new Date(event.end.dateTime), {description: event.description, location: event.location, guests: event.guests, sendInvites: true});}
      
      
      /*try {Calendar.Events.insert(event, CAL, {sendNotifications: true, supportsAttachments:true});} Same error when I use this command*/ 
      catch(fail){return ContentService.createTextOutput(JSON.stringify(fail));}
      
      e.postData.result = 'pass';
      return ContentService.createTextOutput(JSON.stringify(e)); 
    }
    else {
      return ContentService.createTextOutput('Execution not authorized from this source. See CONFIG of target project for details.'); 
    }
  }</code></pre>
  </div>
  </div>
  </p>