Google Apps Platform

Google Documents List API v2 Developer's Guide: Protocol

Important: Versions 1 and 2 of the Google Documents List API have been officially deprecated as of April 20, 2012. They will continue to work as per our deprecation policy, but we encourage you to move to the Google Drive API.

Contents

Audience

This document is intended for programmers who want to write client applications that can interact with Google Documents. It provides a series of examples of basic data API interactions using raw XML/HTTP, with explanations. After reading this document, you can learn more about interacting with the API using our client libraries by reading the language-specific examples found on the other tabs at the top of this document.

For Documents List Data API reference information, see the reference guide.

This document assumes that you understand the general ideas behind the Google Data APIs protocol. Each example in this document first shows how to use the bare protocol to interact with Documents.

Back to top

Authenticating to the Documents service

To request or upload documents, your client needs an authentication token. The following sections explain how to authenticate for different types of client applications.

Your choice of authentication method should be determined by the kind of client you're writing: single-user desktop applications should use the ClientLogin system, while multi-user web apps should use the AuthSub system. For a more detailed discussion of these authentication systems, see the Google Accounts authentication documentation.

Whichever method you choose, you can either send raw HTTP requests or have Google's client libraries handle the authentication for you.

ClientLogin for "installed" applications

To authenticate the user, send a POST request to the following URL:

https://www.google.com/accounts/ClientLogin

Include the relevant parameters in the body of the POST request, as described in the ClientLogin documentation. The service name for Documents is writely.

If the request succeeds, then the response contains an alphanumeric string labeled Auth.

After a successful authentication request, use the Auth value to create an Authorization header for each request:

Authorization: GoogleLogin auth=yourAuthValue

AuthSub for web applications

To acquire an AuthSub token for a given Documents user, your application must redirect the user to the AuthSubRequest URL at Google, which prompts them to log into their Google account.

After the user logs in, the AuthSub system redirects them to the URL you specified in the next query parameter of the AuthSubRequest URL. The AuthSub system appends an authentication token to the next URL as the value of the token query parameter. Your application then uses that authentication token in subsequent interactions with the Documents List API.

The below example shows a request to authorize www.example.com:

https://www.google.com/accounts/AuthSubRequest?scope=https%3A%2F%2Fdocs.google.com%2Ffeeds%2F&session=1&secure=0&next=https%3A%2F%2Fwww.example.com%2Fwelcome.html

The scope parameter for the Documents List API is https://docs.google.com/feeds/.

Upgrading to a session token

By default, the AuthSub token can only be used for one request. To receive a token which can be used for multiple requests, it must be upgraded by making an HTTP GET request which contains the single use token as an Authorization header. A token may only be upgraded if the initial AuthSub request included session=1 as a URL parameter.

GET /accounts/AuthSubSessionToken HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: AuthSub token="yourSingleUseToken"
Host: https://www.google.com
Connection: keep-alive

If the token was upgraded successfully, the server's response contains the new token information in the HTTP headers. Here's an example response:

Token=DQAA...7DCTN

Use the authentication token to create an Authorization header for each request:

Authorization: AuthSub token="yourSessionToken"

Note: The token value in the Authorization header should be surrounded by quotation marks.

Need more information on authentication?

More details on working with the different authentication methods, including information on registering your web application with Google and other topics, see:

Back to top

Specifying a version

Every request that you send using the Documents List Data API should specify version 2 of the API.

To specify a version number, use the GData-Version HTTP header:

GData-Version: 2.0

Alternatively, if you can't set HTTP headers, you can specify v=2 as a query parameter in the URL. But the HTTP header is preferred where possible.

Note: The client libraries supply appropriate version headers automatically, so don't use the v=2 query parameter when you're using a client library.

Back to top

Retrieving a list of documents

You can get a feed containing a list of the currently authenticated user's documents by sending an authenticated GET request to the following URL:

https://docs.google.com/feeds/documents/private/full

The result is a feed that lists all of that user's documents; each entry in the feed represents a document associated with the user. This feed is accessible only using an authentication token.

Entries in the Documents List feed might look something like the following:

