How To Create a Contact in SugarCRM With the Sugar API & PHP

How To Create a Contact in SugarCRM With the Sugar API & PHP

I’ve been quite busy recently, working on a project involving the bidirectional syncing of user data between a client’s WordPress site and their SugarCRM platform via the SugarCRM API. As part of that work, I needed to create a contact in SugarCRM with the Sugar API programmatically, which turned out to be straightforward once I understood the basics. It’s actually been a lot of fun, and even dealing with the SugarCRM docs hasn’t been terrible 😅.

Anywho, in this SugarCRM tutorial, I’ll show you how to connect, and authenticate to the SugarCRM REST API, and create contacts programmatically. Following this tutorial, you’ll be able to use the code as a base to build integrations for lead/contact capture, data syncing, automation workflows etc etc.

The flavour of SugarCRM I will be working with in this tutorial is Sugar Enterprise but the code should work with all SugarCRM editions including Professional, Enterprise, Ultimate, and cloud versions (Sugar Sell/Serve). The REST API is identical across all editions.

What You’ll Learn

  • Authenticating with SugarCRM’s OAuth2 API.
  • Creating contact records via the REST API v11.
  • Building a reusable PHP class for SugarCRM.

Requirements

  • SugarCRM instance with API access (obviously), sandbox or production is fine.
  • PHP with cURL enabled.
  • Basic PHP knowledge.

Righto, let’s begin our tutorial on ‘how to create a contact in SugarCRM with the Sugar API & PHP‘!

1. First Steps On Creating a Contact in SugarCRM With the Sugar API

We first need to create our project files:

  • config.php – Our SugarCRM credentials.
  • bootstrap.php – Loads config, and provides an authenticated SugarCRM connection.
  • sugarcrm.php – Our PHP class that will handle auth and API interactions.
  • get-fields.php – Lists all available fields for the Contacts module.
  • index.php – Script that will hold our contact fields data, push data to Sugar & error check.

2. Creating the Sugar Config File

This file should be outside of the public root directory on your server, and the file permissions should be set to 600!

The very first file we will create is the config file. This will hold all of the information about our specific SugarCRM workspace, and as mentioned above, this file should be placed outside of the public_html (or www, htdocs) directory to prevent it from being potentially accessible via an HTTP request.

<?php
return [
    'url' => 'https://your-instance.sugarcrm.com',
    'username' => 'your_username',
    'password' => 'your_password',
    'client_id' => 'sugar',
    'platform' => 'base',
    'module' => 'Contacts',
    'timeout' => 30,
    'verify_ssl' => true
];

Most of the above should be fairly straightforward, but below are some parameters that I had to double check.

  • module - If you would like to capture leads instead of contacts, change 'module' => 'Contacts' to 'module' => 'Leads'.
  • client_id - The default value for client_id is sugar.
  • platform - Defaults to base.

In my server, I will place this config.php file inside a directory called sugarcrm, in my website's root directory.

logs/
public_html/
sugarcrm/
  └── config.php

3. Creating the Bootstrap File

Right, so we’ve got our config file sorted. Now we need a way to load everything without copy-pasting the same setup into every single file. That’s where bootstrap.php comes in – it’s the entry point for all our SugarCRM files, and provides a reusable connection to the SugarCRM API.

Here’s what it does:

  • Provides a helper function - gives us an easy, reusable way to get an authenticated connection.
  • Loads the SugarCRM class - the one we’ll build next to handle all the API magic.
  • Grabs our config - pulls in those credentials we just set up.
<?php

require_once 'sugarcrm.php';

$configPath = '/home/frontend/sugarcrm/config.php';

if (!file_exists($configPath)) {
    die('Configuration file not found.');
}

$config = require $configPath;

if (!isset($config['url']) || 
    !isset($config['username']) || 
    !isset($config['password']) ||
    !isset($config['client_id']) ||
    !isset($config['platform'])) {
    die('Invalid configuration file.');
}

