Google Code offered in: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
This document describes the protocol used by the Google Data APIs, including information about what a query looks like, what results look like, and so on.
For more information about the Google Data APIs, see the Google Data Developer's Guide document and the Protocol Guide.
This document is intended for anyone wanting to understand the details of the XML format and protocol used by the Google Data APIs.
If you just want to write code that uses the Google Data APIs, then you don't need to know these details; instead, you can use the language-specific client libraries.
But if you want to understand the protocol, read this document. For example, you may want to read this document to help you with any of the following tasks:
This document assumes that you understand the basics of XML, namespaces, syndicated feeds, and the GET
, POST
, PUT
, and DELETE
requests in HTTP, as well as HTTP's concept of a "resource." For more information about those things, see the Additional resources section of this document.
This document doesn't rely on any particular programming language; you can send and receive Data API messages using any programming language that lets you issue HTTP requests and parse XML-based responses.
This section describes the Google Data API document format and query syntax.
The Google Data APIs, Atom, and RSS 2.0 all share the same basic data model: a container that holds both some global data and any number of entries. For each protocol, the format is defined by a base schema, but it can be extended using foreign namespaces.
The Google Data APIs can use either the Atom syndication format (for both reads and writes) or the RSS format (for reads only).
Atom is the default format for the Data APIs. To request a response in RSS format, use the /alt=rss/
parameter; for more information, see Query requests.
When you request data from a service in RSS format, the service supplies a feed (or other representation of the resource) in RSS format. If there's no equivalent RSS property for a given Data API property, the service uses the Atom property, labeling it with an appropriate namespace to indicate that it's an extension to RSS.
Note: Most Data API feeds in Atom format use the Atom namespace as the default namespace by specifying an xmlns
attribute on the feed element; see the examples section for examples of how to do that. Thus, the examples in this document don't explicitly specify atom:
for elements in an Atom-format feed.
The following tables show the Atom and RSS representations of the elements of the schema. All data not mentioned in these tables is treated as plain XML and shows up the same in both representations. Unless indicated otherwise, the XML elements in a given column are in the namespace corresponding to that column. This summary uses standard XPath notation: in particular, slashes show the element hierarchy, and an @ sign indicates an attribute of an element.
In each of the following tables, the highlighted items are required.
The following table shows the elements of a Data API feed:
Feed Schema Item | Atom Representation | RSS Representation |
---|---|---|
Feed Title | /feed/title |
/rss/channel/title |
Feed ID | /feed/id |
/rss/channel/atom:id |
Feed HTML Link | /feed/link[@rel="alternate"] \[@type="text/html"]/@href |
/rss/channel/link |
Feed Description | /feed/subtitle |
/rss/channel/description |
Feed Language | /feed/@xml:lang |
/rss/channel/language |
Feed Copyright | /feed/rights |
/rss/channel/copyright |
Feed Author |
(Required in certain cases; see Atom specification.) |
/rss/channel/managingEditor |
Feed Last Update Date | /feed/updated (RFC 3339 format) |
/rss/channel/lastBuildDate (RFC 822 format) |
Feed Category | /feed/category/@term |
/rss/channel/category |
Feed Category Scheme | /feed/category/@scheme |
/rss/channel/category/@domain |
Feed Generator | /feed/generator /feed/generator/@uri |
/rss/channel/generator |
Feed Icon | /feed/icon |
/rss/channel/image/url (unless there's also a logo, in which case the icon isn't included in the feed) |
Feed Logo | /feed/logo |
/rss/channel/image/url |
The following table shows the elements of a Data API search-results feed. Note that the Data APIs expose some of the OpenSearch 1.1 Response elements in search-results feeds.
Search Result Feed Schema Item | Atom Representation | RSS/OpenSearch Representation |
---|---|---|
Number of Search Results | /feed/openSearch:totalResults |
/rss/channel/openSearch:totalResults |
Search Result Start Index | /feed/openSearch:startIndex |
/rss/channel/openSearch:startIndex |
Number of Search Results Per Page | /feed/openSearch:itemsPerPage |
/rss/channel/openSearch:itemsPerPage |
The following table shows the elements of a Data API entry:
Entry Schema Item | Atom Representation | RSS Representation |
---|---|---|
Entry ID | /feed/entry/id |
/rss/channel/item/guid |
Entry Title | /feed/entry/title |
/rss/channel/item/title |
Entry Link | /feed/entry/link |
/rss/channel/item/link /rss/channel/item/enclosure /rss/channel/item/comments |
Entry Summary |
(Required in certain cases; see Atom specification.) |
/rss/channel/item/atom:summary |
Entry Content |
(If no content element, then entry must contain at least one |
/rss/channel/item/description |
Entry Author |
(Required in certain cases; see Atom specification.) |
/rss/channel/item/author |
Entry Category | /feed/entry/category/@term |
/rss/channel/item/category |
Entry Category Scheme | /feed/entry/category/@scheme |
/rss/channel/item/category/@domain |
Entry Publication Date | /feed/entry/published (RFC 3339) |
/rss/channel/item/pubDate (RFC 822) |
Entry Update Date | /feed/entry/updated (RFC 3339) |
/rss/channel/item/atom:updated (RFC 3339) |
This section describes how to use the query system.
The query model is intentionally very simple. The basic tenets are:
A client queries a Google service by issuing an HTTP GET
request. The query URI consists of the resource's URI (called FeedURI in Atom) followed by query parameters. Most query parameters are represented as traditional ?name=value[&...]
URL parameters. Category parameters are handled differently; see below.
For example, if the FeedURI is http://www.example.com/feeds/jo
, then you might send a query with the following URI:
http://www.example.com/feeds/jo?q=Darcy&updated-min=2005-04-19T15:30:00Z
The Google Data APIs support HTTP Conditional GET
. They set the Last-Modified response header based upon the value of the <atom:updated>
element in the returned feed or entry. A client can send this value back as the value of the If-Modified-Since request header to avoid retrieving the content again if it hasn't changed. If the content hasn't changed since the If-Modified-Since time, then the service returns a 304 (Not Modified) HTTP response.
A Data API must support category queries and alt
queries; support for other parameters is optional. Passing a standard parameter not understood by a given service results in a 403 Forbidden
response. Passing an unsupported nonstandard parameter results in a 400 Bad Request
response. For information on other status codes, see the HTTP status codes section of this document.
The standard query parameters are summarized in the following table. All parameter values need to be URL encoded.
Parameter | Meaning | Notes |
---|---|---|
q |
Full-text query string |
|
/-/category |
Category filter |
|
category |
Category filter |
|
author |
Entry author |
|
alt |
Alternative representation type |
|
updated-min , updated-max |
Bounds on the entry update date |
|
prettyprint |
Returns an XML response with identations and line breaks |
|
published-min , published-max |
Bounds on the entry publication date |
|
start-index |
1-based index of the first result to be retrieved |
|
strict |
Strict query parameter checking |
|
max-results |
Maximum number of results to be retrieved | For any service that has a default max-results value (to limit default feed size), you can specify a very large number if you want to receive the entire feed. |
entryID | ID of a specific entry to be retrieved |
|
We decided to specify a slightly unusual format for category queries. Instead of a query like the following:
http://example.com/jo?category=Fritz&category=2006
we use:
http://example.com/jo/-/Fritz/2006
This approach identifies a resource without using query parameters, and it produces cleaner URIs. We chose this approach for categories because we think that category queries will be the most common queries.
The drawback to this approach is that we require you to use /-/
in category queries, so that services can distinguish category queries from other resource URIs, such as http://example.com/jo/MyPost/comments
.
Queries return an Atom feed, an Atom entry, or an RSS feed, depending on the request parameters.
Query results contain the following OpenSearch elements directly under the <feed>
element or the <channel>
element (depending on whether results are Atom or RSS):
openSearch:totalResults
openSearch:startIndex
openSearch:itemsPerPage
start-index
in the table in the Query requests section.The Atom response feed and entries may also include any of the following Atom and Data API elements (as well as others listed in the Atom specification):
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="..."/>
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="..."/>
<link rel="self" type="..." href="..."/>
type
attribute depends on the requested format. If no data changes in the interim, sending another GET to this URI returns the same response.<link rel="previous" type="application/atom+xml" href="..."/>
<link rel="next" type="application/atom+xml" href="..."/>
<link rel="edit" type="application/atom+xml" href="..."/>
Here's a sample response body, in response to a search query:
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/"C0QBRXcycSp7ImA9WxRVFUk."'> <id>http://www.example.com/feed/1234.1/posts/full</id> <updated>2005-09-16T00:42:06Z</updated> <title type="text">Books and Romance with Jo and Liz</title> <link rel="alternate" type="text/html" href="http://www.example.net/"/> <link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <link rel="self" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> <generator version="1.0" uri="http://www.example.com">Example Generator Engine</generator> <openSearch:totalResults>2</openSearch:totalResults> <openSearch:startIndex>0</openSearch:startIndex> <entry gd:etag='W/"C0QBRXcycSp7ImA9WxRVGUo."'> <id>http://www.example.com/feed/1234.1/posts/full/4521614025009481151</id> <published>2005-01-09T08:00:00Z</published> <updated>2005-01-09T08:00:00Z</updated> <category scheme="http://www.example.com/type" term="blog.post"/> <title type="text">This is the title of entry 1009</title> <content type="xhtml"> <div xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1009</div> </content> <link rel="alternate" type="text/html" href="http://www.example.com/posturl"/> <link rel="edit" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full/4521614025009481151"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> </entry> <entry gd:etag='W/"C0QBRXrurSp7ImA9WxRVGUo."'> <id>http://www.example.com/feed/1234.1/posts/full/3067545004648931569</id> <published>2005-01-07T08:00:00Z</published> <updated>2005-01-07T08:02:00Z</updated> <category scheme="http://www.example.com/type" term="blog.post"/> <title type="text">This is the title of entry 1007</title> <content type="xhtml"> <div xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1007</div> </content> <link rel="alternate" type="text/html" href="http://www.example.com/posturl"/> <link rel="edit" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full/3067545004648931569"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> </entry> </feed>
If the requested feed is in the Atom format, if no query parameters are specified, and if the result doesn't contain all the entries, the following element is inserted into the top-level feed: <link rel="next" type="application/atom+xml" href="..."/>
. It points to a feed containing the next set of entries. Subsequent sets contain a corresponding <link rel="previous" type="application/atom+xml" href="..."/>
element. By following all the next links, a client can retrieve all entries from a feed.
The following table describes what various HTTP status codes mean in the context of the Data APIs.
Code | Explanation |
---|---|
200 OK | No error. |
201 CREATED | Creation of a resource was successful. |
304 NOT MODIFIED | The resource hasn't changed since the time specified in the request's If-Modified-Since header. |
400 BAD REQUEST | Invalid request URI or header, or unsupported nonstandard parameter. |
401 UNAUTHORIZED | Authorization required. |
403 FORBIDDEN | Unsupported standard parameter, or authentication or authorization failed. |
404 NOT FOUND | Resource (such as a feed or entry) not found. |
409 CONFLICT | Specified version number doesn't match resource's latest version number. |
410 GONE | Requested change history is no longer available on the server. Refer to service-specific documentation for more details. |
500 INTERNAL SERVER ERROR | Internal error. This is the default code that is used for all unrecognized errors. |
Sometimes you need to be able to refer to a specific version of a particular entry.
This is important in two cases in particular:
The Google Data APIs handle both of these cases using ETags, a standard part of HTTP.
An ETag is an identifier that specifies a particular version of a particular entry. The server attaches an ETag to entry and feed elements that it sends to clients. When an entry or feed changes, its ETag changes as well.
The Google Data APIs provide ETags in two places: in an ETag
HTTP header, and in a gd:etag
attribute of <feed>
and <entry>
elements.
In the Google Data APIs, an ETag is usually a string of letters and numbers, sometimes also including hyphens and periods; the string is usually enclosed in quotation marks. (The quotation marks are part of the ETag.) For example, here's an ETag from a Data API entry: "S0wCTlpIIip7ImA0X0QI"
.
There are two kinds of ETags: strong and weak. Strong ETags identify a specific version of a specific entry, and can be used to avoid overwriting other clients' changes. Weak ETags, in the context of the Google Data APIs, are used only for conditional retrieval. A weak ETag always starts with W/
. For example: W/"D08FQn8-eil7ImA9WxZbFEw."
Not all Google Data APIs support strong ETags. For those that do, the strong ETags are used only for entries; ETags on feeds are always weak.
Here's an example of a feed (including some of the HTTP headers) retrieved from a service that supports strong ETags:
GData-Version: 2.0 ETag: W/"C0QBRXcycSp7ImA9WxRVFUk." ... <?xml version='1.0' encoding='utf-8'?> <feed xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/"C0QBRXcycSp7ImA9WxRVFUk."'> ... <entry gd:etag='"CUUEQX47eCp7ImA9WxRVEkQ."'> ... </entry> </feed>
The client libraries that support version 2 of the Data APIs handle ETags for you, transparently. The following information is for clients that don't use client libraries, and for readers interested in how versioning is handled at the protocol level.
Note: For information about the resource-versioning system used in version 1.0 of the Data APIs, see 1.0 reference guide.
If you want to retrieve an entry that you've retrieved before, you can improve efficiency by telling the server to send the entry only if it has changed since the last time you retrieved it.
To do this sort of conditional retrieval, send an HTTP GET
request that includes an HTTP If-None-Match
header. In the header, specify the entry's ETag.
Here's an example of an If-None-Match
header:
If-None-Match: W/"D08FQn8-eil7ImA9WxZbFEw."
When the server receives this request, it checks to see whether the entry that you requested has the same ETag as the ETag you specified. If the ETags match, then the entry hasn't changed, and the server returns an HTTP 304 Not Modified
status code.
If the ETags don't match, then the entry has been modified since the last time you requested it, and the server returns the entry.
The easiest way to avoid overwriting another client's changes is for the server to make sure that when your client sends an updated entry, the version of the entry that your client started with is the same as the current version stored by the server. If a second client makes an update before your client does, then your client's update is denied, because your client is no longer basing its modifications on the latest version.
When your client retrieves data from a service that supports strong ETags, each entry has an ETag that acts as a unique version identifier for that version of that entry.
Note: Updating using ETags works only with strong ETags. For services that supply weak ETags, all updates succeed, regardless of whether someone else has updated the entry since you retrieved it; the newest update always overwrites any other prior updates. So don't send weak ETags when updating or deleting; you'll get an error message if you do.
So when your client sends an update to a strong-ETags service, it needs to specify what version of the entry it's updating. There are two ways to do that:
If-Match
HTTP header.gd:etag
attribute in the <atom:entry>
element.We recommend the If-Match
approach where possible.
To update an entry using If-Match
, start by acquiring the entry you're updating. Make any desired changes to the entry, then create a new PUT
request containing the modified entry. (For details of URLs to use, see service-specific documentation.)
Before sending the PUT
, add an HTTP If-Match
header containing the ETag from the original entry:
If-Match: "S0wCTlpIIip7ImA0X0QI"
Then send the PUT
request.
If the update succeeds, then the server returns an HTTP 200 OK
status code, and a copy of the updated entry.
If the update fails because the ETag you specified doesn't match the current ETag on the entry (which implies that the entry has changed on the server since you last retrieved it), then the server returns an HTTP 412 Precondition Failed
status code.
If you can't easily write HTTP headers, or have some other reason to avoid using the If-Match
header, then you can use the gd:etag
attribute instead.
If you don't send an If-Match
header, then the server uses the updated entry's gd:etag
attribute value as an implied If-Match
value.
To override the versioning system and update the entry regardless of whether someone else has updated it since you retrieved it, use If-Match: *
instead of specifying the ETag in the header.
For information about which services support strong ETags, see the Migration Guide.
Deleting entries that use strong ETags works much like updating them.
To delete an entry that has a strong ETag, first you retrieve the entry you want to delete, then you send a DELETE
request to the entry's edit URL.
If you want to make sure that you don't delete an entry that has been changed by another client since you retrieved it, then include an HTTP If-Match
header that contains the original entry's ETag value.
If you want to override the versioning system and delete the entry regardless of whether someone else has updated it since you retrieved it, use If-Match: *
instead of specifying the ETag in the header.
If an entry does not have a strong ETag, then a DELETE
request always succeeds.
When a client tries to access a service, it may need to provide the user's credentials to the service, to demonstrate that the user has the authority to perform the action in question.
The approach that a client should use for authentication depends on the type of client:
In the ClientLogin system, the desktop client asks the user for their credentials, and then sends those credentials to the Google authentication system.
If authentication succeeds, then the authentication system returns a token that the client subsequently uses (in an HTTP Authorization header) when it sends Data API requests.
If authentication fails, then the server returns a 403 Forbidden status code, along with a WWW-Authenticate header containing a challenge applicable to the authentication.
The AuthSub system works similarly, except that instead of asking the user for their credentials, it connects the user to a Google service that requests credentials. The service then returns a token that the web application can use; the advantage of this approach is that Google (rather than the web front end) securely handles and stores the user's credentials.
For details about these authentication systems, see the Google Data APIs Authentication Overview or the Google Account Authentication documentation.
Many business logic implementations require session stickiness—keeping track of the state of a user's session.
Google tracks session state in two ways: using cookies, and using a token that can be sent as a query parameter. Both methods achieve the same effect. We recommend that clients support one of these session-state tracking methods (either one is sufficient). If a client doesn't support either of these methods, then that client will still work with Data APIs, but performance may suffer compared to clients that do support these methods. Specifically, if a client doesn't support these methods, then every request results in a redirect, and therefore every request (and any associated data) is sent to the server twice, which affects the performance of both the client and the server.
The Google client libraries handle session state for you, so if you use our libraries, you don't have to do anything to get session state support.
You may find the following third-party documents useful:
GET
, POST
, PUT
, and DELETE