<entry gd:etag='"BxAUSh5RAyp7ImBq"'>
  <id>https://docs.google.com/feeds/documents/private/full/spreadsheet%3Akey</id>
  <published>2009-03-16T23:26:12.503Z</published>
  <updated>2009-03-16T23:26:12.503Z</updated>
  <app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-18T05:41:45.311Z</app:edited>
  <category scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/docs/2007#spreadsheet" label="spreadsheet"/>
  <category scheme="http://schemas.google.com/docs/2007/folders/user_email"
    term="My Favorite Spreadsheets" label="My Favorite Spreadsheets"/>
  <title type="text">Test Spreadsheet</title>
  <content type="text/html"
    src="https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=key"/>
  <link rel="alternate" type="text/html" href="https://spreadsheets.google.com/ccc?key=key" />
  <link href="https://spreadsheets.google.com/feeds/worksheets/key/private/full"
    rel="http://schemas.google.com/spreadsheets/2006#worksheetsfeed" type="application/atom+xml" />
  <link rel="self" type="application/atom+xml" href="https://docs.google.com/feeds/documents/private/full/spreadsheet%3Akey"/>
  <link rel="edit" type="application/atom+xml" href="https://docs.google.com/feeds/documents/private/full/spreadsheet%3Akey"/>
  <link rel="edit-media" type="text/html" href="https://docs.google.com/feeds/media/private/full/spreadsheet%3Akey"/>
  <author>
    <name>test.user</name>
    <email>test.user@gmail.com</email>
  </author>
  <gd:resourceId>spreadsheet:key</gd:resourceId>
  <gd:lastModifiedBy>
    <name>test.user</name>
    <email>test.user@gmail.com</email>
  </gd:lastModifiedBy>
  <gd:lastViewed>2009-03-10T20:22:42.987Z</gd:lastViewed>
  <docs:writersCanInvite value="true"/>
  <gd:feedLink rel="http://schemas.google.com/acl/2007#accessControlList"
    href="https://docs.google.com/feeds/acl/private/full/spreadsheet%3Akey"/>
</entry>
<entry gd:etag='"HxIRQkRWTip7ImBp"'>
  <id>https://docs.google.com/feeds/documents/private/full/document%3Adocument_id</id>
  <published>2007-07-03T18:02:50.338Z</published>
  <updated>2009-03-16T23:26:12.503Z</updated>
  <app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-16T23:26:12.503Z</app:edited>
  <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#document" label="document"/>
  <category scheme="http://schemas.google.com/g/2005/labels" term="http://schemas.google.com/g/2005/labels#starred" label="starred"/>
  <title type="text">Test Document</title>
  <content src="https://docs.google.com/RawDocContents?action=fetch&amp;docID=document_id" type="text/html"/>
  <link rel="alternate" type="text/html" href="https://foobar.com/Doc?id=document_id"/>
  <link rel="self" type="application/atom+xml" href="https://docs.google.com/feeds/documents/private/full/document%3Adocument_id"/>
  <link rel="edit" type="application/atom+xml" href="https://docs.google.com/feeds/documents/private/full/document%3Adocument_id"/>
  <link rel="edit-media" type="text/html" href="https://docs.google.com/feeds/media/private/full/document%3Adocument_id"/>
  <author>
    <name>test.user</name>
    <email>test.user@gmail.com</email>
  </author>
  <gd:resourceId>document:document_id</gd:resourceId>
  <gd:lastModifiedBy>
    <name>test.user</name>
    <email>test.user@gmail.com</email>
  </gd:lastModifiedBy>
  <gd:lastViewed>2009-03-16T23:26:12.503Z</gd:lastViewed>
  <docs:writersCanInvite value="true"/>
  <gd:feedLink rel="http://schemas.google.com/acl/2007#accessControlList"
    href="https://docs.google.com/feeds/acl/private/full/document%3Adocument_id"/>
</entry>

The first entry is a spreadsheet that is contained in a folder named "My Favorite Spreadsheets" and the second entry is a starred word processor document. Notice that their types can be distinguished by the category element with the http://schemas.google.com/g/2005#kind scheme. The spreadsheet key in the example has been replaced with key and the word processor document id has been replaced with document_id. For the spreadsheet example's folder, the user's email address has been replaced with user_email.

Retrieving a list or document again

If you want to retrieve a document list or document entry that you've retrieved before, you can improve efficiency by telling the server to send the list or 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 list's or entry's ETag, which you can find in the <feed> element's or <entry> element's gd:etag attribute.

For example:

If-None-Match: "BxAaTxRZAyp7ImBq"

When the server receives this request, it checks to see whether the item that you requested has the same ETag as the ETag you specified. If the ETags match, then the item hasn't changed, and the server returns either an HTTP 304 Not Modified status code or an HTTP 412 Precodition Failed status code. Both of those status codes indicate that the item you've already retrieved is up-to-date.

If the ETags don't match, then the item has been modified since the last time you requested it, and the server returns the item.

For more information about ETags, see the Google Data APIs reference guide.

Back to top

Searching the documents feed

You can search the Document List using some of the standard Google Data API query parameters. Categories are used to restrict the type of document (word processor, spreadsheet, presentation, folder, etc.) returned. The full-text query string is used to search the content of all the documents. More detailed information on parameters specific to the Documents List can be found in the Documents List Data API Reference Guide.

Note: The Documents List API currently does not support excluding folders using the /category/-starred syntax.

Retrieving all documents and folders

A list of all documents and folders can be retrieved by using the showfolders parameter on the documents list feed:

GET /feeds/documents/private/full?showfolders=true

For an examply entry of the feed that will be returned, look at the Retrieving a list of documents section.

Retrieving all word processor documents

A list of only word processor documents can be retrieved by using the document category as follows:

GET /feeds/documents/private/full/-/document

Retrieving all spreadsheet documents

A list of only spreadsheet documents can be retrieved by using the spreadsheet category as follows:

GET /feeds/documents/private/full/-/spreadsheet

Retrieving all starred presentations

