Google Apps Platform

Google Calendar API v1 Developer's Guide: .NET

This API is a subject to the Deprecation Policy and will be deprecated on November 17, 2014. Please use APIv3 instead.

Google Calendar allows client applications to view and update calendar events in the form of Google Data API 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.

This document provides detailed examples for using the .NET Client Library to work with the Google Calendar service. For help setting up the client library, see the Getting Started Guide. You will find examples of adding events, updating events, deleting events and querying events. If you're interested in understanding more about the underlying protocol used by the .NET Client Library to interact with the Calendar Data API, please see the protocol tab.



This document is intended for programmers who want to write client applications using the Google Data API .NET client library that can interact with Google Calendar.

Getting started

For help setting up the client library, see the Getting Started Guide. To use the .NET client library, you'll need the .NET 1.1 runtime, and you should also be current on all patches. After downloading the client library, you'll find the DLLs you need to get started in the lib/Release subdirectory of the distribution.

A full working copy of this sample is available in the Google Data API project in the project hosting section of The sample is located at /trunk/clients/cs/samples/calendar/console/CalendarDemo.cs in the SVN repository accessible from the Source tab.

After compiling the sample, run it as follows:

gcal_demo <userName> <userPassword> <feedUri>

The userName and userPassword values represent the credentials used to login to Google Calendar. The feedUri value is typically for working with your primary calendar. To use a non-primary calendar, find the address in the Google Calendar UI by clicking the arrow next to the calendar, choosing calendar settings and copy and paste the XML URL for the 'Calendar Address' seen on the settings tab. Please replace the word public with the word private in the URL, as the sample will be authenticating using the provided credentials.

The sample performs a number of operations on the provided calendar to demonstrate the use of the Calendar Data API. Please see the RunSample method of the code for more details as to which operations are performed.

To compile the examples in this document into your own code, you'll need the following using statements:

using Google.GData.Calendar;
using Google.GData.Client;
using Google.GData.Extensions;

