How to Import and Retrieve SendGrid Contacts using PHP

March 20, 2023
Written by
Reviewed by

How to import and retrieve SendGrid contacts using PHP

Recently, on StackOverflow, a user asked how to import contacts into SendGrid and then retrieve the details afterwards; focusing primarily on the new contact's id. Here's a paraphrased version of the question:

> I am using the SendGrid API to save contacts, but the response only returns the import job id. There is another API to search the contact by their email address. However, I want to get the contact's id at the same time as inserting them, as I need to save the id against the contact in our local DB.

After some research into the SendGrid Contacts API, it's not currently possible to save a contact and retrieve their details in a single request. The process requires three calls to be made:

  1. Import one or more contacts. The response contains a job id for tracking the import job's process
  2. Using the returned job id, check the job's status
  3. If the status is set to completed, then retrieve the details of the newly imported contact(s)

This got me thinking about how I could make the process as streamlined as possible in PHP.  In this tutorial, I'm going to show you the solution that I came up with.

Prerequisites

Before we get started writing code, to follow along with this tutorial, you will need the following:

Create the project's directory structure

Start off by creating the project's directory structure and switching in to it, by running the commands below.

mkdir -p import-and-retrieve-contacts/{data/src}
cd import-and-retrieve-contacts

If you're using Microsoft Windows, use these commands instead.

mkdir import-and-retrieve-contacts
mkdir import-and-retrieve-contacts\data
mkdir import-and-retrieve-contacts\src
cd import-and-retrieve-contacts

Install the required dependencies

Next, you need install two dependencies; these are:

DependencyDescription
PHP DotenvPHP Dotenv populates PHP's $_SERVER and $_ENV superglobals from a configuration file. This encourages keeping sensitive configuration details out of code and version control.
The Official Twilio SendGrid PHP API LibraryThis package simplifies sending emails with the Official Twilio SendGrid PHP API Library.

To install them, run the command below.

composer require sendgrid/sendgrid vlucas/phpdotenv

Add a PSR-4 Autoloader configuration to composer.json

As the code will use a custom namespace (App), add the autoload mapping below to composer.json.

  "autoload": {
        "psr-4": {
          "App\\": "src/"
        }
  },

After that, update Composer's autoloader by running the following command.

composer dump-autoload

Set the required environment variables

Next, you need to store your SendGrid API key as an environment variable. This is required for making authenticated requests against SendGrid's API.

To do this, create a new file in the top-level directory of the project named .env. Then, paste the following configuration into the file.

SENDGRID_API_KEY="<<SENDGRID_API_KEY>>"

Create a SendGrid API key

Now, you need to create and retrieve a SendGrid API key, if you don't already have one. To do that, log in to your SendGrid account and under Settings > API Keys click Create API Key. In the form that appears, enter a meaningful name for the key in the API Key Name field and click Create & View.

Create a SendGrid API key

The SendGrid API key will now be visible. Copy and paste it into .env in place of the <<SENDGRID_API_KEY>> placeholder.

SendGrid API key created.

Be aware that you will only be able to view the API key once. If you navigate away from the page or close the tab/window and haven't copied the API key, you will have to create a new one.

Write the code

In the src directory, create a new directory named Service. Then, in that directory, create a file named SendGridService.php. In that file, paste the code below.

<?php

declare(strict_types=1);

namespace App\Service;

use SendGrid;

class SendGridService
{
    private SendGrid $sg;

    public function __construct(SendGrid $sg)
    {
        $this->sg = $sg;
    }

    public function importContacts(string $contactData): string
    {
        $response = $this->sg
            ->client
            ->marketing()
            ->contacts()
            ->put(json_decode($contactData));

        $response = json_decode($response->body());

        return $response->job_id;
    }

    public function retrieveContactsByEmailAddress(array $emailAddresses): string
    {
        $response = $this->sg
            ->client
            ->marketing()
            ->contacts()
            ->search()
            ->emails()
            ->post([
                "emails" => $emailAddresses,
            ]);

        return $response->body();
    }

    public function checkImportStatus(string $jobId): mixed
    {
        $response = $this->sg
            ->client
            ->marketing()
            ->contacts()
            ->imports()
            ->_($jobId)
            ->get();

        return json_decode($response->body());
    }
}

The class is a small wrapper around the SendGrid object, which does most of the work of interacting with SendGrid's APIs. It provides three utility classes to simplify making the required API requests, covered earlier. These are:

  • importContacts(): This method accepts a JSON string (which you can see below) containing the details of one or more contacts. It passes the string in a request to SendGrid to import the contacts into your account. If successful, the request returns a job ID which can be used to check the import job's status.
  • checkImportStatus(): This method takes the job ID which importContacts() returns and uses it to check if the job is completed or not.
  • retrieveContactsByEmailAddress(): This method takes a list of email addresses and uses them to retrieve matching contact details.

Next, in the data directory, create a new file named user_data.json, and in that file paste the JSON below.

