Posted on September 1st, 2008 by Ray Baxter
The most frequently asked question posed in the Google Calendar Date API Group is, “How do I add events to a secondary calendar?”
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
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
If you specify the user ID, this would be
http://firstname.lastname@example.org/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://email@example.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/
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
firstname.lastname@example.org. 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,
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
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>email@example.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 firstname.lastname@example.org' /> <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@example.com' /> <gd:where /> </entry>
5 Responses to “Adding Events to Secondary Google Calendars”
Leave a Reply
- Fix a Typo, Go to Rails
- Embedding Private and Shared Calendars – Google Apps for Your Domain
- Embedding Private and Shared Google Calendars
- Restyle Google Calendar
- Single Purpose Web Dev Browser
- Getting to know the Atom Publishing Protocol, Part 1: Create and edit Web resources with the Atom Publishing Protocol
- Getting to know the Atom Publishing Protocol, Part 2: Put the Atom Publishing Protocol (APP) to work
Date and Time
- Articles and Tutorials
- Bugs and Enhancements
- Calendar API FAQ
- Calendar Feeds
- Developer’s Guide
- Google Calendar Data API Group
- Reference Guide
- Batch Processing
- Client Libraries
- Common Elements
- Protocol Basics
- Protocol Reference
- Zend Documentation
- 30 Boxes
- CalendarHub – Web Calendars
- Google Calendar
- Online calendar publishing: Google Calendar
- Online calendar publishing: iCal
- Online calendar publishing: Outlook
- The Human Calendar
- Yahoo! Calendar