Google Contacts API version 3.0

The Google Contacts API allows client applications to view and update a user's contacts. Contacts are stored in the user's Google Account; most Google services have access to the contact list.

Your client application can use the Google Contacts API to create new contacts, edit or delete existing contacts, and query for contacts that match particular criteria

Audience

This document is intended for programmers who want to write client applications that can interact with Google's contact lists. It provides a series of examples of basic API interactions. These examples come in various forms, including raw XML/HTTP requests, Java, .NET and Python source code.

This document assumes that you understand the general ideas behind the Google Data APIs protocol. For general Google Contacts API reference information, see the reference guide.

Getting started

This section contains some information to help you get started with the Google Contacts API.

Creating a Google Account

You'll need a Google Account for testing purposes. If you already have a test account with a project registered in the API Console, then you're all set; you can visit the Google Contacts API user interface to set up, edit, or view your test data.

Running the sample code

Protocol

If you're using a UNIX system and you want to try the examples in this document without writing any code, you may find the UNIX command-line utilities curl or wget useful; for more information, see the manual pages for those utilities.

Java

A full working sample client, containing all the sample code shown in this document, is available in the Java client library distribution, under the directory gdata/java/sample/contacts/. Build and execution instructions are included in the same directory in the README.txt file.

The sample client performs several operations on contacts to demonstrate the use of the Contacts Data API. To compile the examples in this document into your own code, you'll need the following import statements:

import com.google.gdata.client.*;
import com.google.gdata.client.contacts.*;
import com.google.gdata.data.*;
import com.google.gdata.data.contacts.*;
import com.google.gdata.data.extensions.*;
import com.google.gdata.util.*;
import java.io.IOException;
import java.net.URL;

// ...
    ContactsService myService = new ContactsService("YOUR_APPLICATION_NAME");
    // Authorize the service object.
// ...

.NET

To compile the examples in this document into your own code, you'll need to download the latest .NET client library distribution and add the following using statements:

using Google.Contacts;
using Google.GData.Contacts;
using Google.GData.Client;
using Google.GData.Extensions;
// ...
    RequestSettings settings = new RequestSettings("YOUR_APPLICATION_NAME");
    // Add authorization token.
    // ...
    ContactsRequest cr = new ContactsRequest(settings);
// ...

Python

A full working sample client, containing all the sample code shown in this document, is available in the Python client library distribution, under the directory samples/contacts/.

The sample client performs several operations on contacts to demonstrate the use of the Contacts Data API. To run the examples in this document in your own code, you'll need the following import statements:

import atom.data
import gdata.data
import gdata.contacts.client
import gdata.contacts.data
# ...
  gd_client = gdata.contacts.client.ContactsClient(source='YOUR_APPLICATION_NAME')
  # Authorize the client.
# ...

Authorizing requests to the Google Contacts API service

When your application requests non-public user data, it must include an access token. The token also identifies your application to Google.

About authorization protocols

Use OAuth 2.0 to authorize requests. You must register your project in the Google API Console and enable the Contacts API service in order to use OAuth 2.0.

OAuth 1.0 was officially deprecated on April 20, 2012 and stopped being supported on May 5, 2015. Old code must be migrated to OAuth 2.0.

Authorizing requests with OAuth 2.0

Requests to the Google Contacts API for non-public user data must be authorized by an authenticated user.