You can combine more than one category. As an example, to retrieve a list of only starred presentations, use the presentation and starred categories together:

GET /feeds/documents/private/full/-/presentation/starred

Retrieving a list of folders

A list of only folders can be retrieved by using the folder category as follows:

GET /feeds/documents/private/full/-/folder?showfolders=true

Retrieving a list of trashed documents

A list of a user's trashed documents can be retrieved by using the trashed category as follows:

GET /feeds/documents/private/full/-/trashed

To include a list of trashed documents along with normal queries results, use the showdeleted parameter:

GET /feeds/documents/private/full?showdeleted=true

Retrieving all documents in a folder named "starred"

A list of only documents contained in a folder named "starred" created by the current user with email address email can be retrieved by using a scheme qualified folder category to disambiguate from a starred category query for starred documents as follows:

GET /feeds/documents/private/full/-/{http:%2F%2Fschemas.google.com%2Fdocs%2F2007%2Ffolders%2Femail}starred

Retrieving only shared documents

A list of PDFs owned by the requesting user:

GET /feeds/documents/private/full/-/pdf/mine

All documents that user1@mail.com and user2@gmail.com are collaborating on:

GET /feeds/documents/private/full?writer=user1%40gmail.com%2Cuser2%40example.com

Performing title queries

You can search for documents matching an exact title or portion of a title by using the title-exact and title query parameters, respectively. For example, if you wanted to search for documents matching the partial title "PR Handbook", you could issue:

GET /feeds/documents/private/full?title=PR+Handbook

To match a title exactly, add the title-exact parameter:

GET /feeds/documents/private/full?title=PR+Handbook&title-exact=true

Please see the Documents List Data API Reference Guide for more details.

Performing a full text query

You can search the content of documents by using the q query parameter on the feed. For example, if you wanted to search a user's documents for the string "example query" you could do the following authenticated GET:

GET /feeds/documents/private/full?q=example+query

Full text query operators

The q parameter supports a series of operators that allow searches to return very specific results. These operators can be combined in order to narrow down search results. An example is:

from:fluffy@catsndogs.com to:fido@catsndogs.com title:peace title:treaty after:2007-07-24 is:starred owner:fluffy@catsndogs.com

Name Description Example
Quotes Matches will contain the exact phrase in quotes. "The quick brown fox jumps over the lazy dog."
Conjunctions Matches will contain all of the given words. This is the default behavior. cats AND dogs AND lizards
Disjunctions Matches will contain one of the given words. cats OR dogs OR lizards
Exclusions Matches will not contain the given words to be excluded. cats -dogs
Title Matches will contain the given word in their title. title:peace title:treaty
Items shared by a user Matches will have been shared by the given user. from:fluffy@catsndogs.com
Items shared with a user Matches will have been shared with the given user. to:fido@catsndogs.com
Items owned by a user Matches will be owned by the given user. owner:fluffy@catsndogs.com
Starred items Matches will have been starred. is:starred
Hidden items Matches will have been hidden. is:hidden
Items of a certain type Matches will be of the given document type. type:document OR type:spreadsheet OR type:presentation
Edited date Matches will have been edited before or after the given date. before:2010-07-13 OR after:2007-07-24

Additional specifics of the q parameter can be found in the Google Data APIs Reference Guide.

Back to top

Retrieving a list of folder contents

To retrieve a list of documents in a particular folder, send an HTTP GET to the folder's feed URL:

https://docs.google.com/feeds/folders/private/full/folder%3Afolder_id

The folders feed can also be queried using the query parameters defined in the Documents List Data API Reference Guide.

Entries in the folder feed might look something like the following:

<entry gd:etag='"B0gUExhDBSp7ImBq"'>
  <id>https://docs.google.com/feeds/folders/private/full/folder%3folder_id/document%3Adocument_id</id>
  <published>0001-01-03T00:00:00.000Z</published>
  <updated>2008-09-02T05:42:27.203Z</updated>
  <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#document" label="document"/>
  <category scheme="http://schemas.google.com/docs/2007/folders/test.user@gmail.com" term="Folder 1" label="Folder 1"/>
  <category scheme="http://schemas.google.com/docs/2007/folders/test.user@gmail.com" term="Folder 2" label="Folder 2"/>
  <title type="text">Document 1</title>
  <content type="text/html"
    src="https://docs.google.com/feeds/download/documents/RawDocContents?action=fetch&docID=document_id"/>
  <link rel="http://schemas.google.com/docs/2007#parent" type="application/atom+xml"
    href="https://docs.google.com/feeds/documents/private/full/folder%3Afolder_id" title="Folder 1"/>
  <link rel="http://schemas.google.com/docs/2007#parent" type="application/atom+xml"
    href="https://docs.google.com/feeds/documents/private/full/folder%3Afolder_id2" title="Folder 2"/>
  <link rel="alternate" type="text/html" href="https://docs.google.com/Doc?id=document_id"/>
  <link rel="self" type="application/atom+xml"
    href="https://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/document%3Adocument_id"/>
  <link rel="edit" type="application/atom+xml"
    href="https://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/document%3Adocument_id"/>
  <link rel="edit-media" type="text/html" href="https://docs.google.com/feeds/media/private/full/document%3Adocument_id"/>
  <author>
    <name>test.user</name>
    <email>test.user@gmail.com</email>
  </author>
  <gd:resourceId>document:document_id</gd:resourceId>
  <gd:lastModifiedBy>
    <name>test.user</name>
    <email>test.user@gmail.com</email>
  </gd:lastModifiedBy>
  <gd:lastViewed>2008-09-02T05:42:27.203Z</gd:lastViewed>
  <docs:writersCanInvite value="true"/>
  <gd:feedLink rel="http://schemas.google.com/acl/2007#accessControlList"
    href="https://docs.google.com/feeds/acl/private/full/document%3Adocument_id"/>