function getSugarConnection($config) {
    static $sugar = null;
    
    if ($sugar === null) {
        $sugar = new SugarCRM($config);
       
        $sugar->authenticate();
    }
    return $sugar;
}

Notes

  • Includes a soon to be created sugarcrm.php file that will handle all of our SugarCRM functionality.
  • Singleton pattern – prevents creating multiple API connections by reusing the same instance. Implemented using the static keyword, which preserves the variable's value across function calls.
  • getSugarConnection() returns the same authenticated instance on every call. Creates new connection only on first invocation.
  • Validation checks - Fail fast with clear error messages if config file is missing or incomplete.

4. Creating the sugarcrm.php File

Next up, we're going to code the brains of the operation, the sugarcrm.php file. This will be a PHP class that connects to, and interacts with SugarCRM's REST API using OAuth2 authentication.

<?php

class SugarCRM {
    
    private $url;
    private $username;
    private $password;
    private $clientId;
    private $platform;
    private $accessToken;
    private $timeout;
    private $verifySSL;

    public function __construct($config) { 
    
    }

    public function authenticate() { 
    
    }

    public function createContact($contactData, $module = null) { 
    
    }

    public function getModuleFields($module = 'Contacts') { 
    
    }

    private function makeRequest($url, $method = 'GET', $data = null, $headers = []) { 
    
    }
}

Notes

  • We first create a class called SugarCRM that encapsulates all the functionality needed to connect to and interact with SugarCRM's API.
  • The first method we create is the constructor, which accepts a $config parameter - an associative array containing all your connection details (URL, username, password etc). It extracts these values and stores them in private properties for use throughout the class.
  • The authenticate() method logs into SugarCRM using OAuth2 password grant flow and stores an access token that's used for all subsequent API calls.
  • The createContact() method accepts two parameters. The first parameter $contactData is an array of field names and values that you want to save (like first name, last name, email, etc.) This data comes from wherever you call the method, such as from our index.php file. The second parameter $module is optional and specifies which SugarCRM module to create the record in, defaulting to Contacts if you don't specify one.
  • The getModuleFields() method retrieves metadata about all available fields in a module, showing you what fields exist, their types, and their validation rules.
  • The makeRequest() private method is the workhorse of the class and handles all the actual HTTP communication using cURL, managing headers, timeouts, and error handling for all the public methods.

4.1 Creating the __construct() Method

The constructor is basically the setup wizard for our class, it runs automatically when we create a new SugarCRM object and loads all of our connection details into place.

public function __construct($config) {
    $this->url = rtrim($config['url'], '/');
    $this->username = $config['username'];
    $this->password = $config['password'];
    $this->clientId = $config['client_id'];
    $this->platform = $config['platform'];
    $this->timeout = $config['timeout'] ?? 30;
    $this->verifySSL = $config['verify_ssl'] ?? true;
}

4.2 Creating the authenticate() Method

The authenticate() method... authenticates with SugarCRM's OAuth2 API :) by sending credentials to the token endpoint. On success, it stores the returned access_token for use in subsequent API requests. If authentication fails, it throws an exception with error details.

public function authenticate() {
    $authUrl = $this->url . '/rest/v11/oauth2/token';
    
    $authData = [
        'grant_type' => 'password',
        'client_id' => $this->clientId,
        'username' => $this->username,
        'password' => $this->password,
        'platform' => $this->platform
    ];

    $response = $this->makeRequest($authUrl, 'POST', $authData);

    if (isset($response['access_token'])) {
        $this->accessToken = $response['access_token'];
        return true;
    }

    throw new Exception('Authentication failed: ' . json_encode($response));
}

4.3 Creating the createContact() Method

This createContact() method creates a new contact (or record in any specified module) in SugarCRM. It first verifies authentication, then constructs the API endpoint URL using the module name (defaulting to 'Contacts'), and sends a POST request with the contact data and OAuth token. The method returns SugarCRM's response, which includes the newly created record with its assigned ID and all field values.