The details of the authorization process, or "flow," for OAuth 2.0 vary somewhat depending on what kind of application you're writing. The following general process applies to all application types:

  1. When you create your application, you register it with Google. Google then provides information you'll need later, such as a client ID and a client secret.
  2. Activate the Google Contacts API in the Services pane of the Google APIs Console. (If it isn't listed in the Console, then skip this step.)
  3. When your application needs access to user data, it asks Google for a particular scope of access.
  4. Google displays an OAuth dialog to the user, asking them to authorize your application to request some of their data.
  5. If the user approves, then Google gives your application a short-lived access token.
  6. Your application requests user data, attaching the access token to the request.
  7. If Google determines that your request and the token are valid, it returns the requested data.

Some flows include additional steps, such as using refresh tokens to acquire new access tokens. For detailed information about flows for various types of applications, see Google's OAuth 2.0 documentation.

Here's the OAuth 2.0 scope information for the Google Contacts API:

Scope Meaning
https://www.google.com/m8/feeds/ read/write access to Contacts and Contact Groups
https://www.googleapis.com/auth/contacts.readonly read-only access to Contacts and Contact Groups

To request access using OAuth 2.0, your application needs the scope information, as well as information that Google supplies during application registration (such as the client ID and/or the client secret).

Tip: The Google APIs client libraries can handle some of the authorization process for you. They are available for a variety of programming languages; check the Libraries and Samples page for more details.

Specifying a version

Every request that you send using the Google Contacts API should specify version 3.0 of the API.

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

GData-Version: 3.0

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

Working with contacts

Contact Entry

The Google Contacts API allows manipulation of Contact Entry implementing the GData Contact kind element with some restrictions described in the Reference Guide.

Version 3 of the API introduces new structured data formats for the contact's name and structured postal address fields.

Each of those fields let applications store data in 2 flavors:

If only one of the flavors is provided, the API uses heuristic parsers to generate the missing flavor using the provided data. Whether or not the heuristic parsers are used is described in the following tabs. Elements generated by the API are shown in bold in the output.

Structured

In the following example, only the structured flavor is provided to the API. The server uses heuristic parsers to try and generate the formatted flavor.

Input:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
  <gd:name>
    <gd:givenName>First</gd:givenName>
    <gd:familyName>Last</gd:familyName>
  </gd:name>
  <!-- ... -->
  <gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work" primary="true">
    <gd:city>Mountain View</gd:city>
    <gd:street>1600 Amphitheatre Pkwy</gd:street>
    <gd:region>CA</gd:region>
    <gd:postcode>94043</gd:postcode>
    <gd:country>United States</gd:country>
  </gd:structuredPostalAddress>
<!-- ... -->

Output:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
  <gd:name>
    <gd:givenName>First</gd:givenName>
    <gd:familyName>Last</gd:familyName>
    <gd:fullName>First Last</gd:fullName>
  </gd:name>
  <!-- ... -->
  <gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work" primary="true">
    <gd:city>Mountain View</gd:city>
    <gd:street>1600 Amphitheatre Pkwy</gd:street>
    <gd:region>CA</gd:region>
    <gd:postcode>94043</gd:postcode>
    <gd:country>United States</gd:country>
    <gd:formattedAddress>1600 Amphitheatre Pkwy Mountain View, CA 94043 United States</gd:formattedAddress>
  </gd:structuredPostalAddress>
  <!-- ... -->
</entry>

Formatted

In the following example, only the formatted flavor is provided to the API. The server uses heuristic parsers to try and generate the structured flavor.

Input:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
  <gd:name>
    <gd:fullName>First Last</gd:fullName>
  </gd:name>
  <!-- ... -->
  <gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work" primary="true">
    <gd:formattedAddress>1600 Amphitheatre Pkwy Mountain View, CA 94043 United States</gd:formattedAddress>
  </gd:structuredPostalAddress>
  <!-- ... -->
</entry>

Output:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
  <gd:name>
    <gd:givenName>First</gd:givenName>
    <gd:familyName>Last</gd:familyName>
    <gd:fullName>First Last</gd:fullName>
  </gd:name>
  <!-- ... -->
  <gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work" primary="true">
    <gd:city>Mountain View</gd:city>
    <gd:street>1600 Amphitheatre Pkwy</gd:street>
    <gd:region>CA</gd:region>
    <gd:postcode>94043</gd:postcode>
    <gd:country>United States</gd:country>
    <gd:formattedAddress>1600 Amphitheatre Pkwy Mountain View, CA 94043 United States</gd:formattedAddress>
  </gd:structuredPostalAddress>
  <!-- ... -->
</entry>

Both

In the following example, both structured and formatted flavors are provided to the API. No elements are generated by the server.

Input:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
  <gd:name>
    <gd:givenName>First</gd:givenName>
    <gd:familyName>Last</gd:familyName>
    <gd:fullName>Last First</gd:fullName>
  </gd:name>
  <!-- ... -->
  <gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work" primary="true">
    <gd:city>Mountain View</gd:city>
    <gd:street>1600 Amphitheatre Pkwy</gd:street>
    <gd:region>CA</gd:region>
    <gd:postcode>94043</gd:postcode>
    <gd:country>United States</gd:country>
    <gd:formattedAddress>
      1600 Amphitheatre Pkwy Mountain View
    </gd:formattedAddress>
  </gd:structuredPostalAddress>
<!-- ... -->
</entry>

Output:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
  <gd:name>
    <gd:givenName>First</gd:givenName>
    <gd:familyName>Last</gd:familyName>
    <gd:fullName>Last First</gd:fullName>
  </gd:name>
  <!-- ... -->
  <gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work" primary="true">
    <gd:city>Mountain View</gd:city>
    <gd:street>1600 Amphitheatre Pkwy</gd:street>
    <gd:region>CA</gd:region>
    <gd:postcode>94043</gd:postcode>
    <gd:country>United States</gd:country>
    <gd:formattedAddress>
      1600 Amphitheatre Pkwy Mountain View
    </gd:formattedAddress>
  </gd:structuredPostalAddress>
  <!-- ... -->
</entry>

Retrieving all contacts

To retrieve all of a user's contacts, send an authorized GET request to the following URL:

https://www.google.com/m8/feeds/contacts/{userEmail}/full

With the appropriate value in place of userEmail.

Upon success, the server responds with a HTTP 200 OK status code and the requested contacts feed.

Protocol

Request:

GET /m8/feeds/contacts/default/full
GData-Version: 3.0
...

Response Header:

HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=UTF-8; type=feed
...

Response Body:

<feed xmlns="http://www.w3.org/2005/Atom"
    xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/"
    xmlns:gContact="http://schemas.google.com/contact/2008"
    xmlns:batch="http://schemas.google.com/gdata/batch"
    xmlns:gd="http://schemas.google.com/g/2005"
    gd:etag="feedEtag">
  <id>userEmail</id>
  <updated>2008-12-10T10:04:15.446Z</updated>
  <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
  <link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml"
      href="https://www.google.com/m8/feeds/contacts/userEmail/full"/>
  <link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml"
      href="https://www.google.com/m8/feeds/contacts/userEmail/full"/>
  <link rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml"
      href="https://www.google.com/m8/feeds/contacts/userEmail/full/batch"/>
  <link rel="self" type="application/atom+xml"
      href="https://www.google.com/m8/feeds/contacts/userEmail/full?max-results=25"/>
  <author>
    <name>User</name>
    <email>userEmail</email>
  </author>
  <generator version="1.0" uri="http://www.google.com/m8/feeds">
    Contacts
  </generator>
  <openSearch:totalResults>1</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
  <entry gd:etag="contactEtag">
    <id>
      http://www.google.com/m8/feeds/contacts/userEmail/base/contactId
    </id>
    <updated>2008-12-10T04:45:03.331Z</updated>
    <app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-10T04:45:03.331Z</app:edited>
    <category scheme="http://schemas.google.com/g/2005#kind"
        term="http://schemas.google.com/contact/2008#contact"/>
    <title>Fitzwilliam Darcy</title>
    <gd:name>
      <gd:fullName>Fitzwilliam Darcy</gd:fullName>
    </gd:name>
    <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
        href="https://www.google.com/m8/feeds/photos/media/userEmail/contactId"
        gd:etag="photoEtag"/>
    <link rel="self" type="application/atom+xml"
        href="https://www.google.com/m8/feeds/contacts/userEmail/full/contactId"/>
    <link rel="edit" type="application/atom+xml"
        href="https://www.google.com/m8/feeds/contacts/userEmail/full/contactId"/>
    <gd:phoneNumber rel="http://schemas.google.com/g/2005#home"
        primary="true">
      456
    </gd:phoneNumber>
    <gd:extendedProperty name="pet" value="hamster"/>
    <gContact:groupMembershipInfo deleted="false"
        href="http://www.google.com/m8/feeds/groups/userEmail/base/groupId"/>
  </entry>
  <!-- Other entries ... -->
</feed>

Java

public static void printAllContacts(ContactsService myService)
    throws ServiceException, IOException {
  // Request the feed
  URL feedUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
  ContactFeed resultFeed = myService.getFeed(feedUrl, ContactFeed.class);
  // Print the results
  System.out.println(resultFeed.getTitle().getPlainText());
  for (ContactEntry entry : resultFeed.getEntries()) {
    if (entry.hasName()) {
      Name name = entry.getName();
      if (name.hasFullName()) {
        String fullNameToDisplay = name.getFullName().getValue();
        if (name.getFullName().hasYomi()) {
          fullNameToDisplay += " (" + name.getFullName().getYomi() + ")";
        }
      System.out.println("\t\t" + fullNameToDisplay);
      } else {
        System.out.println("\t\t (no full name found)");
      }
      if (name.hasNamePrefix()) {
        System.out.println("\t\t" + name.getNamePrefix().getValue());
      } else {
        System.out.println("\t\t (no name prefix found)");
      }
      if (name.hasGivenName()) {
        String givenNameToDisplay = name.getGivenName().getValue();
        if (name.getGivenName().hasYomi()) {
          givenNameToDisplay += " (" + name.getGivenName().getYomi() + ")";
        }
        System.out.println("\t\t" + givenNameToDisplay);
      } else {
        System.out.println("\t\t (no given name found)");
      }
      if (name.hasAdditionalName()) {
        String additionalNameToDisplay = name.getAdditionalName().getValue();
        if (name.getAdditionalName().hasYomi()) {
          additionalNameToDisplay += " (" + name.getAdditionalName().getYomi() + ")";
        }
        System.out.println("\t\t" + additionalNameToDisplay);
      } else {
        System.out.println("\t\t (no additional name found)");
      }
      if (name.hasFamilyName()) {
        String familyNameToDisplay = name.getFamilyName().getValue();
        if (name.getFamilyName().hasYomi()) {
          familyNameToDisplay += " (" + name.getFamilyName().getYomi() + ")";
        }
        System.out.println("\t\t" + familyNameToDisplay);
      } else {
        System.out.println("\t\t (no family name found)");
      }
      if (name.hasNameSuffix()) {
        System.out.println("\t\t" + name.getNameSuffix().getValue());
      } else {
        System.out.println("\t\t (no name suffix found)");
      }
    } else {
      System.out.println("\t (no name found)");
    }
    System.out.println("Email addresses:");
    for (Email email : entry.getEmailAddresses()) {
      System.out.print(" " + email.getAddress());
      if (email.getRel() != null) {
        System.out.print(" rel:" + email.getRel());
      }
      if (email.getLabel() != null) {
        System.out.print(" label:" + email.getLabel());
      }
      if (email.getPrimary()) {
        System.out.print(" (primary) ");
      }
      System.out.print("\n");
    }
    System.out.println("IM addresses:");
    for (Im im : entry.getImAddresses()) {
      System.out.print(" " + im.getAddress());
      if (im.getLabel() != null) {
        System.out.print(" label:" + im.getLabel());
      }
      if (im.getRel() != null) {
        System.out.print(" rel:" + im.getRel());
      }
      if (im.getProtocol() != null) {
        System.out.print(" protocol:" + im.getProtocol());
      }
      if (im.getPrimary()) {
        System.out.print(" (primary) ");
      }
      System.out.print("\n");
    }
    System.out.println("Groups:");
    for (GroupMembershipInfo group : entry.getGroupMembershipInfos()) {
      String groupHref = group.getHref();
      System.out.println("  Id: " + groupHref);
    }
    System.out.println("Extended Properties:");
    for (ExtendedProperty property : entry.getExtendedProperties()) {
      if (property.getValue() != null) {
        System.out.println("  " + property.getName() + "(value) = " +
            property.getValue());
      } else if (property.getXmlBlob() != null) {
        System.out.println("  " + property.getName() + "(xmlBlob)= " +
            property.getXmlBlob().getBlob());
      }
    }
    Link photoLink = entry.getContactPhotoLink();
    String photoLinkHref = photoLink.getHref();
    System.out.println("Photo Link: " + photoLinkHref);
    if (photoLink.getEtag() != null) {
      System.out.println("Contact Photo's ETag: " + photoLink.getEtag());
    }
    System.out.println("Contact's ETag: " + entry.getEtag());
  }
}

.NET

public static void PrintAllContacts(ContactsRequest cr)
{
  Feed<Contact> f = cr.GetContacts();
  foreach (Contact entry in f.Entries)
  {
    if (entry.Name != null)
    {
      Name name = entry.Name;
      if (!string.IsNullOrEmpty(name.FullName))
        Console.WriteLine("\t\t" + name.FullName);
      else
        Console.WriteLine("\t\t (no full name found)");
      if (!string.IsNullOrEmpty(name.NamePrefix))
        Console.WriteLine("\t\t" + name.NamePrefix);
      else
        Console.WriteLine("\t\t (no name prefix found)");
      if (!string.IsNullOrEmpty(name.GivenName))
      {
        string givenNameToDisplay = name.GivenName;
        if (!string.IsNullOrEmpty(name.GivenNamePhonetics))
          givenNameToDisplay += " (" + name.GivenNamePhonetics + ")";
        Console.WriteLine("\t\t" + givenNameToDisplay);
      }
      else
        Console.WriteLine("\t\t (no given name found)");
      if (!string.IsNullOrEmpty(name.AdditionalName))
      {
        string additionalNameToDisplay = name.AdditionalName;
        if (string.IsNullOrEmpty(name.AdditionalNamePhonetics))
          additionalNameToDisplay += " (" + name.AdditionalNamePhonetics + ")";
        Console.WriteLine("\t\t" + additionalNameToDisplay);
      }
      else
        Console.WriteLine("\t\t (no additional name found)");
      if (!string.IsNullOrEmpty(name.FamilyName))
      {
        string familyNameToDisplay = name.FamilyName;
        if (!string.IsNullOrEmpty(name.FamilyNamePhonetics))
          familyNameToDisplay += " (" + name.FamilyNamePhonetics + ")";
        Console.WriteLine("\t\t" + familyNameToDisplay);
      }
      else
        Console.WriteLine("\t\t (no family name found)");
      if (!string.IsNullOrEmpty(name.NameSuffix))
        Console.WriteLine("\t\t" + name.NameSuffix);
      else
        Console.WriteLine("\t\t (no name suffix found)");
      }
      else
        Console.WriteLine("\t (no name found)");
        foreach (EMail email in entry.Emails)
      {
        Console.WriteLine("\t" + email.Address);
      }
  }
}

Python

def PrintAllContacts(gd_client):
  feed = gd_client.GetContacts()
  for i, entry in enumerate(feed.entry):
    print '\n%s %s' % (i+1, entry.name.full_name.text)
    if entry.content:
      print '    %s' % (entry.content.text)
    # Display the primary email address for the contact.
    for email in entry.email:
      if email.primary and email.primary == 'true':
        print '    %s' % (email.address)
    # Show the contact groups that this contact is a member of.
    for group in entry.group_membership_info:
      print '    Member of group: %s' % (group.href)
    # Display extended properties.
    for extended_property in entry.extended_property:
      if extended_property.value:
        value = extended_property.value
      else:
        value = extended_property.GetXmlBlob()
      print '    Extended Property - %s: %s' % (extended_property.name, value)

Retrieving contacts using query parameters

The Contacts Data API lets you request a set of contacts that match specified criteria, such as requesting contacts created or updated in a given date range, or published by a particular author.

Protocol

For example, to send a date-range query, add the updated-min parameter to the request URL. To get all the contact entries updated after March 16, 2007, send an HTTP request to the contact's feed URL:

GET https://www.google.com/m8/feeds/contacts/{userEmail}/full?updated-min=2007-03-16T00:00:00

Or you can simply use the following URL, which points to the authenticated user's contact feed:

GET https://www.google.com/m8/feeds/contacts/default/full?updated-min=2007-03-16T00:00:00

When you send that GET request, the server returns an HTTP 200 OK status code and a feed containing any contacts that were created or updated after the date specified. The Contacts Data API supports query parameters described in the Contacts Data API Reference Guide.

Java

For example, to send a date-range query, use the setUpdatedMin method of the Query object. The following code snippet prints the title of each contact updated after the given start time:

public static void printDateMinQueryResults(
    ContactsService myService, DateTime startTime) throws ServiceException, IOException {
  // Create query and submit a request
  URL feedUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
  Query myQuery = new Query(feedUrl);
  myQuery.setUpdatedMin(startTime);
  ContactFeed resultFeed = myService.query(myQuery, ContactFeed.class);
  // Print the results
  for (ContactEntry entry : resultFeed.getEntries()) {
    System.out.println(entry.getName().getFullname().getValue());
    System.out.println("Updated on: " + entry.getUpdated().toStringRfc822());
  }
}

Notice that the Query object is constructed using the same contact feed URL used to retrieve contacts. The Contacts Data API supports the following Query methods:

setMaxResults
Set the maximum number of entries to return.
setStartIndex
Set the 1-based index of the first result to be retrieved (for paging).
setUpdatedMin
Set the lower bound on entry update dates.
setStringCustomParameter("showdeleted","true")
Include deleted contacts in the returned contacts feed. Deleted contacts are shown as entries that contain nothing but an <atom:id> element and a <gd:deleted> element. (Google retains placeholders for deleted contacts for 30 days after deletion; during that time, you can request the placeholders using the showdeleted query parameter.)
setStringCustomParameter("orderby","lastmodified")
Sort the returned contacts by last-modified date.
setStringCustomParameter("sortorder", "ascending")
Set sorting order direction. direction can be either "ascending" or "descending".
setStringCustomParameter("group", "groupId")
Retrieve contacts belonging to the specified group Atom Id.

.NET

For example, to send a date-range query, use the StartDate property of the ContactsQuery object. The following code snippet prints out each contact updated after the given start time:

public void PrintDateMinQueryResults(ContactsRequest cr)
{
  ContactsQuery query = new ContactsQuery(ContactsQuery.CreateContactsUri("default"));
  query.StartDate = new DateTime(2008, 1, 1);
  Feed<Contact> feed = cr.Get<Contact>(query);
  foreach (Contact contact in feed.Entries)
  {
     Console.WriteLine(contact.Name.FullName);
     Console.WriteLine("Updated on: " + contact.Updated.ToString());
  }
}

The Contacts Data API supports the following ContactsQuery properties:

NumberToRetrieve
Set the maximum number of entries to return.
StartIndex
Set the 1-based index of the first result to be retrieved (for paging).
StartDate
Set the lower bound on entry update dates.
ShowDeleted
Include deleted contacts in the returned contacts feed. Deleted contacts are shown as entries that contain nothing but an <atom:id> element and a <gd:deleted> element. (Google retains placeholders for deleted contacts for 30 days after deletion; during that time, you can request the placeholders using the showdeleted query parameter.)
OrderBy
Sort the returned contacts by last-modified date.
SortOrder
Set sorting order direction. SortOrder can be either "ascending" or "descending".
Group
Retrieve contacts belonging to the specified group Atom Id.

Python

For example, to send a date-range query, set the updated_min property of the ContactsQuery object. The following code snippet prints out each contact updated after the given start time:

def print_datemin_query_results(gd_client):
  updated_min = '2008-01-01'
  query = gdata.contacts.client.ContactsQuery()
  query.updated_min = updated_min
  feed = gd_client.GetContacts(q = query)
  for contact in feed.entry:
    print contact.name.full_name
    print 'Updated on %s' % contact.updated.text

Notice that the ContactsQuery object has a feed member which represents the base URL of the query. It uses the same default URL as GetContactsFeed. The Contacts Data API supports the following ContactsQuery properties:

query.max_results
Set the maximum number of entries to return.
query.start_index
Set the 1-based index of the first result to be retrieved (for paging).
query.updated_min
Set the lower bound on entry update dates.
query['showdeleted'] = 'true'
Include deleted contacts in the returned contacts feed. Deleted contacts are shown as entries that contain nothing but an <atom:id> element and a <gd:deleted> element. (Google retains placeholders for deleted contacts for 30 days after deletion; during that time, you can request the placeholders using the showdeleted query parameter.)
query.orderby = 'lastmodified'
Sort the returned contacts by last-modified date.
query['sortorder'] = "direction"
Set sorting order direction. direction can be either "ascending" or "descending".
query.group
Retrieve contacts belonging to the specified group Atom Id.

Retrieving a single contact

To retrieve a single contact, send an authorized GET request to the contact's selfLink URL:

https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}

With the appropriate values in place of userEmail and contactID.

Upon success, the server responds with an HTTP 200 OK status code and the requested contact entry.

Protocol

Request:

GET /m8/feeds/contacts/default/full/{contactId}
GData-Version: 3.0
...

Response Header:

HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=UTF-8; type=feed
...

Response Body:

<entry xmlns="http://www.w3.org/2005/Atom"
    xmlns:gContact="http://schemas.google.com/contact/2008"
    xmlns:gd="http://schemas.google.com/g/2005"
    gd:etag="contactEtag">
  <id>
    http://www.google.com/m8/feeds/contacts/{userEmail}/base/{contactId}
  </id>
  <updated>2008-12-10T04:45:03.331Z</updated>
  <app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-10T04:45:03.331Z</app:edited>
  <category scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/contact/2008#contact"/>
  <title>Fitzwilliam Darcy</title>
  <gd:name>
    <gd:fullName>Fitzwilliam Darcy</gd:fullName>
  </gd:name>
  <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
    href="https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactId}"
    gd:etag="{photoEtag}"/>
  <link rel="self" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <link rel="edit" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <gd:phoneNumber rel="http://schemas.google.com/g/2005#home"
    primary="true">
    456
  </gd:phoneNumber>
  <gd:extendedProperty name="pet" value="hamster"/>
  <gContact:groupMembershipInfo deleted="false"
    href="http://www.google.com/m8/feeds/groups/{userEmail}/base/{groupId}"/>
</entry>

Java

public static ContactEntry retrieveContact(ContactsService myService) {
  ContactEntry contact =
      myService.getEntry(new URL("https://www.google.com/m8/feeds/contacts/default/full/contactId"),
          ContactEntry.class);
  // Do something with the contact.
  return contact;
}

.NET

public static Contact retrieveContact(ContactsRequest cr)
{
  Contact contact = cr.Retrieve<Contact>("https://www.google.com/m8/feeds/contacts/default/full/contactId");
  // Do something with the contact.
  return contact;
}

Python

def retrieve_contact(gd_client):
  contact = gd_client.GetContact('https://www.google.com/m8/feeds/contacts/default/full/contactId')
  # Do something with the contact.
  return contact

Creating contacts

To create a new contact, send an authorized POST request to the user's contacts feed URL with contact data in the body.

The URL is of the form:

https://www.google.com/m8/feeds/contacts/{userEmail}/full

With the appropriate value in place of userEmail.

