2-Legged OAuth is a useful authorization mechanism for apps that need to manipulate calendars on behalf of users in an organization. Both developers building apps for the Google Apps Marketplace and domain administrators writing tools for their own domains can benefit. Let’s take a look at how to do this with the new Calendar API v3 and Java client library 1.6.0 beta.
To get started as a domain administrator, you need to explicitly enable the new Google Calendar API scopes under Google Apps cPanel > Advanced tools > Manage your OAuth access > Manage third party OAuth Client access:
The scope to include is:
https://www.googleapis.com/auth/calendar
To do the same for a Marketplace app, include the scope in your application's manifest.
Calendar API v3 also needs an API access key that can be retrieved in the APIs Console. Once these requirements are taken care of, a new Calendar service object can be initialized:
public Calendar buildService() { HttpTransport transport = AndroidHttp.newCompatibleTransport(); JacksonFactory jsonFactory = new JacksonFactory(); // The 2-LO authorization section OAuthHmacSigner signer = new OAuthHmacSigner(); signer.clientSharedSecret = "<CONSUMER_SECRET>"; final OAuthParameters oauthParameters = new OAuthParameters(); oauthParameters.version = "1"; oauthParameters.consumerKey = "<CONSUMER_KEY>"; oauthParameters.signer = signer; Calendar service = Calendar.builder(transport, jsonFactory) .setApplicationName("<YOUR_APPLICATION_NAME>") .setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() { @Override public void initialize(JsonHttpRequest request) { CalendarRequest calendarRequest = (CalendarRequest) request; calendarRequest.setKey("<YOUR_API_KEY>"); } }).setHttpRequestInitializer(oauthParameters).build(); return service; }
Once the Calendar service object is properly initialized, it can be used to send authorized requests to the API. To access calendar data for a particular user, set the query parameter xoauth_requestor_id to a user’s email address:
xoauth_requestor_id
public void printEvents() { Calendar service = buildService(); // Add the xoauth_requestor_id query parameter to let the API know // on behalf of which user the request is being made. ArrayMap customKeys = new ArrayMap(); customKeys.add("xoauth_requestor_id", "<USER_EMAIL_ADDRESS>"); List listEventsOperation = service.events().list("primary"); listEventsOperation.setUnknownKeys(customKeys); Events events = listEventsOperation.execute(); for (Event event : events.getItems()) { System.out.println("Event: " + event.getSummary()); } }
Additionally, if the same service will be used to send requests on behalf of the same user, the xoauth_requestor_id query parameter can be set in the initializer:
// … Calendar service = Calendar.builder(transport, jsonFactory) .setApplicationName("<YOUR_APPLICATION_NAME>") .setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() { @Override public void initialize(JsonHttpRequest request) { ArrayMap customKeys = new ArrayMap(); customKeys.add("xoauth_requestor_id", "<USER_EMAIL_ADDRESS>"); calendarRequest.setKey("<YOUR_API_KEY>"); calendarRequest.setUnknownKeys(customKeys); } }).setHttpRequestInitializer(oauthParameters).build(); // ...
We hope you’ll try out 2-Legged OAuth and let us know what you think in the Google Calendar API forum.
With the Google Documents List API, there are two ways to identify resources: typed and untyped resource identifiers. Typed resource identifiers prefix a string of characters with the resource type. Untyped resource identifiers are similar, but do not have a type prefix. For example:
drawing:0Aj01z0xcb9
0Aj01z0xcb9
Client applications often need one type of identifier or the other. For instance, some applications use untyped resource IDs to access spreadsheets using the Google Spreadsheets API. Automatically generated API URLs in the Documents List API use typed or untyped resource IDs in certain situations.
Having two types of resource IDs is something that we will resolve in a future version of the API. Meanwhile, we strongly recommend that instead of using resource identifiers, clients always use URLs provided in feeds and entries of the Google Documents List API. The only time that manual URL modification is required is to add special parameters to a URL given by the API, for instance to search for a resource by title.
For example, the API issues self links along with each entry. To request an entry again, simply GET the self link of the entry. We recommend against constructing the link manually, by inserting the entry’s resource ID into the link.
Common links on entries include:
Accessing these links from a client library is simple. For instance, to retrieve the alternate link in Python, one uses:
resource = client.GetAllResources()[0] print resource.GetHtmlLink()
More information on these links is available in the documentation. For any questions, please post in the forum.
$apiClient = new apiClient(); $apiClient->setUseObjects(true);
$event = $service->events->get("primary", "eventId"); echo $event->getSummary();
result = client.execute( :api_method => service.events.get, :parameters => {'calendarId' => 'primary', 'eventId' => 'eventId'}) print result.data.summary
import randomimport timedef GetResourcesWithExponentialBackoff(client): """Gets all of the resources for the authorized user Args: client: gdata.docs.client.DocsClient authorized for a user. Returns: gdata.docs.data.ResourceFeed representing Resources found in request. """ for n in range(0, 5): try: response = client.GetResources() return response except: time.sleep((2 ** n) + (random.randint(0, 1000) / 1000)) print "There has been an error, the request never succeeded." return None
Developers using the Google Apps APIs owe it to themselves to stay informed. To make it as easy as possible, we’ve adopted a standard process for making important announcements about the APIs.
All major outages or issues, although infrequent, are announced on the Google Apps APIs Downtime Notify list as quickly as possible. We also post updates and resolutions. All developers using the Google Apps APIs should subscribe.
Announcements about new APIs and features as well as best practices about the Google Apps APIs occur on the this blog. You can subscribe via e-mail (see right sidebar), using the feed, by following @GoogleAppsDev on Twitter, or by following members of the team on Google+.
If you want to hear about just the most important announcements, follow the Google Apps APIs Announcements forum. This is a low-volume list and you can subscribe via e-mail.
Lastly, you should subscribe to the individual forums for the Google Apps APIs you care about the most. A lot of technical discussion occurs in the forums and many advanced API users participate in the conversation along with Google engineers.
We recently launched a new version of the Google Calendar API. In addition to the advantages it gains from Google's new infrastructure for APIs, Google Calendar API v3 has a number of improvements that are specific to Google Calendar. In this blog post we’ll highlight a topic that often causes confusion for developers using the Google Calendar API: recurring events.
A recurring event is a 'template' for a series of events that usually happen with some regularity, for example daily or bi-weekly. To create a recurring event, the client specifies the first instance of the event and includes one or more rules that describe when future events should occur. Google Calendar will then 'expand' the event into the specified occurrences. Individual events in a series may be changed, or even deleted. Such events become exceptions: they are still part of the series, but changes are preserved even if the recurring event itself is updated.
Let's create a daily recurring event that will occur every weekday of the current week (as specified by the recurrence rule on the last line):
POST https://www.googleapis.com/calendar/v3/calendars/primary/events { "summary": "Daily project sync", "start": { "dateTime": "2011-12-12T10:00:00", "timeZone": "Europe/Zurich" }, "end": { "dateTime": "2011-12-12T10:15:00", "timeZone": "Europe/Zurich" }, "recurrence": [ "RRULE:FREQ=DAILY;COUNT=5" ] }
When added to a calendar, this will turn into five different events. The recurrence rule is specified according to the iCalendar format (see RFC 5545). Note, however, that, in contrast to the previous versions of the Google Calendar API, the start and end times are specified the same way as for single instance events, and not with iCalendar syntax. Further, note that a timezone identifier for both the start and end time is always required for recurring events, so that expansion happens correctly if part of a series occurs during daylight savings time.
By default, when listing events on a calendar, recurring events and all exceptions (including canceled events) are returned. To avoid having to expand recurring events, a client can set the singleEvents query parameter to true, like in the previous versions of the API. Doing so excludes the recurring events, but includes all expanded instances.
Another way to get instances of a recurring event is to use the 'instances' collection, which is a new feature of this API version. To list all instances of the daily event that we just created, we can use a query like this:
GET https://www.googleapis.com/calendar/v3/calendars/primary/events/7n6f7a9g8a483r95t8en23rfs4/instances
which returns something like this:
{ ... "items": [ { "kind": "calendar#event", "id": "7n6f7a9g8a483r95t8en23rfs4_20111212T090000Z", "summary": "Daily project sync", "start": { "dateTime": "2011-12-12T10:00:00+01:00" }, "end": { "dateTime": "2011-12-12T10:15:00+01:00" }, "recurringEventId": "7n6f7a9g8a483r95t8en23rfs4", "originalStartTime": { "dateTime": "2011-12-12T10:00:00+01:00", "timeZone": "Europe/Zurich" }, ... }, … (4 more instances) ...
Now, we could turn one instance into an exception by updating that event on the server. For example, we could move one meeting in the series to one hour later as usual and change the title. The original start date in the event is kept, and serves as an identifier of the instance within the series.
If you have a client that does its own recurrence rule expansion and knows the original start date of an instance that you want to change, the best way to get the instance is to use the originalStart parameter like so:
originalStart
GET https://www.googleapis.com/calendar/v3/calendars/primary/events/7n6f7a9g8a483r95t8en23rfs4/instances?originalStart=2011-12-16T10:00:00%2B01:00
This would return a collection with either zero or one item, depending on whether the instance with the exact original start date exists. If it does, just update or delete the event as above.
We hope you’ll find value in these changes to recurring events. Keep in mind, too, that these are not the only improvements in Google Calendar API v3. Look for an upcoming post describing best practices for another key area of improvement: reminders.
If you have any questions about handling recurring events or other features of the new Calendar API, post them on the Calendar API forum.
Editor's note:: 2/20/2012 - Removed references to API call which reverted changes made to an individual instance. This feature was deprecated.
We've held many Office Hours on Google+ Hangouts over the last two months, bringing together Google Apps developers from around the world along with Googlers to discuss the Apps APIs. We've heard great feedback about these Office Hours from participants, so we've scheduled a few more in 2011.
General office hours (covering all Google Apps APIs):
Product-specific office hours:
As we add more Office Hours in the new year, we'll post them on the events calendar, and announce them on @GoogleAppsDev and our personal Google+ profiles.
Hope you’ll hang out with us soon!