"conferenceData": { "entryPoints": [ { "entryPointType": "video", "uri": "https://meet.google.com/wix-pvpt-njj", "label": "meet.google.com/wix-pvpt-njj" }, { "entryPointType": "more", "uri": "https://tel.meet/wix-pvpt-njj?pin=1701789652855", "pin": "1701789652855" }, { "entryPointType": "phone", "uri": "tel:+44-20-3873-7654", "label": "+44 20 3873 7654", "pin": "6054226" } ], "conferenceSolution": { "key": { "type": "hangoutsMeet" }, "name": "Hangouts Meet", "iconUri": "https://blogger.googleusercontent.com/img/proxy/AVvXsEiaSY9_YfMdiWryFlVhzIs3jdKPPiVuvOTO4I2Roz_qnNGdmlz30rPKsRQpH_zL9sBemoQxmsA-Djl4q_jhz1-as83Gq-49NjORxptsEGxLEp4stip8yhdVitDBWRjGoECBYqs7fbAaINxFem2mwR8pCQXsn1dvNRegYieao0vH5kxDUWsI20mcOka_r5ha_zusG4YlXHa2mzRjZOc=" }, "conferenceId": "wix-pvpt-njj", "signature": "ADwwud9tLfjGQPpT7bdP8f3bq3DS" }
var solution = event.conferenceData.conferenceSolution; var content = document.getElementById("content"); var text = document.createTextNode("Join " + solution.name); var icon = document.createElement("img"); icon.src = solution.iconUri; content.appendChild(icon); content.appendChild(text);
var eventPatch = { conferenceData: { createRequest: {requestId: "7qxalsvy0e"} } }; gapi.client.calendar.events.patch({ calendarId: "primary", eventId: "7cbh8rpc10lrc0ckih9tafss99", resource: eventPatch, sendNotifications: true, conferenceDataVersion: 1 }).execute(function(event) { console.log("Conference created for event: %s", event.htmlLink); });
"conferenceData": { "createRequest": { "requestId": "7qxalsvy0e", "conferenceSolutionKey": { "type": "hangoutsMeet" }, "status": { "statusCode": "pending" } } }
var TIMEZONE = "America/Los_Angeles"; var EVENT = { "start": {"dateTime": "2017-07-01T19:00:00", "timeZone": TIMEZONE}, "end": {"dateTime": "2017-07-01T22:00:00", "timeZone": TIMEZONE}, "recurrence": ["RRULE:FREQ=MONTHLY;INTERVAL=2;UNTIL=20171231"] };
GCAL.events().patch(calendarId='primary', eventId=EVENT_ID, sendNotifications=True, body=EVENT).execute()
Google Calendar and Google Drive for Atlassian HipChat
Guest post by Rich Manalang, Partner Engineering Lead at Atlassian. Posted by Wesley Chun, Developer Advocate, Google Apps.
Atlassian has been building collaboration software for over 14 years. With products that include JIRA, Confluence, Bitbucket, and HipChat, our organization has learned a lot about how teams work effectively.
HipChat launched the Connect API in November 2015, and since then we’ve continued to build upon our ecosystem of integrations and collaborations. A few months ago, our team looked at potential integrations that would be a perfect marriage with HipChat — and today, we’re excited to share the Google Calendar and Google Drive integration for HipChat.
Millions of people use Google’s products everyday, so we instantly knew this was the right opportunity. Many of HipChat’s customers are developers, and they told us that managing time and better access to files were two of the most important things in their day-to-day. Now with Google integrations available inside of HipChat, there’s no need to launch another browser tab or app.
By building Google Calendar directly into HipChat, we’re improving the signal-to-noise ratio on a daily basis. Before this integration, we all dealt with context-switching between apps and browser tabs. Now, customers can use HipChat to view and share various calendars, schedules and important dates in the right sidebar. Our customers spend their entire working day inside our HipChat app — unlike email, you don’t just fire it up and quit periodically. So naturally, having your calendar up-front is compelling. And what’s more, you can slice and dice which ones you see on a per-room basis. Say you’re a program manager — if you go into the Engineering HipChat “room,” you can see the Engineering and related calendars. Then, when you switch into the Marketing room, you may see different calendars depending on whom you’re collaborating with.
Having dual calendars front and center within HipChat is critical for staying on top of my work. I’m personally very excited about the Google Calendar integration because it’s one of the most important apps I use day-in and day-out. As a single parent with two kids busy at school, I need to know everything that's going on. My calendar is stacked, and I want to see it all at a glance. That urgency is similar when considering the most important documents in someone's daily workflow.
When we started working on the Google Drive integration, we wanted to focus on what was most important — accessibility, shareability, and ease of use.
There are many benefits to bringing third party integrations right into HipChat. The Google Drive integration allows teams to collaborate and work together while saving time and eliminating context switching. Being able to access documents, presentations, and files is critical whether a user is at the office or remote. It integrates nicely into the right side bar, enabling users to access, share to the room, and collaborate around important documents, presentations, and spreadsheets. We worked with third party developer Topdox, who was a tremendous partner in bringing this new feature into HipChat. We’re getting great feedback around the speed and simplicity of sharing files without ever having to leave the HipChat application.
Why would Google Developers be interested?
When we built these integrations, we wanted to give our users a nice balance between out-of-the-box usefulness but also ultimate flexibility in which calendars and accounts a user can view. To do that, we wanted one UI that can display multiple calendars from multiple Google accounts — similar to what most Calendar mobile apps do today, including Google’s own mobile Calendar app.
These new integrations were built entirely on top of Google’s API. Google’s Calendar API is a full featured API that gave us everything we needed to create a calendar experience fit for HipChat’s users. On top of that, the API was designed with efficiency in mind with push notifications for changes to resources and incremental syncing to improve performance and bandwidth use.
Building on top of Google APIs has allowed us to think of new ways to bring even tighter integrations with our products along with the myriad of add-ons built by Atlassian’s ecosystem. One idea under consideration is to link JIRA Software and Google Calendar so that all your JIRA issues are overlayed onto a Google Calendar. Then this calendar can be shared with the relevant HipChat room bringing it all together and enabling teams to get more done. We’d love to hear your feedback on this idea.
We think there are many opportunities to improve how teams work together by integrating with Google and Atlassian. You can find out more about Atlassian Connect on our developer’s site and the Google APIs on theirs.
Posted by Muzammil Esmail, Product Manager, Google for Work and Wesley Chun, Developer Advocate, Google Apps
Over the years, we’ve been updating our APIs with new versions across Drive and Calendar, as well as those used for managing Google Apps for Work domains. These new services offer developers improvements over previous functionality and introduces new features that help Apps administrators better manage their domains.
To deliver even more granular control, today we are announcing the new Calendar Resource API as part of the Admin SDK’s Directory API that enables Google for Work customers to manage their physical resources, like conference rooms, printers, nap pods, tennis courts, walkstations, etc. These physical resources can be added to meetings by end users as needed. The API released today replaces the GDATA Calendar Resource API, so we encourage developers to begin moving their applications and tools to the new API. Please note that we will begin deprecation in January 2016 and sunset the existing API in January 2017. Stay tuned for a formal deprecation announcement with details.
Originally posted on the Google Developers Blog.
Posted by Wesley Chun, Developer Advocate
Have you ever booked a dining reservation, plane ticket, hotel room, concert ticket, or seats to the game from your favorite app, only to have to exit that booking app to enter the details into your calendar? It doesn’t make for a friendly user experience. Why can’t today’s apps do that for you automatically?
In case you missed it the episode 97 of #GoogleDev100 the other week, I aim to inspire how app developers can streamline that process with the help of the Google Calendar API. A short Python script, anchored by the following snippet, is illustrated to show developers how easy it is to programmatically add calendar events:
CALENDAR = apiclient.discovery.build('calendar', 'v3', http=creds.authorize(Http())) GMT_OFF = '-07:00' # PDT/MST/GMT-7 EVENT = { 'summary': 'Dinner with friends', 'start': {'dateTime': '2015-09-18T19:00:00%s' % GMT_OFF}, 'end': {'dateTime': '2015-09-18T22:00:00%s' % GMT_OFF}, 'attendees': [ {'email': 'friend1@example.com'}, {'email': 'friend2@example.com'}, ], } CALENDAR.events().insert(calendarId='primary', body=EVENT).execute()
For deeper dive into the script, check out the corresponding blogpost. With code like that, your app can automatically insert your relevant events into your users’ calendars, saving them the effort of manually doing it themselves. One of the surprising aspects is that a limited set of actions, such as RSVPing, is even available to non-Google Calendar users. By the way, inserting events is just the beginning. Developers can also delete or update events instantly in case that upcoming dinner gets pushed back a few weeks. Events can even be repeated with a recurrence rule. Attachments are also supported so you can provide your users a PDF of the concert tickets they just booked. Those are just some of the things the API is capable of.
Ready to get started? Much more information, including code samples in Java, PHP, .NET, Android, iOS, and more, can be found in the Google Calendar API documentation. If you’re new to the Launchpad Online developer series, we share technical content aimed at novice Google developers… the latest tools and features with a little bit of code to help you launch that app. Please give us your feedback below and tell us what topics you would like to see in future episodes!
Posted by Iskander Akishev, Software Engineer, Google Calendar
The Google Calendar API allows you to create and modify events on Google Calendar. Starting today, you can use the API to also attach Google Drive files to Calendar events to make them—and your app—even more useful and integrated. With the API, you can easily attach meeting notes or add PDFs of booking confirmations to events.
Here's how you set it up:
1) Get the file information from Google Drive (e.g. via the Google Drive API):
GET https://www.googleapis.com/drive/v2/files { ... "items": [ { "kind": "drive#file", "id": "9oNKwQI7dkW-xHJ3eRvTO6Cp92obxs1kJsZLFRGFMz9Q, ... "alternateLink": "https://docs.google.com/presentation/d/9oNKwQI7dkW-xHJ3eRvTO6Cp92obxs1kJsZLFRGFMz9Q/edit?usp=drivesdk", "title": "Workout plan", "mimeType": "application/vnd.google-apps.presentation", ... }, ... ] }
2) Pass this information into an event modification operation using the Calendar API:
POST https://www.googleapis.com/calendar/v3/calendars/primary/events?supportsAttachments=true { "summary": "Workout", "start": { ... }, "end": { ... }, ... "attachments": [ { "fileUrl": "https://docs.google.com/presentation/d/9oNKwQI7dkW-xHJ3eRvTO6Cp92obxs1kJsZLFRGFMz9Q/edit?usp=drivesdk", "title": "Workout plan", "mimeType": "application/vnd.google-apps.presentation" }, ... ] }
Voilà!
You don’t need to do anything special in order to see the existing attachments - they are now always exposed as part of an event:
GET https://www.googleapis.com/calendar/v3/calendars/primary/events/ja58khmqndmulcongdge9uekm7 { "kind": "calendar#event", "id": "ja58khmqndmulcongdge9uekm7", "summary": "Workout", ... "attachments": [ { "fileUrl": "https://docs.google.com/presentation/d/9oNKwQI7dkW-xHJ3eRvTO6Cp92obxs1kJsZLFRGFMz9Q/edit?usp=drivesdk", "title": "Workout plan", "mimeType": "application/vnd.google-apps.presentation", "iconLink": "https://ssl.gstatic.com/docs/doclist/images/icon_11_presentation_list.png" }, ... ] }
Check out the guide and reference in the Google Calendar API documentation for additional details.
For any questions related to attachments or any other Calendar API features you can reach out to us on StackOverflow.com, using the tag #google-calendar.
Posted by Janet Traub, Program Manager, Google Apps APIs
The Google Apps Developer team recently hosted a 3-part Hangout On Air series that provided the developer community a unique opportunity to engage with the creative minds behind Google Apps developer tools. Each session covered topics ranging from business automation using Apps Script to Google Calendar API usage to creating Add-Ons for Docs & Sheets.
In the first installment of the series, Mike Harm, the creator of Apps Script and his colleague Kenzley Alphonse delivered a captivating session entitled, “Automate your Business with Apps Script.” Together, they reviewed the various features of Apps Script that can help developers build powerful solutions with Google Apps, such as simple scripts, to easily do a mail merge, export calendars into a Sheet, and to generate regularly scheduled reports.
The series then shifted focus to Google Calendar. In “Creating Calendar Events - Easy and Useful” Ali A. Rad (Product Manager) and Lucia Fedorova (Tech Lead) for Google Calendar API, explained how developers can benefit from injecting content into users’ calendars. In addition, they reviewed different approaches on Google Calendar to create events and meetings, such as API features, email markups, Android intents, Calendar import, and more.
We concluded the series with “How to Increase Traffic to Your Add-On with Google Apps Script.” This session, delivered by Apps Script Product Manager, Saurabh Gupta and Mike Harm, gave developers an in depth understanding of the Add-Ons framework, steps to deployment and strategies to increase adoption of their Docs, Sheets and Forms Add-Ons.
For more information on developing for Google Apps, visit developers.google.com/google-apps
Editor’s note: This is a guest post by Martin Böhringer, Co-Founder and CEO of Hojoki. -- Steve Bazyl
Hojoki integrate productivity cloud apps into one newsfeed and enables sharing and discussions on top of the feed. We’ve integrated 17 apps now and counting, so it’s safe to say that we’re API addicts. Now it's Time to share with you what we learned about the Google Apps APIs!
Our initial reason for building Hojoki was because of the fragmentation we experience in all of our cloud apps. And all those emails. Still, there was this feeling of “I don’t know what’s going on” in our distributed teamwork. So we decided to build something like a Google+ where streams get automatically filled by activities in the apps you use.
This leads to a comprehensive stream of everything that’s going on in your team combined with comments and microblogging. You can organize your stream into workspaces, which are basically places for discussions and collaboration with your team.
To build this, we first need some kind of information on recent events. As we wanted to be able to aggregate similar activities and to provide a search, as well as splitting up the stream in workspaces, we also had to be able to sort events as unique objects like files, calendar entries and contacts.
Further, it’s crucial to not only know what has changed, but who did it. So providing unique identities is important for building federated feeds.
Google’s APIs share some basic architecture and structure, described in their Google Data Protocol. Based on that, application-specific APIs provide access to the application’s data. What we use is the following:
The basic call for Google Contacts for example looks like this:
https://www.google.com/m8/feeds/contacts/default/full
This responds with a complete list of your contacts. Once we have this list all we have to do is to ask for the delta to our existing knowledge. For such use cases, Google’s APIs support query parameters as well as sorting parameters. So we can set “orderby” to “lastmodified” as well as “updated-min” to the timestamp of our last call. This way we are able to keep the traffic low and get quick results by only asking for things we might have missed.
If you want to develop using those APIs you should definitely have a look at the SDKs for them. We used the Google Docs SDK for an early prototype and loved it. Today, Hojoki uses its own generic connection handler for all our integrated systems so we don’t leverage the SDKs anymore.
If you’re into API development, you’ve probably already realized that our information needs don’t fit into many of the APIs out there. Most of the APIs are object centric. They can tell you what objects are included in a certain folder, but they can’t tell you which object in this folder has been changed recently. They just aren’t built with newsfeeds in mind.
Google Apps APIs support most of our information needs. Complete support of OAuth and very responsive APIs definitely make our lives easier.
However, the APIs are not built with Hojoki-like newsfeeds in mind. For example, ETags may change even if nothing happened to an object because of asynchronous processing on Google’s side (see Google’s comment on this). For us this means that, once we detect an altered ETag, in some cases we still have to check based on our existing data if there really have been relevant activities. Furthermore, we often have trouble with missing actors in our activities. For example, up to now we know when somebody changed a calendar event, but there is no way to find out who this was.
Another issue is the classification of updates. Google’s APIs tell us that something changed with an object. But to build a nice newsfeed you also want to know what exactly has been changed. So you’re looking for a verb like created, updated, shared, commented, moved or deleted. While Hojoki calls itself an aggregator for activities, technically we’re primarily an activity detector.
You can think of Hojoki as a multi-layer platform. First of all, we try to get a complete overview on your meta-data of the connected app. In Google Docs, this means files and collections, and we retrieve URI and name as well as some additional information (not the content itself). This information fills a graph-based data storage (we use RDF, read more about it here).
At the moment, we subscribe to events in the integrated apps. If detected, they create a changeset for the existing data graph. This changeset is an activity for our newsfeed and related to the object representation. This allows us to provide a very flexible aggregation and filtering on the client side. See the following screenshot. You can filter the stream for a certain collection (“Analytics”) or only for the file history or for the Hojoki workspace where this file is added (“Hojoki Marketing”).
What’s really important in terms of such heavy API processing is to use asynchronous calls. We use the great Open Source project async-http-client for this task.
When I wrote that “we subscribe to events” this is a very nice euphemism for “we’re polling every 30s to see if something changed”. This is not really optimal and we’d love to change it. If Google Apps APIs would support a feed of user events modelled in a common standard like ActivityStrea.ms, combined with reliable ETags and maybe even a push API (e.g. Webhooks) this would also make life easier for lots of developers syncing their local files with Google and help to reduce traffic on both sides.
We recently posted some best practices for working with recurring events in Google Calendar API v3. In this blog post we’ll highlight another improved area in the v3 API: event reminders.
Google Calendar API v3 offers developers flexible control over event reminders, including per-calendar default settings and custom overrides for individual events.
The user’s default reminders for events on a given calendar can be found in the corresponding entry in the Calendar List collection. The Calendar List collection acts a bit like a list of bookmarks, containing entries for the calendars that the user owns or has looked at in the past (it corresponds to the content of the "My Calendars" and "Other Calendars" list on the bottom left in the Web version of Google Calendar). Each entry is annotated with user-specific settings for the individual calendar, such as the preferred color in the UI and the default reminders.
Google Calendar currently supports three ways of reminding its users of events: "popup", prompting a message directly in the browser, mobile phone or desktop client, as well as "email" and "sms" for messages sent through the respective channels. To change the defaults, update the Calendar List entry and include the reminder method and how many minutes in advance the user should be alerted. In the following example, we set an email reminder to be sent 60 minutes before an event, and a popup reminder 10 minutes before.
{ "summary": "Work Calendar", ... "defaultReminders": [ { "method": "email", "minutes": 60 }, { "method": "popup", "minutes": 10 } ] }
The default reminders will be applied to all existing and future events on this calendar, provided they don’t have custom reminders set already. In contrast to earlier versions of the API, newly created events will also have reminders set by default.
Sometimes, there are events that we want a special reminder for, or none at all. To override the defaults for a specific event, switch the useDefault flag in the reminders section to false, and include a set of custom reminders, or leave the list empty. When you define a set of override reminders for a recurring series, they are automatically applied to each of its occurrences, unless they have been overridden explicitly. Like the default reminders on the calendar, these are personal reminders for the user that is logged in, and will not influence the settings others might have for the same calendar or event. Here is an example that overrides the default reminders with a 15 minute SMS reminder for that specific event.
useDefault
reminders
false
{ "summary": "API Office Hours", ... "reminders": { "useDefault": false, "overrides": [ { "method": "sms", "minutes": 15 } ] } }
The defaults for the given calendar are included at the top of any event listing result. This way, reminder settings for all events in the result can be determined by the client without having to make the additional API call to the corresponding entry in the Calendar List collection.
In this post and an earlier post about best practices with recurring events, we have covered some improved areas of the latest version of the Google Calendar API. Have a look at the migration guide for a more complete view of other changes we made in the new version, and let us know what you think.
If you have any questions about handling reminders or other features of the new Calendar API, post them on the Calendar API forum.
Are you ever at an airport with no internet access, and realize that you forgot to set your "Out of Office" (OOO) message?" I forget regularly, but always remember to block off my calendar. Why not have the calendar automatically update my OOO message? We can! With the Calendar API, we can retrieve calendar events and set a vacation responder for the event duration for any user in the domain using the Email Settings API.
The first step is to authorize the Calendar and Email Settings client to make any call to the APIs respectively. The new Calendar API requires google-api-client library while the Email settings API still works with the gdata-client library in Python. These libraries use different underlying protocols and handle authorization differently.
Fortunately we can use the same code to get an OAuth 2.0 token for both the Calendar API and the Email Settings API.
from oauth2client.file import Storage from oauth2client.client import AccessTokenRefreshError from oauth2client.client import OAuth2WebServerFlow from oauth2client.tools import run SCOPES = ('https://www.googleapis.com/auth/calendar ' 'https://apps-apis.google.com/a/feeds/emailsettings/2.0/') FLOW = flow_from_clientsecrets('client_secrets.json', scope=SCOPES) storage = Storage('vacation.dat') credentials = storage.get() if credentials is None or credentials.invalid: credentials = run(FLOW, storage)
Now that we have obtained the OAuth 2.0 token from OAuth2WebServerFlow, we can use it in either library. To authorize the Calendar service:
# Create an httplib2.Http object to handle the HTTP # requests and authorize it with our good Credentials. http = httplib2.Http() http = credentials.authorize(http) # Build authorized service for Calendar API service = build('calendar', 'v3', http=http)
Authorizing the Email Settings client requires adapting the credentials:
auth2token = gdata.gauth.OAuth2Token(client_id=client_id, client_secret=client_secret, scope=SCOPE, access_token=credentials.access_token, refresh_token=credentials.refresh_token, user_agent='vacation-responder-sample/1.0') email_client = auth2token.authorize( gdata.apps.emailsettings.client.EmailSettingsClient( domain=domain))
Now its time to update the vacation responder based on calendar event using the authorized client. Lets query for events containing the string ‘vacation’ from the Calendar API. The following code snippet shows the retrieval of events.
# Convert the date to the RFC 3339 timestamp format # for Calendar API. cur_datetime = datetime.datetime.now() cur_date = cur_datetime.strftime('%Y-%m-%dT%H:%M:%SZ') events = service.events().list(calendarId=username, q='vacation', timeMin=cur_date, singleEvents=True, orderBy='startTime').execute()
By specifying a user’s email address as the calendarID, we can query against any primary calendars in our domain that are shared and readable by the administrator. If the user opts to hide their calendar, we won’t find any of their events. For additional details about the query on calendar events, refer to the calendar query parameters from the reference guide.
Next we can obtain the start and end time of the event and update the vacation responder using the Email Settings client if the event’s duration is day long or more.
if 'items' in events: for event in events['items']: startDate = event['start'] endDate = event['end'] # If event is set for the day not just for a time slot. if 'date' in startDate: email_client.UpdateVacation(username=username, enable=True, subject='Out of office', message='If urgent call me.', domain_only=True, start_date=startDate['date'], end_date=endDate['date']) print '\nVacation responder set for the days between %s to %s' % (startDate['date'], endDate['date']) break
You can download the sample and build your own application on top of it. We hope that this sample makes it easier to get started, particularly for apps that need to combine APIs from the two API clients. Please feel free to reach us in the Google Domain Info and Management Forum with any questions you have or write us feedback on this post.
Though developers are quite comfortable thinking in abstractions, we still find a lot of value in code examples and fully developed sample applications. Judging by the volume of comments, tweets, and git checkouts of the Au-to-do sample code we released a few weeks ago, our readers agree.
For Google Apps API developers who want to get started writing mobile apps, here’s a great new resource: a sample application that integrates Google Calendar API v3 with Android and illustrates best practices for OAuth 2.0. This meeting scheduler app built by Alain Vongsouvanh gets the user’s contact list, lets users select attendees, and matches free/busy times to suggest available meeting times. It provides a simple Android UI for user actions such as attendee selection:
The sample code for Meeting Scheduler demonstrates many key aspects of developing with Google Apps APIs. After authorizing all required access using OAuth 2.0, the Meeting Scheduler makes requests to the Calendar API. For example, the class FreeBusyTimesRetriever queries the free/busy endpoint to find available meeting times:
FreeBusyTimesRetriever
FreeBusyRequest request = new FreeBusyRequest(); request.setTimeMin(getDateTime(startDate, 0)); request.setTimeMax(getDateTime(startDate, timeSpan)); for (String attendee : attendees) { requestItems.add(new FreeBusyRequestItem().setId(attendee)); } request.setItems(requestItems); FreeBusyResponse busyTimes; try { Freebusy.Query query = service.freebusy().query(request); // Use partial GET to retrieve only needed fields. query.setFields("calendars"); busyTimes = query.execute(); // ... } catch (IOException e) { // ... }
In this snippet above, note the use of a partial GET request. Calendar API v3, along with many other new Google APIs, provides partial response with GET and PATCH to retrieve or update only the data fields you need for a given request. Using these methods can help you streamline your code and conserve system resources.
For the full context of all calls that Meeting Scheduler makes, including OAuth 2.0 flow and the handling of expired access tokens, see Getting Started with the Calendar API v3 and OAuth 2.0 on Android. The project site provides all the source code and other resources, and there’s a related wiki page with important configuration details.
We hope you’ll have a look at the sample and let us know what you think in the Google Apps Calendar API forum. You’re welcome to create a clone of the source code and do some Meeting Scheduler development of your own. If you find a bug or have an idea for a feature, don’t hesitate to file it for evaluation.
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.
$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
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.
Yesterday, the Google APIs Client Library for JavaScript was released, unlocking tons of possibilities for fast, dynamic web applications, without requiring developers to run their own backend services to talk to Google APIs. This client library supports all discovery-based APIs, including the Google Tasks, Google Calendar v3 and Groups Settings APIs. To make it easy to get started using the JS client with Google Apps APIs, we’ve provided an example below.
After you’ve configured your APIs console project as described in the client library instructions, grab a copy of your client ID and API key, as well as the scopes you need to access the API of your choice.
var clientId = 'YOUR_CLIENT_ID'; var apiKey = 'YOUR_API_KEY'; var scopes = 'https://www.googleapis.com/auth/calendar';
You’ll also need several boilerplate methods to check that the user is logged in and to handle authorization:
function handleClientLoad() { gapi.client.setApiKey(apiKey); window.setTimeout(checkAuth,1); checkAuth(); } function checkAuth() { gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult); } function handleAuthResult(authResult) { var authorizeButton = document.getElementById('authorize-button'); if (authResult) { authorizeButton.style.visibility = 'hidden'; makeApiCall(); } else { authorizeButton.style.visibility = ''; authorizeButton.onclick = handleAuthClick; } } function handleAuthClick(event) { gapi.auth.authorize( {client_id: clientId, scope: scopes, immediate: false}, handleAuthResult); return false; }
Once the application is authorized, the makeApiCall function makes a request to the API of your choice. Here we make a request to retrieve a list of events from the user’s primary calendar, and use the results to populate a list on the page:
function makeApiCall() { gapi.client.load('calendar', 'v3', function() { var request = gapi.client.calendar.events.list({ 'calendarId': 'primary' }); request.execute(function(resp) { for (var i = 0; i < resp.items.length; i++) { var li = document.createElement('li'); li.appendChild(document.createTextNode(resp.items[i].summary)); document.getElementById('events').appendChild(li); } }); }); }
To tie all of this together, we use the following HTML, which configures the DOM elements we need to display the list, a login button the user can click to grant authorization, and a script tag to initially load the client library:
<html> <body> <div id='content'> <h1>Events</h1> <ul id='events'></ul> </div> <a href='#' id='authorize-button' onclick='handleAuthClick();'>Login</a> <script> // Insert the JS from above, here. </script> <script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script> </body> </html>
Making requests to other discovery-based APIs, such as the Tasks API requires only small modifications to the above:
As additional discovery-based APIs are released, they’ll be automatically supported by the library (just like the Python and Ruby clients).
If you have general questions about the JS client, check out the JavaScript client group. For questions on specific Apps APIs come find us in the respective Apps API forum.
The Google Calendar API is one of Google’s most used APIs. Today, we’re rolling out a new version of the API that will give developers even more reasons to use it. Version three of the Google Calendar API provides several improvements over previous versions of the API:
Developers familiar with the Google Tasks API will feel right at home with Calendar API v3, as it uses similar syntax and conventions, as well as the same base client libraries. These Google-supported client libraries, based on discovery, are available in many languages with:
If you’re new to the Google Calendar API, getting started is easy. Check out the Getting Started Guide, which will walk you through the basic concepts of Google Calendar, the API, and authorization. Once you’re ready to start coding, the Using the API page will explain how to download and use the client libraries in several languages.
If you’d like to try out some queries before you start coding, check out the APIs Explorer and try out some example queries with the new API.
Developers already using older versions of the API can refer to our Migration Guide. This interactive guide offers side-by-side examples of the API in v2 and v3 flavors across both the protocol and multiple languages. Simply hover over the code in v2 (or v3) and see the equivalent in the other version.
With our announcement of v3 of the API, we’re also announcing the deprecation of the previous versions (v1 and v2). The older versions enter into a three year deprecation period, beginning today, and will be turned off on November 17, 2014.
We’d love to hear your feedback on the Google Calendar API v3. Please feel free to reach out to us in the Google Calendar API forum with any questions or comments you have. We’ll also be hosting live Office Hours (via Google+ Hangout) on 11/30 from 8am-8:45am EST to discuss the new API. We hope to see you then!
We have released version 1.9 of the .NET Library for Google Data APIs and it is available for download.
This version adds the following new features:
This new version also removes the client library for the deprecated Google Base API and fixes 20 bugs.
For more details, please check the Release Notes and remember to file feature requests or bugs in the project issue tracker.
https://www.google.com/calendar/feeds/default/freebusy/busy-times/userID
userID
https://www.google.com/calendar/feeds/default/freebusy/busy-times/batch
<feed xmlns='http://www.w3.org/2005/Atom'xmlns:app='http://www.w3.org/2007/app'xmlns:batch='http://schemas.google.com/gdata/batch'xmlns:gCal='http://schemas.google.com/gCal/2005'xmlns:gd='http://schemas.google.com/g/2005'> <batch:operation type='query'/> <entry> <id>http://www.google.com/calendar/feeds/default/freebusy/busy-times/liz%40example.com</id> </entry> <entry> <id>http://www.google.com/calendar/feeds/default/freebusy/busy-times/bob%40example.com</id> </entry> <entry> <id>http://www.google.com/calendar/feeds/default/freebusy/busy-times/luke%40example.com</id> </entry></feed>
<feed xmlns="http://www.w3.org/2005/Atom" …> <id>https://www.google.com/calendar/feeds/default/freebusy/batch/1234</id> <updated>2010-03-13T00:00:00.000Z</updated> <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/gCal/2005#freebusy"/> <title>Batch Feed</title> <entry xmlns:batch="http://schemas.google.com/gdata/batch" …> <id>http://www.google.com/calendar/feeds/default/freebusy/liz%40example.com</id> … updated, category, self link, author and batch info … <gCal:timeRange> <gd:when startTime='2010-03-13T00:00:00Z' endTime='2010-03-14T00:00:00Z'/> <gCal:timeRange> <gCal:busy> <gd:when startTime='2010-03-13T14:00Z' endTime='2010-03-13T14:30Z'/> </gCal:busy> <gCal:busy> <gd:when startTime='2010-03-13T16:00Z' endTime='2010-03-13T16:30Z'/> </gCal:busy> </entry> <entry …> <id>http://www.google.com/calendar/feeds/default/freebusy/bob%40example.com</id> … Free-busy entry content for Bob … </entry> <entry …> <id>http://www.google.com/calendar/feeds/default/freebusy/luke%40example.com</id> … Free-busy entry content for Luke … </entry></feed>
https://www.google.com/calendar/feeds/default/freebusy/group/groupID/busy-times
groupID
Posted by Alain Vongsouvanh and Nicolas Garnier, Google Calendar API Team
Want to weigh in on this topic? Discuss on Buzz