Adding Events to Secondary Google Calendars

Posted on timeSeptember 1st, 2008 by userRay Baxter


The most frequently asked question posed in the Google Calendar Date API Group is, “How do I add events to a secondary calendar?”

In this series of posts, I am going to attempt to provide an answer for using every language that has a client library. I discuss the “official” client libraries for Python, Php, .NET, Java and Javascript as well as the slightly less official Objective-C library and some of the attempts to create Ruby library for interacting with Google Calendar and GData. If there are other client libraries, just let me know in the comments and I’ll add instructions here, or link to them elsewhere as I have time, interest and understanding.

I start with describing how to POST XML to a calendar url. This is “The Protocol”. You should read this information about the protocol, even if you plan to use a client library. Each client library is using this protocol under the covers, so understanding what is happening will help you better use your client library. In addition, I’ll only explain some terms in this section, so you’ll need to read it to understand what I am talking about.

All information in these posts comes from the Google Developer’s Guides, the Client Library Documentation, the source code for the client library and my own exploration and testing. I’ll provide links to these resources in the text as appropriate. For simplicity’s sake, I only cover creating single-occurrence events for users that have properly authenticated using client login. These cases should be sufficient for illustrating how to add to secondary calendars, but 1) I’m not aware of any differences in creating single-occurrence versus quickadd or recurrent events on secondary calendars in any of the client libraries and 2) I haven’t used AuthSub.

I have personally tested all of the code that I present here, unless otherwise noted. That means that I was able to create an event on a calendar using that code. In all cases, I am adding events to my Secondary Calendar which is public, so have a look. I’ll be trying to add an event that occurs at the time when the relevant article is posted.

Here is a table of contents of the language-specific treatments. I’ll update the links as I complete the sections.

Python – Complete September 29, 2008
Php
.NET
Java
Javascript
Objective C
Ruby

The Protocol

To create an event on any Google Calendar you POST the appropriate XML to the calendar’s url. The easiest way to obtain the appropriate XML is to start with an existing event. The easiest way to obtain the calendar’s url, well, that’s a really the rub.

Here’s what Google says about finding the appropriate url:

To post an entry, send the following HTTP request to Calendar, using a special “default” URL (and an Authorization header; see the section on authentication above). Calendar automatically redirects the default URL to the URL of the read/write private feed of the calendar belonging to the authenticated user. (Note that you don’t have to use the default URL to send a POST request to Calendar; you can specify the user ID instead of “default” if you prefer. For more information, see the Calendar feed types reference.)

This is the source of all the confusion on the issue of creating events on secondary calendars.
As mentioned further on after this quote, the “default” URL is
http://www.google.com/calendar/feeds/default/private/full
If you specify the user ID, this would be http://www.google.com/calendar/feeds/user@gmail.com/private/full, you get another URL for the user’s primary calendar. You can POST to this url and create events.

The question is, what is the user ID for a secondary calendar? If the calendar belongs to your friend, then http://www.google.com/calendar/feeds/friend@gmail.com/private/full works. Suppose that I have created a personal calendar and a work calendar. The user ID for my personal (primary) calendar is my gmail address. What is the user ID for my work calender? My gmail address? No, that is the user ID for my personal calendar.

The problem is that Google doesn’t use the term user ID consistently and what they really mean here is what they call calendar ID in other contexts.

To get the calendar ID, there are a couple of methods.

Google suggests that you parse the calendar ID from the calendar’s edit link in the allcalendars feed. Here is the entire entry for my secondary calendar from the all calendar’s feed.