</entry>
<entry gd:etag='"B0gUFA1eEyp7ImBq"'>
  <id>https://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/folder%3Afolder_id2</id>
  <published>0001-01-03T00:00:00.000Z</published>
  <updated>2008-07-31T00:36:07.091Z</updated>
  <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#folder" label="folder"/>
  <category scheme="http://schemas.google.com/docs/2007/folders/test.user@gmail.com" term="Folder 1" label="Folder 1"/>
  <title type="text">Folder 2</title>
  <content type="application/atom+xml"
    src="https://docs.google.com/feeds/folders/private/full/folder%3Afolder_id"/>
  <link rel="http://schemas.google.com/docs/2007#parent" type="application/atom+xml"
    href="https://docs.google.com/feeds/documents/private/full/folder%3Afolder_id" title="Folder 1"/>
  <link rel="alternate" type="text/html" href="https://docs.google.com/#folders/folder.0.0bd9c3c3-d771-4278-b71b-3f519ab36b74"/>
  <link rel="self" type="application/atom+xml"
    href="https://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/folder%3Afolder_id2"/>
  <link rel="edit" type="application/atom+xml"
    href="https://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/folder%3Afolder_id2/fk6cwqd4"/>
  <author>
    <name>test.user</name>
    <email>test.user@gmail.com</email>
  </author>
  <gd:resourceId>folder:folder_id</gd:resourceId>
  <docs:writersCanInvite value="false"/>
  <gd:feedLink rel="http://schemas.google.com/acl/2007#accessControlList"
    href="https://docs.google.com/feeds/acl/private/full/folder%3Afolder_id"/>
</entry>

Back to top

Downloading Documents

Once you have a document's id, you can download the file in a variety of formats. This download functionality is provided outside the document list feed itself, but is still accessible using the same authentication mechanisms supported by the DocList API. The Authsub and OAuth tokens you use to interact with the DocList API will still be valid when accessing the URLs referenced below.

Note: If you wish to use the same OAuth/AuthSub token to download both documents and spreadsheets, you will need to request a token that works in both the docs.google.com and spreadsheets.google.com scope.)

Downloading Documents and Presentations

Documents are accessible via the following URL:

GET /feeds/download/documents/Export?docID=example_document_id&exportFormat=example_format

If the download request is sucessful, an HTTP 200 is returned and the file is served in the requested format.

Valid Formats for Documents

When downloading documents, the exportFormat parameter controls the format of the output. Valid values for this parameter appear below.

exportFormat Parameter Value Format of the returned Document
doc Microsoft Word
html HTML Format
odt Open Document Format
pdf Portable Document Format
png Portable Networks Graphic Image Format
rtf Rich Format
txt TXT File
zip ZIP archive. Contains the images (if any) used in the document and an exported .html file.

Presentations are accessible via the following URL:

GET /feeds/download/presentations/Export?docID=example_document_id&exportFormat=example_format

If the download request is sucessful, an HTTP 200 is returned and the file is served in the requested format.

Valid Formats for Presentations

Presentation formats are also controlled via the exportFormat parameter. Valid values for this parameter appear below.

exportFormat Parameter Value Format of the returned Presentation
pdf Portable Document Format
png Portable Networks Graphic Image Format
ppt Powerpoint Format
txt TXT file

Downloading Spreadsheets

Spreadsheets can be downloaded via the following URL:

GET /feeds/download/spreadsheets/Export?key=example_spreadsheet_id&exportFormat=example_format

If the download request is successful, an HTTP 200 is returned and the file is served in the requested format.

Note: The server to use when downloading spreadsheets is https://spreadsheets.google.com (as opposed to https://docs.google.com). Therefore the previous GET request would be sent to: https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=example_spreadsheet_id&exportFormat=example_format.

Valid Formats for Spreadsheets

When downloading spreadsheets, value of the exportFormat parameter controls the format of the output. Valid values for this parameter appear below:

exportFormat Parameter Value Format of the returned Spreadsheet
xls XLS (Microsoft Excel)
csv CSV (Comma Seperated Value)
pdf PDF (Portable Document Format)
ods ODS (Open Document Spreadsheet)
tsv TSV (Tab Seperated Value)
html HTML Format

Exporting a single worksheet