public function createContact($contactData, $module = null) {
    if (!$this->accessToken) {
        throw new Exception('Not authenticated. Call authenticate() first.');
    }

    $module = $module ?? 'Contacts';
    
    $createUrl = $this->url . '/rest/v11/' . $module;
    
    $response = $this->makeRequest($createUrl, 'POST', $contactData, [
        'OAuth-Token: ' . $this->accessToken
    ]);

    return $response;
}

4.4 Creating the getModuleFields() Method

The getModuleFields() method retrieves the field definitions for a specified SugarCRM module (defaulting to 'Contacts'). It sends a GET request to the metadata endpoint, which returns information about all available modules and their fields. The method extracts and returns only the fields array for the requested module, or throws an exception if the module doesn't exist in the metadata response.

public function getModuleFields($module = 'Contacts') {
    if (!$this->accessToken) {
        throw new Exception('Not authenticated. Call authenticate() first.');
    }

    $metadataUrl = $this->url . '/rest/v11/metadata';
    
    $response = $this->makeRequest($metadataUrl, 'GET', null, [
        'OAuth-Token: ' . $this->accessToken
    ]);

    if (isset($response['modules'][$module]['fields'])) {
        return $response['modules'][$module]['fields'];
    }

    throw new Exception("Module '$module' not found in metadata");
}

4.5 Creating the makeRequest() Method

This private method handles all HTTP communication with the SugarCRM API using cURL. It configures the request with appropriate headers, timeout settings, and SSL verification, then JSON-encodes and sends the provided data in a POST request. It checks for both cURL errors and HTTP error status codes (400+), throwing exceptions if problems occur, and returns the decoded JSON response as a PHP array.

private function makeRequest($url, $method = 'GET', $data = null, $headers = []) {
    $ch = curl_init($url);
    
    $defaultHeaders = ['Content-Type: application/json'];
    $headers = array_merge($defaultHeaders, $headers);
    
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verifySSL);
    
    if ($method === 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);
        if ($data) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
    }

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    if (curl_errno($ch)) {
        $error = curl_error($ch);
        curl_close($ch);
        throw new Exception('cURL error: ' . $error);
    }
    
    curl_close($ch);

    $decoded = json_decode($response, true);
    
    if ($httpCode >= 400) {
        throw new Exception('HTTP Error ' . $httpCode . ': ' . json_encode($decoded));
    }

    return $decoded;
}

5. Creating the get-fields.php File

Now, with our above files created, we are now in a position to start doing some useful (and fun) stuff such as authenticating and pulling in some data! Let us create this get-fields.php file and utilise the code in the previous files to show all available fields in our Sugar instance.

<?php

require_once 'bootstrap.php';