<entry>
  <id>
  http://www.google.com/calendar/feeds/default/allcalendars/full/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com</id>
  <published>2008-09-01T05:24:24.673Z</published>
  <updated>2008-09-01T04:13:31.000Z</updated>
  <title type='text'>Secondary Calendar</title>
  <summary type='text'>This calendar is for testing and
  illustrating the creation of events using the Google Calendar
  Data API on a secondary calendar.</summary>
  <content type='application/atom+xml'
  src='http://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com/private/full' />
  <link rel='alternate' type='application/atom+xml'
  href='http://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com/private/full' />
  <link rel='http://schemas.google.com/acl/2007#accessControlList'
  type='application/atom+xml'
  href='http://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com/acl/full' />
  <link rel='self' type='application/atom+xml'
  href='http://www.google.com/calendar/feeds/default/allcalendars/full/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com' />
  <link rel='edit' type='application/atom+xml'
  href='http://www.google.com/calendar/feeds/default/allcalendars/full/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com' />
  <author>
    <name>Secondary Calendar</name>
  </author>
  <gCal:timezone value='America/Los_Angeles' />
  <gCal:timesCleaned value='0' />
  <gCal:hidden value='false' />
  <gCal:color value='#5229A3' />
  <gCal:selected value='true' />
  <gCal:accesslevel value='owner' />
  <gd:where valueString='' />
</entry>

So, Google is suggesting that you take the element element , parse out the href, extract the calendar ID, “2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com”, and substitute it into “http://www.google.com/calendar/feeds/default//full”. That works, but isn’t the most intuitive series of steps.

A more direct way is to just use the src attribute of the content. Since the content of the calendar is empty, Atom specifies that the src attribute must be present, and contain a link to the content. That’s a long way of saying, “This is the link that we want!” To read the content of a calendar, GET the url indicated by the src attribute link of the content. To create an event, POST appropriately formed XML to the src attribute link of the calendar. This is REST 101.

Note that the link in the src attribute of the content is exactly the same as the alternate link. This might be useful information as we work through the various client libraries.

The easiest method is to look it up manually through the UI. In the UI, under the Calendar Details tab of Calendar Settings, there is a section for Calendar Address and included in that section is a parenthetical notation of the Calendar ID.

Note that this is called Calendar ID whether the calendar is the user’s primary calendar (in which case the calendar ID is also the user ID) or a secondary calendar, in which case it is some other user’s email address, or a long string that looks like an e-mail address for an obscure user in the group.calendar.google.com domain, like 2v78cr597kh4kduf3db9t4p1es@group.calendar.google.com. That by the way is the calendar ID in my Secondary Calendar. You can see how Google has used the calendar ID as the src parameter in the link to that calendar, http://www.google.com/calendar/embed?src=2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com.

So now the hard part is over. We have the correct url. Here’s the XML that we’ll send as the data in our post request, cribbed from the Developer’s Guide and modified for our purposes. Follow that link for more details about how additional elements will be added on creation.

<entry xmlns='http://www.w3.org/2005/Atom'
    xmlns:gd='http://schemas.google.com/g/2005'>
  <category scheme='http://schemas.google.com/g/2005#kind'
    term='http://schemas.google.com/g/2005#event'></category>
  <title type='text'>POSTed XML</title>
  <content type='text'>I was POSTed using hand-crafted XML via the Protocol!</content>
  <gd:transparency
    value='http://schemas.google.com/g/2005#event.opaque'>
  </gd:transparency>
  <gd:eventStatus
    value='http://schemas.google.com/g/2005#event.confirmed'>
  </gd:eventStatus>
  <gd:when startTime='2008-09-01'
    endTime='2008-09-02'></gd:when>
</entry>

Wrap this up in a script that I have that does authentication and handles the redirects and POST that to

https://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es@group.calendar.google.com/private/full

.

Below is Google’s response. More importantly, see the resulting event here. Enjoy.

