# Read and Manage Contacts

<br />

After you've completed the steps in
[Get Ready to Use the People API](https://developers.google.com/people/v1/getting-started) you are ready
to read and manage contacts.

The following code samples demonstrate how to send a few simple requests. For a
full list of methods, see the [reference documentation](https://developers.google.com/people/api/rest).

> [!IMPORTANT]
> **Important:** Only contact based people can be modified. Profile based people read using resource name [`"people/me"`](https://developers.google.com/people/v1/profiles#get_the_person_for_the_authenticated_user) or by an [account ID](https://developers.google.com/people/v1/profiles#get_the_person_for_a_google_account_id) can not be modified.

## List the user's contacts

To
[get a list of people in the user's contacts](https://developers.google.com/people/api/rest/v1/people.connections/list),
use the following code:

### Protocol

```
GET /v1/people/me/connections?personFields=names,emailAddresses HTTP/1.1
Host: people.googleapis.com
```

### Java

```java
ListConnectionsResponse response = peopleService.people().connections().list("people/me")
    .setPersonFields("names,emailAddresses")
    .execute();
List<Person> people = response.getConnections();
```

### Python

```python
people = people_service.people().connections()
    .list('people/me', personFields='names,emailAddresses')
```

### PHP

```php
$people = $people_service->people_connections->listPeopleConnections(
    'people/me', array('personFields' => 'names,emailAddresses'));
```

### .NET

```c#
PeopleResource.ConnectionsResource.ListRequest peopleRequest =
    peopleService.People.Connections.List("people/me");
peopleRequest.PersonFields = "names,emailAddresses";
ListConnectionsResponse response = peopleRequest.Execute();
IList<Person> people = response.Connections;
```

## List the user's contacts that have changed

### Java

```java
// Initial request
ListConnectionsResponse fullSyncResponse = peopleService.people().connections().list("people/me")
    .setPersonFields("metadata,names,emailAddresses")
    .setRequestSyncToken(true)
    .execute();
// Fetch all the pages
while (fullSyncResponse.getNextPageToken() != null) {
  fullSyncResponse = peopleService.people().connections().list("people/me")
      .setPersonFields("metadata,names,emailAddresses")
      .setRequestSyncToken(true)
      .setPageToken(fullSyncResponse.getNextPageToken())
      .execute();
}

// Some time passes

// Fetch incremental changes using the sync token returned in the last fullSyncResponse.
try {
  ListConnectionsResponse incrementalSyncResponse = peopleService.people().connections().list("people/me")
      .setPersonFields("metadata,names,emailAddresses")
      .setSyncToken(fullSyncResponse.getNextSyncToken())
      .execute();
  for (Person person : incrementalSyncResponse.getConnections()) {
    handlePerson(person);
  }

  // Fetch all the pages
  while (incrementalSyncResponse.getNextPageToken() != null) {
    incrementalSyncResponse = peopleService.people().connections().list("people/me")
        .setPersonFields("metadata,names,emailAddresses")
        .setSyncToken(fullSyncResponse.getNextSyncToken())
        .setPageToken(incrementalSyncResponse.getNextPageToken())
        .execute();
    for (Person person : incrementalSyncResponse.getConnections()) {
      handlePerson(person);
    }
  }
} catch (GoogleJsonResponseException e) {
  if (e.getStatusCode() == 410) {
    // Sync token expired. Make full sync request.
  }
}

void handlePerson(Person person) {
  if (person.getMetadata().getDeleted()) {
    // Handle deleted person
  } else {
    // Handle changed person
  }
}
```

> [!NOTE]
> **Note:** Writes may have a propagation delay of several minutes for sync requests. Incremental syncs are not intended for read-after-write use cases.

More details about sync behavior at [ListConnections](https://developers.google.com/people/api/rest/v1/people.connections/list).

## Search the user's contacts

To [search all of the user's contacts](https://developers.google.com/people/api/rest/v1/people/searchContacts), use the following code:

### Protocol

```
// Warmup cache
GET /v1/people:searchContacts?query=&readMask=names,emailAddresses HTTP/1.1
Host: people.googleapis.com

// Send search request after several seconds
GET /v1/people:searchContacts?query=query&readMask=names,emailAddresses HTTP/1.1
Host: people.googleapis.com
```

### Java

```java
// Warmup cache
SearchResponse response = peopleService.people().searchContacts()
    .setQuery("")
    .setReadMask("names,emailAddresses")
    .execute();

// Wait a few seconds
Thread.sleep(5);

// Send search request
SearchResponse response = peopleService.people().searchContacts()
    .setQuery("query")
    .setReadMask("names,emailAddresses")
    .execute();
```

<br />

> [!IMPORTANT]
> **Important:** Search uses a lazy cache that is updated after a request. Clients should first send a warmup search request with an empty query to make sure the cache has the latest data.

> [!NOTE]
> **Note:** Search does a prefix match of the query with the fields on a person. For example, a person with name "foo name" matches queries such as "f", "fo", "foo", "foo n", "nam", etc., but not "oo n".

## Create a new contact

To [create a new contact](https://developers.google.com/people/api/rest/v1/people/createContact), use the
following code:

### Protocol

```
POST /v1/people:createContact HTTP/1.1
Body: { "names": [{ "givenName": "John", "familyName": "Doe" }] }
Host: people.googleapis.com
```

### Java

```java
Person contactToCreate = new Person();
List<Name> names = new ArrayList<>();
names.add(new Name().setGivenName("John").setFamilyName("Doe"));
contactToCreate.setNames(names);

Person createdContact = peopleService.people().createContact(contactToCreate).execute();
```

### Quota usage per request

- 1 Critical read requests (Contact and Profile Reads)
- 1 Critical write requests (Contact Creates and Updates)
- 1 Daily Contact Writes (Total)

> [!WARNING]
> **Warning:** Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.

## Update an existing contact

To [update an existing contact](https://developers.google.com/people/api/rest/v1/people/updateContact),
you must include the `person.metadata.sources.etag` field in the person for the
contact to be updated to make sure the contact has not changed since your last
read. Use the following code:

### Protocol

```
PATCH /v1/resource_name:updateContact?updatePersonFields=emailAddresses HTTP/1.1
Body: {
    "resourceName": "resource_name",
    "etag": "etag",
    "emailAddresses": [{ "value": "john.doe@gmail.com" }],
}
Host: people.googleapis.com
```

### Java

```java
Person contactToUpdate = peopleService.people().get("resource_name").execute();

List<EmailAddress> emailAddresses = new ArrayList<>();
emailAddresses.add(new EmailAddress().setValue("john.doe@gmail.com"));
contactToUpdate.setEmailAddresses(emailAddresses);

Person updatedContact = peopleService.people()
    .updateContact(contactToUpdate.getResourceName(), contactToUpdate)
    .setUpdatePersonFields("emailAddresses")
    .execute();
```

### Quota usage per request

- 1 Critical read requests (Contact and Profile Reads)
- 1 Critical write requests (Contact Creates and Updates)
- 1 Daily Contact Writes (Total)

> [!WARNING]
> **Warning:** Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.

## Delete an existing contact

To [delete an existing contact](https://developers.google.com/people/api/rest/v1/people/deleteContact),
use the following code:

### Protocol

```
DELETE /v1/resource_name:deleteContact HTTP/1.1
Host: people.googleapis.com
```

### Java

```java
peopleService.people().deleteContact("resource_name").execute();
```

### Quota usage per request

- 1 Write requests (Contact Deletes and Contact Group Writes)

> [!WARNING]
> **Warning:** Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.

## Batch create new contacts

To
[batch create new contacts](https://developers.google.com/people/api/rest/v1/people/batchCreateContacts),
use the following code:

### Protocol

```
POST /v1/people:batchCreateContacts?readMask=names HTTP/1.1
Body: {
  "contacts": [
    {
      "contactPerson": {
        "names": [
          {
            "givenName": "John",
            "familyName": "Doe"
          }
        ]
      }
    }
  ]
}
Host: people.googleapis.com
```

### Java

```java
Person person1 = new Person();
person1.setNames(ImmutableList.of(new Name().setGivenName("John").setFamilyName("Doe")));
ContactToCreate contactToCreate1 = new ContactToCreate();
contactToCreate1.setContactPerson(person1);

Person person2 = new Person();
person2.setNames(ImmutableList.of(new Name().setGivenName("Bob").setFamilyName("Dylan")));
ContactToCreate contactToCreate2 = new ContactToCreate();
contactToCreate2.setContactPerson(person2);

BatchCreateContactsRequest request = new BatchCreateContactsRequest();
request.setContacts(ImmutableList.of(contactToCreate1, contactToCreate2)).setReadMask("names");

BatchCreateContactsResponse response =
    peopleService.people().batchCreateContacts(request).execute();
```

### Quota usage per request

- 6 Critical read requests (Contact and Profile Reads)
- 6 Critical write requests (Contact Creates and Updates)
- 200 Daily Contact Writes (Total)

> [!WARNING]
> **Warning:** Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.

## Batch update existing contacts

To
[update an existing contact](https://developers.google.com/people/api/rest/v1/people/batchUpdateContacts),
you must include the `person.metadata.sources.etag` field in each person for the
contact to be updated to make sure the contact has not changed since your last
read. Use the following code:

### Protocol

```
POST /v1/people:batchUpdateContacts?updateMask=names&readMask=names,emailAddresses HTTP/1.1
Body: {
  "contacts": {
    "resource_name": {
      "emailAddresses": [
        {
          "value": "john.doe@gmail.com"
        }
      ]
      "etag": "etag"
    }
  }
}
Host: people.googleapis.com
```

### Java

```java
Person contactToUpdate = peopleService.people().get("resource_name").execute();

contactToUpdate.setNames(
    ImmutableList.of(new Name().setGivenName("John").setFamilyName("Doe")));

BatchUpdateContactsRequest request = new BatchUpdateContactsRequest();
ImmutableMap<String, Person> map =
    ImmutableMap.of(contactToUpdate.getResourceName(), contactToUpdate);
request.setContacts(map).setUpdateMask("names").setReadMask("names,emailAddresses");

BatchUpdateContactsResponse response =
    peopleService.people().batchUpdateContacts(request).execute();
```

### Quota usage per request

- 6 Critical read requests (Contact and Profile Reads)
- 6 Critical write requests (Contact Creates and Updates)
- 200 Daily Contact Writes (Total)

> [!WARNING]
> **Warning:** Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.

## Batch delete existing contacts

To
[batch delete existing contacts](https://developers.google.com/people/api/rest/v1/people/batchDeleteContacts),
use the following code:

### Protocol

```
POST /v1/people:batchDeleteContacts HTTP/1.1
Body: {"resource_names": ["resource_name"]}
Host: people.googleapis.com
```

### Java

```java
BatchDeleteContactsRequest request = new BatchDeleteContactsRequest();

request.setResourceNames(ImmutableList.of(resource_name));

peopleService.people().batchDeleteContacts(request).execute();
```

### Quota usage per request

- 10 Write requests (Contact Deletes and Contact Group Writes)

> [!WARNING]
> **Warning:** Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.