try {
    
    $sugar = getSugarConnection($config);
    
    $fields = $sugar->getModuleFields('Contacts'); ?>
    
<pre>
<?php 
    print_r($fields);
?>
</pre>

<?php 
    
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

Notes

  • We have added our bootstrap.php at the top.
  • Then we use a try / catch block, create a new instance, connecting to our SugarCRM platform.
  • Then store all available fields in the response and output them.

What we are left with is the following PHP array:

Array
(
    [id] => Array
        (
            [name] => id
            [vname] => LBL_ID
            [type] => id
            [required] => 1
            [reportable] => 1
            [duplicate_on_record_copy] => no
            [comment] => Unique identifier
            [mandatory_fetch] => 1
        )

    [name] => Array
        (
            [name] => name
            [vname] => LBL_NAME
            [type] => fullname
            [fields] => Array
                (
                    [0] => first_name
                    [1] => last_name
                    [2] => salutation
                    [3] => title
                )

            [sort_on] => last_name
            [source] => non-db
            [group] => last_name
            [db_concat_fields] => Array
                (
                    [0] => first_name
                    [1] => last_name
                )

            [importable] => false
            [duplicate_on_record_copy] => always
        )
    ...
)

This information is invaluable for identifying exact field names, types, and string lengths in our SugarCRM instance. For example, from the fields array, I've chosen the following field names to use when creating my SugarCRM contacts:

Field NameField Type
titlevarchar
first_namevarchar
last_namevarchar
descriptiontext
phone_workphone
email_addressemail
primary_address_streettext
primary_address_cityvarchar
primary_address_postalcodevarchar
countrydd_cenum
do_not_callbool

So, now that we know which fields we’ll be populating when creating a new contact, we can go ahead and code up the final index.php file and add a sample contact to SugarCRM via the REST API!

A little note on the countrydd_c enum field type.

An enum (short for enumeration) is a data type that consists of a set of named, constant values. An enum field is a variable or database column that can only be assigned one of the predefined, symbolic names from this set.

So, when you're sending data to SugarCRM via the REST API, to populate the countrydd_c field, the value you send must exactly match one of the predefined country values in SugarCRM's countries_dom dropdown list.

6. Creating the index.php File and Adding a Contact to SugarCRM!

Now for ze moment of truth! We've got everything in place, our class is ready to go, and we've identified exactly which fields we want to populate. It's time to create the index.php file that brings it all together and actually pushes a contact into SugarCRM.

<?php

require_once 'bootstrap.php';
    
try {
        
    $contactData = [
        'title' => 'Mr',
        'first_name' => 'Peter',
        'last_name' => 'Smith',
        'description' => 'Demo contact created via Frontend Hero API tutorial',
        'phone_work' => '555-123456',
        'email' => [
            [
                'email_address' => 'peter.smith@example.com',
                'primary_address' => true
            ]
        ],
        'primary_address_street' => '123 Evergreen Street',
        'primary_address_city' => 'Newhaven',
        'primary_address_postalcode' => 'BN9 9PE',
        'countrydd_c' => 'CONGO',
        'do_not_call' => 1
    ];

    $sugar = getSugarConnection($config);
        
    $result = $sugar->createContact($contactData, $config['module']);
        
    echo "Contact created! ID: {$result['id']}";
        
    // print_r($result);

} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

Notes

  • Again, we include our bootstrap.php file at the top of the page, to authenticate to our SugarCRM workspace.
  • We use a try / catch block to safely handle errors, then create a $contactData array populated with sample contact information (name, email, phone, address, etc.).
  • We establish a connection to SugarCRM using getSugarConnection(), then call createContact() to submit the contact data and receive back the newly created contact's ID and details.
  • To see the response from Sugar (including all field values), you can uncomment the print_r function.

Now, before we access the index.php file directly, let's first add a little URL parameter check so we can control when the contact actually gets created. That way, we won't accidentally create a new contact every time we refresh the page!

<?php

require_once 'bootstrap.php';

if (isset($_GET['action']) && $_GET['action'] === 'create') {
    // existing code
    
} else {
    echo "Add ?action=create to the URL to create a contact";
}

Now, the only way that we will be able to add a contact into SugarCRM is by appending the following to the URL:

https://www.example.com/index.php?action=create

And after appending this query parameter, and refreshing the page, the result we get now is:

Contact created! ID: 18c4b6c8-ac50-11f0-b879-a0d3c106b134

Annnnnnd we can now view this new contact in SugarCRM! 🥳

Conclusion: Creating a Contact in SugarCRM With the Sugar API & PHP

And that's it! You now (hopefully) have a solid understanding of how to create a contact in SugarCRM with the Sugar API & PHP. With this knowledge, you can expand upon this, and build some pretty powerful integrations, automate your CRM workflows, and sync data seamlessly between your systems. The possibilities are endless!

If you might need help with syncing data in your SugarCRM platform with WordPress (or any other third party platforms), you can get in touch with me here, or here to hire me ;)

If this tutorial has helped you, I wouldn't say no to a coffee as a tip ☕️

Buy Me a Coffee at ko-fi.com

Leave a Reply

Your email address will not be published. Required fields are marked *