When requesting a CSV, TSV, PDF, or HTML file you may specify an additional (optional) parameter called gid which indicates which grid, or sheet, you wish to export (the index is 0 based, so gid 1 actually refers to the second sheet sheet on a given spreadsheet). If left unspecified, the first sheet will be exported for these formats. In the case of a PDF, the whole document will be exported.

Here is an example request for a CSV representation of the second sheet in a spreadsheet:

https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=example_spreadsheet_id&exportFormat=csv&gid=1

Back to top

Uploading documents

Documents are uploaded to the server via an HTTP POST optionally using MIME multipart encoding to combine the the document contents with a <atom:entry> describing the document. Any combination of <atom:entry> and an HTTP Slug header can be used to specify the title of the uploaded document, but the following precedence will determine the final document name:

  1. The Atom entry <atom:title> if present
  2. The HTTP Slug header value if present. This value should be percent encoded.
  3. A default filename chosen by Google Documents

Note: Currently you can upload word processor documents, spreadsheets and presentations.

Uploading with metadata

Here is an example of uploading a document named test.doc on the client computer which will be called example document on Google Documents (See Uploading Docs for the precedence rules that determine this document name).

POST /feeds/documents/private/full HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 73612
Content-Type: multipart/related; boundary=END_OF_PART
Slug: test.doc
--END_OF_PART
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
  <atom:category scheme="http://schemas.google.com/g/2005#kind"
      term="http://schemas.google.com/docs/2007#document" label="document"/>
  <atom:title>example document</atom:title>
</atom:entry>

--END_OF_PART
Content-Type: application/msword

... doc contents here ...

--END_OF_PART--

If the upload is successful, a 201 Created response will be returned along with a <atom:entry> describing the document on the server.

Uploading without metadata

Here is an example of uploading a spreadsheet which will be called Example Spreadsheet on Google Documents.

POST /feeds/documents/private/full HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 81047
Content-Type: application/vnd.ms-excel
Slug: Example Spreadsheet

... spreadsheet contents here ...

Again, if the upload is successful, a 201 Created response will be returned along with a <atom:entry> describing the document on the server.

Uploading only metadata (no content)

Here is an example of creating a document by uploading metadata to the server with an HTTP POST request. This will create an empty document called new document on Google Documents.

POST /feeds/documents/private/full HTTP/1.1
Content-Length: 287
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:docs="http://schemas.google.com/docs/2007">
  <atom:category scheme="http://schemas.google.com/g/2005#kind"
      term="http://schemas.google.com/docs/2007#document" label="document"/>
  <atom:title>new document</atom:title>
  <docs:writersCanInvite value="false" />
</atom:entry>

Note: The previous example includes the optional <docs:writersCanInvite> setting, which prevents collaborators from sharing the document with others. writersCanInvite can be included when creating or updating a document. In the case of an update, the previous value is retained if the tag is omitted. Possible values are "true", "false" (case sensitive), "1", or "0" (1=true, 0=false). Only the owner of a document can change the writersCanInvite setting.

Uploading a document to a folder

The same methodology can be used to upload a document to a particular folder. Instead of using the /feed/documents/ feed, send and HTTP POST request to the /feeds/folders/ feed and reference the folder ID you wish to upload to.

This example creates an empty presentation called new preso in the folder referenced by folder_id.

POST /feeds/folders/private/full/folder%3Afolder_id HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 292
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
  <atom:category scheme="http://schemas.google.com/g/2005#kind"
      term="http://schemas.google.com/docs/2007#presentation" label="presentation"/>
  <atom:title>new preso</atom:title>
</atom:entry>

Back to top

Updating documents

To update an existing document, first you retrieve the document you want to update, then you modify it as desired, and then you send a PUT request to either the edit link or the edit-media link, depending on what is to be updated.

You can update any of the following:

  • The document's metadata
  • The document's contents
  • Both metadata and contents at once (using a MIME multipart request)

The following sections describe how to perform each of those types of update.

The new document contents, which form part of the MIME multipart request, must have a content-type for which conversion is supported--for instance, to update a Google Docs document with new content, it could have content-type application/msword, or content-type text/plain, but not content-type application/vnd.ms-excel. When updating a Google Docs spreadsheet, however, content-type application/vnd.ms-excel would be appropriate. Content-types which are not supported by the document type being updated will result in an HTTP 400 Bad Request response.

To make sure that your update doesn't overwrite another client's changes, include the original entry's ETag value. You can do this by providing the ETag value in an HTTP If-Match header, or by including the original entry's gd:etag attribute in the updated entry. To determine the original document's ETag value, examine the <entry> element's gd:etag attribute. For media entries, the ETag of the media may be available in the gd:etag attribute of the edit-media link.

If you want to update the document regardless of whether someone else has updated it since you retrieved it, then use If-Match: * and don't include the ETag.

For more information about ETags, see the Google Data APIs reference guide.

Updating metadata

Here is an example of updating a spreadsheet's metadata, but leaving its content unchanged. The spreadsheet's name will be changed to example spreadsheet. Since the request does not contain new document content, the edit link is used.