<?xml version='1.0' encoding='utf-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:batch='http://schemas.google.com/gdata/batch'
xmlns:gCal='http://schemas.google.com/gCal/2005'
xmlns:gd='http://schemas.google.com/g/2005'>
  <id>
  http://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com/private/full/5q38q19h2s756um8902b9f7mrs</id>
  <published>2008-09-01T11:32:34.000Z</published>
  <updated>2008-09-01T11:32:35.000Z</updated>
  <category scheme='http://schemas.google.com/g/2005#kind'
  term='http://schemas.google.com/g/2005#event' />
  <title type='text'>POSTed XML</title>
  <content type='text'>I was POSTed using hand-crafted XML via the
  Protocol!</content>
  <link rel='alternate' type='text/html'
  href='http://www.google.com/calendar/event?eid=NXEzOHExOWgyczc1NnVtODkwMmI5ZjdtcnMgMnY3OGNyNTk3a2g0a2R1ZjNkYjl0NHAxZXNAZw'
  title='alternate' />
  <link rel='self' type='application/atom+xml'
  href='http://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com/private/full/5q38q19h2s756um8902b9f7mrs' />
  <link rel='edit' type='application/atom+xml'
  href='http://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com/private/full/5q38q19h2s756um8902b9f7mrs/63355951955' />
  <author>
    <name>Calendar Maven</name>
    <email>calendar.maven@gmail.com</email>
  </author>
  <gd:comments>
    <gd:feedLink href='http://www.google.com/calendar/feeds/2v78cr597kh4kduf3db9t4p1es%40group.calendar.google.com/private/full/5q38q19h2s756um8902b9f7mrs/comments' />
  </gd:comments>
  <gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed' />
  <gd:visibility value='http://schemas.google.com/g/2005#event.default' />
  <gd:transparency value='http://schemas.google.com/g/2005#event.opaque' />
  <gCal:uid value='5q38q19h2s756um8902b9f7mrs@google.com' />
  <gCal:sequence value='0' />
  <gd:when startTime='2008-09-01' endTime='2008-09-02' />
  <gd:who rel='http://schemas.google.com/g/2005#event.organizer'
  valueString='Secondary Calendar'
  email='2v78cr597kh4kduf3db9t4p1es@group.calendar.google.com' />
  <gd:where />
</entry>

tag



tag5 Responses to “Adding Events to Secondary Google Calendars”

  1. Joseph Says:

    Looks good, I am looking forward to the Python version.

  2. Boundary Conditions » Blog Archive » Adding Events to Secondary Google Calendars in Python Says:

    [...] writing, I assumed that I would need to refer any reader to the introductory post of this series on adding events to secondary calendars. Depending on your skill level and [...]

  3. hugues93 Says:

    Thanks!
    But i’m writing in Java, and I heard that there is a method with getHref().
    For exemple, i create a calendar by this way:

    private static CalendarEntry createCalendar(CalendarService service) throws IOException, ServiceException {
    System.out.println(“Creating a secondary calendar”);

    // Create the calendar
    CalendarEntry calendar = new CalendarEntry();
    calendar.setTitle(new PlainTextConstruct(“My secondary calendar”));
    calendar.setSummary(new PlainTextConstruct(“this is my project”));

    // Insert the calendar
    return service.insert(owncalendarsFeedUrl, calendar);
    }

    And i don’t know if i can do “calendar.getHref()”, or something like this. (i know that calendar.getHref() isn’t working, but it’s the idea :p)

    Thanks again!!

  4. yesteray Says:

    hugeus93,

    A CalendarEntry object has a getEditLink method which returns a Link. Link has an href method.

    Put those together, and you should be able to do something like:

    calendar.getEditLink().href to the the URI that you would post to to add an event to the calendar that you have created.

    Ray

  5. Alex Says:

    Thanks for the post! Really helped

    this is what I had to do when using the java/groovy client. It may not be the best way, but it works.

          def list = calendar.getEditLink().getHref().split("/")
          URL postURL = new URL("http://www.google.com/calendar/feeds/" + list[list.length-1].replace("%40","@") + "/private/full");
    

    may be a bit late for hugues93. but others might find it useful.

Leave a Reply


Search:

Recent Posts

Categories

Relevant Links

AtomPub

Date and Time

GCalendar

GData

iCalendar Tools

Online Calendars

REST

RFCs

Timelines

Zend GData

Feeds: