Google APIs Discovery Service

Using the API

Contents

  1. Introduction
  2. Discovery document format
    1. Basic API description
    2. Authentication
    3. Resources and schemas
    4. Methods
      1. Scopes
      2. Request and response
      3. Parameters
      4. Media upload
      5. Media download
    5. Common parameters
    6. Features
    7. Inline documentation
  3. Building a client library using APIs Discovery Service
    1. Step 1: Fetch the Discovery document
    2. Step 2: Compose a request
    3. Step 3: Make a call and handle the response
  4. Examples
    1. Simple client

Introduction

This document is intended for developers who want to write client libraries, IDE plugins, and other tools for interacting with Google APIs. The Google APIs Discovery Service allows you to do all of the above by exposing machine readable metadata about other Google APIs through a simple API. This guide provides an overview of each section of the Discovery document, as well as helpful tips on how to use the document.

All calls to the API are unauthenticated, JSON-based, REST requests that use SSL, i.e. URLs begin with https.

If you're unfamiliar with Google APIs Discovery Service concepts, you should read Getting Started before starting to code.

Discovery document format

This section gives an overview of the Discovery document.

All the examples below use the Discovery document from the URL Shortener API. You can load the Discovery document for the URL Shortener API by executing this GET request:

GET https://www.googleapis.com/discovery/v1/apis/urlshortener/v1/rest

Try it now in APIs Explorer!

The format of a Discovery document includes information that falls into six main categories:

Each of these Discovery document sections is described below. Consult the Reference documentation for more details about each property.

Basic API Description

The Discovery document begins with a set of API-specific properties:

  "kind": "discovery#restDescription",
  "name": "urlshortener",
  "version": "v1",
  "title": "Lets you create, inspect, and manage goo.gl short URLs",
  "description": "Lets you create, inspect, and manage goo.gl short URLs",
  "protocol": "rest",
  "basePath": (Deprecated) "/urlshortener/v1/",
  "rootUrl": "https://www.googleapis.com/. Root URL under which all API services live",
  "servicePath": "/urlshortener/v1/. Base path for all REST requests",

These API-level properties include details about a particular version of an API, including the name, version, title and description. The protocol always has a fixed value of rest, as the APIs Discovery Service only supports RESTful methods of accessing the APIs.

The basePath field indicates the path prefix for this particular API version.

Authentication

The auth section contains details about the OAuth 2.0 auth scopes for the API. To learn more about how to use scopes with OAuth 2.0, visit Using OAuth 2.0 to Access Google APIs.

The auth section contains a nested oauth2 and scopes section. The scopes section is a key/value mapping from the scope value to more details about the scope:

"auth": {
  "oauth2": {
    "scopes": {
      "https://www.googleapis.com/auth/urlshortener": {
        "description": "Manage your goo.gl short URLs"
      }
    }
  }
},

The auth section only defines the scopes for a particular API. To learn how these scopes are associated with an API method, consult the Methods section below.

Resources and schemas

An API's operations act on data objects called resources. The Discovery document is built around the concept of resources. Each Discovery document has a top-level resources section that groups all the resources associated with the API. For example, the URL Shortener API has a url resource:

"resources": {
  "url": {
    // Methods associated with the url resource
  }
}

Inside each resource section are the methods associated with that resource. The URL Shortener API has three methods associated with the url resource: get, list and insert.

Schemas tell you what the resources in an API look like. Each Discovery document has a top-level schemas section, which contains a name/value pair of schema ID to object. Schema IDs are unique per API, and are used to uniquely identify the schema in the methods section of the Discovery document:

"schemas": {
  "Url": {
    // JSON Schema of the Url resource.
  }
}

APIs Discovery Service uses JSON Schema draft-03 for its schema representations. Here is a snippet of the JSON Schema for the Url resource, along with an actual response resource:

Url Resource JSON Schema: Actual Url Resource Response:
{
  "id": "Url",
  "type": "object",
  "properties": {
    "analytics": {
      "$ref": "AnalyticsSummary",
    },
    "id": {
      "type": "string",
      "description": "..."
    },
    "kind": {
      "type": "string",
      "description": "...",
      "default": "urlshortener#url"
    },
    "longUrl": {
      "type": "string",
      "description": "..."
    }
  }
}