PUT /feeds/documents/private/full/spreadsheet%3Aspreadsheet_id
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 292
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom"
    gd:etag="BxAaTxRZAyp7ImBq">
  <atom:category scheme="http://schemas.google.com/g/2005#kind"
      term="http://schemas.google.com/docs/2007#spreadsheet" label="spreadsheet"/>
  <atom:title>example spreadsheet</atom:title>
</atom:entry>

Updating content

Here is an example of changing the content of a document, but leaving its metadata unchanged. The document's name will stay the same, but its contents will be replaced with the contents of word document test.doc. Since the request contains new document content, the edit-media link is used.

PUT /feeds/media/private/full/document%3Adocument_id
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 70581
Content-Type: application/msword
Slug: test.doc

... doc contents here ...

Updating metadata and content

Here is an example of updating both the document's metadata and its content at the same time. The document's name will be updated to example document and its contents will be replaced with the contents of the Microsoft Word document test.doc. Since the request contains new document content, the edit-media link is used.

Note that including the ETag for the metadata provides an implicit If-Match for the media content as well, because any update to the media content causes the metadata's ETag to change.

PUT /feeds/media/private/full/document%3Adocument_id
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 73612
Content-Type: multipart/related; boundary="END_OF_PART"
Slug: test.doc
--END_OF_PART
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom"
    gd:etag="BxAaTxRZAyp7ImBq">
  <atom:category scheme="http://schemas.google.com/g/2005#kind"
      term="http://schemas.google.com/docs/2007#document" label="document"/>
  <atom:title>example document</atom:title>
</atom:entry>
--END_OF_PART
Content-Type: application/msword

... doc contents here ...

--END_OF_PART

In all of these cases, a successful update will return an HTTP 201 Updated status code with an <atom:entry> describing the document on the server.

Back to top

Creating a folder

To create a folder, send an HTTP POST request with an <atom:entry> containing a category element with http://schemas.google.com/g/2005#kind scheme and http://schemas.google.com/docs/2007#folder term. The folder name will be determined by the value of the atom:title element if present. If no atom:title element is submitted, a default name will be chosen.

Here is an example of creating a folder which will be called Example Folder on Google Documents.

POST /feeds/documents/private/full HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 384
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
  <atom:category scheme="http://schemas.google.com/g/2005#kind"
      term="http://schemas.google.com/docs/2007#folder" label="folder"/>
  <atom:title>Example Folder</atom:title>
</atom:entry>

If the request is successful, a 201 Created response will be returned along with a <atom:entry> describing the folder on the server.

Back to top

Trashing documents and folders

To put a document or folder in the trash, first you retrieve the entry for the document or folder you want to delete, then you send a DELETE request to the entry's edit URL. This is the same URL used to update the document.

Deleting a document

DELETE /feeds/documents/private/full/document%3Adocument_id HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>

If the document was deleted successfully, the server responds with an HTTP 200 OK.

Deleting a folder

The process for deleting a folder is very similar. Instead, reference the folder and its folder_id

DELETE /feeds/documents/private/full/folder%3Afolder_id HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>

If the folder was deleted successfully, the server responds with an HTTP 200 OK.

If you want to make sure that you don't delete a document that has been changed by another client since you retrieved it, include an HTTP If-Match header that contains the original entry's ETag value. You can determine the original entry's ETag value by examining the <entry> element's gd:etag attribute.

If you want to delete the document regardless of whether someone else has updated it since you retrieved it, then use If-Match: * and don't include the ETag. (In this case, you don't need to retrieve the entry before deleting it.)

For more information about ETags, see the Google Data APIs reference guide.

Back to top

Moving documents and folders

Documents and folders can be moved in and out of folders via the folders feed.

Moving a document into a folder

To either move a document into a folder or to move a folder into another folder, send an HTTP POST request to the feed of the destination folder. The feed URL will have the folder ID represented by destination_folder_id in the example below. The request should contain an <atom:entry> with the document's <atom:id> you want to move.

Note: If no <atom:id> is provided in the request body's <atom:entry>, a new document will be created in the folder.

POST /feeds/folders/private/full/folder%3Adestination_folder_id HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 180
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>https://docs.google.com/feeds/documents/private/full/document%3Adocument_id</id>
</entry>

The entry is a word processor document with id document_id.

Moving a document out of a folder

To move a document or folder out of a folder, sent an HTTP DELETE request to the destination folder's edit link. The edit link will have a folder id and a document id, represented by folder_id and document_id respectively in the example below.

DELETE /feeds/folders/private/full/folder%3Afolder_id/document%3Adocument_id
Host: docs.google.com
Authorization: <your authorization header here>

Moving a folder into another folder

To move a folder into a different folder, send an HTTP POST request to the destination folder's edit link. The body of the request should contain an <atom:entry> that references the <atom:id> of the folder you wish to move.

This example moves the folder source_folder_id to folder destination_folder_id.

POST /feeds/folders/private/full/folder%3Adestination_folder_id HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>
Content-Length: 183
Content-Type: application/atom+xml

