The Google Documents List Data API allows client applications to view and update documents (spreadsheets and word processor) using a Google Data API feed. Your client application can request a list of a user's documents, query the content of a user's documents, and upload new documents.
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.
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 Account Authentication document.
Whichever method you choose, you can either send raw HTTP requests or have Google's client libraries handle the authentication for you.
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
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=http%3A%2F%2Fdocs.google.com%2Ffeeds%2F&session=1&secure=0&next=http%3A%2F%2Fwww.example.com%2Fwelcome.html
The scope parameter for the Documents List API is http://docs.google.com/feeds/. For a list of valid scopes for
other Google Data APIs, see the FAQ.
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.
More details on working with the different authentication methods, including information on registering your web application with Google and other topics, see:
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.
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:
http://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>http://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="http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=key"/>
<link rel="alternate" type="text/html" href="http://spreadsheets.google.com/ccc?key=key" />
<link href="http://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="http://docs.google.com/feeds/documents/private/full/spreadsheet%3Akey"/>
<link rel="edit" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full/spreadsheet%3Akey"/>
<link rel="edit-media" type="text/html" href="http://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="http://docs.google.com/feeds/acl/private/full/spreadsheet%3Akey"/>
</entry>
<entry gd:etag='"HxIRQkRWTip7ImBp"'>
<id>http://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="http://docs.google.com/RawDocContents?action=fetch&docID=document_id" type="text/html"/>
<link rel="alternate" type="text/html" href="http://foobar.com/Doc?id=document_id"/>
<link rel="self" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full/document%3Adocument_id"/>
<link rel="edit" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full/document%3Adocument_id"/>
<link rel="edit-media" type="text/html" href="http://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="http://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.
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.
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.
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.
A list of only word processor documents can be retrieved by using the document category as follows:
GET /feeds/documents/private/full/-/document
A list of only spreadsheet documents can be retrieved by using the spreadsheet category as follows:
GET /feeds/documents/private/full/-/spreadsheet
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
A list of only folders can be retrieved by using the folder category as follows:
GET /feeds/documents/private/full/-/folder?showfolders=true
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
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
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
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.
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
A more detailed description of how the q parameter works can be found on the
Google Data APIs Reference Guide.
To retrieve a list of documents in a particular folder, send an HTTP GET to the folder's feed URL:
http://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>http://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="http://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="http://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="http://docs.google.com/feeds/documents/private/full/folder%3Afolder_id2" title="Folder 2"/>
<link rel="alternate" type="text/html" href="http://docs.google.com/Doc?id=document_id"/>
<link rel="self" type="application/atom+xml"
href="http://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/document%3Adocument_id"/>
<link rel="edit" type="application/atom+xml"
href="http://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/document%3Adocument_id"/>
<link rel="edit-media" type="text/html" href="http://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="http://docs.google.com/feeds/acl/private/full/document%3Adocument_id"/>
</entry>
<entry gd:etag='"B0gUFA1eEyp7ImBq"'>
<id>http://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="http://docs.google.com/feeds/folders/private/full/folder%3Afolder_id"/>
<link rel="http://schemas.google.com/docs/2007#parent" type="application/atom+xml"
href="http://docs.google.com/feeds/documents/private/full/folder%3Afolder_id" title="Folder 1"/>
<link rel="alternate" type="text/html" href="http://docs.google.com/#folders/folder.0.0bd9c3c3-d771-4278-b71b-3f519ab36b74"/>
<link rel="self" type="application/atom+xml"
href="http://docs.google.com/feeds/folders/private/full/folder%3Afolder_id/folder%3Afolder_id2"/>
<link rel="edit" type="application/atom+xml"
href="http://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="http://docs.google.com/feeds/acl/private/full/folder%3Afolder_id"/>
</entry>
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.)
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.
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.
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 |
swf |
Flash Format |
txt |
TXT file |
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 http://spreadsheets.google.com (as opposed to http://docs.google.com). Therefore the previous GET request would be sent to: http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=example_spreadsheet_id&exportFormat=example_format.
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 |
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:
http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=example_spreadsheet_id&exportFormat=csv&gid=1
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:
<atom:title> if presentSlug header value if present. This value should be percent encoded.Note: Currently you can upload word processor documents, spreadsheets and presentations. A list of accepted formats can be found here.
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.
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.
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.
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>
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 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.
Note: For more information, see the complete list of accepted formats.
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.
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>
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 ...
For word documents, you can append data to the document's content by using the append=true parameter.
The process is exactly the same as updating a document's content above. Here is an example of appending
the text Appending this data! to a document.
PUT /feeds/media/private/full/document%3Adocument_id?append=true Host: docs.google.com Authorization: <your authorization header here> Content-Length: 20 Content-Type: text/plain Appending this data!
Note: Content-Type: text/plain is the only accepted content type when appending data.
For example, you cannot append the contents of a Microsoft Word document with Content-Type: application/msword.
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.
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.
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.
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.
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.
Documents and folders can be moved in and out of folders via the folders feed.
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>http://docs.google.com/feeds/documents/private/full/document%3Adocument_id</id> </entry>
The entry is a word processor document with id document_id.
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>
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>http://docs.google.com/feeds/documents/private/full/folder%3Asource_folder_id</id> </entry>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:
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.
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:
<?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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id' />
<link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
href='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id' />
<link rel='self' type='application/atom+xml'
href='http://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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Adocument.owner%40example.com' />
<link rel='edit' type='application/atom+xml'
href='http://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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.writer%40example.com' />
<link rel='edit' type='application/atom+xml'
href='http://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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aa.reader%40example.com' />
<link rel='edit' type='application/atom+xml'
href='http://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>
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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com'/>
<link rel='edit' type='application/atom+xml'
href='http://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='http://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
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>http://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>http://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>http://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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id'/>
<link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
href='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id'/>
<link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml'
href='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/batch'/>
<entry>
<id>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aowner%40example.com'/>
<link rel='edit' type='application/atom+xml'
href='http://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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Anew_writer%40example.com'/>
<link rel='edit' type='application/atom+xml'
href='http://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>http://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='http://docs.google.com/feeds/acl/private/full/document%3Adocument_id/user%3Aold_writer%40example.com'/>
<link rel='edit' type='application/atom+xml'
href='http://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>http://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>