Upon success, the server responds with an HTTP 201 Created status code and the created contact entry with some additional elements and properties (shown in bold) that are set by the server, such as id, various link elements and properties.

Protocol

Request Header:

POST /m8/feeds/contacts/default/full
Content-Type: application/atom+xml
GData-Version: 3.0
...

Request Body:

<atom:entry xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:gd="http://schemas.google.com/g/2005">
  <atom:category scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/contact/2008#contact"/>
  <gd:name>
     <gd:givenName>Elizabeth</gd:givenName>
     <gd:familyName>Bennet</gd:familyName>
     <gd:fullName>Elizabeth Bennet</gd:fullName>
  </gd:name>
  <atom:content type="text">Notes</atom:content>
  <gd:email rel="http://schemas.google.com/g/2005#work"
    primary="true"
    address="liz@gmail.com" displayName="E. Bennet"/>
  <gd:email rel="http://schemas.google.com/g/2005#home"
    address="liz@example.org"/>
  <gd:phoneNumber rel="http://schemas.google.com/g/2005#work"
    primary="true">
    (206)555-1212
  </gd:phoneNumber>
  <gd:phoneNumber rel="http://schemas.google.com/g/2005#home">
    (206)555-1213
  </gd:phoneNumber>
  <gd:im address="liz@gmail.com"
    protocol="http://schemas.google.com/g/2005#GOOGLE_TALK"
    primary="true"
    rel="http://schemas.google.com/g/2005#home"/>
  <gd:structuredPostalAddress
      rel="http://schemas.google.com/g/2005#work"
      primary="true">
    <gd:city>Mountain View</gd:city>
    <gd:street>1600 Amphitheatre Pkwy</gd:street>
    <gd:region>CA</gd:region>
    <gd:postcode>94043</gd:postcode>
    <gd:country>United States</gd:country>
    <gd:formattedAddress>
      1600 Amphitheatre Pkwy Mountain View
    </gd:formattedAddress>
  </gd:structuredPostalAddress>
</atom:entry>

Response Header:

HTTP/1.1 201 Created
Content-Type: application/atom+xml; charset=UTF-8; type=feed
...

Response Body:

<atom:entry xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:gd="http://schemas.google.com/g/2005">
  <id>http://www.google.com/m8/feeds/contacts/userEmail</bar>/base/{contactId}</id>
  <updated>2008-12-10T04:45:03.331Z</updated>
  <app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-10T04:45:03.331Z</app:edited>
  <category scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/contact/2008#contact"/>
  <title>Elizabeth Bennet</title>
  <gd:name>
     <gd:givenName>Elizabeth</gd:givenName>
     <gd:familyName>Bennet</gd:familyName>
     <gd:fullName>Elizabeth Bennet</gd:fullName>
  </gd:name>
  <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
    href="https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactId}"/>
  <link rel="self" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <link rel="edit" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <atom:content type="text">Notes</atom:content>
  <gd:email rel="http://schemas.google.com/g/2005#work"
    primary="true"
    address="liz@gmail.com" displayName="E. Bennet"/>
  <gd:email rel="http://schemas.google.com/g/2005#home"
    address="liz@example.org"/>
  <gd:phoneNumber rel="http://schemas.google.com/g/2005#work"
    primary="true">
    (206)555-1212
  </gd:phoneNumber>
  <gd:phoneNumber rel="http://schemas.google.com/g/2005#home">
    (206)555-1213
  </gd:phoneNumber>
  <gd:im address="liz@gmail.com"
    protocol="http://schemas.google.com/g/2005#GOOGLE_TALK"
    primary="true"
    rel="http://schemas.google.com/g/2005#home"/>
  <gd:structuredPostalAddress
      rel="http://schemas.google.com/g/2005#work"
      primary="true">
    <gd:city>Mountain View</gd:city>
    <gd:street>1600 Amphitheatre Pkwy</gd:street>
    <gd:region>CA</gd:region>
    <gd:postcode>94043</gd:postcode>
    <gd:country>United States</gd:country>
    <gd:formattedAddress>
      1600 Amphitheatre Pkwy Mountain View
    </gd:formattedAddress>
  </gd:structuredPostalAddress>
</atom:entry>

Java

import com.google.gdata.client.contacts.ContactsService;
import com.google.gdata.data.contacts.ContactEntry;
import com.google.gdata.data.contacts.ContactGroupFeed;
import com.google.gdata.data.extensions.City;
import com.google.gdata.data.extensions.Country;
import com.google.gdata.data.extensions.Email;
import com.google.gdata.data.extensions.ExtendedProperty;
import com.google.gdata.data.extensions.FormattedAddress;
import com.google.gdata.data.extensions.FullName;
import com.google.gdata.data.extensions.Im;
import com.google.gdata.data.extensions.Name;
import com.google.gdata.data.extensions.PhoneNumber;
import com.google.gdata.data.extensions.PostCode;
import com.google.gdata.data.extensions.Region;
import com.google.gdata.data.extensions.Street;
import com.google.gdata.data.extensions.StructuredPostalAddress;
// ...
public static ContactEntry createContact(ContactsService myService) {
  // Create the entry to insert.
  ContactEntry contact = new ContactEntry();
  // Set the contact's name.
  Name name = new Name();
  final String NO_YOMI = null;
  name.setFullName(new FullName("Elizabeth Bennet", NO_YOMI));
  name.setGivenName(new GivenName("Elizabeth", NO_YOMI));
  name.setFamilyName(new FamilyName("Bennet", NO_YOMI))
  contact.setName(name);
  contact.setContent(new PlainTextConstruct("Notes"));
  // Set contact's e-mail addresses.
  Email primaryMail = new Email();
  primaryMail.setAddress("liz@gmail.com");
  primaryMail.setDisplayName("E. Bennet");
  primaryMail.setRel("http://schemas.google.com/g/2005#home");
  primaryMail.setPrimary(true);
  contact.addEmailAddress(primaryMail);
  Email secondaryMail = new Email();
  secondaryMail.setAddress("liz@example.com");
  secondaryMail.setRel("http://schemas.google.com/g/2005#work");
  secondaryMail.setPrimary(false);
  contact.addEmailAddress(secondaryMail);
  // Set contact's phone numbers.
  PhoneNumber primaryPhoneNumber = new PhoneNumber();
  primaryPhoneNumber.setPhoneNumber("(206)555-1212");
  primaryPhoneNumber.setRel("http://schemas.google.com/g/2005#work");
  primaryPhoneNumber.setPrimary(true);
  contact.addPhoneNumber(primaryPhoneNumber);
  PhoneNumber secondaryPhoneNumber = new PhoneNumber();
  secondaryPhoneNumber.setPhoneNumber("(206)555-1213");
  secondaryPhoneNumber.setRel("http://schemas.google.com/g/2005#home");
  contact.addPhoneNumber(secondaryPhoneNumber);
  // Set contact's IM information.
  Im imAddress = new Im();
  imAddress.setAddress("liz@gmail.com");
  imAddress.setRel("http://schemas.google.com/g/2005#home");
  imAddress.setProtocol("http://schemas.google.com/g/2005#GOOGLE_TALK");
  imAddress.setPrimary(true);
  contact.addImAddress(imAddress);
  // Set contact's postal address.
  StructuredPostalAddress postalAddress = new StructuredPostalAddress();
  postalAddress.setStreet(new Street("1600 Amphitheatre Pkwy"));
  postalAddress.setCity(new City("Mountain View"));
  postalAddress.setRegion(new Region("CA"));
  postalAddress.setPostcode(new PostCode("94043"));
  postalAddress.setCountry(new Country("US", "United States"));
  postalAddress.setFormattedAddress(new FormattedAddress("1600 Amphitheatre Pkwy Mountain View"));
  postalAddress.setRel("http://schemas.google.com/g/2005#work");
  postalAddress.setPrimary(true);
  contactOne.addStructuredPostalAddress(postalAddress);
  // Ask the service to insert the new entry
  URL postUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
  ContactEntry createdContact = myService.insert(postUrl, contact);
  System.out.println("Contact's ID: " + createdContact.getId());
  return createdContact;
}

.NET

public static Contact CreateContact(ContactsRequest cr)
{
  Contact newEntry = new Contact();
  // Set the contact's name.
  newEntry.Name = new Name()
      {
        FullName = "Elizabeth Bennet",
        GivenName = "Elizabeth",
        FamilyName = "Bennet",
      };
  newEntry.Content = "Notes";
  // Set the contact's e-mail addresses.
  newEntry.Emails.Add(new EMail()
      {
        Primary = true,
        Rel = ContactsRelationships.IsHome,
        Address = "liz@gmail.com"
      });
  newEntry.Emails.Add(new EMail()
      {
        Rel = ContactsRelationships.IsWork,
        Address = "liz@example.com"
      });
  // Set the contact's phone numbers.
  newEntry.Phonenumbers.Add(new PhoneNumber()
      {
        Primary = true,
        Rel = ContactsRelationships.IsWork,
        Value = "(206)555-1212",
      });
  newEntry.Phonenumbers.Add(new PhoneNumber()
      {
        Rel = ContactsRelationships.IsHome,
        Value = "(206)555-1213",
      });
  // Set the contact's IM information.
  newEntry.IMs.Add(new IMAddress()
      {
        Primary = true,
        Rel = ContactsRelationships.IsHome,
        Protocol = ContactsProtocols.IsGoogleTalk,
      });
  // Set the contact's postal address.
  newEntry.PostalAddresses.Add(new StructuredPostalAddress()
      {
        Rel = ContactsRelationships.IsWork,
        Primary = true,
        Street = "1600 Amphitheatre Pkwy",
        City ="Mountain View",
        Region = "CA",
        Postcode = "94043",
        Country = "United States",
        FormattedAddress = "1600 Amphitheatre Pkwy Mountain View",
      });
  // Insert the contact.
  Uri feedUri = new Uri(ContactsQuery.CreateContactsUri("default"));
  Contact createdEntry = cr.Insert(feedUri, newEntry);
  Console.WriteLine("Contact's ID: " + createdEntry.Id)
  return createdEntry;
}

Python

import atom.data
import gdata.data
import gdata.contacts.client
import gdata.contacts.data

def create_contact(gd_client):
  new_contact = gdata.contacts.data.ContactEntry()
  # Set the contact's name.
  new_contact.name = gdata.data.Name(
      given_name=gdata.data.GivenName(text='Elizabeth'),
      family_name=gdata.data.FamilyName(text='Bennet'),
      full_name=gdata.data.FullName(text='Elizabeth Bennet'))
  new_contact.content = atom.data.Content(text='Notes')
  # Set the contact's email addresses.
  new_contact.email.append(gdata.data.Email(address='liz@gmail.com',
      primary='true', rel=gdata.data.WORK_REL, display_name='E. Bennet'))
  new_contact.email.append(gdata.data.Email(address='liz@example.com',
      rel=gdata.data.HOME_REL))
  # Set the contact's phone numbers.
  new_contact.phone_number.append(gdata.data.PhoneNumber(text='(206)555-1212',
      rel=gdata.data.WORK_REL, primary='true'))
  new_contact.phone_number.append(gdata.data.PhoneNumber(text='(206)555-1213',
      rel=gdata.data.HOME_REL))
  # Set the contact's IM address.
  new_contact.im.append(gdata.data.Im(text='liz@gmail.com',
      primary='true', rel=gdata.data.HOME_REL, protocol=gdata.data.GOOGLE_TALK_PROTOCOL))
  # Set the contact's postal address.
  new_contact.structured_postal_address.append(
      rel=gdata.data.WORK_REL, primary='true',
      street=gdata.data.Street(text='1600 Amphitheatre Pkwy'),
      city=gdata.data.City(text='Mountain View'),
      region=gdata.data.Region(text='CA'),
      postcode=gdata.data.Postcode(text='94043'),
      country=gdata.data.Country(text='United States'))
  # Send the contact data to the server.
  contact_entry = gd_client.CreateContact(new_contact)
  print "Contact's ID: %s" % contact_entry.id.text
  return contact_entry

Updating contacts

To update a contact, first retrieve the contact entry, modify the data and send an authorized PUT request to the contact's edit URL with the modified contact entry in the body.

The URL is of the form:

https://www.google.com/m8/feeds/contacts/userEmail/full/{contactId}

With the appropriate values in place of userEmail and contactId.

To ensure that the data sent to the API doesn't overwrite another client's changes, the contact entry's Etag should be provided in the request header.

If-Match: Etag

If the Etag is outdated, the server responds with an HTTP 412 Precondition Failed status code.

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

Upon success, the server responds with an HTTP 200 OK status code and the updated contact entry.

Protocol

Request Header:

PUT /m8/feeds/contacts/default/full/{contactId}
If-Match: {lastKnownEtag}
GData-Version: 3.0
Content-Type: application/atom+xml
...

Request Body:

<entry gd:etag="{lastKnownEtag}">
  <id>http://www.google.com/m8/feeds/contacts/{userEmail}/base/{contactId}</id>
  <updated>2008-02-28T18:47:02.303Z</updated>
  <category scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/contact/2008#contact"/>
  <gd:name>
    <gd:givenName>New</gd:givenName>
    <gd:familyName>Name</gd:familyName>
    <gd:fullName>New Name</gd:fullName>
  </gd:name>
  <content type="text">Notes</content>
  <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
    href="https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactId}"/>
  <link rel="self" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <link rel="edit" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <gd:phoneNumber rel="http://schemas.google.com/g/2005#other"
    primary="true">456-123-2133</gd:phoneNumber>
  <gd:extendedProperty name="pet" value="hamster"/>
  <gContact:groupMembershipInfo deleted="false"
    href="http://www.google.com/m8/feeds/groups/{userEmail}/base/{groupId}"/>