<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>https://docs.google.com/feeds/documents/private/full/folder%3Asource_folder_id</id>
</entry>

Back to top

Modifying Document Sharing Permissions

Overview of Document Sharing (ACLs)

Document sharing is controlled via the access control list feed. Access control lists are just basic lists that show who has access to a given resource. In the ACL feed, we have the following roles for a given document:

  • owner — the owner of the document. As an owner you have the ability to modify the ACL feed, delete the document, etc.
  • writer — a collaborator.
  • reader — a viewer (equivalent to read-only access).

Note: Please note that the accepted values for each role are case-sensitive. Also note that you cannot change the 'owner' role for a document.

Retrieving the ACL feed for a Document

The ACL feed can be retrieved by acessing the <gd:feedLink> element. Please note that you must use the full projection to receive 'gd' specific extension elements in your DocumentsList feed. The 'rel' attribute must correspond to http://schemas.google.com/acl/2007#accessControlList

GET /feeds/acl/private/full/document%3Adocument_id HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>

This feed will contain an <entry> element for each ACL entry that exists for the given document.

The XML snippet below shows the ACL feed for the example document. Note that the feed contains three ACL entries. The <id> element of each ACL entry ends with the email address of the specific user that the ACL entry corresponds to:

  • document.owner@example.com — the ACL entry for the document's owner
  • a.writer@example.com — the ACL entry for a collaborator
  • a.reader@example.com — the ACL entry for a reader
<?xml version='1.0' encoding='utf-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
    xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'
    xmlns:gAcl='http://schemas.google.com/acl/2007'
    xmlns:gd='http://schemas.google.com/g/2005'
    gd:etag='W/"CUUNSXYyfCp7ImA9WxRVGUo."'>
  <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id</id>
  <updated>2008-09-03T22:03:04.733Z</updated>
  <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule' />
  <title type='text'>Document Permissions</title>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
  href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id' />
  <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
  href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id' />
  <link rel='self' type='application/atom+xml'
  href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id' />
  <openSearch:totalResults>3</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>

  <entry gd:etag='W/"CUUNSXYyfCp7ImA9WxRVGUo."'>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Adocument.owner%40example.com</id>
    <updated>2008-09-03T22:03:04.756Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule' />
    <title type='text'>Document Permission - document.owner@example.com</title>
    <link rel='self' type='application/atom+xml'
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Adocument.owner%40example.com' />
    <link rel='edit' type='application/atom+xml'
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Adocument.owner%40example.com' />
    <gAcl:role value='owner' />
    <gAcl:scope type='user' value='document.owner@example.com' />
  </entry>
  <entry gd:etag='W/"CUMFQnc4fip7ImA9WxRVGUo."'>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.writer%40example.com</id>
    <updated>2008-09-03T22:03:04.762Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule' />
    <title type='text'>Document Permission - a.writer@example.com</title>
    <link rel='self' type='application/atom+xml'
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.writer%40example.com' />
    <link rel='edit' type='application/atom+xml'
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.writer%40example.com' />
    <gAcl:role value='writer' />
    <gAcl:scope type='user' value='a.writer@example.com' />
  </entry>
  <entry gd:etag='W/"CUMASXg8fCp7ImA9WxRVGUo."'>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.reader%40example.com</id>
    <updated>2008-09-03T22:03:04.763Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule' />
    <title type='text'>Document Permission - a.reader@example.com</title>
    <link rel='self' type='application/atom+xml'
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.reader%40example.com' />
    <link rel='edit' type='application/atom+xml'
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.reader%40example.com' />
    <gAcl:role value='reader'/>
    <gAcl:scope type='user' value='a.reader@example.com' />
  </entry>
</feed>

Modifying the ACL feed for a Document

The ACL feed accepts GET, POST and PUT requests. To insert a new role into the ACL feed, simply issue a POST request.

Note: You need to be the document's owner to modify the ACL feed.

The example belows how to insert a new collaborator to the document:

POST /feeds/acl/private/full/document%3Adocument_id HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl='http://schemas.google.com/acl/2007'>
  <category scheme='http://schemas.google.com/g/2005#kind'     
    term='http://schemas.google.com/acl/2007#accessRule'/>
  <gAcl:role value='writer'/>
  <gAcl:scope type='user' value='new_writer@example.com'/>
</entry>

The new entry is returned on a successful insertion:

201 Created

<entry gd:etag='W/"CUUNSXYyfCp7ImA9WxRVGUo."'>
  <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com</id>
  <updated>2008-09-11T03:10:00.913Z</updated>
  <category scheme='http://schemas.google.com/g/2005#kind'    
        term='http://schemas.google.com/acl/2007#accessRule'/>
  <title type='text'>Document Permission - new_writer@example.com</title>
  <link rel='self' type='application/atom+xml'
        href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com'/>
  <link rel='edit' type='application/atom+xml'
        href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com'/>
  <gAcl:role value='writer'/>
  <gAcl:scope type='user' value='new_writer@example.com'/>
</entry>

