# Google Contacts API PHP example

Source: https://developer.nylas.com/docs/cookbook/contacts/google-contacts-api-php/

Nylas doesn't require a PHP SDK to read Google Contacts. You can call the REST API directly from PHP with the connected user's grant ID and your server-side API key.

This is useful when you want a lightweight Google Contacts integration without wiring up the Google People API client, OAuth token refresh, and provider-specific contact schema yourself.

## Before you begin

You'll need:

- A [Nylas application](/docs/v3/getting-started/) with a valid API key
- A Google grant created through [hosted OAuth](/docs/cookbook/use-cases/build/connect-user-accounts-oauth/)
- Contact scopes on the Google connector, usually `https://www.googleapis.com/auth/contacts.readonly`
- PHP with cURL enabled

Store `NYLAS_API_KEY` in your server environment. Don't put it in a browser bundle, template, or public repository.

## Fetch Google Contacts in PHP

Send a `GET` request to `/v3/grants/{grant_id}/contacts`. The example below reads saved contacts from the Google address book and prints the first email address for each contact.

```php
<?php

$apiKey = getenv("NYLAS_API_KEY");
$grantId = "<NYLAS_GRANT_ID>";

$url = "https://api.us.nylas.com/v3/grants/{$grantId}/contacts"
  . "?limit=50&source=address_book";

$ch = curl_init($url);
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => [
    "Accept: application/json",
    "Authorization: Bearer {$apiKey}",
  ],
  CURLOPT_RETURNTRANSFER => true,
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

if ($status < 200 || $status >= 300) {
  throw new RuntimeException("Nylas request failed: {$body}");
}

$payload = json_decode($body, true);

foreach ($payload["data"] as $contact) {
  $firstName = $contact["given_name"] ?? "";
  $lastName = $contact["surname"] ?? "";
  $email = $contact["emails"][0]["email"] ?? "";

  echo htmlspecialchars(trim("{$firstName} {$lastName}")) . " ";
  echo htmlspecialchars($email) . "<br>";
}
```

Use `source=address_book` for contacts the user saved in Google Contacts. Use `source=inbox` for automatically created contacts from Gmail correspondents, but only if your connector includes the `contacts.other.readonly` scope.

## Page through all contacts

The Contacts API returns contacts in pages. Set `limit=200` for bulk sync, then pass `next_cursor` back as `page_token` until no cursor remains.

```php
<?php

function listContactsPage(string $grantId, ?string $cursor = null): array {
  $apiKey = getenv("NYLAS_API_KEY");
  $params = ["limit" => 200, "source" => "address_book"];

  if ($cursor) {
    $params["page_token"] = $cursor;
  }

  $url = "https://api.us.nylas.com/v3/grants/{$grantId}/contacts?"
    . http_build_query($params);

  $ch = curl_init($url);
  curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer {$apiKey}"],
    CURLOPT_RETURNTRANSFER => true,
  ]);

  $body = curl_exec($ch);
  $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
  curl_close($ch);

  if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Nylas request failed: {$body}");
  }

  return json_decode($body, true);
}

$contacts = [];
$cursor = null;

do {
  $page = listContactsPage("<NYLAS_GRANT_ID>", $cursor);
  $contacts = array_merge($contacts, $page["data"]);
  $cursor = $page["next_cursor"] ?? null;
} while ($cursor);
```

For a customer relationship management import or address-book sync, fetch all pages first, then remove duplicate records by lowercase email before writing to your database.

## Find a contact by email

Use the `email` query parameter when you already know the address and need the contact record behind it.

```php
<?php

$apiKey = getenv("NYLAS_API_KEY");
$grantId = "<NYLAS_GRANT_ID>";
$email = rawurlencode("maya@example.com");

$url = "https://api.us.nylas.com/v3/grants/{$grantId}/contacts?email={$email}";

$ch = curl_init($url);
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => ["Authorization: Bearer {$apiKey}"],
  CURLOPT_RETURNTRANSFER => true,
]);

$payload = json_decode(curl_exec($ch), true);
curl_close($ch);

$matches = $payload["data"] ?? [];
```

The API doesn't have fuzzy name search. If you need a search box, list contacts, cache them, and then filter `given_name`, `surname`, and `emails` in PHP or JavaScript. See [Search contacts](/docs/cookbook/contacts/search-contacts/) for the exact filter behavior.

## Things to know about PHP Google Contacts integrations

**Use OAuth once, then store the grant ID.** Your PHP app doesn't need to store Google access tokens. Nylas refreshes provider tokens for the grant.

**Escape output.** Contact names and notes come from a user's address book. Treat them as data from outside your app and escape before rendering HTML.

**Handle empty fields.** Many Google contacts have no company, title, phone number, or name. Build your display around email as the most reliable identifier.

**Watch rate limits on bulk imports.** Use `limit=200`, page through results, and avoid one API request per rendered row.

## What's next

- [How to list Google contacts](/docs/cookbook/contacts/list-contacts-google/) for Google source fields and OAuth scopes
- [Sync Google Contacts into customer relationship management systems](/docs/cookbook/contacts/sync-google-contacts-crm/) for duplicate handling and webhook sync
- [Connect user accounts with OAuth](/docs/cookbook/use-cases/build/connect-user-accounts-oauth/) to create the Google grant
- [Contacts API reference](/docs/reference/api/contacts/) for request and response details