Google Calendar allows client applications to view and update calendar events in the form of Google data API ("GData") feeds. Your client application can use the Google Calendar data API to create new events, edit or delete existing events, and query for events that match particular criteria.
There are many possible uses for the Calendar data API. For example, you can create a web front end for your group's calendar that uses Google Calendar as a back end. Or you can generate a public calendar for Google Calendar to display, based on your organization's event database. Or you can search relevant calendars to display a list of upcoming events on those calendars.
In addition to providing some background on the capabilities of the Google Calendar data API, this document provides examples interacting with the API by sending HTTP messages containing XML formatted messages. If you're using one of our client libraries to interact with the API, you may also be interested in exploring the examples found on the appropriate tab above.
This document is intended for programmers who want to write client applications that can interact with Google Calendar. It provides a series of examples of basic data API interactions using raw XML/HTTP, with explanations. After reading this document, you may wish to learn more about interacting with the API using our client libraries by reading the language-specific examples found on the other tabs at the top of this document.
For Calendar data API reference information, see the reference guide. This document assumes that you understand the general ideas behind the Google data APIs protocol. Each example in this document shows how to use the bare protocol to interact with Calendar.
You agree to abide by the Google Calendar Terms of Use when using the Calendar data API.
Inserting, updating or deleting entries requires authenticating using one of the two different authentication systems supported by GData services. The appropriate method of authentication depends on the type of client you're writing.
If your client is a standalone single-user "installed" client (such as a desktop application), then you should use the ClientLogin system; if your client is a multi-user web application client, then you should use the AuthSub system. Both of these methods involve interacting with an authentication service. The authentication service returns an authentication token that your client can then send to the Calendar data API service along with every subsequent request on behalf of that user.
AuthSub proxy authentication is used by web applications which need to authenticate their users to Google accounts. The website operator does not need access to the username and password for the user - only special AuthSub tokens are required. Please see the AuthSub documentation for more detailed information.
To acquire an AuthSub token for a given user, your application must redirect the user to the AuthSubRequest URL, which prompts them to log into their Google account. The AuthSubRequest URL might look like this:
https://www.google.com/accounts/AuthSubRequest?scope=http%3A%2F%2Fwww.google.com%2fcalendar%2Ffeeds%2F&session=1&secure=0&next=http%3A%2F%2Fwww.coolcalendarsite.com%2Fwelcome.html
Notice the query parameters sent to the AuthSubRequest URL:
| Parameter | Description |
|---|---|
scope |
A base URL for feed requests. For Google Calendar feeds this value is http://www.google.com/calendar/feeds/. |
session |
Indicates whether the token returned can be exchanged for a multi-use (session) token. |
secure |
Indicates whether the token returned will be a secure token. |
next |
The URL of the page that Google should redirect the user to after authentication. |
After the user logs in, the AuthSub system redirects them to the URL you specified in the next query parameter of the AuthSubRequest URL. The AuthSub system appends an authentication token to that URL, as the value of the token query parameter like this:
http://www.coolcalendarsite.com/welcome.html?token=yourAuthToken
This token value represents a single-use AuthSub token. Since session = True was specified above, this token can be exchanged for an AuthSub session token using by calling the AuthSubSessionToken service with the single-use token in an Authorization header like this:
GET /accounts/AuthSubSessionToken HTTP/1.1 Content-Type: application/x-www-form-urlencoded Authorization: AuthSub token="yourAuthToken" User-Agent: Java/1.5.0_06 Host: https://www.google.com Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive
The AuthSubSessionToken service response will include a Token header that contains the session token and an Expiration header that indicates how long the token will remain valid. Your server-side application can use the session token value in the Authorization header of subsequent interactions with Google Calendar. Here's an example of a HTTP request you would send to the Google Calendar feed service that contains a non-secure token:
GET /calendar/feeds/default/private/full HTTP/1.1 Content-Type: application/x-www-form-urlencoded Authorization: AuthSub token="yourSessionToken" User-Agent: Java/1.5.0_06 Host: www.google.com Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive
The ClientLogin method requires having access to the username and password for a Google Account. To receive an authentication token using the ClientLogin mechanism, send a POST request to the following URL:
https://www.google.com/accounts/ClientLogin
The POST body should contain a set of query parameters, as described in the following table. They should look like parameters passed by an HTML form, using the application/x-www-form-urlencoded content type.
| Parameter | Description |
|---|---|
Email |
The user's email address. |
Passwd |
The user's password. |
source |
Identifies your client application. Should take the form companyName-applicationName-versionID; below, we'll use the name exampleCo-exampleApp-1. |
service |
The string cl, which is the service name for Google Calendar. |
If the authentication request fails, you'll receive an HTTP 403 Forbidden status code.
If it succeeds, then the response from the service is an HTTP 200 OK status code, plus three long alphanumeric codes in the body of the response: SID, LSID, and Auth. The Auth value is the authorization token that you'll send to Calendar with your request, so keep a copy of that value. You can ignore the SID and LSID values.
Since all requests to private feeds require authentication, you have to set the Authorization header in the request, using the following format:
Authorization: GoogleLogin auth=yourAuthToken
Where yourAuthToken is the Auth string returned by the login request.
As mentioned earlier, this authentication system (known as "Google Authentication for Installed Applications"; also known as "ClientLogin") is appropriate only for use in installed client applications such as desktop clients, not for use in web applications. For web applications, you should instead use the account authentication proxy, also known as "AuthSub".
For more information about authentication, including detailed instructions for using AuthSub, see the Google Data APIs Authentication Overview and the Google Account Authentication documentation.
The simplest feed URL to use is that of the calendar's read-only, "magic cookie" private feed, because that URL doesn't require authentication. The usual procedure for determining that URL involves using a JavaScript-enabled GUI browser to get the URL manually. If you can't or don't want to use such a browser, then you can instead interact with Calendar using one of the other feed URLs, which require authentication, but which you can construct without using a browser.
To find your calendar's "magic cookie" feed URL:
The feed URL has the following form:
http://www.google.com/calendar/feeds/userID/private-magicCookie/basic
You can modify this URL in the following ways:
<gd:feedLink> element) as a link to a separate comment feed.The "basic" form of the feed holds event information that is formatted for reading, more suited to human consumption of the feed. The "full" form of the feed holds structured events that are represented as "Kinds", so they are more suited to computer processing.
If you're looking at settings for the user's main calendar, then userID is the user's email address. If you're looking at settings for another calendar, then userID is a longer and more complicated email address. In either case, magicCookie is a special code that lets you read the private feed without having to do authentication. Here's an example of a feed URL:
http://www.google.com/calendar/feeds/jo@gmail.com/private-08ce2fac8efa42f2a0d04eceb7d68cc9/full
Under some circumstances, you may want to generate a new "magic cookie" URL. (Note that if someone else gets access to that URL, they can view your calendar without authentication.) To do that, click the "Reset Private URLs" link in the Calendar Details page.
The Calendar data API provides several ways to access the list of calendars that appear in the Google Calendar web application. There are three types of calendars in this list: primary, secondary, and imported calendars. A primary calendar is created for a user when they sign up for a Google Calendar account. All other calendars created by that user are called secondary calendars. Imported calendars are calendars that a user subscribes to that someone else has created.
You can get a list of a user's calendars by sending an authenticated GET request to the allcalendars feed URL:
http://www.google.com/calendar/feeds/default/allcalendars/full
The result is a feed that includes all primary, secondary, and imported calendars:
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:gd='http://schemas.google.com/g/2005'
xmlns:gCal='http://schemas.google.com/gCal/2005'>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full</id>
<updated>2007-07-11T22:10:30.252Z</updated>
<title type="text">Coach's Calendar List</title>
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.google.com/calendar/feeds/default/allcalendars/full"/>
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="http://www.google.com/calendar/feeds/default/allcalendars/full"/>
<link rel="self" type="application/atom+xml" href="http://www.google.com/calendar/feeds/default/allcalendars/full"/>
<author>
<name>Coach</name>
<email>user@gmail.com</email>
</author>
<generator version="1.0" uri="http://www.google.com/calendar">Google Calendar</generator>
<openSearch:startIndex>1</openSearch:startIndex>
<entry>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full/user%40gmail.com</id>
<published>2007-07-11T22:10:30.257Z</published>
<updated>2007-07-11T21:46:35.000Z</updated>
<title type="text">My Primary Calendar</title>
<summary type="text">A primary calendar is created by default for each Google Calendar user.</summary>
<link rel="alternate" type="text/html" href="http://www.google.com/calendar/feeds/user%40gmail.com/private/full"/>
<link rel="http://schemas.google.com/acl/2007#accessControlList" type="application/atom+xml" href="http://www.google.com/calendar/feeds/user%40gmail.com/acl/full"/>
<link rel="self" type="application/atom+xml" href="http://www.google.com/calendar/feeds/default/allcalendars/full/user%40gmail.com"/>
<author>
<name>Coach</name>
<email>user@gmail.com</email>
</author>
<gCal:timezone value="America/Los_Angeles"/>
<gCal:hidden value="false"/>
<gCal:color value="#2952A3"/>
<gCal:selected value="true"/>
<gCal:accesslevel value="owner"/>
<gd:where valueString="Mountain View"/>
</entry>
<entry>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com</id>
<published>2007-07-11T22:10:30.258Z</published>
<updated>2007-07-11T21:50:15.000Z</updated>
<title type="text">Little Giants</title>
<summary type="text">This calendar contains practice times and this season's Little League game schedule. Go Little Giants!</summary>
<link rel="alternate" type="text/html" href="http://www.google.com/calendar/feeds/rf1c66uld6dgk2t5lh43svev6g%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/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com/acl/full"/>
<link rel="self" type="application/atom+xml" href="http://www.google.com/calendar/feeds/default/allcalendars/full/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com"/>
<author>
<name>Little Giants</name>
</author>
<gCal:timezone value="America/Los_Angeles"/>
<gCal:hidden value="false"/>
<gCal:color value="#5A6986"/>
<gCal:selected value="false"/>
<gCal:accesslevel value="owner"/>
<gd:where valueString="San Fransisco"/>
</entry>
<entry>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com</id>
<published>2007-07-11T22:10:30.297Z</published>
<updated>2007-06-05T09:38:50.000Z</updated>
<title type="text">Google Doodles</title>
<summary type="text"/>
<link rel="alternate" type="text/html" href="http://www.google.com/calendar/feeds/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com/private/full"/>
<link rel="self" type="application/atom+xml" href="http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com"/>
<author>
<name>Google Doodles</name>
</author>
<gCal:timezone value="Etc/GMT"/>
<gCal:hidden value="false"/>
<gCal:color value="#5229A3"/>
<gCal:selected value="false"/>
<gCal:accesslevel value="read"/>
<gd:where valueString=""/>
</entry>
</feed>
There are several new elements here, all in the gCal namespace. For information about those elements, see GCal namespace element reference.
Note: This feed is accessible only using an authentication token, so you cannot use a magic cookie URL to access the feed. For information on authentication, see the earlier Authenticating to the Calendar service section.
There is also an owncalendars feed that you can query to retrieve the list of calendars that the authenticated user has owner access to. The owncalendars feed is located at:
http://www.google.com/calendar/feeds/default/owncalendars/full
Querying this feed will return a list of calendars that includes the user's primary and secondary calendars, as well as any imported calendars for which the user has been granted ownership. The feed will resemble the feed in the previous example, but it will contain only calendars where the <gCal:accesslevel> has a value of owner.
The owncalendars feed can also be used to create, update, and delete calendars. Calendars created through the owncalendars feed will be secondary calendars.
To create a new calendar, first create the XML for a calendar <entry> element like the ones in the previous example. For example, you might create the following XML to represent a calendar to keep track of your Little League team:
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:gd='http://schemas.google.com/g/2005'
xmlns:gCal='http://schemas.google.com/gCal/2005'>
<title type='text'>Little League Schedule</title>
<summary type='text'>This calendar contains the practice schedule and game times.</summary>
<gCal:timezone value='America/Los_Angeles'></gCal:timezone>
<gCal:hidden value='false'></gCal:hidden>
<gCal:color value='#2952A3'></gCal:color>
<gd:where rel='' label='' valueString='Oakland'></gd:where>
</entry>
To insert this calendar, send an HTTP POST message with this calendar <entry> element in the message body, using the application/atom+xml content type, to the owncalendars feed URL:
POST http://www.google.com/calendar/feeds/default/owncalendars/full
Upon success, the server will respond with an HTTP 201 Created message that contains the calendar <entry> element you submitted, but with some additional elements (shown in bold) that are set by the server such as <atom:id>, <atom:published>, <atom:updated>, and mulitple <atom:link> elements:
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:gCal='http://schemas.google.com/gCal/2005'
xmlns:gd='http://schemas.google.com/g/2005'>
<id>http://www.google.com/calendar/feeds/default/owncalendars/full/ppgcfga9qo8jmdwan231w7s8h4%40group.calendar.google.com</id>
<published>2007-07-12T16:46:11.815Z</published>
<updated>2007-07-12T16:46:11.000Z</updated>
<title type='text'>Little League Schedule</title>
<summary type='text'>This calendar contains the practice schedule and game times.</summary>
<link rel='alternate' type='text/html' href='http://www.google.com/calendar/feeds/ppgcfga9qo8jmdwan231w7s8h4%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/ppgcfga9qo8jmdwan231w7s8h44%40group.calendar.google.com/acl/full'/>
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/owncalendars/full/ppgcfga9qo8jmdwan231w7s8h4%40group.calendar.google.com'/>
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/owncalendars/full/ppgcfga9qo8jmdwan231w7s8h4%40group.calendar.google.com'/>
<author>
<name>Little League Schedule</name>
</author>
<gCal:timezone value='America/Los_Angeles'/>
<gCal:hidden value='false'/>
<gCal:color value='#2952A3'/>
<gCal:selected value='false'/>
<gCal:accesslevel value='owner'/>
<gd:where valueString='Oakland'/>
</entry>
You can update most information about a user's calendar via the owncalendars feed. You'll need to parse out the calendar entry's edit URL. This URL is found in the <link> element where the value of the rel attribute is edit:
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/calendarId'></link>
To update the calendar, send an HTTP PUT to the edit URL with the updated calendar <entry> element in the message body. The following entry will update the calendar's title and color, and mark it as selected:
PUT http://www.google.com/calendar/feeds/default/owncalendars/full/calendarID
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:gCal='http://schemas.google.com/gCal/2005'
xmlns:gd='http://schemas.google.com/g/2005'>
<id>http://www.google.com/calendar/feeds/default/owncalendars/full/ppgcfga9qo8jmdwan231w7s8h4%40group.calendar.google.com</id>
<published>2007-07-12T16:46:11.815Z</published>
<updated>2007-07-12T16:46:11.000Z</updated>
<title type='text'>New Title</title>
<summary type='text'>This calendar contains the practice schedule and game times.</summary>
<link rel='alternate' type='text/html' href='http://www.google.com/calendar/feeds/ppgcfga9qo8jmdwan231w7s8h4%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/ppgcfga9qo8jmdwan231w7s8h44%40group.calendar.google.com/acl/full'/>
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/owncalendars/full/ppgcfga9qo8jmdwan231w7s8h4%40group.calendar.google.com'/>
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/owncalendars/full/ppgcfga9qo8jmdwan231w7s8h4%40group.calendar.google.com'/>
<author>
<name>Little League Schedule</name>
</author>
<gCal:timezone value='America/Los_Angeles'/>
<gCal:hidden value='false'/>
<gCal:color value='#0D7813'/>
<gCal:selected value='true'/>
<gCal:accesslevel value='owner'/>
<gd:where valueString='Oakland'/>
</entry>
Calendars are deleted by sending a DELETE request to the calendar's edit URL. This is the same URL used to update the calendar. For example, to delete the above calendar send the following HTTP request:
DELETE /calendar/feeds/default/owncalendars/full/ppgcfga9qo8jmdwan231w7s8h44%40group.calendar.google.com
Note: You can't delete a user's primary calendar, i.e. the calendar with the user's email address in the ID. If you try to delete a primary calendar you will get an HTTP 400 Bad Request error.
The allcalendars feed can be used to modify the list of imported calendars that a user has subscribed to. Calendars inserted via the allcalendars feed will be added as imported calendars.
To subscribe to an existing calendar, you first need to find the calendar's ID. The calendar ID is available on the calendar settings page, next to the Calendar Address buttons. If you're subscribing to a user's primary calendar, the id will just be the user's email address.
Once you have the calendar ID, create a calendar <entry> element that contains the <atom:id> of the calendar you wish to subscribe to. For example, you could use the following XML to subscribe to the Google Doodles calendar:
<entry xmlns='http://www.w3.org/2005/Atom' <id>c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com</id> </entry>
To then subscribe to the Google Doodles calendar, send an HTTP POST message to the allcalendars feed URL with this calendar <entry> element in the message body (using the application/atom+xml content type):
POST http://www.google.com/calendar/feeds/default/allcalendars/full
Upon success, the server will respond with an HTTP 201 Created message that contains the calendar <entry> that corresponds to the calendar you subscribed to. This calendar <entry> will be populated with data specific to the Google Doodles calendar such as the <title>, <summary>, and <gd:where>, as well as elements that are specific to this subscription, such as <gCal:color>, <gCal:hidden>, and <gCal:selected>. Here's an example of the XML returned by the server, with personalization settings shown in bold:
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:gCal='http://schemas.google.com/gCal/2005'
xmlns:gd='http://schemas.google.com/g/2005'>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com</id>
<published>2007-07-12T17:09:08.033Z</published>
<updated>2007-06-05T09:38:50.000Z</updated>
<title type='text'>Google Doodles</title>
<summary type='text'></summary>
<link rel='alternate' type='text/html' href='http://www.google.com/calendar/feeds/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com/private/full'/>
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com'/>
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com'/>
<author>
<name>Google Doodles</name>
</author>
<gCal:timezone value='Etc/GMT'/>
<gCal:hidden value='false'/>
<gCal:color value='#2952A3'/>
<gCal:selected value='true'/>
<gCal:accesslevel value='read'/>
<gd:where valueString=''/>
</entry>
You can update the following personalization settings of a calendar using the allcalendars feed:
The personalization settings can be modified with the allcalendars feed even if the user doesn't own the calendar. However, the title and summary of the calendar can only be updated by an owner of the calendar using the owncalendars feed.
To update a subscription you'll need to parse out the calendar entry's edit URL. This URL is found in the <link> element where the value of the rel attribute is edit:
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/calendarId'></link>
Send an HTTP PUT to the edit URL with the updated calendar <entry> element in the message body. The following entry will update the color and unselected the calendar:
PUT http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:gCal='http://schemas.google.com/gCal/2005'
xmlns:gd='http://schemas.google.com/g/2005'>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com</id>
<published>2007-07-12T17:09:08.033Z</published>
<updated>2007-06-05T09:38:50.000Z</updated>
<title type='text'>Google Doodles</title>
<summary type='text'></summary>
<link rel='alternate' type='text/html' href='http://www.google.com/calendar/feeds/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com/private/full'/>
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com'/>
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com'/>
<author>
<name>Google Doodles</name>
</author>
<gCal:timezone value='Etc/GMT'/>
<gCal:hidden value='false'/>
<gCal:color value='#A32929'/>
<gCal:selected value='false'/>
<gCal:accesslevel value='read'/>
<gd:where valueString=''/>
</entry>
Subscriptions are deleted by sending a DELETE request to the calendar's edit URL. This is the same URL used to update the subscription. For example, to delete the subscription to the Google Doodles calendar, send the following HTTP request:
DELETE /calendar/feeds/default/owncalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com
The general idea of how to request a Calendar feed is that you determine the URL of the feed type you want (see Calendar feed types), and then you send an HTTP GET request for that URL. Calendar then returns a GData feed containing calendar events, each of which is an Event kind. For more information about kinds, see the Kinds document.
Google provides client libraries for interacting with Google data API services in a variety of programming languages. You can use the client libraries to send the HTTP request and handle the returned feed; see the other tabs of this document for information on how to do this in various languages. But whether or not you use the client library, the following is what's going on at the protocol level. If you're using a UNIX system and you want to try this out without writing any code, you may find the UNIX command-line utilities curl or wget useful; for more information, see the manual pages for those utilities.
To get a feed, you send the following HTTP request to Calendar, using the URL you found in the previous section of this document:
GET http://www.google.com/calendar/feeds/userID/private-magicCookie/full
(With the appropriate values in place of userID and magicCookie, of course.)
When you send that GET request, Calendar may return an HTTP 302 redirect; the redirect URL has a new query parameter, gsessionid, appended to it. (Note that some methods of sending the GET request may not show you the response headers by default; if you receive a blank response, check your HTTP utility's documentation to find out how to view response headers.) That gsessionid parameter is the way that Calendar keeps track of your session, to improve speed of response.
(Some methods of sending the GET request may automatically follow redirects, and in some cases Calendar may not send a redirect at all; in such cases, you don't need to send the second request described below.)
So after you've sent the GET request, you have to read the HTTP headers of the response to find the URL with the session ID appended; then you need to send another GET request with that new URL. (Note that if you're using the UNIX command line to send requests, you may have to precede the question mark in the new URL with a backslash to keep your shell from interpreting it.)
In response to the second GET request, Calendar returns an HTTP 200 OK status code and a feed containing all the events in your calendar. If there's only one event in your calendar, then Calendar returns something similar to the following feed. We've edited the following example a little to make it a little more readable by humans; in particular, a real Calendar feed contains actual magic-cookie values and entry IDs.
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:gd='http://schemas.google.com/g/2005'>
<id>http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full</id>
<updated>2006-03-29T07:35:59.000Z</updated>
<title type='text'>Jo March</title>
<subtitle type='text'>This is my main calendar.</subtitle>
<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full'></link>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full'></link>
<author>
<name>Jo March</name>
<email>jo@gmail.com</email>
</author>
<generator version='1.0' uri='http://www.google.com/calendar/'>CL2</generator>
<gd:where valueString='California'></gd:where>
<entry>
<id>http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID</id>
<published>2006-03-30T22:00:00.000Z</published>
<updated>2006-03-28T05:47:31.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/g/2005#event'></category>
<title type='text'>Lunch with Darcy</title>
<content type='text'>Lunch to discuss future plans.</content>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=aTJxcnNqbW9tcTJnaTE5cnMybmEwaW04bXMgbWFyY2guam9AZ21haWwuY29t'
title='alternate'></link>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID'></link>
<author>
<name>Jo March</name>
<email>jo@gmail.com</email>
</author>
<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:comments>
<gd:feedLink
href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID/comments/'></gd:feedLink>
</gd:comments>
<gd:when startTime='2006-03-30T22:00:00.000Z'
endTime='2006-03-30T23:00:00.000Z'></gd:when>
<gd:where></gd:where>
</entry>
</feed>
For information about what each of those elements means, see the Google Data APIs Protocol Reference document and the Calendar elements reference.
If your request fails for some reason, Calendar may return a different status code; for information about the status codes, see the GData Protocol Reference document.
Note: The events in a feed are ordered by the values of their updated elements by default, with the most recently updated event appearing first in the feed. For information on changing the ordering, see Calendar query parameters reference.
GData lets you request a set of entries that match specified criteria. In addition to the standard GData query parameters, Calendar provides two additional query parameters, start-min and start-max, to let you request all events that fall within or overlap a range of dates. For more information, see Calendar query parameters reference.
It's a good idea to limit your queries to a range of dates if you're not limiting them in any other way, just to avoid retrieving all entries ever posted to the calendar.
Here's how to create and send a date-range query at the protocol level:
First, authenticate the user, if you haven't already done so. See the previous example for information on how to do that.
Then send an HTTP request like the following to Calendar, using the special "default" URL:
GET http://www.google.com/calendar/feeds/default/private/full?start-min=2006-03-16T00:00:00&start-max=2006-03-24T23:59:59
Be sure to include the Authorization header in the request, as described in the previous example.
When you send that GET request, Calendar may return an HTTP 302 redirect with a gsessionid appended to it, just like in the earlier examples. In that case, read the HTTP headers of the response to find the URL with the session ID appended; then send another GET request with that new URL. (This second GET request also needs to have the Authorization header set.)
In response to the second GET request (or the first one if there was no redirect), Calendar returns an HTTP 200 OK status code and a feed containing any event that overlaps the minimum and maximum start times you specified.
Google Calendar supports full-text queries that search the title and content of an event. To perform a full-text query send an HTTP request using the 'q' parameter in the URL.
GET http://www.google.com/calendar/feeds/default/private/full?q=Tennis
To query using standard GData query parameters, just change the URL to use other parameters.
Note: Google Calendar doesn't support GData category queries.
The Calendar data API allows you to create two types of events: single-occurrence events and recurring events, which are set up to repeat on a predetermined schedule.
Adding an event to a calendar is a little bit more complicated than getting a feed, because you need to create the XML code or client-library object representing the event, and you need to use authentication.
First, create an entry of the Event kind. (For more information about kinds, see the Kinds document.) For example, you might create the following entry:
<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'>Tennis with Beth</title>
<content type='text'>Meet for a quick lesson.</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:where valueString='Rolling Lawn Courts'></gd:where>
<gd:when startTime='2006-04-17T15:00:00.000Z'
endTime='2006-04-17T17:00:00.000Z'></gd:when>
</entry>
Note that this entry does not contain the standard APP <author> tag. The server will insert author information based on the user that submits the request (i.e. the user whose authentication token accompanies the request).
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.)
POST http://www.google.com/calendar/feeds/default/private/full
The content that you send with the POST request should be the <entry> element you created above, using the application/atom+xml content type.
Just like in the previous example, Calendar may return an HTTP 302 redirect; if so, then the redirect URL has a new parameter, gsessionid, appended to it. If you received the redirect, then send the same POST request again, with the same Authorization header and the same content, but with the gsessionid parameter appended. The response may also include a S cookie, which you should store and send this cookie with future requests as appropriate. Please see the knowledge base for more information on handling sessions with the Calendar data API. Please note: if a session ID indicated in a cookie header conflicts with the session ID passed as a gsessionid URL parameter, you will get caught in a redirect loop.
When you send that second POST request (or the first one in cases where there's no redirect), Calendar creates a calendar event, then returns an HTTP 201 CREATED status code, along with a copy of the new event in the form of an <entry> element. The returned entry is similar to the one you sent, but the returned one contains various elements added by Calendar, such as an <id> element.
If your request fails for some reason, Calendar may return a different status code; for information about the status codes, see the GData Protocol Reference document.
Note that if you use GData to add an event to your calendar that involves multiple participants, the event appears on the other people's calendars just as it would if you added it by hand using the Calendar GUI.
To create an event using Google Calendar's quick add feature, set the event entry's content to the quick add string you'd like to use. Then add a <gCal:quickadd> element with a value attribute set to true. For example, the following event <entry> element will create an event on April 11 from 3pm-3:30pm with a title of 'Tennis with John':
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gCal='http://schemas.google.com/gCal/2005'> <content type="html">Tennis with John April 11 3pm-3:30pm</content> <gCal:quickadd value="true"/> </entry>
The response from the server will contain an event <entry> with the appropriate fields populated by the server. Note that the <content> element is now empty and the <gCal:quickadd> element is no longer present:
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005"> ... <title type="text">Tennis with John</title> <content type="text" /> <gd:when endTime="2007-04-11T15:30:00.000-07:00" startTime="2007-04-11T15:00:00.000-07:00" /> ... </entry>
You can also create Calendar Gadgets as events in Google Calendar. Calendar Gadgets, formerly called web content, can contain images, HTML pages, or gadgets.
To create a simple Calendar Gadget that displays an image first create the XML for a calendar event <entry> element that contains a <link> element with the rel attribute set to http://schemas.google.com/gCal/2005/webContent. This <link> element should then contain a <gCal:webContent> element.
For example, the following entry would create a Calendar Gadget that displays the World Cup doodle (dimensions 276x120, and located at http://www.google.com/logos/worldcup06.gif). The icon at http://www.google.com/calendar/images/google-holiday.gif will be used to display the Calendar Gadget in the Calendar user interface before it is clicked.
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gCal="http://schemas.google.com/gCal/2005" >
<link rel="http://schemas.google.com/gCal/2005/webContent"
href="http://www.google.com/calendar/images/google-holiday.gif"
title="World Cup"
type="image/gif">
</gCal:webContent url="http://www.google.com/logos/worldcup06.gif" width="276" height="120" />
</link>
</entry>
To create a Calendar Gadget that displays a gadget, create an event entry with a web content link again, but this time the type should be application/x-google-gadgets+xml. You'll also need to get the gadget's URL from the iGoogle Directory. This example configures a Calendar Gadget to display the DateTime gadget and specifies the appropriate user preferences.
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gCal="http://schemas.google.com/gCal/2005" >
<link rel="http://schemas.google.com/gCal/2005/webContent"
href="http://www.google.com/favicon.ico"
title="DateTime Gadget (a classic!)"
type="application/x-google-gadgets+xml">
<gCal:webContent url="http://google.com/ig/modules/datetime.xml" width="300" height="136">
<gCal:webContentGadgetPref name="color" value="green" />
</gCal:webContent>
</link>
</entry>
Once you've created the Calendar Gadget event, insert it just like normal event by sending an HTTP POST to the event feed URL with the event <entry> element in the message body.
POST http://www.google.com/calendar/feeds/default/private/full
Note: For more information on Calendar Gadgets, check out the documentation here.
Creating recurring events is very similar to creating a single-occurrence event. The event is created as a XML element of the Event kind, but includes a gd:recurrence element instead of a gd:when element. A gd:recurrence element contains syntax for recurring events based upon the iCalendar standard (RFC 2445).
Here's an example of an all-day recurring event that occurs weekly on Tuesdays from May 1st, 2007 through September 4th, 2007:
<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'>Tuesday Tennis Lessons with Jane</title>
<content type='text'>Meet on Tuesdays for a quick lesson.</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:where valueString='Rolling Lawn Courts'></gd:where>
<gd:recurrence>DTSTART;VALUE=DATE:20070501
DTEND;VALUE=DATE:20070502
RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904
</gd:recurrence>
</entry>
As per RFC 2445, each line of the recurrence syntax ends in a carriage return and a line feed (CRLF). As the event is an all-day event, it does not include a reference to a timezone. If you do include a recurring event which references a timezone, you don't need to include the VTIMEZONE definition if the timezone used is a standard Java timezone definition.
This entry can then be sent via a POST to the Calendar servers using the method described in the Creating a single-occurrence event section.
Retrieving recurring events using the Calendar data API can be done via several methods, using the query parameters defined in the Reference Guide. Here's a basic overview:
entry element, with a gd:recurrence child element. No gd:when elements are returned for the recurring event.start-min and/or start-max specified: a recurring event is represented as a single entry element, with multiple gd:when elements for each occurrence in the range specified. The gd:recurrence element is also included in the entry.singleevents=true: recurring events are represented in the same format as single events, with a single entry element per occurrence of the event. Each entry includes a single gd:when element, but does not include the gd:recurrence syntax. It does, however, include a gd:originalEvent element.To update an existing event send a PUT request with the updated entry in the message body to the post's edit URL. Be sure that the <id> value in the entry you POST exactly matches the <id> of the existing entry. The edit URL is highlighted in the following event entry:
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:gd='http://schemas.google.com/g/2005'
xmlns:gCal='http://schemas.google.com/gCal/2005'>
<id>http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID</id>
<published>2006-03-30T22:00:00.000Z</published>
<updated>2006-03-28T05:47:31.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/g/2005#event'></category>
<title type='text'>Lunch with Darcy</title>
<content type='text'>Change of plans - Let's discuss the new proposal.</content>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=aTJxcnNqbW9tcTJnaTE5cnMybmEwaW04bXMgbWFyY2guam9AZ21haWwuY29t'
title='alternate'></link>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID'></link>
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID/version' />
...
</entry>
IMPORTANT! To ensure forward compatibility, be sure that when you POST an updated entry you preserve all the XML that was present when you retrieved the entry from Google Calendar. Otherwise, when we implement new stuff and include <new-awesome-feature> elements in the feed, your client won't return them and your users will miss out! The Google data API client libraries all handle this correctly, so if you're using one of the libraries you're all set.
Calendar events are deleted by sending a DELETE request to the event's edit URL. This is the same URL used to update the event.
If you're performing a lot of operations, the time it takes to send and and receive all those HTTP messages can really add up, making your app slow and unresponsive. With batch requests you can have the server perform multiple operations with a single HTTP request. The basic idea is that you create a calendar event feed and add an entry for each operation you want to perform. The following snippet shows a batch request that contains four operations, one each for creating, querying, updating, and deleting an event, but you can use any combination of operations that you want. Most of the unnecessary elements have been omitted.
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:batch='http://schemas.google.com/gdata/batch'
xmlns:gCal='http://schemas.google.com/gCal/2005'>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<entry>
<batch:id>1</batch:id>
<batch:operation type='insert' />
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event inserted via batch</title>
</entry>
<entry>
<batch:id>2</batch:id>
<batch:operation type='query' />
<id>http://www.google.com/calendar/feeds/default/private/full/glcs0kv2qqa0gf52qi1jo018gc</id>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event queried via batch</title>
</entry>
<entry>
<batch:id>3</batch:id>
<batch:operation type='update' />
<id>http://www.google.com/calendar/feeds/default/private/full/ujm0go5dtngdkr6u91dcqvj0qs</id>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event updated via batch</title>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=dWptMGdvNWR0bmdka3I2dTkxZGNxdmowcXMgaGFyaXNodi50ZXN0QG0' title='alternate' />
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/ujm0go5dtngdkr6u91dcqvj0qs' />
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/ujm0go5dtngdkr6u91dcqvj0qs/63326098791' />
</entry>
<entry>
<batch:id>4</batch:id>
<batch:operation type='delete' />
<id>http://www.google.com/calendar/feeds/default/private/full/d8qbg9egk1n6lhsgq1sjbqffqc</id>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event deleted via batch</title>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=ZDhxYmc5ZWdrMW42bGhzZ3Exc2picWZmcWMgaGFyaXNodi50ZXN0QG0' title='alternate' />
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/d8qbg9egk1n6lhsgq1sjbqffqc' />
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/d8qbg9egk1n6lhsgq1sjbqffqc/63326018324' />
</entry>
</feed>
Note: The update and delete entries require an edit link in order for optimistic concurrency to work.
Once you build your batch request feed, you need to send an authenticated POST request to the batch URL of the events feed. The batch URL is highlighed in the following events feed:
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>
<id>http://www.google.com/calendar/feeds/<calendarId>/private/full</id>
<updated>2007-09-21T22:59:51.000Z</updated>
<title type='text'>Jo March</title>
<subtitle type='text'>This is my main calendar.</subtitle>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/embed?src=<calendarId>' />
<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/<calendarId>/private/full' />
<link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/<calendarId>/private/full' />
<link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/<calendarId>/private/full/batch' />
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/<calendarId>/private/full?max-results=25' />
.
.
.
</feed>
After submitting the batch request, the server will respond with a feed that contains the status of each operation. You can parse this response to see if each operation was successful or not. Here's an abbreviated version of the response when submitting the above batch request feed.
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:batch='http://schemas.google.com/gdata/batch'
xmlns:gCal='http://schemas.google.com/gCal/2005'>
<id>http://www.google.com/calendar/feeds/default/private/full</id>
<updated>2007-09-21T23:01:00.380Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category>
<title type='text'>Batch Feed</title>
<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full' />
<link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full' />
<link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/batch' />
<entry>
<batch:id>1</batch:id>
<batch:status code='201' reason='Created' />
<batch:operation type='insert' />
<id>http://www.google.com/calendar/feeds/default/private/full/n9ug78gd9tv53ppn4hdjvk68ek</id>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event inserted via batch</title>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=bjl1Zzc4Z2Q5dHY1M3BwbjRoZGp2azY4ZWsgaGFyaXNodi50ZXN0QG0' title='alternate' />
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/n9ug78gd9tv53ppn4hdjvk68ek' />
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/n9ug78gd9tv53ppn4hdjvk68ek/63326098860' />
</entry>
<entry>
<batch:id>2</batch:id>
<batch:status code='200' reason='Success' />
<batch:operation type='query' />
<id>http://www.google.com/calendar/feeds/default/private/full/glsc0kv2aqa0ff52qi1jo018gc</id>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event queried via batch</title>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=Z2xzYzBrdjJhcWEwZmY1MnFpMWpvMDE4Z2MgaGFyaXNodi50ZXN0QG0' title='alternate' />
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/glsc0kv2aqa0ff52qi1jo018gc' />
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/glsc0kv2aqa0ff52qi1jo018gc/63326098791' />
</entry>
<entry xmlns:gCal='http://schemas.google.com/gCal/2005'>
<batch:id>3</batch:id>
<batch:status code='200' reason='Success' />
<batch:operation type='update' />
<id>http://www.google.com/calendar/feeds/default/private/full/ujm0go5dtngdkr6u91dcqvj0qs</id>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event updated via batch</title>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=dWptMGdvNWR0bmdka3I2dTkxZGNxdmowcXMgaGFyaXNodi50ZXN0QG0' title='alternate' />
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/ujm0go5dtngdkr6u91dcqvj0qs' />
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/default/private/full/ujm0go5dtngdkr6u91dcqvj0qs/63326098860' />
<batch:id>3</batch:id>
<batch:status code='200' reason='Success' />
<batch:operation type='update' />
</entry>
<entry>
<batch:id>4</batch:id>
<batch:status code='200' reason='Success' />
<batch:operation type='delete' />
<id>http://www.google.com/calendar/feeds/default/private/full/d8qbg9egk1n6lhsgq1sjbqffqc</id>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' />
<title type='text'>Event deleted via batch</title>
<content type='text'>Deleted</content>
</entry>
</feed>
When working with batch requests, the size of the request must be under a megabyte and it's best to limit batches to 50-100 operations at a time. You can find more information about batch operations in the Google Data Batch Processing documentation.
This section describes how to retrieve and modify Google Calendar access control lists (ACLs) using the raw protocol. An access control list identifies the set of users with whom a given calendar is shared, and the level of access for each user (such as read-only access, full access, and so on).
Specifically, an ACL is a list of access rules. Each access rule specifies a "scope" (a person or set of people) and then associates a "role" (an access level) with that scope. Those terms are defined as follows:
user) and a value (such as an email address).none, freebusy, read, and owner. (Note that most role names must be preceded by a specific namespace URI; see the examples and reference document for details.) A given scope can have only one role. For information about the other defined scopes and roles, see the GAcl namespace element reference in the Calendar reference document.
Note: For a given scope, having a role of none is equivalent to having no role defined.
The ACL for each calendar is available as a GData feed. Each entry in the feed defines a single access rule.
Google Calendar does not support query parameters on requests for ACL feeds.
To retrieve a calendar's ACL feed, you send an authenticated GET to the feed's URI. Only someone with owner access to a calendar can view that calendar's ACL feed.
You can determine the URI of a calendar's ACL feed by
looking at the calendar's entry in one of the calendar feeds (see Retrieving Calendars). The ACL feed URI is given in the <link rel="http//schemas.google.com/acl/2007#accessControlList"> element.
For example, the following partial entry from a metafeed includes the URI of the ACL feed for a particular calendar.
<entry>
<id>http://www.google.com/calendar/feeds/liz%40gmail.com/liz%40gmail.com</id>
<published>2007-04-24T01:40:29.752Z</published>
<updated>2007-04-21T00:52:04.000Z</updated>
<title type='text'>My Calendar</title>
...
<link rel='http://schemas.google.com/acl/2007#accessControlList'
type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full'>
</link>
...
</entry>
If you send a GET to that ACL feed URI, you might receive a feed like the following.
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'
xmlns:gAcl='http://schemas.google.com/acl/2007'>
<id>http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full</id>
<updated>2007-04-21T00:52:04.000Z</updated>
<title type='text'>Elizabeth Bennet's access control list</title>
<link rel='http://schemas.google.com/acl/2007#controlledObject'
type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/private/full'>
</link>
<link rel='http://schemas.google.com/g/2005#feed'
type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full'>
</link>
<link rel='http://schemas.google.com/g/2005#post'
type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full'>
</link>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full'>
</link>
<generator version='1.0'
uri='http://www.google.com/calendar'>Google Calendar</generator>
<openSearch:totalResults>2</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<entry>
<id>http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/user%3Aliz%40gmail.com</id>
<updated>2007-04-21T00:52:04.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/acl/2007#accessRule'>
</category>
<title type='text'>owner</title>
<content type='text'></content>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/user%3Aliz%40gmail.com'>
</link>
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/user%3Aliz%40gmail.com'>
</link>
<author>
<name>Elizabeth Bennet</name>
<email>liz@gmail.com</email>
</author>
<gAcl:scope type='user' value='liz@gmail.com'></gAcl:scope>
<gAcl:role value='http://schemas.google.com/gCal/2005#owner'>
</gAcl:role>
</entry>
<entry>
<id>http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/default</id>
<updated>2007-04-21T00:52:04.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/acl/2007#accessRule'>
</category>
<title type='text'>read</title>
<content type='text'></content>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/default'>
</link>
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/default'>
</link>
<author>
<name>Elizabeth Bennet</name>
<email>liz@gmail.com</email>
</author>
<gAcl:scope type='default'></gAcl:scope>
<gAcl:role value='http://schemas.google.com/gCal/2005#read'>
</gAcl:role>
</entry>
</feed>
A few comments on that feed:
<link rel='http://schemas.google.com/acl/2007#controlledObject'> element contains the URI of the calendar feed for the calendar that this ACL belongs to. <category scheme='http://schemas.google.com/g/2005#kind'> element, with term='http://schemas.google.com/acl/2007#accessRule'.gAcl.owner) for a specific user (liz@gmail.com). read) for all other users (default). To retrieve a single ACL rule rather than the entire feed, you can construct the URI for a single rule using the scope type (such as user) and the scope value (such as the user's email address).
To construct the URI for a particular rule, start with the ACL feed URI; then add the scope type and value (URL-encoded as needed), separated by a colon, as an additional path element. For example, the following is the URI for the ACL rule (for the example calendar we've been using) for user darcy@gmail.com:
http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/user%3Adarcy%40gmail.com
If you request a rule that hasn't been defined, then the service returns an HTTP 404 NOT FOUND status code.
A requester with permission to modify the access control list can add a new ACL rule by posting a new entry to the ACL feed's POST URI. The entry should contain the following elements:
<category><gAcl:scope><gAcl:role>Any other elements that appear in the entry you send are ignored by the server.
Note: Another way to add a rule is to use PUT. For more information, see Changing a rule.
For example, you could send a POST request to the following URI, after authenticating as user liz@gmail.com:
POST /calendar/feeds/liz@gmail.com/acl/full
With the following entry in the body of the POST:
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/acl/2007#accessRule'/>
<gAcl:scope type='user' value='darcy@gmail.com'></gAcl:scope>
<gAcl:role
value='http://schemas.google.com/gCal/2005#editor'>
</gAcl:role>
</entry>
If the specified scope does not already have a role defined (or,
equivalently, if the role for that scope is currently none), then Calendar creates a new
ACL rule, and returns the corresponding ACL entry in the response. The returned
entry includes several new elements provided by the server.
If there is already a rule in the access control list with a
scope whose type and value match that in the request, and whose role is anything other than none, then the POST operation fails with error code 409 Conflict.
The above POST might receive the following successful result:
200 OK
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>
<id>http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/user%3Adarcy%40gmail.com</id>
<updated>2007-04-15T22:03:57.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/acl/2007#accessRule'>
</category>
<title type='text'>editor</title>
<content type='text'></content>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/user%3Adarcy%40gmail.com'>
</link>
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/liz%40gmail.com/acl/full/user%3Adarcy%40gmail.com'>
</link>
<author>
<name>Elizabeth Bennet</name>
<email>liz@gmail.com</email>
</author>
<gAcl:scope type='user' value='darcy@gmail.com'></gAcl:scope>
<gAcl:role value='http://schemas.google.com/gCal/2005#editor'>
</gAcl:role>
</entry>
To change an ACL rule, you can send a PUT request to the edit URI of the entry
you want to modify. (You can also use this approach as an alternate method of creating new rules.)
You can construct the edit URI for a Google Calendar ACL rule entry using the entry's scope type and scope value, without having to retrieve the entry first.
For example, to change the ACL rule for user darcy@gmail.com, you could send the following PUT request:
PUT /calendar/feeds/liz@gmail.com/acl/full/user%3Adarcy%40gmail.com
With the following entry in the request body:
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/acl/2007#accessRule'/>
<gAcl:scope type='user' value='darcy@gmail.com'></gAcl:scope>
<gAcl:role value='http://schemas.google.com/gCal/2005#read'></gAcl:role>
</entry>
The URI fragment following /full/ in the PUT URI must indicate the same scope type and value as the <gAcl:scope> element in the entry you're sending.
The server silently overwrites any previous access level set for the indicated scope. If there is no existing rule for that scope, it will create a new one.
Note: Because a given rule is associated with a particular scope, it is not possible to modify the scope of a rule when updating it; only the role can be modified. An attempt to modify the scope will result in a 403 Forbidden error.
To remove a specific access rule for a calendar, you may do either of the following:
DELETE request to the appropriate ACL entry's edit URI.PUT) and set <gAcl:role value="none" />.Doing either of those things causes the user (or group of users) specified in the scope to lose access to the calendar.
You can add extended properties (arbitrary name-value pairs) to Calendar events. These can be used to store application-specific IDs or other small amounts of information your application needs when interacting with a Google Calendar. The name of a property can contain up to 47 characters, and the value can contain up to 1024 characters. Extended properties are only accessible through the API – they do not appear in the Calendar user interface.
To include extended properties in your events, add the <extendedProperty> element like this:
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005" >
<id>http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID</id>
<published>2006-03-30T22:00:00.000Z</published>
<updated>2006-03-28T05:47:31.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/g/2005#event'></category>
<title type='text'>Lunch with Darcy</title>
<content type='text'>Lunch to discuss future plans.</content>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=aTJxcnNqbW9tcTJnaTE5cnMybmEwaW04bXMgbWFyY2guam9AZ21haWwuY29t'
title='alternate'></link>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID'></link>
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID/version' />
<gd:extendedProperty name="propname" value="propvalue" />
...
</entry>
Note: Extended properties are not indexed so you can't query based on their keys or values.
To include reminders in your events, add the <gd:reminder> element as a child of the <when> element like this:
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005" >
<id>http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID</id>
<published>2006-03-30T22:00:00.000Z</published>
<updated>2006-03-28T05:47:31.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/g/2005#event'></category>
<title type='text'>Lunch with Darcy</title>
<content type='text'>Lunch to discuss future plans.</content>
<link rel='alternate' type='text/html'
href='http://www.google.com/calendar/event?eid=aTJxcnNqbW9tcTJnaTE5cnMybmEwaW04bXMgbWFyY2guam9AZ21haWwuY29t'
title='alternate'></link>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID'></link>
<link rel='edit' type='application/atom+xml'
href='http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID/version' />
<gd:when startTime='2006-03-30T22:00:00.000Z' endTime='2006-03-30T23:00:00.000Z'>
<gd:reminder minutes='30' method='email' />
<gd:reminder minutes='10' method='alert' />
</gd:when> ...
</entry>
You can include up to five reminders per event. The available methods are email, alert (a popup in the browser), sms (a text message), or none.
By default every event created through the Google Calendar interface is associated with a SMS reminder, even if SMS notifications are not enabled in your Google Calendar account setting.
For an event to inherit the default reminder setting of your Google Calendar account, you can either add an empty reminder element with no method value <gd:reminder /> or add a <gd:reminder method='all' /> element.
If you want to ensure that no reminders are sent, add a <gd:reminder method='none' /> element.
Note: The value of the minutes attribute must correspond to one of the reminder time increments available in the Google Calendar web application.