To update the entry, we will need to issue an HTTP PUT request to the entry's edit link, which is simply a <link> element, whose 'rel' attribute is set to 'edit'. In our case it is:

<link rel='edit'
      type='application/atom+xml'
      href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com'/>

The snippet below changes the entry's role to that of a 'reader':

PUT /feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl='http://schemas.google.com/acl/2007'
       xmlns:gd='http://schemas.google.com/g/2005'
       gd:etag='W/"CUUNSXYyfCp7ImA9WxRVGUo."'>
  <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>
  <gAcl:role value='reader'/>
  <gAcl:scope type='user' value='new_writer@gmail.com'/>
</entry>

To remove permissions for this user, issue a DELETE request to the same edit link that was used for the PUT request:

DELETE /feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>

HTTP/1.1 200 OK

ACL modification with batch processing

Batch processing gives you the ability to execute multiple operations in one request, rather than submitting each operation individually.

The server will perform as many of the requested changes as possible and return status information that you can use to evaluate the success or failure of each operation. For more details about batch processing in Google Data API, see Batch Processing with Google Data APIs

In a batch ACL feed, every operation has an <id> element except for insert operations. This element is the same as the request URL used in updating, deleting or querying a document ACL. It is used to identify the target entry. New entries do not have <id> elements as they have not been created yet. You can instead define a string value in <batch:id>, which will be returned in the server's response and used to look up the corresponding entry.

The example below shows how to query, insert, update and delete users of a document:

POST /feeds/acl/private/full/document%3Adocument_id/batch HTTP/1.1
Host: docs.google.com
Authorization: <your authorization header here>

<feed xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl='http://schemas.google.com/acl/2007'
      xmlns:batch='http://schemas.google.com/gdata/batch'>
  <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>
  <entry>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aowner%40example.com</id>
    <batch:operation type="query"/>
  </entry>
  <entry>
    <batch:id>1</batch:id>
    <batch:operation type='insert'/>
    <gAcl:role value='writer'/>
    <gAcl:scope type='user' value='new_writer@example.com'/>
  </entry>
  <entry>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aold_writer%40example.com</id>
    <batch:operation type='update'/>
    <gAcl:role value='reader'/>
    <gAcl:scope type='user' value='old_writer@example.com'/>
  </entry>
  <entry>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Adeprecated_writer%40example.com</id>
    <batch:operation type='delete'/>
    <gAcl:role value='writer' />
    <gAcl:scope type='user' value='deprecated_writer@example.com' />
  </entry>
</feed>

The returned feed will contain one result entry for each operation:

 
<?xml version='1.0' encoding='utf-8'?>
<feed xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'
      xmlns:gAcl='http://schemas.google.com/acl/2007' xmlns:batch='http://schemas.google.com/gdata/batch'>
  <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id</id>
  <updated>2009-03-06T09:13:23.382Z</updated>
  <title type='text'>Batch Feed</title>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id'/>
  <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' 
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id'/>
  <link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml' 
    href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/batch'/>
  <entry>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aowner%40example.com</id>
    <updated>2009-03-06T09:13:23.381Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>
    <title type='text'>Document Permission - owner@example.com</title>
    <link rel='self' type='application/atom+xml'
      href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aowner%40example.com'/>
    <link rel='edit' type='application/atom+xml'
      href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aowner%40example.com'/>
    <gAcl:role value='owner'/>
    <gAcl:scope type='user' value='owner@example.com'/>
    <batch:status code='200' reason='Success'/>
    <batch:operation type='query'/>
  </entry>
  <entry>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com</id>
    <updated>2009-03-06T09:13:25.381Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>
    <title type='text'>Document Permission - new_writer@example.com</title>
    <link rel='self' type='application/atom+xml'
      href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com'/>
    <link rel='edit' type='application/atom+xml'
      href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com'/>
    <gAcl:role value='writer'/>
    <gAcl:scope type='user' value='new_writer@example.com'/>
    <batch:id>1</batch:id>
    <batch:status code='201' reason='Created'/>
    <batch:operation type='insert'/>
  </entry>
  <entry>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aold_writer%40example.com</id>
    <updated>2009-03-06T09:13:27.737Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>
    <title type='text'>Document Permission - old_writer@example.com</title>
    <link rel='self' type='application/atom+xml'
      href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aold_writer%40example.com'/>
    <link rel='edit' type='application/atom+xml'
      href='https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aold_writer%40example.com'/>
    <gAcl:role value='reader'/>
    <gAcl:scope type='user' value='old_writer@example.com'/>
    <batch:status code='200' reason='Success'/>
    <batch:operation type='update'/>
  </entry>
  <entry>
    <id>https://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Adeprecated_writer%40example.com</id>
    <updated>2009-03-06T09:13:29.743Z</updated>
    <title type='text'>Deleted</title>
    <content type='text'>Deleted</content>
    <batch:status code='200' reason='Success'/>
    <batch:operation type='delete'/>
  </entry>
</feed>

Back to top

Authentication required

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

Signing you in...

Google Developers needs your permission to do that.