</entry>
</pre>

Response Header:

HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=UTF-8; type=entry
...

Response Body:

<entry gd:etag="{newEtag}">
  <id>http://www.google.com/m8/feeds/contacts/{userEmail}/base/{contactId}</id>
  <updated>2011-05-11T09:30:00.000Z</updated>
  <category scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/contact/2008#contact"/>
  <title type="text">New Name</title>
  <gd:name>
    <gd:givenName>New</gd:givenName>
    <gd:familyName>Name</gd:familyName>
    <gd:fullName>New Name</gd:fullName>
  </gd:name>
  <content type="text">Notes</content>
  <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
    href="https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactId}"/>
  <link rel="self" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <link rel="edit" type="application/atom+xml"
    href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
  <gd:phoneNumber rel="http://schemas.google.com/g/2005#other"
    primary="true">456-123-2133</gd:phoneNumber>
  <gd:extendedProperty name="pet" value="hamster"/>
  <gContact:groupMembershipInfo deleted="false"
    href="http://www.google.com/m8/feeds/groups/{userEmail}/base/{groupId}"/>
</entry>

Java

public static ContactEntry updateContactName(
    ContactsService myService, URL contactURL)
    throws ServiceException, IOException {
  // First retrieve the contact to updated.
  ContactEntry entryToUpdate = myService.getEntry(contactURL, ContactEntry.class);
  entryToUpdate.getName().getFullName().setValue("New Name");
  entryToUpdate.getName().getGivenName().setValue("New");
  entryToUpdate.getName().getFamilyName().setValue("Name");
  URL editUrl = new URL(entryToUpdate.getEditLink().getHref());
  try {
    ContactEntry contactEntry = myService.update(editUrl, entryToUpdate);
    System.out.println("Updated: " + contactEntry.getUpdated().toString());
    return contactEntry;
  } catch (PreconditionFailedException e) {
    // Etags mismatch: handle the exception.
  }
  return null;
}

.NET

public static Contact UpdateContactName(ContactsRequest cr, Uri contactURL)
{
  // First, retrieve the contact to update.
  Contact contact = cr.Retrieve<Contact>(contactURL);
  contact.Name.FullName = "New Name";
  contact.Name.GivenName = "New";
  contact.Name.FamilyName = "Name";
  try
  {
    Contact updatedContact = cr.Update(contact);
    Console.WriteLine("Updated: " + updatedEntry.Updated.ToString())
    return updatedContact;
  }
  catch (GDataVersionConflictException e)
  {
    // Etags mismatch: handle the exception.
  }
  return null;
}

Python

def update_contact_name(gd_client, contact_url):
  # First retrieve the contact to modify from the API.
  contact_entry = gd_client.GetContact(contact_url)
  contact_entry.name.full_name.text = 'New Name'
  contact_entry.name.given_name.text = 'New'
  contact_entry.name.family_name.text = 'Name'
  try:
    updated_contact = gd_client.Update(contact_entry)
    print 'Updated: %s' % updated_contact.updated.text
    return updated_contact
  except gdata.client.RequestError, e:
    if e.status == 412:
      # Etags mismatch: handle the exception.
      pass
  return None

Changing group membership

