Please note that the contents of this offline web site may be out of date. To access the most recent documentation visit the online version .
Note that links that point to online resources are green in color and will open in a new window.
We would love it if you could give us feedback about this material by filling this form (You have to be online to fill it)



Getting Started with Google Tasks API on Google App Engine

Johan Euphrosine
June 2011
Updated January 2013 by Danny Hermes

This article shows how to build a simple Python App Engine application that retrieves a list of tasks with the Google Tasks API. Google Tasks stores tasks that users enter via GMail, their mobile device, or calendar. The Google Tasks API provides developers with a powerful set of API endpoints for searching, reading, and updating Google Tasks content and metadata.

During this tutorial you will learn how to:

  • Create a simple App Engine app using the Google APIs Client Library for Python.
  • Provide Google Tasks users a mechanism to authorize your app to access their tasks.
  • Make authorized requests to the Google Tasks API.

The source code for the final step of this tutorial is available in Google APIs Client Library for Python samples directory .

Before You Start

  1. Install Google App Engine SDK for Python for local testing and deployment of your application.
  2. Install Mercurial to check out a repository.
  3. Get the Google APIs Client Library for Python . This library supports the Google Tasks API.

Step 1: Create Your App Engine Project

First, you need to create a web application:

  1. Create a new directory named mytasks . This will contain your new application.

  2. In the mytasks directory, create a file named app.yaml with the following contents:

    application: mytasks
    version: 1
    runtime: python27
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: .*
      script: main.application
    

    For more information, see Python Application Configuration .

  3. In the mytasks directory, create a file named main.py with the following contents:

    import webapp2
    
    class MainHandler(webapp2.RequestHandler):
      def get(self):
        self.response.write('Hello App Engine!')
    
    application = webapp2.WSGIApplication([('/', MainHandler)], debug=True)
    
  4. Run dev_appserver.py app.yaml .

  5. Point your browser to http://localhost:8080 .

  6. You will see Hello App Engine! in the browser window.

Step 2: Enabling Your Application for the Tasks API

Next, you need to enable your application to use the Tasks API. The following instructions take you through the process for an app named mytasks :

To get started using Tasks API, you need to first create or select a project in the Google Developers Console and enable the API . Using this link guides you through the process and activates the Tasks API automatically.

Alternatively, you can activate the Tasks API yourself in the Developers Console by doing the following:

  1. Go to the Google Developers Console .
  2. Select a project, or create a new one.
  3. In the sidebar on the left, expand APIs & auth . Next, click APIs . In the list of APIs, make sure the status is ON for the Tasks API.
  4. In the sidebar on the left, select Credentials .

In either case, you end up on the Credentials page and can create your project's credentials from here.

If you haven't done so already, create your OAuth 2.0 credentials by clicking Create new Client ID under the OAuth heading. Next, look for your application's client ID and client secret in the relevant table. You may also create and edit redirect URIs from this page.

Record your client ID and client secret from the Google Developers Console .

In the mytasks directory, create a new file named settings.py . Copy the following test into the new file, replacing the 'client id' and the 'client secret' with those from your registered application.

CLIENT_ID='PASTE_YOUR_GENERATED_CLIENT_ID_HERE'
CLIENT_SECRET='PASTE_YOUR GENERATED_CLIENT_SECRET_HERE'
SCOPE='https://www.googleapis.com/auth/tasks'

This file will be imported and used by your authorization code. Replace the above placeholder values using those you've just generated.

Step 3: Add the Google Tasks API

Next, we need to import and use Google API Python client modules in order to retrieve the list of tasks for the current user.

  1. Follow the Google APIs Client Library for Python install instructions .

  2. Download the file named google-api-python-client-gae-N.M.zip from the list of downloads .

  3. Unzip that file into the mytasks directory.

  4. Replace the current contents of main.py with the following:

    import webapp2
    
    from apiclient.discovery import build
    from oauth2client.appengine import OAuth2Decorator
    
    import settings
    
    decorator = OAuth2Decorator(client_id=settings.CLIENT_ID,
                                client_secret=settings.CLIENT_SECRET,
                                scope=settings.SCOPE)
    service = build('tasks', 'v1')
    
    class MainHandler(webapp2.RequestHandler):
    
       @decorator.oauth_required
       def get(self):
         tasks = service.tasks().list(tasklist='@default').execute(
             http=decorator.http())
         self.response.write('<html><body><ul>')
         for task in tasks['items']:
           self.response.write('<li>%s</li>' % task['title'])
         self.response.write('</ul></body><html>')
    
    application = webapp2.WSGIApplication([
        ('/', MainHandler),
        (decorator.callback_path, decorator.callback_handler()),
        ], debug=True)
    
  5. Go to http://localhost:8080 .

  6. Login.

  7. Authorize. After authorizing, you will see the list of tasks from the default task list of this user.

You've now completed your first Google Tasks API application and you are ready to deploy to Google App Engine.

Step 4: Deploy Your Application

Finally, we will create a new Application Identifier for your app, and deploy it to Google App Engine.

  1. Go to the Google App Engine Administration Console .

  2. Create a new application or choose an existing one to re-use.

  3. Choose an Application Identifier .

  4. Update application in app.yaml with your new Application Identifier .

    application: your_app_id
    version: 1
    runtime: python27
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: .*
      script: main.application
    
  5. Go to the Google Developers Console . Select the application from the list.

  6. In the sidebar on the left, click APIs and auth .

  7. Click Credentials .

  8. Add the following Authorized Redirect URIs to the Client ID for web application panel, replacing your_app_id with your Application Identifier .

    http://your_app_id.appspot.com/oauth2callback
    https://your_app_id.appspot.com/oauth2callback

  9. Run google_appengine/appcfg.py update mytasks/ .

  10. Go to https://your_app_id.appspot.com .

  11. Login.

  12. Authorize. After authorizing, you should see the list of tasks from the default task list of this user.