The CalendarService class represents a client connection (with authentication) to a Calendar service. The general procedure for sending a query to a service using the client library consists of the following steps:

  1. Obtain or construct the appropriate URL.
  2. If you're sending data to a service (for example, if you're inserting a new entry), then transform the raw data into objects using the client library classes. (This step doesn't apply if you're just requesting a feed, as we're doing in this example.)
  3. Create a new CalendarService instance, setting your application's name (in the form companyName-applicationName-versionID).
  4. Set the appropriate credentials.
  5. Call a method to send the request and receive any results.

Authenticating to the Calendar service

The .NET client library can be used to work with either public or private feeds. Public feeds are read-only, but do not require any authentication. Private feeds require that you authenticate to the calendar servers. This can be done via ClientLogin username/password authentication or AuthSub proxy authentication. The calendar service also allows authentication to a read-only private feed using magic cookie authentication.

Please see the authentication documentation for more information on AuthSub and ClientLogin.

AuthSub proxy authentication

As of version 1.09 of the .NET client library, it is possible for applications to authenticate using the AuthSub login protocol. This is useful, for example, if you have an ASP application that requires Calendar authentication.

To acquire an AuthSub token for a given user and a given service, your application must redirect the user to the AuthSubRequest URL, which prompts them to log into their Google account. (For more information on the AuthSubRequest URL, see the AuthSub documentation.)

Supposing we have the following ASP hyperlink defined in our page:

<asp:HyperLink ID="GotoAuthSubLink" runat="server"/>

then to construct the AuthSubRequest URL for your application, make a .NET client library call as follows:

GotoAuthSubLink.Text = "Login to your Google Account";
GotoAuthSubLink.NavigateUrl = AuthSubUtil.getRequestUrl("",

The getRequestUrl method takes several parameters (corresponding to the query parameters used by the AuthSubRequest handler): the "next" URL (which is the URL that Google will redirect to after the user logs into their account and grants access); the scope (as determined in the previous section); and two Booleans, one to indicate whether the token will be used in registered mode or not, and one to indicate whether the token will later be exchanged for a session token or not. The above example shows a call in unregistered mode (the first Boolean is false), for a token that will be exchanged for a session token later (the second Boolean is true); adjust the Booleans appropriately for your application.

After the user follows the link to the AuthSub page at Google and logs in, the AuthSub system then redirects the user back to your application, using the "next" URL you provided.

When Google redirects back to your application, the token is appended to the "next" URL as a query parameter. So in the case of the above "next" URL, after the user logs in, Google redirects to a URL like Therefore, the token is accessible as a variable in the ASP page's Request.QueryString object.

The token you initially retrieve is always a one-time use token. You can exchange this token for a session token using the AuthSubSessionToken URL, as described in the AuthSub documentation. Your application can make this exchange using the .NET client library as follows:

Session[[]"sessionToken"] = AuthSubUtil.exchangeForSessionToken(Request.QueryString[[]"token"], null);

You pass your one-time use token to the exchangeForSessionToken method, along with either null (for unregistered mode) or a private key (for registered mode), and the AuthSub interface returns a session token. For more information about registered applications and private keys, refer to the Signing requests section of the AuthSub documentation.

Now you are ready to use the session token to authenticate requests to the Calendar server by placing the token in the Authorization header. To tell the .NET client library to automatically send the Authorization header (containing the session token) with each request, do the following:

GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl","CalendarSampleApp");
authFactory.Token = Session[[]"sessionToken"].ToString();
Service service = new Service("cl", authFactory.ApplicationName);
service.RequestFactory = authFactory;

ClientLogin username/password authentication

To use ClientLogin (also called "Authentication for Installed Applications"), invoke the setUserCredentials method of CalendarService, specifying the ID and password of the user on whose behalf your client is sending the query. For example:

CalendarService myService = new CalendarService("exampleCo-exampleApp-1");
myService.setUserCredentials("", "mypassword");

For more information about authentication systems, see the Google Account Authentication documentation.

Magic cookie authentication

The simplest feed URL to use is that of the calendar's read-only so-called "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. Those URLs (and information on how to use authentication) are covered in later examples, but even if you aren't going to use the "magic cookie" URL, you should read through the first couple of examples to learn the basics of sending Calendar requests.

To find your calendar's "magic cookie" feed URL:

  1. In the list of calendars on the left side of the page, find the calendar you want to interact with. You can create a new calendar for this purpose if you want to.
  2. Click the arrow button to the right of the calendar. Select "Calendar settings" from the drop-down menu. The Calendar Details page appears.
  3. Scroll down to the Private Address section. There are two buttons; select the XML button. The feed URL appears.
  4. Copy the URL. This is the URL of your calendar's read-only "magic cookie" private feed; it includes a special coded string that lets you read the private feed without having to do authentication. This is the URL you'll use to request a feed from Calendar, so you won't have to do authentication just to view the feed.

The feed URL has the following form:

You can modify this URL in the following ways:

  • If you want a private feed that requires authentication, convert the "private-{magic-cookie}" part of this path to just "private".
  • If you want the "full" calendar project, change the last component from "basic" to "full" in the URL. Using "basic" returns a basic Atom feed without any extension elements. Using "full" returns a feed that includes all event properties, but comments aren't included inline. Instead, they're specified (in the <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:

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.

Retrieving calendar lists

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.

Retrieving all calendars

You can get a list of a user's calendars by sending an authenticated GET request to the allcalendars feed URL:

The result is a feed that includes all primary, secondary, and imported calendars.

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.

To request this feed using the .NET client library, first instantiate a new CalendarService object and authenticate the user. Then use the Query method to retrieve a CalendarFeed object that contains entries for all of the user's calendars.

// Create a CalenderService and authenticate
CalendarService myService = new CalendarService("exampleCo-exampleApp-1");
myService.setUserCredentials("", "mypassword");

CalendarQuery query = new CalendarQuery();
query.Uri = new Uri("");
CalendarFeed resultFeed = (CalendarFeed) service.Query(query);
Console.WriteLine("Your calendars:\n");
foreach (CalendarEntry entry in resultFeed.Entries)
    Console.WriteLine(entry.Title.Text + "\n");

Retrieving only calendars that a user owns

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:

Querying this feed will return a list of calendars that includes the user's primary and secondary calendars, as well as any imported calendars that the user has been granted "ownership" of. The feed can be accessed by replacing the URL in the previous example:

// Create a CalenderService and authenticate
CalendarService myService = new CalendarService("exampleCo-exampleApp-1");
myService.setUserCredentials("", "mypassword");

CalendarQuery query = new CalendarQuery();
query.Uri = new Uri("");
CalendarFeed resultFeed = (CalendarFeed) service.Query(query);
Console.WriteLine("Your calendars:\n");
foreach (CalendarEntry entry in resultFeed.Entries)
    Console.WriteLine(entry.Title.Text + "\n");

Managing Calendars

The owncalendars feed can also be used to create, update, and delete calendars. Calendars created through the owncalendars feed will be secondary calendars.

Creating new calendars

To create a new calendar, first instantiate a CalendarEntry object and set the appropriate values. Then call the CalendarService.Insert method, specifying the owncalendars feed. The following example uses an authenticated CalendarService object called service:

CalendarEntry calendar = new CalendarEntry();
calendar.Title.Text = "Little League Schedule";
calendar.Summary.Text = "This calendar contains the practice schedule and game times.";
calendar.TimeZone =  "America/Los_Angeles";
calendar.Hidden = false;
calendar.Color = "#2952A3";
calendar.Location = new Where("", "", "Oakland");

Uri postUri = new Uri("");
CalendarEntry createdCalendar = (CalendarEntry) service.Insert(postUri, calendar);

Note: The <atom:id> field of the calendar entry should be null because the Google Calendar server will create an id for the entry when it process the request.

Updating existing calendars

You can update most information about a user's calendar via the owncalendars feed. The following example updates the title and color of the first calendar retrieved from the owncalendars feed.

CalendarQuery query = new CalendarQuery();
query.Uri = new Uri("");
CalendarFeed resultFeed = (CalendarFeed) service.Query(query);

CalendarEntry calendar = (CalendarEntry) resultFeed.Entries[[]0];
calendar.Title.Text = "New Title";
calendar.Color = "#A32929";
calendar.Selected = true;

Deleting calendars

To delete a calendar, simply call the Delete method. The following example attempts to delete all the calendars that are returned in the feed:

CalendarQuery query = new CalendarQuery();
query.Uri = new Uri("");
CalendarFeed resultFeed = (CalendarFeed) service.Query(query);

foreach (CalendarEntry entry in resultFeed.Entries)
    Console.WriteLine("Deleting calendar: " + entry.Title.Text + "\n");
    catch (GDataRequestException)
        Console.WriteLine("Unable to delete primary calendar.\n");

Note: You cannot delete a user's primary calendar.

Managing subscriptions to calendars

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.

Adding new subscriptions

To subscribe to an existing calendar, first instantiate a CalendarEntry object and use the Id property to specify the calendar to subscribe to. Then call the CalendarService.insert method, specifying the allcalendars feed. The following example uses an authenticated CalendarService object called service to subscribe to the Google Doodles calendar:

CalendarEntry calendar = new CalendarEntry();
calendar.Id = new AtomId("");
Uri postUri = new Uri("");
CalendarEntry createdCalendar = (CalendarEntry) service.Insert(postUri, calendar);

This invocation of insert will have different results based on the current state of the calendar. If the subscription doesn't exist, then the calendar is added to the user's list of imported calendars. If the user has already subscribed to the calendar, then the server will return a 409 Conflict. If the calendar inserted is currently hidden, it will become visible.

Updating calendar subscriptions

You can update the personalization settings of a calendar using the allcalendars feed. Settings such as color and visibility can be updated 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. The following example turns all the calendars in the feed green:

CalendarQuery query = new CalendarQuery();
query.Uri = new Uri("");
CalendarFeed resultFeed = (CalendarFeed) service.Query(query);

foreach (CalendarEntry entry in resultFeed.Entries)
    entry.Color = "#0D7813";

Deleting subscriptions

To remove an imported calendar, retrieve the calendar from the allcalendars feed and call the Delete method. The following example removes the subscription to the Google Doodles gadget that was added in a previous example:

string doodleCalendarUrl = "";
CalendarEntry doodleCalendar = (CalendarEntry) service.Get(doodleCalendarUrl);

Retrieving events

Retrieving events without query parameters

To request a Calendar feed using the .NET client library, for a user with email address "", use the following code:

// Create the query object:
EventQuery query = new EventQuery();
query.Uri = new Uri("");

// Tell the service to query:
EventFeed calFeed = service.Query(query);

Again, this example assumes that service is a CalendarService object that has been properly authenticated using one of the methods described above.

Retrieving events for a specified date range

To view events on your calendar that overlap a particular date range, use the following .NET code:

EventQuery myQuery = new EventQuery(feedUrl);
myQuery.StartTime = new DateTime(2007, 1, 5);
myQuery.EndTime = new DateTime(2007, 1, 7);

EventFeed myResultsFeed = myService.Query(myQuery);

The above code creates a new EventQuery for the feed whose URL is feedUrl. It specifies that we want to retrieve all events from January 5, 2007 (inclusive) to January 7, 2007 (exclusive). Finally, the query is executed by calling the Query method of myService, which we assume is an authenticated CalendarService.

Retrieving events matching a full text query

To retrieve the first match in a full-text search, use the following code:

EventQuery myQuery = new EventQuery(feedUrl);
myQuery.Query = "Tennis";
EventFeed myResultsFeed = myService.Query(myQuery);
if (myResultsFeed.Entries.Count > 0) {
  AtomEntry firstMatchEntry = myResultsFeed.Entries[[]0];
  String myEntryTitle = firstMatchEntry.Title.Text;

This example starts by constructing an EventQuery object, which consists mostly of a URL plus associated query parameters. Each of the standard Data API query parameters has a property.

After constructing the EventQuery, we pass it to the service's Query method, which returns a feed containing the query results. An alternative approach would be to construct a URL yourself (by appending query parameters to the feed URL) and then call the Query method, but the EventQuery method provides a useful layer of abstraction so that you don't have to construct the URL yourself.

The feed's Entries collection returns a list of the entries in the feed; Entries.Count returns the number of entries in the feed.

In this case, if the query returned any results, we assign the first matching result to an AtomEntry object. Then we use the AtomEntry class's Title property to retrieve the entry's title.

The above code is equivalent to sending GET to Calendar.

Creating events

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.

Creating single-occurrence events

To insert a single-occurrence event into a Calendar feed, you might use the following code:

EventEntry entry = new EventEntry();

// Set the title and content of the entry.
entry.Title.Text = "Tennis with Beth";
entry.Content.Content = "Meet for a quick lesson.";

// Set a location for the event.
Where eventLocation = new Where();
eventLocation.ValueString = "South Tennis Courts";

When eventTime = new When(DateTime.Now, DateTime.Now.AddHours(2));

Uri postUri = new Uri("");

// Send the request and receive the response:
AtomEntry insertedEntry = service.Insert(postUri, entry);

In this example, we first construct an EventEntry object. Then the code sets several properties of the entry we're adding: its Title and Content text, as well as its location. Note that to set the event's location, we must first construct a Where object whose ValueString is the desired location text. Similarly, we construct a When object to contain the start and end times of the event.

We're using the same Service object that we created in the previous example. In this case, the method to call is Insert, which sends an item to the specified insertion URL.

The service returns the newly created entry, which may contain additional server-generated elements, such as an edit URL for the entry.

The above code is equivalent to sending POST (with proper authentication) and providing an entry.

Note: Some of these code snippets show adding an event to a default calendar or to a specific user's primary calendar (substituting a gmail address for the 'default' string in the POST URI), but events can also be added to non-primary calendars as well. To do this, you simply need the calendar ID which can be retrieved from the allcalendars feed, and is also shown in the Calendar Settings page of the UI. This id is again used in the feed URI:<id>/private/full.

Creating quick add events

To create an event using Google Calendar's quick add feature, set the entry's content to the quick add string you'd like to use. Then call setQuickAdd on the new entry, as follows:

EventEntry myEntry = new EventEntry();
myEntry.QuickAdd = true;
myEntry.Content.Content = "Tennis with John Sep 20 3pm-3:30pm";
Uri postUri = new Uri("");

EventEntry createdEntry = (EventEntry) service.Insert(postUri, myEntry);

Notice that it's not necessary to set the Title property when creating an event with quick add; the title is parsed automatically (in this case, "Tennis with John").

Creating Calendar Event Gadgets

You can also insert Calendar Event Gadgets events using the .NET Client Library. Calendar Event Gadgets, formerly called web content, can contain images, HTML pages, or gadgets.

To create a simple Calendar Event Gadget that displays and image first instantiate a new WebContentLink object and set its properties, as follows:

WebContentLink wc = new WebContentLink();
wc.Title = "World Cup";
wc.Type = "image/gif";
wc.Url = "";
wc.Icon = "";
wc.Width = 276;
wc.Height = 120;

This code sets up a WebContentLink object to display the World Cup doodle (dimensions 276x120, and located at The icon at will be used to display the Calendar Event Gadget in the Calendar user interface before it is clicked.

To create a Calendar Event Gadget that displays a gadget, create a WebContentLink object 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 Event Gadget to display the DateTime gadget and specifies the appropriate user preferences.

WebContentLink wc = new WebContentLink();
wc.Title = "DateTime Gadget (a classic!)";
wc.Type = "application/x-google-gadgets+xml";
wc.Url = "";
wc.Icon = "";
wc.Width = 300;
wc.Height = 136;
wc.GadgetPreferences[[]"color"] = "green";

Once you've created the WebContentLink object, use the WebContentLink property to associate the WebContentLink object with your new entry, and insert the event as follows:

EventEntry entry = new EventEntry();
entry.WebContentLink = wc;
entry.Title.Text = "Content Title";
Uri postUri = new Uri("");
EventEntry createdEntry = (EventEntry) service.Insert(postUri, entry);

It's also possible to add web content to an existing event, as follows:

entry.WebContentLink = wc;

This inserts the Calendar Event Gadget on the current date. Please see the section on Creating single-occurrence events for information on how to set the Times property to choose the date when the Calendar Event Gadget should appear on the calendar.

Note: For more information on Calendar Event Gadgets, check out the documentation here.

Creating recurring events

To create a recurring event, use code similar to the following:

EventEntry myEntry = new EventEntry();

String recurData =
  "DTSTART;VALUE=DATE:20070501\r\n" +
  "DTEND;VALUE=DATE:20070502\r\n" +

Recurrence recurrence = new Recurrence();
recurrence.Value = recurData;
myEntry.Recurrence = recurrence;

In this example, we first create a string containing an iCalendar (RFC 2445) specification of the desired event recurrence. Here, the all-day event occurs first on 2007/05/01 and repeats weekly on Tuesdays until 2007/09/04. Next, a new Recurrence object is constructed and its Value is set to the recurrence string. Finally, a new EventEntry is created and the recurrence added by setting its Recurrence property.

Updating events

To update an existing item, use the following code. In the following example, we're changing the previously retrieved entry's title from its old text ("Tennis with Beth") to "Important meeting."

retrievedEntry.Title.Text = "Important meeting";

First we set a new title for the entry we fetched earlier. Then we just call the Update method to send the updated entry to the service.

The service returns the updated entry, including a new URL for this entry's new version. (For more information on entry versions, see the Optimistic concurrency section of the Google Data API Protocol Reference.)

The above code is roughly equivalent to sending PUT to the service, along with the new entry (in Atom format) to replace the original entry.

Deleting events

To delete an existing item, use the following code:


The URL to use for deletion is the same as the edit URL, so this example is very similar to the previous one, except of course that we're calling the Delete method instead of Update.

The above code is roughly equivalent to sending DELETE to the service.

Performing multiple operations with a batch request

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 an EventFeed object and add an entry for each operation you want to perform. The following code snippet builds and submits 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. The snippet also shows how to check the batch response to make sure the operations were successful. Note that the service object is an authenticated instance of the CalendarService class.

// Get some events to operate on.
EventQuery query = new EventQuery("");
EventFeed feed = service.Query(query);

// Create an batch entry to update an existing event.
EventEntry toUpdate = (EventEntry) feed.Entries[[]0];
toUpdate.Content.Content = "updated description";
toUpdate.BatchData = new GDataBatchEntryData("A", GDataBatchOperationType.update);

// Create an batch entry to query an event.
EventEntry toGet = (EventEntry) feed.Entries[[]1];
toGet.BatchData = new GDataBatchEntryData("B", GDataBatchOperationType.query);

// Create an batch entry to delete an existing event.
EventEntry toDelete = (EventEntry)feed.Entries[[]2];
toDelete.Id = new AtomId(toDelete.EditUri.ToString());
toDelete.BatchData = new GDataBatchEntryData("C", GDataBatchOperationType.delete);

// Create an batch entry to insert a new event.
EventEntry toCreate = new EventEntry("new event");
toCreate.Times.Add(new When(DateTime.Now, DateTime.Now.AddHours(2)));
toCreate.BatchData = new GDataBatchEntryData("D", GDataBatchOperationType.insert);

// Add the entries to a new feed.
AtomFeed batchFeed = new AtomFeed(feed);

EventFeed batchResultFeed = (EventFeed)service.Batch(batchFeed, new Uri(feed.Batch));

//check the return values of the batch operations to make sure they all worked.
//the insert operation should return a 201 and the rest should return 200
bool success = true;
foreach (EventEntry entry in batchResultFeed.Entries)
    if (entry.BatchData.Status.Code != 200 && entry.BatchData.Status.Code != 201)
        success = false;
        Console.WriteLine("The batch operation with ID " +
            entry.BatchData.Id + " failed.");

if (success)
    Console.WriteLine("All batch operations successful!");

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 API Batch Processing documentation.

Sharing calendars

This section describes how to share calendars by retrieving and modifying Calendar access control lists (ACLs) with the .NET client library. An access control list identifies the set of users with whom a calendar is shared, and the access permissions (read-only access, full access, etc.) of each user or group of users. For more information, see the ACL topic of the Protocol section.

Retrieving access control lists

To retrieve and print the access control lists of all of your calendars, use the following code. Here service is an authenticated CalendarService object.

FeedQuery query = new FeedQuery();
query.Uri = new Uri("");
AtomFeed calFeed = service.Query(query);

// Retrieve the meta-feed of all calendars.
foreach (AtomEntry calendarEntry in calFeed.Entries)
    Console.WriteLine("Calendar: {0}", calendarEntry.Title.Text);
    AtomLink link = calendarEntry.Links.FindService(
        AclNameTable.LINK_REL_ACCESS_CONTROL_LIST, null);

    // For each calendar, retrieve its ACL feed.
    if (link != null)
        AclFeed feed = service.Query(new AclQuery(link.HRef.ToString()));
        foreach (AclEntry aclEntry in feed.Entries)
            Console.WriteLine("\tScope: Type={0} ({1})", aclEntry.Scope.Type,
            Console.WriteLine("\tRole: {0}", aclEntry.Role.Value);

After accessing the "meta-feed" to retrieve a list of all calendars, we extract the ACL link for each calendar and retrieve that feed. These links have the following form:<userId>/acl/full

We then print each entry in the feed. An AclEntry consists of a scope, which defines a user with access to this calendar, and a role, which defines how much access he or she has. Valid roles are:

  • AclRole.ACL_CALENDAR_FREEBUSY – this user can only see free/busy information
  • AclRole.ACL_CALENDAR_READ – this user can see all event details
  • AclRole.ACL_CALENDAR_EDITOR – this user can make changes to events
  • AclRole.ACL_CALENDAR_OWNER – this user can make changes and manage sharing

Note: Google Data ACLs define scopes that encompass more than one user, though the examples here only use AclScope.SCOPE_USER for simplicity. Specifically, AclScope.SCOPE_DOMAIN (available only in Google Apps) indicates that an access rule applies to all users with email addresses in the domain, while AclScope.SCOPE_DEFAULT specifies an access rule that applies to all users. For more information, see the GAcl namespace element reference.

Adding a rule to an access control list

To add a user to a calendar's access control list, you might do the following:

AclEntry entry = new AclEntry();

entry.Scope = new AclScope();
entry.Scope.Type = AclScope.SCOPE_USER;
entry.Scope.Value = "";

entry.Role = AclRole.ACL_CALENDAR_READ;

Uri aclUri = new Uri("");

AclEntry insertedEntry = service.Insert(feedUri, entry) as AclEntry;

This code allows to have read-only access to's calendar. Note that if an attempt is made to add an entry with a scope whose type and value match another entry already in the access control list, the operation will fail with error code 409 (Conflict).

Updating a rule in an access control list

In order to change a user's access level to a calendar, update the AclEntry with the following code:

entry.Role = AclRole.ACL_CALENDAR_OWNER;
AclEntry updatedEntry = entry.Update() as AclEntry;

This code changes entry to a rule indicating that the user defined in its scope has full (owner) access privileges.

Note: It is not possible to modify the scope of an AclEntry when updating it; only the role can be modified. An attempt to update the scope will result in a 403 (Forbidden) error.

Removing a rule from an access control list

To remove a user from a calendar's access control list, do the following:


Here entry is an AclEntry that was already defined as a variable or retrieved from an AclFeed. Executing this code will cause the user defined in entry's scope to lose access to this calendar.

Additional operations

This section describes other Calendar operations you can perform with the Google Data API .NET client library.

Extended properties

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. Extended properties are only accessible through the API – they do not appear in the Calendar user interface.

In this example, we are adding an extended property id with value 1234 to the Calendar entry myEntry. It is recommended that you specify the complete schema URL to avoid namespace collisions with other applications that use the same property name:

EventEntry myEntry = new EventEntry();

ExtendedProperty property = new ExtendedProperty();
property.Name = "";
property.Value = "1234";


Reminders and Notifications

To set a reminder for a calendar event, you can do the following:

Reminder fifteenMinReminder = new Reminder();
fifteenMinReminder.Minutes = 15;
fifteenMinReminder.Method =;

This code sets a 15-minute email reminder for the event 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, use the Reminder.ReminderMethod.all value for the Method property.

If you want to ensure that no reminders are sent, use the Reminder.ReminderMethod.none value for the Method property.

Note: The value of the minutes attribute must correspond to one of the reminder time increments available in the Google Calendar web application.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.