To determine what groups a given contact belongs to, examine the contact's <gContact:groupMembershipInfo> elements. Each such element contains a group Atom ID as the value of its href attribute.

  • <entry gd:etag='contactEtag'>
      <id>http://www.google.com/m8/feeds/contacts/userEmail/base/contactId</id>
      ...
      <gContact:groupMembershipInfo deleted='false'
        href='http://www.google.com/m8/feeds/groups/userEmail/base/groupId'/>
      ...
    </entry>
    
    

  • public static void printGroupMembershipInfo(ContactsService myService, URL contactURL)
        throws IOException, ServiceException {
      ContactEntry contact = myService.getEntry(contactURL, ContactEntry.class);
    
      for (GroupMembershipInfo groupMembershipInfo : contact.getGroupMembershipInfos()) {
        System.out.println("Group's Atom ID: " + groupMembershipInfo.getHref());
      }
    }
    
    

  • public static void PrintGroupMembershipInfo(ContactsRequest cr, Uri contactURL)
    {
      Contact contact = cr.Retrieve(contactURL);
    
      foreach (GroupMembership groupMembership in contact.GroupMembership)
      {
        Console.WriteLine("Group's Atom ID: " + groupMembership.HRef);
      }
    }
    

  • def print_group_membership_info(gd_client, contact_url):
      contact = gd_client.GetContact(contact_url)
      for group_membership_info in contact.group_membership_info:
        print "Group's Atom ID: %s" % group_membership_info.href
    

  • To change a contact's group membership, edit the contact's gd:groupMembershipInfo fields to reflect the new group this contact belongs to and send an update request to the API.

    The group's Atom ID can be found as the value of the element for that group which can be retrieved by getting the user's contact groups feed.

    Protocol

    Request Header:

    PUT https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}
    If-Match: {lastKnownEtag}
    GData-Version: 3.0
    Content-Type: application/atom+xml
    ...
    

    Request Body:

    <entry gd:etag="{lastKnownEtag}">
      <id>http://www.google.com/m8/feeds/contacts/{userEmail}/base/{contactId}</id>
      <updated>2008-02-28T18:47:02.303Z</updated>
      ...
      <gContact:groupMembershipInfo deleted="false"
        href="http://www.google.com/m8/feeds/groups/{userEmail}/base/{groupId}"/>
    </entry>
    

    Response Header:

    HTTP/1.1 200 OK
    ...
    

    Response Body:

    <entry gd:etag="{newEtag}">
      <id>http://www.google.com/m8/feeds/contacts/{userEmail}/base/{contactId}</id>
      <updated>2011-05-11T09:30:00.000Z</updated>
      ...
      <gContact:groupMembershipInfo deleted="false"
        href="http://www.google.com/m8/feeds/groups/{userEmail}/base/{groupId}"/>
    </entry>
    

    Java

    public static ContactEntry addGroupMembership(ContactsService myService, URL contactURL, String groupAtomId)
        throws IOException, ServiceException {
      ContactEntry contact = myService.getEntry(contactURL, ContactEntry.class);
      contact.addGroupMembershipInfo(new GroupMembershipInfo(false, groupAtomId));
      URL editUrl = new URL(contact.getEditLink().getHref());
      try {
        ContactEntry updatedContact = myService.update(editUrl, contact);
        return contact;
      } catch (PreconditionFailedException e) {
        // Etags mismatch: handle the exception.
      }
      return null;
    }
    

    .NET

    public static Contact addGroupMembership(ContactsRequest cr, Uri contactURL, string groupAtomId)
    {
      Contact contact = cr.Retrieve<Contact>(contactURL);
      contact.GroupMembership.Add(new GroupMembership()
          {
            HRef = groupAtomId
          });
      try
      {
        Contact updatedContact = cr.Update(contact);
        return updatedContact;
      }
      catch (GDataVersionConflictException e)
      {
        // Etags mismatch: handle the exception.
      }
      return null;
    }
    

    Python

    def add_group_membership(gd_client, contact_url, group_atom_id):
      contact = gd_client.GetContact(contact_url)
      contact.group_membership_info.append(gdata.contacts.data.GroupMembershipInfo(href=group_atom_id))
      try:
        updated_contact = gd_client.Update(contact)
        return updated_contact
      except gdata.client.RequestError, e:
        if e.status == 412:
          # Etags mismatch: handle the exception.
          pass
      return None
    

    Deleting contacts

    To delete a contact, send an authorized DELETE request to the contact's edit URL.

    The URL is of the form:

    https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}
    

    With the appropriate values in place of userEmail and contactID.

    To ensure that the request sent to the API doesn't overwrite another client's changes, the contact entry's Etag should be provided in the request header.

    If-Match: Etag
    

    If the Etag is outdated, the server responds with an HTTP 412 Precondition Failed status code.

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

    Upon success, the server responds with an HTTP 200 OK status code.

  • <!-- Request -->
    DELETE /m8/feeds/contacts/default/full/contactId
    If-match: Etag
    ...
    <!-- Response -->
    HTTP/1.1 200 OK
    
    

  • public static void deleteContact(ContactsService myService, URL contactURL)
        throws ServiceException, IOException {
      // Retrieving the contact is required in order to get the Etag.
      ContactEntry contact = myService.getEntry(contactURL, ContactEntry.class);
    
      try {
        contact.delete();
      } catch (PreconditionFailedException e) {
        // Etags mismatch: handle the exception.
      }
    }
    
    

  • public static void DeleteContact(ContactsRequest cr, Uri contactURL)
    {
      // Retrieving the contact is required in order to get the Etag.
      Contact contact = cr.retrieve<Contact>(contactURL);
    
      try
      {
        cr.Delete(contact);
      }
      catch (GDataVersionConflictException e)
      {
        // Etags mismatch: handle the exception.
      }
    }
    

  • def delete_contact(gd_client, contact_url):
      # Retrieving the contact is required in order to get the Etag.
      contact = gd_client.GetContact(contact_url)
    
      try:
        gd_client.Delete(contact)
      except gdata.client.RequestError, e:
        if e.status == 412:
          # Etags mismatch: handle the exception.
          pass
    

  • Troubleshooting Tip: Some firewalls block HTTP DELETE messages. To get around this, you can include an X-HTTP-Method-Override: DELETE header in a POST request. For details, see the Google Data API protocol basics document.

    Contact photo management

    Retrieving a contact's photo

    To retrieve a contact's photo, send an authorized GET request to the contact's photo link URL.

    The URL is of the form:

    https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactId}
    

    With the appropriate values in place of userEmail and contactID.

    The photo link can be retrieved from the contact entry returned by the API:

    <entry xmlns="http://www.w3.org/2005/Atom"
        xmlns:gContact="http://schemas.google.com/contact/2008"
        xmlns:gd="http://schemas.google.com/g/2005"
        gd:etag="{contactEtag}">
      <id>
        http://www.google.com/m8/feeds/contacts/{userEmail}/base/{contactId}
      </id>
      ...
      <title>Full Name</title>
      <gd:name>
        <gd:fullName>Full Name</gd:fullName>
      </gd:name>
      <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
        href="https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactId}"
        gd:etag="{photoEtag}"/>
      <link rel="self" type="application/atom+xml"
        href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
      ...
    </entry>
    

    Upon success, the server responds with an HTTP 200 OK status code and the photo data bytes.

  • <!-- Request -->
    GET /m8/feeds/photos/media/default/contactId
    
    ...
    <!-- Response -->
    HTTP/1.1 200 OK
    Content-Type: image/*
    ...
    [Photo data bytes]
    
    

  • public static void downloadPhoto(ContactsService service, URL contactURL)
        throws ServiceException, IOException {
      ContactEntry entry = service.getEntry(contactURL,  ContactEntry.class);
    
      Link photoLink = entry.getContactPhotoLink();
      if (photoLink != null) {
        InputStream in = service.getStreamFromLink(photoLink);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        RandomAccessFile file = new RandomAccessFile("test.jpg", "rw");
        byte[] buffer = new byte[4096];
        while (true) {
          if ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
          } else {
            break;
          }
        }
        file.write(out.toByteArray());
        file.close();
      }
    }
    
    

  • public static void DownloadPhoto(ContactsRequest cr, Uri contactURL)
    {
      Contact contact = cr.Retrieve<Contact>(contactURL);
    
      Stream photoStream = cr.GetPhoto(contact);
      FileStream outStream = File.OpenWrite("test.jpg");
      byte[] buffer = new byte[photoStream.length];
    
      photoStream.Read(buffer, 0, photoStream.length);
      outStream.Write(buffer, 0, photoStream.length);
      photoStream.Close();
      outStream.Close();
    }
    
    

  • def download_photo(gd_client, contact_url):
      contact = gd_client.GetContact(contact_url)
    
      hosted_image_binary = gd_client.GetPhoto(contact_entry)
      image_file = open('test.jpg', 'wb')
      image_file.write(hosted_image_binary)
      image_file.close()
    
    

  • Adding/Updating a photo for a contact

    To add or update a photo for a contact, send an authorized PUT request to the contact's photo URL with the photo data bytes in the body.

    The URL is of the form:

    https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactID}
    

    With the appropriate values in place of userEmail and contactID.

    The photo link can be retrieved from the contact entry returned by the API:

    <entry xmlns="http://www.w3.org/2005/Atom"
        xmlns:gContact="http://schemas.google.com/contact/2008"
        xmlns:gd="http://schemas.google.com/g/2005"
        gd:etag="{contactEtag}">
      <id>
        http://www.google.com/m8/feeds/contacts/{userEmail}/base/{contactId}
      </id>
      ...
      <title>Full Name</title>
      <gd:name>
        <gd:fullName>Full Name</gd:fullName>
      </gd:name>
      <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
        href="https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactId}"
        gd:etag="{photoEtag}"/>
      <link rel="self" type="application/atom+xml"
        href="https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}"/>
      ...
    </entry>
    

    To ensure that the request sent to the API doesn't overwrite another client's changes, the contact entry's Etag should be provided in the request header.

    If-Match: Etag
    

    If the Etag is outdated, the server responds with an HTTP 412 Precondition Failed status code.

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

    If a contact does not have a photo, then the photo link element has no gd:etag attribute and no If-match is required.

    Upon success, the server responds with an HTTP 200 OK status code.

  • <!-- Request -->
    PUT /m8/feeds/photos/media/default/contactId
    If-match: Etag
    Content-Type: image/*
    ...
    [Photo data bytes]
    
    ...
    <!-- Response -->
    HTTP/1.1 OK
    ...
    
    

  • public static void updateContactPhoto(ContactsService myService, URL contactURL, byte[] photoData)
        throws ServiceException, IOException {
      ContactEntry contact = myService.getEntry(contactURL, ContactEntry.class);
      Link photoLink = contact.getContactPhotoLink();
      URL photoUrl = new URL(photoLink.getHref());
    
      GDataRequest request = myService.createRequest(GDataRequest.RequestType.UPDATE,
          photoUrl, new ContentType("image/jpeg"));
    
      request.setEtag(photoLink.getEtag());
    
      OutputStream requestStream = request.getRequestStream();
      requestStream.write(photoData);
    
      try {
        request.execute();
      } catch (PreconditionFailedException e) {
        // Etags mismatch: handle the exception.
      }
    }
    

  • public static void UpdateContactPhoto(ContactsRequest cr, Uri contactURL, Stream photoStream)
    {
      Contact contact = cr.Retrieve<Contact>(contactURL);
    
      try
      {
        cr.SetPhoto(contact, photoStream);
      }
      catch (GDataVersionConflictException e)
      {
        // Etags mismatch: handle the exception.
      }
    }
    

  • def update_contact_photo(gd_client, contact_url, media_object):
      contact = gd_client.GetContact(contact_url)
      try:
        gd_client.ChangePhoto(media_object, contact)
      except gdata.client.RequestError, e:
        if e.status == 412:
          # Etags mismatch: handle the exception.
          pass
    
    

  • Deleting a contact's photo

    To delete a contact's photo, send an authorized DELETE request to the contact's photo URL.

    The URL is of the form:

    https://www.google.com/m8/feeds/photos/media/{userEmail}/{contactID}
    

    With the appropriate values in place of userEmail and contactID.

    The photo link can be retrieved from the contact entry returned by the API:

    <entry xmlns="http://www.w3.org/2005/Atom"
        xmlns:gContact="http://schemas.google.com/contact/2008"
        xmlns:gd="http://schemas.google.com/g/2005"
        gd:etag="contactEtag">
      <id>
        http://www.google.com/m8/feeds/contacts/userEmail/base/contactId
      </id>
      ...
      <title>Full Name</title>
      <gd:name>
        <gd:fullName>Full Name</gd:fullName>
      </gd:name>
      <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"
        href="https://www.google.com/m8/feeds/photos/media/userEmail/contactId"
        gd:etag="photoEtag"/>
      <link rel="self" type="application/atom+xml"
        href="https://www.google.com/m8/feeds/contacts/userEmail/full/contactId"/>
      ...
    </entry>
    

    To ensure that the request sent to the API doesn't overwrite another client's changes, the contact entry's Etag should be provided in the request header.

    If-Match: Etag
    

    If the Etag is outdated, the server responds with an HTTP 412 Precondition Failed status code.

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

    If a contact does not have a photo, then the photo link element has no gd:etag.

    Upon success, the server responds with an HTTP 200 OK status code.

  • <!-- Request -->
    DELETE /m8/feeds/photos/media/default/contactId
    If-match: Etag
    
    ...
    <!-- Response -->
    HTTP/1.1 OK
    ...
    
    

  • public static void deleteContactPhoto(ContactsService myService, URL contactURL)
        throws ServiceException, IOException {
      ContactEntry contact = myService.getEntry(contactURL, ContactEntry.class);
      Link photoLink = contact.getContactPhotoLink();
      URL photoUrl = new URL(photoLink.getHref());
      try {
        service.delete(photoUrl, photoLink.getEtag());
      } catch (PreconditionFailedException e) {
        // Etags mismatch: handle the exception.
      }
    }
    
    

  • public static void UpdateContactPhoto(ContactsRequest cr, Uri contactURL)
    {
      Contact contact = cr.Retrieve<Contact>(contactURL);
      try
      {
        cr.Delete(contact.PhotoUri, contact.PhotoETag);
      }
      catch (GDataVersionConflictException e)
      {
        // Etags mismatch: handle the exception.
      }
    }
    
    

  • def update_contact_photo(gd_client, contact_url):
      contact = gd_client.GetContact(contact_url)
      try:
        gd_client.DeletePhoto(contact)
      except gdata.client.RequestError, e:
        if e.status == 412:
          # Etags mismatch: handle the exception.
          pass
    

  • ...

    Working with contact groups

    Contact Group Entry

    Contacts can be placed into user-defined groups. You can create, retrieve, update, and delete these groups using the Contacts Data API, and you can add contacts to a group or remove contacts from a group. For details, see the following sections.

    The Contacts Data API also provides access to four predefined "system groups" for each user:

    • My Contacts
    • Friends
    • Family
    • Coworkers

    System groups appear in a groups feed just like user-defined groups do. In fact, system groups are mostly treated just like other groups. The differences are:

    Each system group entry contains a <gContact:systemGroup> subelement. The id attribute of that subelement indicates which system group the group is: Contacts, Friends, Family, or
    Coworkers. Note that the My Contacts ID value is simply
    Contacts, without the "My". Also note that this system group ID value is different from the group ID given in the group entry's
    <id> element.
    You can't add new system groups, change the name of a system group, add extended properties to a system group, or delete a system group. * The contact-group entry representing a system group doesn't contain a rel="edit" link.

    More information about the Contact Group Entry element can be found in the reference guide.

    Retrieving all contact groups

    To retrieve the user's contact groups, send an authorized GET request to the contact groups feed URL:

    https://www.google.com/m8/feeds/groups/{userEmail}/full
    

    With the proper value in place of userEmail.

    Upon success, the server responds with an HTTP 200 OK status code and the user contact groups feed.

  • <!-- Request -->
    GET /m8/feeds/groups/default/full
    ...
    <!-- Response -->
    HTTP/1.1 200 OK
    Content-Type: application/atom+xml; charset=UTF-8; type=entry
    ...
    
    <feed xmlns='http://www.w3.org/2005/Atom'
        xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'
        xmlns:gContact='http://schemas.google.com/contact/2008'
        xmlns:batch='http://schemas.google.com/gdata/batch'
        xmlns:gd='http://schemas.google.com/g/2005'
        gd:etag='feedEtag'>
      <id>jo@gmail.com</id>
      <updated>2008-12-10T10:44:43.955Z</updated>
      <category scheme='http://schemas.google.com/g/2005#kind'
        term='http://schemas.google.com/contact/2008#group'/>
      <title>Jo March's Contact Groups</title>
      <link rel='alternate' type='text/html'
        href='http://www.google.com/'/>
      <link rel='http://schemas.google.com/g/2005#feed'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full'/>
      <link rel='http://schemas.google.com/g/2005#post'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full'/>
      <link rel='http://schemas.google.com/g/2005#batch'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full/batch'/>
      <link rel='self'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full?max-results=25'/>
      <author>
        <name>Jo March</name>
        <email>jo@gmail.com</email>
      </author>
      <generator version='1.0'
        uri='http://www.google.com/m8/feeds'>Contacts</generator>
      <openSearch:totalResults>5</openSearch:totalResults>
      <openSearch:startIndex>1</openSearch:startIndex>
      <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
      <entry>
        <id>http://www.google.com/m8/feeds/groups/userEmail/base/6</id>
        <updated>1970-01-01T00:00:00.000Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#group'/>
        <title>System Group: My Contacts</title>
        <content>System Group: My Contacts</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/6'/>
        <gContact:systemGroup id='Contacts'/>
      </entry>
      [...Other system groups removed for ease of reading...]
      <entry gd:etag='Etag'>
        <id>http://www.google.com/m8/feeds/groups/userEmail/base/groupId</id>
        <updated>2008-12-10T04:44:37.324Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#group'/>
        <title>joggers</title>
        <content>joggers</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
      </entry>
    </feed>
    

  • public static void printAllGroups(ContactsService myService)
        throws ServiceException, IOException {
      // Request the feed
      URL feedUrl = new URL("https://www.google.com/m8/feeds/groups/default/full");
      ContactGroupFeed resultFeed = myService.getFeed(feedUrl, ContactGroupFeed.class);
    
      for (ContactGroupEntry groupEntry : resultFeed.getEntries()) {
        System.out.println("Atom Id: " + groupEntry.getId());
        System.out.println("Group Name: " + groupEntry.getTitle().getPlainText());
        System.out.println("Last Updated: " + groupEntry.getUpdated());
    
        System.out.println("Extended Properties:");
        for (ExtendedProperty property : groupEntry.getExtendedProperties()) {
          if (property.getValue() != null) {
            System.out.println("  " + property.getName() + "(value) = " +
                property.getValue());
           } else if (property.getXmlBlob() != null) {
            System.out.println("  " + property.getName() + "(xmlBlob) = " +
                property.getXmlBlob().getBlob());
          }
        }
        System.out.println("Self Link: " + groupEntry.getSelfLink().getHref());
        if (!groupEntry.hasSystemGroup()) {
          // System groups do not have an edit link
          System.out.println("Edit Link: " + groupEntry.getEditLink().getHref());
          System.out.println("ETag: " + groupEntry.getEtag());
        }
        if (groupEntry.hasSystemGroup()) {
          System.out.println("System Group Id: " +
              groupEntry.getSystemGroup().getId());
        }
      }
    }
    

  • public static void PrintAllGroups(ContactsRequest cr)
    {
      Feed<Group> fg = cr.GetGroups();
    
      foreach (Group group in groups.Entries)
      {
        Console.WriteLine("Atom Id: " + group.Id);
        Console.WriteLine("Group Name: " + group.Title);
        Console.WriteLine("Last Updated: " + group.Updated.ToString());
    
        Console.WriteLine("Extended Properties:");
        foreach (ExtendedProperty property in group.ExtendedProperties)
        {
          Console.WriteLine("  " + property.Name + " = " + property.Value);
        }
        Console.WriteLine("Self Link: " + group.Self);
        if (!string.IsNullOrEmpty(group.SystemGroup))
        {
          // System groups do not have an edit link.
          Console.WriteLine("Edit Link: " + group.GroupEntry.EditUri.Content);
          Console.WriteLine("Etag: " + group.ETag);
        }
        else
        {
          Console.WriteLine("System Group Id: " + group.SystemGroup);
        }
      }
    }
    

  • def PrintAllGroups(gd_client):
      feed = gd_client.GetGroups()
      for entry in feed.entry:
        print 'Atom Id: %s' % group.id.text
        print 'Group Name: %s' % group.title.text
        print 'Last Updated: %s' % group.updated.text
    
        print 'Extended Properties:'
        for extended_property in entry.extended_property:
          if extended_property.value:
            value = extended_property.value
          else:
            value = extended_property.GetXmlBlob()
          print '  %s = %s' % (extended_property.name, value)
        print 'Self Link: %s' % entry.GetSelfLink().href
        if not entry.system_group:
          print 'Edit Link: %s' % entry.GetEditLink().href
          print 'ETag: %s' % entry.etag
        else:
          print 'System Group Id: %s' % entry.system_group.id
    

  • Retrieving contact groups using query parameters

    The Contacts Data API supports query parameters described in the Contacts Data API Reference Guide.

    It allows a user to request a set of contact groups that match specified criteria, such as requesting contact groups updated after a given date. For example, to send a date-range query, add the updated-min parameter to the request URL. To get all the contact-group entries updated after March 16, 2007, send an HTTP request to the contact group's feed URL:

    GET https://www.google.com/m8/feeds/groups/{userEmail}/full?updated-min=2007-03-16T00:00:00
    

    When you send that GET request, the server returns an HTTP 200 OK status code and a feed containing any contact groups that were created or updated after the date specified.

    For the client library examples, the properties corresponding to updated-min are:

    • Java: setUpdatedMin
    • .NET: StartDate
    • Python: updated_min

  • <!-- Request -->
    GET /m8/feeds/groups/default/full
    ...
    <!-- Response -->
    HTTP/1.1 200 OK
    Content-Type: application/atom+xml; charset=UTF-8; type=entry
    ...
    
    <feed xmlns='http://www.w3.org/2005/Atom'
        xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'
        xmlns:gContact='http://schemas.google.com/contact/2008'
        xmlns:batch='http://schemas.google.com/gdata/batch'
        xmlns:gd='http://schemas.google.com/g/2005'
        gd:etag='feedEtag'>
      <id>jo@gmail.com</id>
      <updated>2008-12-10T10:44:43.955Z</updated>
      <category scheme='http://schemas.google.com/g/2005#kind'
        term='http://schemas.google.com/contact/2008#group'/>
      <title>Jo March's Contact Groups</title>
      <link rel='alternate' type='text/html'
        href='http://www.google.com/'/>
      <link rel='http://schemas.google.com/g/2005#feed'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full'/>
      <link rel='http://schemas.google.com/g/2005#post'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full'/>
      <link rel='http://schemas.google.com/g/2005#batch'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full/batch'/>
      <link rel='self'
        type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full?max-results=25'/>
      <author>
        <name>Jo March</name>
        <email>jo@gmail.com</email>
      </author>
      <generator version='1.0'
        uri='http://www.google.com/m8/feeds'>Contacts</generator>
      <openSearch:totalResults>5</openSearch:totalResults>
      <openSearch:startIndex>1</openSearch:startIndex>
      <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
      <entry>
        <id>http://www.google.com/m8/feeds/groups/userEmail/base/6</id>
        <updated>1970-01-01T00:00:00.000Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#group'/>
        <title>System Group: My Contacts</title>
        <content>System Group: My Contacts</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/6'/>
        <gContact:systemGroup id='Contacts'/>
      </entry>
      [...Other system groups removed for ease of reading...]
      <entry gd:etag='Etag'>
        <id>http://www.google.com/m8/feeds/groups/userEmail/base/groupId</id>
        <updated>2008-12-10T04:44:37.324Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#group'/>
        <title>joggers</title>
        <content>joggers</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
      </entry>
    </feed>
    

  • public static void printDateMinQueryResults(
        ContactsService myService, DateTime startTime) throws ServiceException, IOException {
      // Create query and submit a request
      URL feedUrl = new URL("https://www.google.com/m8/feeds/groups/default/full");
      Query myQuery = new Query(feedUrl);
      myQuery.setUpdatedMin(startTime);
      ContactGroupFeed resultFeed = myService.query(myQuery, ContactGroupFeed.class);
    
      // Print the results
      for (ContactGroupEntry entry : resultFeed.getEntries()) {
        System.out.println(entry.getTitle().getPlainText());
        System.out.println("Updated on: " + entry.getUpdated().toStringRfc822());
      }
    }
    

  • public static void PrintDateMinQueryResults(ContactsRequest cr, DateTime startTime)
    {
      GroupsQuery query = new GroupsQuery(GroupsQuery.CreateGroupUri("default"));
      query.StartDate = startTime;
      Feed<Group> feed = cr.Get(query);
    
      foreach (Group group in feed.Entries)
      {
        Console.WriteLine(group.Title);
        Console.WriteLine("Updated on: " + group.Updated.ToString());
      }
    }
    

  • def print_date_min_query_results(gd_client, start_time):
      query = gdata.service.Query(feed='/m8/feeds/groups/default/full')
      query.updated_min = start_time
      feed = gd_client.GetGroups(q=query)
    
      for entry in feed.entry:
        print entry.title.text
        print 'Updated on: %s' % entry.updated.text
    

  • Retrieving a single contact group

    To retrieve a single group, send an authorized HTTP GET request to the contact group's edit URL.

    The URL is of the form:

    https://www.google.com/m8/feeds/{userEmail}/full/{groupID}
    

    With the proper values in place of userEmail and groupID.

    Upon success, the server responds with an HTTP 200 OK status code and the requested group entry.

  • <!-- Request -->
    GET /m8/feeds/groups/default/full/groupID
    ...
    <!-- Response -->
    HTTP/1.1 200 OK
    Content-Type: application/atom+xml; charset=UTF-8; type=entry
    ...
    
    <entry xmlns='http://www.w3.org/2005/Atom'
        gd:etag='ETAG'>
      <id>http://www.google.com/m8/feeds/groups/userEmail/base/groupID</id>
      <updated>2008-12-10T04:44:37.324Z</updated>
      <category scheme='http://schemas.google.com/g/2005#kind'
        term='http://schemas.google.com/contact/2008#group'/>
      <title>joggers</title>
      <content>joggers</content>
      <link rel='self' type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full/groupID'/>
      <link rel='edit' type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full/groupID'/>
    </entry>
    

  • public static ContactGroupEntry retrieveContactGroup(ContactsService myService)
        throws ServiceException, IOException {
      ContactGroupEntry group =
          myService.getEntry(new URL("https://www.google.com/m8/feeds/groups/default/full/groupId"),
              ContactGroupEntry.class);
    
      // Do something with the contact group.
      return group;
    }
    

  • public static Group retrieveContactGroup(ContactsRequest cr)
    {
      Group group = cr.Retrieve<Group>("https://www.google.com/m8/feeds/groups/default/full/groupId");
    
      // Do something with the contact group.
      return group;
    }
    

  • def retrieve_contact_group(gd_client):
      group = gd_client.GetGroup('https://www.google.com/m8/feeds/groups/default/full/groupId')
    
      # Do something with the contact group.
      return group
    

  • Creating contact groups

    To create a new contact group, send an authorized POST request to the contact groups feed URL with the contact group entry data in the body:

    https://www.google.com/m8/feeds/groups/{userEmail}/full
    

    With the appropriate value in place of userEmail.

    Upon success, the server responds with an HTTP 201 Created status code and the newly created contact group with some additional elements and properties (shown in bold) such as id, various link elements and properties.

  • <!-- Request -->
    POST /m8/feeds/groups/default/full
    ...
    
    <atom:entry xmlns:gd="http://schemas.google.com/g/2005">
      <atom:category scheme="http://schemas.google.com/g/2005#kind"
        term="http://schemas.google.com/contact/2008#group"/>
      <atom:title type="text">Salsa group</atom:title>
      <gd:extendedProperty name="more info about the group">
        <info>Nice people.</info>
      </gd:extendedProperty>
    </atom:entry>
    ...
    <!-- Response -->
    HTTP/1.1 201 Created
    Content-Type: application/atom+xml; charset=UTF-8; type=entry
    ...
    
    <entry xmlns='http://www.w3.org/2005/Atom'
        gd:etag='ETAG'>
      <id>http://www.google.com/m8/feeds/groups/userEmail/base/groupID</id>
      <updated>2008-12-10T04:44:37.324Z</updated>
      <category scheme='http://schemas.google.com/g/2005#kind'
        term='http://schemas.google.com/contact/2008#group'/>
      <atom:title type="text">Salsa group</atom:title>
      <gd:extendedProperty name="more info about the group">
        <info>Nice people.</info>
      </gd:extendedProperty>
      <link rel='self' type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full/groupID'/>
      <link rel='edit' type='application/atom+xml'
        href='https://www.google.com/m8/feeds/groups/userEmail/full/groupID'/>
    </entry>
    

  • public static ContactGroupEntry createContactGroup(ContactsService service)
        throws ServiceException, IOException {
      // Create the entry to insert
      ContactGroupEntry newGroup = new ContactGroupEntry();
      newGroup.setTitle(new PlainTextConstruct("Salsa group"));
    
      ExtendedProperty additionalInfo = new ExtendedProperty();
      additionalInfo.setName("more info about the group");
      additionalInfo.setValue("Nice people.");
      newGroup.addExtendedProperty(additionalInfo);
    
      // Ask the service to insert the new entry
      URL postUrl = new URL("https://www.google.com/m8/feeds/groups/default/full");
      ContactGroupEntry createdGroup = service.insert(postUrl, newGroup);
    
      System.out.println("Contact group's Atom Id: " + group.getId());
      return createdGroup;
    }
    

  • public static Group createContactGroup(ContactsRequest cr)
    {
      Group newGroup = new Group();
      newGroup.Title = "Salsa group";
    
      newGroup.ExtendedProperties.Add(new ExtendedProperty()
          {
            Name = "more info about the group",
            Value = "Nice people.",
          });
      Group createdGroup = cr.Insert(new Uri("https://www.google.com/m8/feeds/groups/default/full"),
          newGroup);
    
      Console.WriteLine("Contact group's Atom Id: " + createdGroup.Id);
      return createdGroup;
    }
    

  • def create_contact_group(gd_client):
      new_group = gdata.contacts.data.GroupEntry(title=atom.data.Title(text='Salsa group'))
      new_group.extended_properties.append(
          gdata.data.ExtendedProperty(name='more info about the group', value='Nice people.'))
    
      created_group = gd_client.CreateGroup(new_group)
      print "Contact group's Atom Id: %s" % created_group.id.text
      return created_group
    

  • Updating contact groups

    To update a contact group, first retrieve the group entry, modify the data and send an authorized PUT request to the contact group's edit URL with the updated contact group's entry in the body.

    The URL is of the form:

    https://www.google.com/m8/feeds/groups/{userEmail}/full/{groupID}
    

    With the appropriate values in place of userEmail and groupID.

    To ensure that the data sent to the API doesn't overwrite another client's changes, the contact entry's Etag should be provided in the request header.

    If-Match: Etag
    

    If the Etag is outdated, the server responds with an HTTP 412 Precondition Failed status code.

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

    Upon success, the server responds with an HTTP 200 OK status code and the updated contact group entry.

  • <!-- Request -->
     POST /m8/feeds/groups/default/full/groupID
      If-Match: Etag
      ...
      
      <entry xmlns:gd="http://schemas.google.com/g/2005"
          gd:etag="Etag">
        <category scheme="http://schemas.google.com/g/2005#kind"
          term="http://schemas.google.com/g/2005#group"/>
        <id>http://www.google.com/feeds/groups/userEmail/base/groupId</id>
        <published>2005-01-18T21:00:00Z</published>
        <updated>2006-01-01T00:00:00Z</updated>
        <title type="text">Salsa friends</title>
        <content type="text">Friends from Salsa class</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
        <gd:extendedProperty name="more info about the group">
          <info>Very nice people.</info>
        </gd:extendedProperty>
      </entry>
    ...
    <!-- Response -->
      HTTP/1.1 200 OK
      Content-Type: application/atom+xml; charset=UTF-8; type=entry
      ...
      
      <entry xmlns:gd="http://schemas.google.com/g/2005"
          gd:etag="newEtag">
        <category scheme="http://schemas.google.com/g/2005#kind"
          term="http://schemas.google.com/g/2005#group"/>
        <id>http://www.google.com/feeds/groups/userEmail/base/groupId</id>
        <published>2005-01-18T21:00:00Z</published>
        <updated>2011-05-11T00:00:00Z</updated>
        <title type="text">Salsa friends</title>
        <content type="text">Friends from Salsa class</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/groupId'/>
        <gd:extendedProperty name="more info about the group">
          <info>Very nice people.</info>
        </gd:extendedProperty>
      </entry>
    

  • public static ContactGroupEntry updateContactGrpup(ContactsService myService, URL contactGroupURL)
        throws ServiceException, IOException {
      ContactGroupEntry group = myService.getEntry(contactGroupURL, ContactGroupEntry.class);
    
      group.setTitle(new PlainTextConstruct("Salsa Friends"));
      group.setContent(new PlainTextconstruct("Friends from Salsa class"));
      URL editUrl = new URL(entryToUpdate.getEditLink().getHref());
    
      try {
        ContactGroupEntry updatedGroup = myService.update(editUrl, entryToUpdate);
        System.out.println("Updated: " + updatedGroup.getUpdated().toString());
        return updatedGroup;
      } catch (PreconditionFailedException e) {
        // Etags mismatch: handle the exception.
      }
      return null;
    }
    

  • public static Group UpdateContactGroup(ContactsRequest cr, Uri contactGroupUrl)
    {
      Group group = cr.Retrieve<Group>(contactGroupUri);
    
      group.Title = "Salsa Friends";
      group.Content = "Friends from Salsa class";
    
      try
      {
        Group updatedGroup = cr.Update(group);
        Console.WriteLine("Updated: " + updatedGroup.Updated.ToString());
        return updatedGroup;
      }
      catch (GDataVersionConflictException e)
      {
        // Etags mismatch: handle the exception.
      }
      return null;
    }
    

  • def create_contact_group(gd_client):
      new_group = gdata.contacts.data.GroupEntry(title=atom.data.Title(text='Salsa group'))
      new_group.extended_properties.append(
          gdata.data.ExtendedProperty(name='more info about the group', value='Nice people.'))
    
      created_group = gd_client.CreateGroup(new_group)
      print "Contact group's Atom Id: %s" % created_group.id.text
      return created_group
    

  • Deleting contact groups

    To delete a contact group, send an authorized DELETE request to the contact group's edit URL.

    The URL is of the form:

    https://www.google.com/m8/feeds/groups/{userEmail}/full/{groupID}
    

    With the appropriate values in place of userEmail and groupID.

    To ensure that the data sent to the API doesn't overwrite another client's changes, the contact entry's Etag should be provided in the request header.

    If-Match: Etag
    

    If the Etag is outdated, the server responds with an HTTP 412 Precondition Failed status code.

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

    Upon success, the server responds with an HTTP 200 OK status code.

  • <!-- Request -->
    DELETE /m8/feeds/groups/default/full/groupID
    If-Match: Etag
    ...
    <!-- Response -->
    HTTP/1.1 200 OK
    ...
    
    

  • public static void deleteContactGroup(ContactsService myService, URL contactGroupURL)
        throws ServiceException, IOException {
      // Retrieving the contact group is required in order to get the Etag.
      ContactGroupEntry group = myService.getEntry(contactGroupURL, ContactGroupEntry.class);
    
      try {
        group.delete();
      } catch (PreconditionFailedException e) {
        // Etags mismatch: handle the exception.
      }
    }
    

  • public static void DeleteContactGroup(ContactsRequest cr, Uri contactGroupURL)
    {
      // Retrieving the contact group is required in order to get the Etag.
      Group group = cr.Retrieve<Group>(contactGroupURL);
    
      try
      {
        cr.Delete(group);
      }
      catch (GDataVersionConflictException e)
      {
        // Etags mismatch: handle the exception.
      }
    }
    
    

  • def delete_contact_group(gd_client, contact_group_url):
      # Retrieving the contact group is required in order to get the Etag.
      group = gd_client.GetGroup(contact_group_url)
    
      try:
        gd_client.Delete(group)
      except gdata.client.RequestError, e:
        if e.status == 412:
          # Etags mismatch: handle the exception.
          pass
    

  • Batch operations

    If you're performing a lot of operations, the time it takes to send and and receive all those HTTP messages can really add up, making your app slow and unresponsive. With batch requests you can have the server perform multiple operations with a single HTTP request. The basic idea is that you create a contacts or contact groups feed and add an entry for each operation you want to perform.

    Batch requests are limited to 100 operations at a time. You can find more information about batch operations in the Google Data APIs Batch Processing documentation.

    Batch operations for Contacts

    To send a batch request for operations on contacts, send an authorized POST request to the contacts batch feed URL with the batch feed data in the body:

    https://www.google.com/m8/feeds/contacts/{userEmail}/full/batch
    

    With the appropriate value in place userEmail.

    Upon success, the server responds with an HTTP 200 OK status code and the batch feed containing each single operation's status code.

  • <!-- Request -->
    POST /m8/feeds/contacts/default/private/full/batch
    ...
    
    <?xml version='1.0' encoding='UTF-8'?>
    <feed xmlns='http://www.w3.org/2005/Atom'
          xmlns:gContact='http://schemas.google.com/contact/2008'
          xmlns:gd='http://schemas.google.com/g/2005'
          xmlns:batch='http://schemas.google.com/gdata/batch'>
      <entry>
        <batch:id>retrieve</batch:id>
        <batch:operation type='query'/>
        <id>https://www.google.com/m8/feeds/contacts/default/full/retrieveContactId</id>
      </entry>
      <entry>
        <batch:id>create</batch:id>
        <batch:operation type='insert'/>
        <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2008#contact'/>
        <gd:name>
          <gd:fullName>Elizabeth Bennet</gd:fullName>
          <gd:givenName>Elizabeth</gd:givenName>
          <gd:familyName>Bennet</gd:familyName>
        </gd:name>
        <gd:email rel='http://schemas.google.com/g/2005#home' address='liz@gmail.com' primary='true'/>
      </entry>
      <entry gd:etag='updateContactEtag'>
        <batch:id>update</batch:id>
        <batch:operation type='update'/>
        <id>http://www.google.com/m8/feeds/contacts/userEmail/base/updateContactId</id>
        <updated>2008-02-28T18:47:02.303Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#contact'/>
        <gd:name>
          <gd:givenName>New</gd:givenName>
          <gd:familyName>Name</gd:familyName>
          <gd:fullName>New Name</gd:fullName>
        </gd:name>
        <content type='text'>Notes</content>
        <link rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/*'
          href='https://www.google.com/m8/feeds/photos/media/userEmail/updateContactId'/>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/updateContactId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/updateContactId'/>
        <gd:phoneNumber rel='http://schemas.google.com/g/2005#other'
          primary='true'>456-123-2133</gd:phoneNumber>
        <gd:extendedProperty name='pet' value='hamster'/>
        <gContact:groupMembershipInfo deleted='false'
          href='http://www.google.com/m8/feeds/groups/userEmail/base/groupId'/>
      </entry>
      <entry gd:etag='deleteContactEtag'>
        <batch:id>delete</batch:id>
        <batch:operation type='delete'/>
        <id>https://www.google.com/m8/feeds/contacts/default/full/deleteContactId</id>
      </entry>
    </feed>
    <!-- Response -->
    HTTP/1.1 200 OK
    Content-Type: application/atom+xml;
    ...
    
    <?xml version='1.0' encoding='UTF-8'?>
    <feed xmlns='http://www.w3.org/2005/Atom'
          xmlns:gContact='http://schemas.google.com/contact/2008'
          xmlns:gd='http://schemas.google.com/g/2005'
          xmlns:batch='http://schemas.google.com/gdata/batch'>
      <entry gd:etag='retrieveContactEtag'>
        <batch:id>retrieve</batch:id>
        <batch:operation type='query'/>
        <batch:status code='200' reason='Success'/>
        <id>
          http://www.google.com/m8/feeds/contacts/userEmail/base/retrieveContactId
        </id>
        <updated>2008-12-10T04:45:03.331Z</updated>
        <app:edited xmlns:app='http://www.w3.org/2007/app'>2008-12-10T04:45:03.331Z</app:edited>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#contact'/>
        <title>Fitzwilliam Darcy</title>
        <gd:name>
          <gd:fullName>Fitzwilliam Darcy</gd:fullName>
        </gd:name>
        <link rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/*'
          href='https://www.google.com/m8/feeds/photos/media/userEmail/retrieveContactId'
          gd:etag='photoEtag'/>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/retrieveContactId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/retrieveContactId'/>
        <gd:phoneNumber rel='http://schemas.google.com/g/2005#home'
          primary='true'>
          456
        </gd:phoneNumber>
        <gd:extendedProperty name='pet' value='hamster'/>
        <gContact:groupMembershipInfo deleted='false'
          href='http://www.google.com/m8/feeds/groups/userEmail/base/groupId'/>
      </entry>
      <entry gd:etag='createContactEtag'>
        <batch:id>create</batch:id>
        <batch:operation type='insert'/>
        <batch:status code='201' reason='Created'/>
        <id>http://www.google.com/m8/feeds/contacts/userEmail/base/createContactId</id>
        <updated>2008-12-10T04:45:03.331Z</updated>
        <app:edited xmlns:app='http://www.w3.org/2007/app'>2008-12-10T04:45:03.331Z</app:edited>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#contact'/>
        <title>Elizabeth Bennet</title>
        <gd:name>
           <gd:givenName>Elizabeth</gd:givenName>
           <gd:familyName>Bennet</gd:familyName>
           <gd:fullName>Elizabeth Bennet</gd:fullName>
        </gd:name>
        <link rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/*'
          href='https://www.google.com/m8/feeds/photos/media/userEmail/createContactId'/>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/createContactId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/createContactId'/>
        <gd:email rel='http://schemas.google.com/g/2005#work' primary='true' address='liz@gmail.com'/>
      </entry>
      <entry gd:etag='newUpdateContactEtag'>
        <batch:id>update</batch:id>
        <batch:operation type='update'/>
        <batch:status code='200' reason='Success'/>
        <updated>2011-05-11T09:30:00.000Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#contact'/>
        <title type='text'>New Name</title>
        <gd:name>
          <gd:givenName>New</gd:givenName>
          <gd:familyName>Name</gd:familyName>
          <gd:fullName>New Name</gd:fullName>
        </gd:name>
        <content type='text'>Notes</content>
        <link rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/*'
          href='https://www.google.com/m8/feeds/photos/media/userEmail/updateContactId'/>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/updateContactId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/contacts/userEmail/full/updateContactId'/>
        <gd:phoneNumber rel='http://schemas.google.com/g/2005#other'
          primary='true'>456-123-2133</gd:phoneNumber>
        <gd:extendedProperty name='pet' value='hamster'/>
        <gContact:groupMembershipInfo deleted='false'
          href='http://www.google.com/m8/feeds/groups/userEmail/base/groupId'/>
      </entry>
      <entry>
        <batch:id>delete</batch:id>
        <batch:operation type='delete'/>
        <batch:status code='200' reason='Success'/>
        <updated>2011-05-11T09:30:00.000Z</updated>
        <content type='text'>Deleted</content>
        <id>https://www.google.com/m8/feeds/contacts/default/full/deleteContactId</id>
      </entry>
    </feed>
    
    

  • public static ContactFeed executeBatchRequest(ContactsService myService)
        throws ServiceException, IOException {
      // Feed that holds all the batch request entries.
      ContactFeed requestFeed = new ContactFeed();
    
      // Create a ContactEntry for the retrieve request.
      ContactEntry retrieveContact = new ContactEntry();
      retreiveContact.setId("https://www.google.com/m8/feeds/contacts/default/private/full/retrieveContactId");
      BatchUtils.setBatchId(retrieveContact, "retrieve");
      BatchUtils.setBatchOperationType(retrieveContact, BatchOperationType.QUERY);
    
      // Create a ContactEntry for the create request.
      ContactEntry createContact = new ContactEntry();
      final String NO_YOMI = null;
      Name contactTwoName = new Name();
      name.setFullName(new FullName("Elizabeth Bennet", NO_YOMI));
      name.setGivenName(new GivenName("Elizabeth", NO_YOMI));
      name.setFamilyName(new FamilyName("Bennet", NO_YOMI))
      createContact.setName(name);
    
      Email primaryMail = new Email();
      primaryMail.setAddress("liz@gmail.com");
      primaryMail.setRel("http://schemas.google.com/g/2005#home");
      primaryMail.setPrimary(true);
      createContact.addEmailAddress(primaryMail);
    
      BatchUtils.setBatchId(createContact, "create");
      BatchUtils.setBatchOperationType(createContact, BatchOperationType.INSERT);
    
      // Retrieve the ContactEntry to update.
      ContactEntry updateContact =
          myService.getEntry(new URL("https://www.google.com/m8/feeds/contacts/default/full/updateContactId"),
              ContactEntry.class);
      updateContact.getName().getFullName().setValue("New Name");
      updateContact.getName().getGivenName().setValue("New");
      updateContact.getName().getFamilyName().setValue("Name");
      BatchUtils.setBatchId(updateContact, "update");
      BatchUtils.setBatchOperationType(updateContact, BatchOperationType.UPDATE);
    
      // Retrieve the ContactEntry to delete.
      ContactEntry deleteContact =
          myService.getEntry(new URL("https://www.google.com/m8/feeds/contacts/default/full/deleteContactId"),
              ContactEntry.class);
      BatchUtils.setBatchId(deleteContact, "delete");
      BatchUtils.setBatchOperationType(deleteContact, BatchOperationType.DELETE);
    
      // Insert the entries to the batch feed.
      requestFeed.getEntries().add(retrieveContact);
      requestFeed.getEntries().add(createContact);
      requestFeed.getEntries().add(updateContact);
      requestFeed.getEntries().add(deleteContact);
    
      // Submit the batch request to the server.
      ContactFeed responseFeed =
          myService.batch(new URL("https://www.google.com/m8/feeds/contacts/default/full/batch"),
              requestFeed);
    
      // Check the status of each operation.
      for (ContactEntry entry : responseFeed.getEntries()) {
        String batchId = BatchUtils.getBatchId(entry);
        BatchStatus status = BatchUtils.getBatchStatus(entry);
        System.out.println(batchId + ": " + status.getCode() + " (" + status.getReason() + ")");
      }
      return responseFeed;
    }
    

  • public static Feed<Contact> ExecuteBatchRequest(ContactsRequest cr)
    {
      // List that holds the batch request entries.
      List<Contact> requestFeed = new List<Contact>();
    
      // Create a Contact entry for the retrieve request.
      Contact retrieveContact = new Contact();
      retrieveContact.Id = "https://www.google.com/m8/feeds/contacts/default/private/full/retrieveContactId";
      retrieveContact.BatchData = new GDataBatchEntryData("retrieve", GDataBatchOperationType.query);
    
      // Create a Contact entry for the create request.
      Contact createContact = new Contact();
      createContact.Name = new Name()
          {
            FullName = "Elizabeth Bennet",
            GivenName = "Elizabeth",
            FamilyName = "Bennet",
          };
      createContact.Emails.Add(new EMail()
          {
            Address = "liz@gmail.com",
            Rel = ContactsRelationships.IsHome,
            Primary = true,
          });
      createContact.BatchData = new GDataBatchEntryData("create", GDataBatchOperationType.insert);
    
      // Retrieve the Contact entry to update.
      Contact updateContact = cr.Retrieve<Contact>(
          new Uri("https://www.google.com/m8/feeds/contacts/default/full/updateContactId"));
      updateContact.Name.FullName = "New Name";
      updateContact.Name.GivenName = "New";
      updateContact.Name.FamilyName = "Name";
      updateContact.BatchData = new GDataBatchEntryData("update", GDataBatchOperationType.update);
    
      // Retrieve the Contact entry to delete.
      Contact deleteContact = cr.Retrieve<Contact>(
          new Uri("https://www.google.com/m8/feeds/contacts/default/full/deleteContactId"));
      deleteContact.BatchData = new GDataBatchEntryData("delete", GDataBatchOperationType.delete);
    
      // Insert the entries to the batch feed.
      requestFeed.Add(retrieveContact);
      requestFeed.Add(createContact);
      requestFeed.Add(updateContact);
      requestFeed.Add(deleteContact);
    
      // Submit the batch request to the server.
      Feed<Contact> responseFeed = cr.Batch(requestFeed, new Uri("https://www.google.com/m8/feeds/contacts/default/full/batch"),
          GDataBatchOperationType.Default);
    
      // Check the status of each operation.
      foreach (Contact entry in responseFeed.Entries)
      {
        Console.WriteLine(entry.BatchData.Id + ": " + entry.BatchData.Status.Code + " (" + entry.BatchData.Status.Reason + ")");
      }
      return responseFeed;
    }
    

  • def execute_batch_request(gd_client):
      # Feed that holds the batch request entries.
      request_feed = gdata.contacts.data.ContactsFeed()
    
      # Create a ContactEntry for the retrieve request.
      retrieve_contact = gdata.contacts.data.ContactEntry()
      retrieve_contact.id = atom.data.Id(
          text='https://www.google.com/m8/feeds/contacts/default/private/full/retrieveContactId')
    
      # Create a ContactEntry for the create request.
      create_contact = gdata.contacts.data.ContactEntry()
      create_contact.name = gdata.data.Name(
          full_name=gdata.data.FullName(text='Elizabeth Bennet'),
          given_name=gdata.data.GivenName(text='Elizabeth'),
          family_name=gdata.data.FamilyName(text='Bennet'))
      create_contact.email.append(gdata.data.Email(address='liz@gmail.com',
          primary='true', rel=gdata.data.HOME_REL))
    
      # Retrieve the ContactEntry to update.
      update_contact = gd_client.GetContact('https://www.google.com/m8/feeds/contacts/default/full/updateContactId')
      update_contact.name.full_name = 'New Name'
      update_contact.name.given_name = 'New'
      update_contact.name.family_name = 'Name'
    
      # Retrieve the ContactEntry to delete.
      delete_contact = gd_client.GetContact('https://www.google.com/m8/feeds/contacts/default/full/deleteContactId')
    
      # Insert the entries to the batch feed.
      request_feed.AddQuery(entry=retrieve_contact, batch_id_string='retrieve')
      request_feed.AddInsert(entry=create_contact, batch_id_string='create')
      request_feed.AddUpdate(entry=update_contact, batch_id_string='update')
      request_feed.AddDelete(entry=delete_contact, batch_id_string='delete')
    
      # submit the batch request to the server.
      response_feed = gd_client.ExecuteBatch(request_feed,
          'https://www.google.com/m8/feeds/contacts/default/full/batch')
    
      for entry in response_feed.entry:
        print '%s: %s (%s)' % (entry.batch_id.text, entry.batch_status.code, entry.batch_status.reason)
    
      return response_feed
    

  • Batch operations for Contact Groups

    To send a batch request for operations on contact groups, send an authorized POST request to the contact groups batch feed URL with the batch feed data in the body:

    https://www.google.com/m8/feeds/groups/{userEmail}/full/batch
    

    With the appropriate value in place userEmail.

    Upon success, the server responds with an HTTP 200 OK status code and the batch feed containing each single operation's status code.

  • <!-- Request -->
    POST /m8/feeds/groups/default/private/full/batch
    ...
    
    <?xml version='1.0' encoding='UTF-8'?>
    <feed xmlns='http://www.w3.org/2005/Atom'
          xmlns:gContact='http://schemas.google.com/contact/2008'
          xmlns:gd='http://schemas.google.com/g/2005'
          xmlns:batch='http://schemas.google.com/gdata/batch'>
      <entry>
        <batch:id>retrieve</batch:id>
        <batch:operation type='query'/>
        <id>https://www.google.com/m8/feeds/groups/default/full/retrieveContactGroupId</id>
      </entry>
      <entry>
        <batch:id>create</batch:id>
        <batch:operation type='insert'/>
        <atom:category scheme="http://schemas.google.com/g/2005#kind"
          term="http://schemas.google.com/contact/2008#group"/>
        <atom:title type="text">Salsa group</atom:title>
        <gd:extendedProperty name="more info about the group">
          <info>Nice people.</info>
      </entry>
      <entry gd:etag='updateContactGroupEtag'>
        <batch:id>update</batch:id>
        <batch:operation type='update'/>
        <category scheme="http://schemas.google.com/g/2005#kind"
          term="http://schemas.google.com/g/2005#group"/>
        <id>http://www.google.com/feeds/groups/userEmail/base/updateContactGroupId</id>
        <published>2005-01-18T21:00:00Z</published>
        <updated>2006-01-01T00:00:00Z</updated>
        <title type="text">New Group Title</title>
        <content type="text">New Group Content</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/updateContactGroupId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/updateContactGroupId'/>
      </entry>
      <entry gd:etag='deleteContactGroupEtag'>
        <batch:id>delete</batch:id>
        <batch:operation type='delete'/>
        <id>https://www.google.com/m8/feeds/groups/default/full/deleteContactGroupId</id>
      </entry>
    </feed>
    <!-- Response -->
    HTTP/1.1 200 OK
    Content-Type: application/atom+xml;
    ...
    
    <?xml version='1.0' encoding='UTF-8'?>
    <feed xmlns='http://www.w3.org/2005/Atom'
          xmlns:gContact='http://schemas.google.com/contact/2008'
          xmlns:gd='http://schemas.google.com/g/2005'
          xmlns:batch='http://schemas.google.com/gdata/batch'>
      <entry gd:etag='retrieveContactGroupEtag'>
        <batch:id>retrieve</batch:id>
        <batch:operation type='query'/>
        <batch:status code='200' reason='Success'/>
        <id>http://www.google.com/m8/feeds/groups/userEmail/base/retrieveContactGroupId</id>
        <updated>2008-12-10T04:44:37.324Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#group'/>
        <title>joggers</title>
        <content>joggers</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/retrieveContactGroupId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/retrieveContactGroupId'/>
      </entry>
      <entry gd:etag='createContactGroupEtag'>
        <batch:id>create</batch:id>
        <batch:operation type='insert'/>
        <batch:status code='201' reason='Created'/>
        <id>http://www.google.com/m8/feeds/groups/userEmail/base/createContactGroupID</id>
        <updated>2008-12-10T04:44:37.324Z</updated>
        <category scheme='http://schemas.google.com/g/2005#kind'
          term='http://schemas.google.com/contact/2008#group'/>
        <atom:title type="text">Salsa group</atom:title>
        <gd:extendedProperty name="more info about the group">
          <info>Nice people.</info>
        </gd:extendedProperty>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/createContactGroupID'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/createContactGroupID'/>
      </entry>
      <entry gd:etag='newUpdateContactGroupEtag'>
        <batch:id>update</batch:id>
        <batch:operation type='update'/>
        <batch:status code='200' reason='Success'/>
        <category scheme="http://schemas.google.com/g/2005#kind"
          term="http://schemas.google.com/g/2005#group"/>
        <id>http://www.google.com/feeds/groups/userEmail/base/updateContactGroupId</id>
        <published>2005-01-18T21:00:00Z</published>
        <updated>2011-05-11T00:00:00Z</updated>
        <title type="text">New Group Title</title>
        <content type="text">New Group Content</content>
        <link rel='self' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/updateContactGroupId'/>
        <link rel='edit' type='application/atom+xml'
          href='https://www.google.com/m8/feeds/groups/userEmail/full/updateContactGroupId'/>
      </entry>
      <entry>
        <batch:id>delete</batch:id>
        <batch:operation type='delete'/>
        <batch:status code='200' reason='Success'/>
        <updated>2011-05-11T09:30:00.000Z</updated>
        <content type='text'>Deleted</content>
        <id>https://www.google.com/m8/feeds/groups/default/full/deleteContactGroupId</id>
      </entry>
    </feed>
    

  • public static ContactGroupFeed executeGroupBatchRequest(ContactsService myService)
        throws ServiceException, IOException {
      // Feed that holds all the batch request entries.
      ContactGroupFeed requestFeed = new ContactGroupFeed();
    
      // Create a ContactEntry for the retrieve request.
      ContactGroupEntry retrieveContactGroup = new ContactGroupEntry();
      retrieveContactGroup.setId("https://www.google.com/m8/feeds/contacts/default/private/full/retrieveContactId");
      BatchUtils.setBatchId(retrieveContactGroup, "retrieve");
      BatchUtils.setBatchOperationType(retrieveContactGroup, BatchOperationType.QUERY);
    
      // Create a ContactGroupEntry for the create request.
      ContactGroupEntry createContactGroup = new ContactGroupEntry();
      createContactGroup.setTitle(new PlainTextConstruct("Salsa group"));
    
      ExtendedProperty additionalInfo = new ExtendedProperty();
      additionalInfo.setName("more info about the group");
      additionalInfo.setValue("Nice people.");
      createContactGroup.addExtendedProperty(additionalInfo);
      BatchUtils.setBatchId(createContactGroup, "create");
      BatchUtils.setBatchOperationType(createContactGroup, BatchOperationType.INSERT);
    
      // Retrieve the ContactGroupEntry to update.
      ContactGroupEntry updateContactGroup =
          myService.getEntry(new URL("https://www.google.com/m8/feeds/groups/default/full/updateContactGroupId"),
                             ContactGroupEntry.class);
      updateContactGroup.setTitle(new PlainTextConstruct("New Group Title"));
      updateContactGroup.setContent(new PlainTextConstruct("New Group Content"));
      BatchUtils.setBatchId(updateContactGroup, "update");
      BatchUtils.setBatchOperationType(updateContactGroup, BatchOperationType.UPDATE);
    
      // Retrieve the ContactGroupEntry to delete.
      ContactGroupEntry deleteContactGroup =
          myService.getEntry(new URL("https://www.google.com/m8/feeds/groups/default/full/deleteContactGroupId"),
                             ContactGroupEntry.class);
      BatchUtils.setBatchId(deleteContactGroup, "delete");
      BatchUtils.setBatchOperationType(deleteContactGroup, BatchOperationType.DELETE);
    
      // Insert the entries to the batch feed.
      requestFeed.getEntries().add(retrieveContactGroup);
      requestFeed.getEntries().add(createContactGroup);
      requestFeed.getEntries().add(updateContactGroup);
      requestFeed.getEntries().add(deleteContactGroup);
    
      // Submit the batch request to the server.
      ContactGroupFeed responseFeed =
          myService.batch(new URL("https://www.google.com/m8/feeds/groups/default/full/batch"),
                          requestFeed);
    
      // Check the status of each operation.
      for (ContactGroupEntry entry : responseFeed.getEntries()) {
        String batchId = BatchUtils.getBatchId(entry);
        BatchStatus status = BatchUtils.getBatchStatus(entry);
        System.out.println(batchId + ": " + status.getCode() + " (" + status.getReason() + ")");
      }
      return responseFeed;
    }
    
    

  • ublic static Feed<ContactGroup> ExecuteGroupBatchRequest(ContactGroupsRequest cr)
    {
      // List that holds the batch request entries.
      List<Group> requestFeed = new List<Group>();
    
      // Create a Group entry for the retrieve request.
      Group retrieveContactGroup = new Group();
      retrieveContactGroup.Id = "https://www.google.com/m8/feeds/groups/default/private/full/retrieveContactGroupId";
      retrieveContactGroup.BatchData = new GDataBatchEntryData("retrieve", GDataBatchOperationType.query);
    
      // Create a Group entry for the create request.
      Group createContactGroup = new Group();
      createContactGroup.Title = "Salsa group";
      createContactGroup.ExtendedProperties.Add(new ExtendedProperty()
          {
            Name = "more info about the group",
            Value = "Nice people.",
          });
      createContactGroup.BatchData = new GDataBatchEntryData("create", GDataBatchOperationType.insert);
    
      // Retrieve the Group entry to update.
      Group updateContactGroup = cr.Retrieve<Group>(
          new Uri("https://www.google.com/m8/feeds/groups/default/full/updateContactGroupId"));
      updateContactGroup.Title = "New Group Title";
      updateContactGroup.Content = "New Group Content";
      updateContactGroup.BatchData = new GDataBatchEntryData("update", GDataBatchOperationType.update);
    
      // Retrieve the Group entry to delete.
      Group deleteContactGroup = cr.Retrieve<Group>(
          new Uri("https://www.google.com/m8/feeds/groups/default/full/deleteContactGroupId"));
      deleteContactGroup.BatchData = new GDataBatchEntryData("delete", GDataBatchOperationType.delete);
    
      // Insert the entries to the batch feed.
      requestFeed.Add(retrieveContactGroup);
      requestFeed.Add(createContactGroup);
      requestFeed.Add(updateContactGroup);
      requestFeed.Add(deleteContactGroup);
    
      // Submit the batch request to the server.
      Feed<Group> responseFeed = cr.Batch(requestFeed, new Uri("https://www.google.com/m8/feeds/groups/default/full/batch"),
                                                  GDataBatchOperationType.Default);
    
      // Check the status of each operation.
      foreach (Group entry in responseFeed.Entries)
      {
        Console.WriteLine(entry.BatchData.Id + ": " + entry.BatchData.Status.Code + " (" + entry.BatchData.Status.Reason + ")");
      }
      return responseFeed;
    }
    
    

  • def execute_batch_request(gd_client):
      # Feed that holds the batch request entries.
      request_feed = gdata.contacts.data.GroupsFeed()
    
      # Create a GroupEntry for the retrieve request.
      retrieve_group = gdata.contacts.data.GroupEntry()
      retrieve_group.id = atom.data.Id(
          text='https://www.google.com/m8/feeds/groups/default/private/full/retrieveContactGroupId')
    
      # Create a GroupEntry for the create request.
      create_group = gdata.contacts.data.GroupEntry()
      create_group.title = atom.data.Title(text='Salsa group')
      create_group.extended_property.append(gdata.data.ExtendedProperty(name='more info about the group', value='Nice people')
    
      # Retrieve the GroupEntry to update.
      update_group = gd_client.GetGroup('https://www.google.com/m8/feeds/groups/default/full/updateContactGroupId')
      update_group.title.text = 'New Group Title'
      update_group.content.text = 'New Group Content'
    
      # Retrieve the GroupEntry to delete.
      delete_group = gd_client.GetGroup('https://www.google.com/m8/feeds/groups/default/full/deleteContactGroupId')
    
      # Insert the entries to the batch feed.
      request_feed.AddQuery(entry=retrieve_group, batch_id_string='retrieve')
      request_feed.AddInsert(entry=create_group, batch_id_string='create')
      request_feed.AddUpdate(entry=update_group, batch_id_string='update')
      request_feed.AddDelete(entry=delete_group, batch_id_string='delete')
    
      # submit the batch request to the server.
      response_feed = gd_client.ExecuteBatch(request_feed,
                                             'https://www.google.com/m8/feeds/groups/default/full/batch')
    
      for entry in response_feed.entry:
        print '%s: %s (%s)' % (entry.batch_id.text, entry.batch_status.code, entry.batch_status.reason)
    
      return response_feed
    
    

  • Send feedback about...

    Contacts API