Congratulations! You've just deployed your first Google Tasks API application to Google App Engine.

Bonus Task: Add Landing Page, Style and Template

Providing a landing page for your application is also important for making a less jarring OAuth experience, letting the user know up front why they are being directed into the OAuth flow before it begins as documented in the Google APIs Client Library for Python documentation .

You need to choose scopes wisely and not request for more permission than your application actually needs.

Lastly, if you'd like to add some polish, add some CSS styling to your HTML. You can use ours below, or create your own.

  1. Update settings.py by changing the scope to readonly :

    CLIENT_ID='PASTE_YOUR_GENERATED_CLIENT_ID_HERE'
    CLIENT_SECRET='PASTE_YOUR GENERATED_CLIENT_SECRET_HERE'
    SCOPE='https://www.googleapis.com/auth/tasks.readonly'

  2. Update main.py with the following contents:

    import webapp2
    from webapp2_extras import jinja2
    
    from apiclient.discovery import build
    from oauth2client.appengine import OAuth2Decorator
    
    import settings
    
    decorator = OAuth2Decorator(client_id=settings.CLIENT_ID,
                                client_secret=settings.CLIENT_SECRET,
                                scope=settings.SCOPE)
    service = build('tasks', 'v1')
    
    class MainHandler(webapp2.RequestHandler):
    
      def render_response(self, template, **context):
        renderer = jinja2.get_jinja2(app=self.app)
        rendered_value = renderer.render_template(template, **context)
        self.response.write(rendered_value)
    
      @decorator.oauth_aware
      def get(self):
        if decorator.has_credentials():
          result = service.tasks().list(tasklist='@default').execute(
              http=decorator.http())
          tasks = result.get('items', [])
          for task in tasks:
            task['title_short'] = truncate(task['title'], 26)
          self.render_response('index.html', tasks=tasks)
        else:
          url = decorator.authorize_url()
          self.render_response('index.html', tasks=[], authorize_url=url)
    
    def truncate(s, l):
      return s[:l] + '...' if len(s) > l else s
    
    application = webapp2.WSGIApplication([
        ('/', MainHandler),
        (decorator.callback_path, decorator.callback_handler()),
        ], debug=True)
    
  3. In the mytasks directory, create a file named templates/index.html with the following contents:

    <!doctype html>
    <html>
      <head>
        <link href="/css/style.css" rel="stylesheet" type="text/cs">
        <link href="http://fonts.googleapis.com/css?family=Coming+Soon:regular" rel="stylesheet" type="text/css">
      </head>
      <body>
        <ul id="tasklist">
          {% if tasks|length == 0 %}
          <li>
            <span class="check">
              <span>
    
              </span>
            </span>
          {% if authorize_url %}
            <a class="title" title="Grant read access to your tasks" href="{{ authorize_url }}">Grant Access</a>
          {% else %}
            <a class="title" title="Add more tasks in Gmail" href="http://mail.google.com/">Add More Tasks</a>
          {% endif %}
          </li>
          {% endif %}
          {% for task in tasks %}
          <li class="{{ task.status }}">
            <span class="check">
              <span>
                {% if task.status == "completed" %}
                &#x2713;
                {% else %}
                &nbsp;
                {% endif %}
              </span>
            </span>
            <a class="title" title="{{ task.title }}">{{ task.title_short }}</a>
          </li>
          {% endfor %}
        </ul>
      </body>
    </html>
    
  4. In the mytasks directory, create a file named css/style.css with the following contents:

    body {
        width: 600px;
        margin: auto;
        margin-top: 48px;
        margin-bottom: 48px;
        font-family: 'Coming Soon', serif;
        font-size: 35px;
    }
    
    ul {
        -moz-border-radius: 20px;
        -webkit-border-radius: 20px;
        border-radius: 20px;
        background-color: #f8f6c6;
        background-image: -webkit-linear-gradient(#fdfce8, #f8f6c6);
        list-style-type: none;
        padding: 0;
        margin: 0;
        border: 5px solid #e3e2be;
        -moz-box-shadow: 8px 8px 8px #ccc;
        -webkit-box-shadow: 8px 8px 8px #ccc;
        box-shadow: 8px 8px 8px #ccc;
    }
    
    li {
        padding-left: 20px;
        border-bottom: 4px solid #e3e2be;
    }
    
    li .check {
        display: block;
        float: left;
        border-right: 8px solid #e3e2be;
        padding-right: 20px;
        width: 20px;
    }
    
    li .title {
        margin-left: 4px;
        padding-left: 20px;
        border-left: 4px solid #e3e2be;
        color: black;
        text-decoration: none;
    }
    
    li:last-child {
        border-bottom: none;
    }
    
  5. Update app.yaml with the following contents:

    application: mytasks
    version: 1
    runtime: python27
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: /css
      static_dir: css
    
    - url: .*
      script: main.application
    
    libraries:
    - name: jinja2
      version: latest
    
  6. Deploy your application by following the instructions in Step 4 .

  7. Go to https://your_app_id.appspot.com You should see a well-designed lists of tasks.

Authentication required

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

Signing you in...

Google Developers needs your permission to do that.