{
  "kind": "urlshortener#url",
  "id": "http://goo.gl/fbsS",
  "longUrl": "http://www.google.com/"
}

The fields in bold show the mapping between the JSON Schema and the actual response.

Schemas may also contain references to other schemas. If you are building a client library, this can help you effectively model the objects of an API in your data model classes. In the Url example above, the analytics property is actually a reference to a schema with ID AnalyticsSummary. If you look at the schemassection, you will find the AnalyticsSummary schema. The value of this schema can be substituted for the analytics property in the Url resource (note that the $ref syntax comes from the JSON Schema spec).

Methods may also reference schemas when indicating their request and response bodies. Refer to the Methods section for more details.

Methods

The core of the Discovery document is built around methods. Methods are the operations that can be performed on an API. You will find the methods section in various areas of the Discovery document, including at the top level (which we call API-level methods) or at the resources level.

"methods": {
  // API-level methods
}
"resources": {
  "resource1": {
    "method": {
      // resource-level methods
    }
    "resources": {
      "nestedResource": {
        "methods": {
          // methods can even be found in nested-resources
        }
      }
    }
  }
}

While an API may have API-level methods, a resource must have a methods section.

Each methods section is a key/value map from method name to other details about that method. The example below documents two methods, get and insert:

"methods": {
  "get": { //details about the "get" method },
  "insert": { //details about the "insert" method }
}

Finally, each method's section details various properties about that method. Here is an example of the get method:

"get": {
  "id": "urlshortener.url.get",
  "path": "url",
  "httpMethod": "GET",
  "description": "Expands a short URL or gets creation time and analytics.",
  "response" : { "$ref": "Url"},
  "parameters": { // parameters related to the method },
  "mediaUpload": { // optional media upload information },
}

This section contains general method details such as a unique ID to identify the method, the httpMethod to use, and the path of the method (for details on how to use the path property to calculate the full method url, see the Compose a request section). In addition to these general method properties, there are a few properties that connect the method with other sections in the Discovery document:

Scopes

The auth section defined earlier in this documentation contains information about all the scopes supported by a particular API. If a method supports one of these scopes, it will have a scopes array. There is one entry in this array for each scope supported by the method. For example, the scopes section of the URL Shortener insert method looks like this:

"scopes": [
  "https://www.googleapis.com/auth/urlshortener"
]

Note that choosing an auth scope to use in your application depends on various factors such as which methods are being called and what parameters are sent along with the method. Therefore, the decision of which scope to use is left to the developer. Discovery only documents which scopes are valid for a method.

Request and response

If the method has a request or response body, these are documented in the request or response sections, respectively. In the get example above, the method has a response body:

"response" : { "$ref": "Url"},

The syntax above indicates that the response body is defined by a JSON Schema with an ID of Url. This schema can be found in the top-level schemas section. Both request and response bodies use the $ref syntax for referring to schemas.

Parameters

If a method has parameters that should be specified by the user, these parameters are documented the the method-level parameters section. This section contains a key/value mapping of the parameter name to more details about that parameter:

"parameters": {
  "shortUrl": {
    "type": "string",
    "description": "The short URL, including the protocol.",
    "required": true,
    "location": "query"
  },
  "projection": { ... }
},
"parameterOrder": [
  "shortUrl"
],

In the example above, there are two parameters for the get method:shortUrl and projection. Parameters can either go in the path or the URL query; the location property indicates where the client library should put the parameter.

There are many other properties describing the parameter, including the parameter data type (useful for strongly-typed languages), whether the parameter is required, and whether the parameter is an enum. Consult the Reference Guide for more details on the properties.

Parameter order

There are many ways for client libraries to structure their interfaces. One way is to have a method with each API parameter in the method signature. However, since JSON is an unordered format, it's difficult to know programmatically how to order the parameters in the method signature.  The parameterOrder array provides a fixed parameter ordering for making requests. The array lists the name of each parameter in order of significance; it can contain either path or query parameters, but every parameter in the array is required. In the example above, a Java method signature might look something like this:

public Request get(String shortUrl, Map<String, Object> optionalParameters);

The first value in the parameterOrder array, shortUrl, is also the first element in the method signature.  If there were other parameters in the parameterOrder array, they would go after the shortUrl parameter.  Since the parameterOrder array only contains the required parameters, it is a good practice to include a way for users to specify optional parameters as well.  The example above does this with the optionalParameters map.

Media upload

If a method supports uploading media, such as images, audio, or video, then the location and protocols supported for uploading that media are documented in the mediaUpload section. This section contains details about which upload protocols are supported, and information about what kinds of media can be uploaded:

"supportsMediaUpload": true,
"mediaUpload": {
  "accept": [
    "image/*"
  ],
  "maxSize": "10MB",
  "protocols": {
    "simple": {
      "multipart": true,
      "path": "/upload/storage/v1beta1/b/{bucket}/o"
    },
    "resumable": {
     "multipart": true,
     "path": "/resumable/upload/storage/v1beta1/b/{bucket}/o"
    }
  }
}

In the example above, the supportsMediaUpload property is a boolean value that determines if the method supports uploading media. If the value is true then the mediaUpload section documents the kinds of media that can be uploaded.

The accept property is a list of media-ranges that determine which mime-types are acceptable to upload. The endpoint shown in the example above will accept any image format.

The maxSize property has the maximum size of an upload. The value is a string in units of MB, GB or TB. In the example above, uploads are limited to a maximum size of 10 MB. Note that this value doesn't reflect an individual user's remaining storage quota for that API, so even if the upload is less than maxSize the client library should still be prepared to handle an upload that fails because of insufficient space.

The protocols section lists the upload protocols that a method supports. The simple protocol is simply POSTing the media to the given endpoint in a single HTTP request. The resumable protocol implies that the endpoint given in the path URI supports the resumable upload protocol. If the multipart property is true then the endpoint accepts multipart uploads, which means both the JSON request and the media can be wrapped together in a mutlipart/related body and sent together. Note that both simple and resumable protocols may support multipart uploads.

The path property is a URI Template and should be expanded just like the path property for the method, as outlined in the Compose a request section.

Media download

If a method supports downloading media, such as images, audio, or video, then that is indicated by the supportsMediaDownload parameter:

"supportsMediaDownload": true,

When downloading media you must set the alt query parameter to media in the request URL.

Common parameters

The top-level Discovery document contains a parameters property. This section is similar to the parameters section for each method, however these parameters can be applied to any method in the API.

For example, the get, insert or list methods of the URL Shortener API can have a prettyPrint parameter in the request parameters, which will format the response for all those methods in a human-readable format. Here's a list of common parameters:

Parameter Meaning Notes Applicability
alt

Data format for the response.

  • Valid values: json, atom, csv.
  • Default value: varies per API.
  • Not all values are available for every API.
  • Applies to all operations for all resources.
key API key. (REQUIRED*)
  • *Required unless you provide an OAuth 2.0 token.
  • Your API key identifies your project and provides you with API access, quota, and reports.
  • Obtain your project's API key from the APIs console.
access_token OAuth 2.0 token for the current user.
prettyPrint

Returns response with identations and line breaks.

  • Returns the response in a human-readable format if true.
  • Default value: varies per API.
  • When this is false, it can reduce the response payload size, which might lead to better performance in some environments.
quotaUser Alternative to userIp.
  • Lets you enforce per-user quotas from a server-side application even in cases when the user's IP address is unknown. This can occur, for example, with applications that run cron jobs on App Engine on a user's behalf.
  • You can choose any arbitrary string that uniquely identifies a user, but it is limited to 40 characters.
  • Overrides userIp if both are provided.
  • Learn more about capping usage.
userIp IP address of the end user for whom the API call is being made.
  • Lets you enforce per-user quotas when calling the API from a server-side application.
  • Learn more about capping usage.

Features

There are some cases where APIs support custom features outside the scope of the rest of the Discovery document. These are collected in the features array. The features array contains a string label for each special feature supported by the API. Currently, dataWrapper is the only supported feature, but other features might be supported in the future.

"features": dataWrapper

The dataWrapper feature indicates that all requests to and responses from the API are wrapped in a data JSON object. This is a feature of older Google APIs, but it is being deprecated moving forward. The following APIs support the dataWrapper feature: Latitude v1, Moderator v1, and Translate v2.

As a client library developer, if an API supports the "dataWrapper" feature, you should do the following:

  1. On requests: Wrap the request resource in a data JSON object.
  2. On responses: Find the resource inside a data JSON object.

The schemas in the Discovery document do not contain the data wrapper, so you must explicitly add and remove them. For example, suppose there is an API with a resource named "Foo" that looks like this:

{
  "id": 1,
  "foo": "bar"
}

Before inserting this resource using the API, you need to wrap it in a data element:

{
  "data": {
    "id": 1,
    "foo": "bar"
  }
}

On the flip side, when you get a response from the API, it also contains the data wrapper:

{
  "data": {
    "id": 1,
    "foo": "bar"
  }
}

In order to get the resource defined by the schema, you need to remove the data wrapper:

{
  "id": 1,
  "foo": "bar"
}

Inline documentation

Each Discovery document is annotated with a number of description fields that provide inline documentation for the API. The description fields can be found for the following API elements:

  • API itself
  • OAuth scopes
  • Resource schemas
  • API Methods
  • Method parameters
  • Acceptable values for certain parameters

These fields are especially useful if you wish to use the Google APIs Discovery Service to generate human readable documentation for a client library, e.g. JavaDoc.

Building a client library using APIs Discovery Service

You can use the Google APIs Discovery Service for building a variety of different tools to use with Google APIs. However, the primary purpose of the Discovery document is to allow Google to create client libraries in various programming languages. This section describes how you could go about building a custom client library for Google APIs.

A stable and feature-complete client library is a complicated tool that can take months to develop. However, the general instructions for building a simple client library for Google APIs can be broken down to three simple steps:

  1. Fetching the Discovery document and constructing API surface
  2. Composing a request
  3. Making a call and fetching the response

These steps are described in more detail in the following sections. You can also have a look at the Simple APIs client sample in the Examples section to see how these instructions map to the code.

Step 1: Fetch the Discovery document

Before you begin implementing a client library, there are some basic requirements that impact how you will proceed down your development path. For example, your programming language of choice may be either typed or untyped; if is typed it could be either statically or dynamically typed. It may be compiled or interpreted. These requirements will guide your approach to consuming and using the Discovery document.

The first development task is to fetch the Discovery document. Your strategy for exactly when the document is to be fetched is determined by the requirements you identified. For example, in a statically-typed language, you might fetch the Discovery document early in the process and then generate code to handle the specific API described by the Discovery document. For a strongly-typed language, you might generate some code and build a compiled library. For a dynamically typed language, you can lazily construct the programming structures to interface to the API on the fly as the programming surface is used.

Step 2: Compose a request

Composing a requests involves two separate steps:

  1. Composing the request body.
  2. Constructing the request URL.

You need to convert the request body, if any, from a language-appropriate representation into the correct wire format. For example, in a Java client library, there may be a class for each request type that allows type-safe manipulation of the request data and is serializable into JSON.

The construction of the request URL is a slightly more complicated process.

The path property of each method in the API uses URI Template v04 syntax. This property may contain variables, which are surrounded by curly braces. Here is an example of a path property with variables:

/example/path/var

In the path above, var is a variable. The value for this variable comes from the Discovery document’s parameters section for that method. Each variable name has a corresponding value in the parameters object. In the example above, there is a parameter named var in the parameters section (and its location property is path, to indicate that it is a path variable).

When making a request, you should substitute the value for var into the URL. For example, if the user of the library makes a choice that sets var to the value foo, the new URL will be /example/path/foo.

Also note that the path property is a relative URI. In order to calculate the absolute URI, follow these steps:

  1. Grab the rootUrl property from the top level of the Discovery document.
    For example, the rootUrl property in the Discovery document for URL Shortener is:
    https://www.googleapis.com/
  2. Grab the servicePath from the top level of the Discovery document.
    For example, the servicePath property in the Discovery document for URL Shortener is:
    urlshortener/v1/
  3. Concatenate them together to get:
    https://www.googleapis.com/urlshortener/v1/
  4. Grab the path property, expand it as a URI Template, and combine the results of that expansion with the URI from the previous step.
    For example, in URL Shortener's get method, the value of the path property is url. So, the full URI for the method is:
    https://www.googleapis.com/urlshortener/v1/url

Step 3: Make a call and handle the response

After you send the request, the you need to deserialize the response into the appropriate language representation, taking care to handle error conditions that could occur — both in the underlying HTTP transport and error messages generated from the API service. The format of the errors is documented as part of the Google JSON Style Guide.

Examples

For some concrete examples of client libraries and tools that have been implemented using Google APIs Discovery Service, see the Libraries and Samples document. In addition, the following section gives a simple example of an APIs client library.

Simple APIs client

Below is an example of a very simple client library written in Python. The client builds an interface for interacting with the Google URL Shortener API, then shortens a URL using that interface.

Warning: the code below is a significally simplified version of a typical client library. It is an incomplete implementation that is provided to demonstrate some aspects of building a client library. It is not production-ready code.

import httplib2
import json
import uritemplate
import urllib
import urlparse

# Step 1: Fetch Discovery document
DISCOVERY_URI = "https://www.googleapis.com/discovery/v1/apis/urlshortener/v1/rest"
h = httplib2.Http()
resp, content = h.request(DISCOVERY_URI)
discovery = json.loads(content)

# Step 2.a: Construct base URI
BASE_URL = discovery['rootUrl'] + discovery['servicePath']

class Collection(object): pass

def createNewMethod(name, method):
  # Step 2.b Compose request
  def newMethod(**kwargs):
    body = kwargs.pop('body', None)
    url = urlparse.urljoin(BASE_URI, uritemplate.expand(method['path'], kwargs))
    for pname, pconfig in method.get('parameters', {}).iteritems():
      if pconfig['location'] == 'path' and pname in kwargs:
        del kwargs[pname]
    if kwargs:
      url = url + '?' + urllib.urlencode(kwargs)
    return h.request(url, method=method['httpMethod'], body=body,
                     headers={'content-type': 'application/json'})

  return newMethod

# Step 3.a: Build client surface
def build(discovery, collection):
  for name, resource in discovery.get('resources', {}).iteritems():
    setattr(collection, name, build(resource, Collection()))
  for name, method in discovery.get('methods', {}).iteritems():
    setattr(collection, name, createNewMethod(name, method))
  return collection

# Step 3.b: Use the client
service = build(discovery, Collection())
print service.url.insert(body='{"longUrl": "http://www.google.com/"}')

The key components of the client are:

  • Step 1: Fetch the Discovery document.
    The Discovery document for the Google URL Shortener API is retrieved and parsed into a data structure. Since Python is a dynamically typed language, the Discovery document can be fetched at runtime.
  • Step 2.a: Construct the base URI.
    The base URI is calculated.
  • Step 2.b: Compose the request.
    When a method is called on a collection the URI Template is expanded with the parameters passed into the method, and parameters with a location of query are put into the query parameters of the URL. Finally a request is sent to the composed URL using the HTTP method specified in the Discovery document.
  • Step 3.a: Build the client surface.
    The client surface is built by recursively descending over the parsed Discovery document. For each method in the methods section a new method is attached to the Collection object. Because collections can be nested we look for resources and recursively build a Collection object for all of its members if one is found. Each nested collection is also attached as an attribute to the Collection object.
  • Step 3.b: Use the client.
    This demonstrates how the built API surface is used. First a service object is built from the Discovery document, then a new URL is shortened via Google URL Shortener API by inserting a long URL into the url collection.

Authentication required

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

Signing you in...

Google Developers needs your permission to do that.