{
    "contacts": [
        {
            "email": "annahamilton@example.org",
            "first_name": "Anna",
            "last_name": "Hamilton",
            "country": "Canada"
        }
    ]
}

This file contains a JSON object with one property, contacts. That property contains an array of objects containing contact details. These objects include details such as email address, first and last names, and country. Feel free to change the example above, and add as many further contact detail objects to the contacts array as you like from the list of supported fields.

Create the import code

Next, in the project's top-level directory, create a new file name import-contacts.php and in that file paste the following code.

<?php

use App\Service\SendGridService;

require_once 'vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
$dotenv->required('SENDGRID_API_KEY');

$sg = new \SendGrid($_ENV['SENDGRID_API_KEY']);
$service = new SendGridService($sg);

$contactData = file_get_contents(
    __DIR__ . '/data/user_data.json'
);
$jobId = $service->importContacts($contactData);
echo "Job ID is: {$jobId}\n";

The code initialises a new SendGrid object with the stored SendGrid API key, and uses that to initialise a new SendGridService object. It then retrieves the contact details in data/user_data.json, and passes them to the call to importContacts(). Assuming that the request was successful, the returned job ID is then printed to the terminal.

Create the contact retrieval code

Next, in the project's top-level directory, create a new file name retrieve-contacts.php and in that file paste the following code.

<?php

use App\Service\SendGridService;

require_once 'vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
$dotenv->required('SENDGRID_API_KEY');

$sg = new \SendGrid($_ENV['SENDGRID_API_KEY']);
$jobId = "<<JOB ID>>";
$service = new SendGridService($sg);

$response = $service->checkImportStatus($jobId);
switch ($response->status) {
    case 'completed':
        $contactData = json_decode(
            file_get_contents(__DIR__ . '/data/user_data.json')
        );
        $contacts = $service->retrieveContactsByEmailAddress(
            array_column($contactData->contacts, 'email')
        );
        print_r($contacts);
        break;
    case 'pending':
        echo 'The contacts have not been fully imported yet';
        break;
    case 'errored':
    case 'failed':
        echo 'The contacts were not able to be imported';
        break;
};

The code initialises a new SendGrid object with the stored SendGrid API key, and uses that to initialise a new SendGridService object. It then passes the job ID ($jobId) to a call to checkImportStatus() to check if the import process has completed.

If the returned status is completed, it then retrieves the email addresses defined in data/user_data.json and passes them to retrieveContactsByEmailAddress(), to retrieve the matching contact details. Assuming that the request was successful, the contact information is printed to the terminal.

Test that the application works

Now, with all of the code written, it's time to check that it works. To do that, first import your contacts by running the following command.

php import-contacts.php

You should see a job ID printed to the terminal, as in the output below.

Job ID is: dfa6eaee-f0d0-48f3-8888-762b97879507

Take the job ID and paste it into retrieve-contacts.php in place of <<JOB ID>>. Then, retrieve the newly imported contacts by running the following command.

php retrieve-contacts.php

You should see output similar to the following, formatted, example.

{
	"result": {
		"annahamilton@example.org": {
			"contact": {
				"address_line_1": "",
				"address_line_2": "",
				"alternate_emails": [],
				"city": "",
				"country": "Canada",
				"email": "annahamilton@example.org",
				"first_name": "Anna",
				"id": "ce558c7a-127c-41c8-070b-531cb777625f",
				"last_name": "Hamilton",
				"list_ids": [],
				"segment_ids": [],
				"postal_code": "",
				"state_province_region": "",
				"phone_number": "",
				"whatsapp": "",
				"line": "",
				"facebook": "",
				"unique_name": "",
				"custom_fields": {},
				"created_at": "2023-03-10T11:59:04Z",
				"updated_at": "2023-03-10T11:59:34Z",
				"_metadata": {
					"self": "https://api.sendgrid.com/v3/marketing/contacts/ce558c7a-127c-41c8-070b777625f"
				}
			}
		}
	}
}

To make the JSON response easier to read, like the example above, consider piping the output of php retrieve-contacts.php to jq, a "lightweight and flexible command-line JSON processor". Among other things, it can beautifully format JSON data. Alternatively, use a web-based tool such as JSONLint.

That's how to import and retrieve SendGrid contacts with PHP

There isn't a lot to it. While it might be handy to be able to do this in one call, that's not supported by SendGrid's API. So here's the next best thing.

How would you improve the code in this tutorial? Share your thoughts with me on LinkedIn. I'd love to get your feedback.

Matthew Setter is a PHP Editor in the Twilio Voices team and a PHP, Go, and Rust developer. He’s also the author of Mezzio Essentials and Docker Essentials. When he's not writing PHP code, he's editing great PHP articles here at Twilio. You can find him at msetter[at]twilio.com, on Twitter, and on GitHub.

"Rolodex" by Ged Carroll is licensed under CC BY 2.0.