Techniques

The API

CiviCRM has a stable comprehensive API (Application Programming Interface) that can be used to access much of the functionality of CiviCRM. The API is the recommended way for any external programme to interact with CiviCRM.

Why use the API?

If you're not familiar with APIs, you might ask why you would use the API when you could access the core functions (e.g. the BAO files) directly?

The answer is that the community will ensure that the API will function as expected with every new release. If you decide to use other ways to collect data (like your own MySQL statements), you are left to your own devices.

Learning about (and experimenting with) the API

The best place to learn about the API is your own test install of CiviCRM.  Be wary about using the API on your live site because the the API does not ask for confirmation, and therefore you can easily make significant changes to your data. 

Each install comes with two tools that are useful for this. 

  1. The API parameter list, which shows all available entities which can be manipulated by the API and is available at http://[CIVICRM_URL]/civicrm/api/doc. You will get a list of parameters that are available for each API, with the type of the parameter.
  2. The API explorer, which is available at http://[CIVICRM_URL]/civicrm/api/explorer. This gives you the possibility to actually try out the API in action. You can select the entity you want to use, for example ' Contact' and the action you want to perform, for example ' Get' . Again, be careful as the API explorer will actually perform your actions! So if you delete a contact to check what API call to use, it will really delete the contact. The API explorer will show you the code you need to have to execute the API call you have been testing. To see the API explorer in action check http://civicrm.org/API_version_3. It may be that it uses an older version of the API explorer, but you will get the idea!

How to use the API

There are at least 5 different ways of using an API function. In each environment, the API uses the same names for entities, actions, and parameters, but the syntax is slightly different. Entities are the data collections you want to operate on, for example Contact, Event or Group. The actions are the thing you want to do to the entity, for example get, create, delete or update.

You can use the API: 

  1. as a PHP function, to run your own code on the same server as CiviCRM 
  2. via the AJAX interface, to be called from JavaScript code
  3. via the REST* interface, can be called from another server via http calls
  4. as a Smarty function to add data to templates 
  5. from drush on the command line for Drupal installations. 

Calling the API in PHP 

If you write custom code that is going to run within the same environment as CiviCRM, calling the API as a PHP function is the recommended way of modifying or fetching data. You will see examples of API calls throughout the developer documentation. For example, you could create several tags from a script rather than doing it manually from the CiviCRM admin page. In general you can use the API in a procedural way, or in a OOP way. 

The recommended procedural way to call the API in PHP is

 civicrm_initialize( );
 $result = civicrm_api( $entity, $actions, $params);

The recommended OOP way to call the API is

require_once 'api/class.api.php';
$api = new civicrm_api3();
$result = $api->Entity->Action ( $params );

or even

require_once '/your/civi/folder/api/class.api.php' ;
$api = new civicrm_api3( array( ' conf_path' => '/your/path/to/your/civicrm/site' ) );
$result = $api->Entity->Action ( $params ); 

where $entity/Entity is the object you want to manipulate and $action/Action is what you want to do with the entity. 

The advantage of using the OOP way rather than the procedural way is that you can use the same syntax on the same server or on a remote server. For more details, check the comments in the top section of <your civicrm>/api/class.api.php.

In this book we will mainly use the procedural way for our examples.

So with real data:

civicrm_initialize( );
$contact = civicrm_api('Contact','Get',array('first_name' => 'Michael', 'last_name' => 'McAndrew', 'version' =>3)); 

The version parameter is used to enable us to have and use different versions of the API. So we could for example improve a specific API with some new functionality that is only used for a set of parameters that has 'version' => 4. At the same time all existing users can continue to use the version 3 functionality. Actually, in the api folder in your install you might still have a folder with version 2 api scripts, even if they are deprecated. 

Further examples are in the api/v3/examples folder in your install or in the svn repo. Note that the examples are all generated by the test suite. If there is something missing from the examples post on the API forum board and help us add it to the test suite. This may be a function or a field within that function. 

Calling the API from smarty

CiviCRM defines a smarty function {crmAPI} which can be used to call the API from the template layer.

{crmAPI var="ContactS" entity="Contact" action="get" version="3" first_name="Michael" last_name="McAndrew" }
{foreach from=$ContactS.values item=Contact}
<li>{$Contact.example}</li>
{/foreach} 

Calling the API via javascript

It also defines a javascript function crmAPI() which can be used to call the API from javascript. 

 $().crmAPI ('Contact','get',{'version' :'3', 'first_name' :'Michael', 'first_name' :'McAndrew'}}
  ,{ success:function (data){    
      $.each(data, function(key, value) {// do something });
    }
});

Calling the API via Ajax or REST

You can also call the API via Ajax or REST.  Have a look at the api explorer for examples of how you call the API with these methods.

Calling the API via drush

Obviously you can only call the API using drush on a Drupal site (as drush is a Drupal module). For a single site use:

drush civicrm-api contact.get first_name=Michael last_name=McAndrew 

If you are using drush on a Drupal multi-site you have to specify the site name:

drush -l www.example.org  civicrm-api contact.get first_name=Michael last_name=McAndrew 

Calling the API from an external server via the REST API

The syntax and principle are identical to the other methods, but with one major difference: the external server needs to authenticate itself before being able to use any API functions.

To call the API with a browser, use:

http://www.example.org/path/to/civi/codebase/civicrm/extern/rest.php?q=civicrm/<function> 

The first call is to authenticate the caller on the CiviCRM server:

https://eg.org/path/to/civi/codebase/civicrm/extern/rest.php?q=civicrm    /login&name=user&pass=password&key=yoursitekey&json=1 

The key is in the CIVICRM_SITE_KEY variable defined in your civicrm.settings.php file.

Note: On the first call, you might get an error message like "This user does not have a valid API key in the database, and therefore cannot authenticate through this interface". This means that you need to generate a key for the user, and add it to the api_key field in the civicrm_contact table in the database.

{"is_error":0,"api_key":"as-in-your-setting.civicrm.php",    "PHPSESSID":"4984783cb5ca0d51a622ff35fb32b590",    "key": "2e554f49c9fc5c47548da4b24da64681b77dca08"}

It returns a session id. You can then use any API adding the extra param PHPSESSID = the value returned by the log-in call.

For example:

http://www.example.org/civicrm/ajax/rest?fnName=civicrm/contact/search&json=1&key= yoursitekey&PHPSESSID=4984783cb5ca0d51a622ff35fb32b590 

Note: An action that modifies the database (such as creating a contact or group) should have the parameters passed as POST, not GET. The REST interface accepts both a GET and a POST, but you should follow the web standard and use POST for things that alter the database. You'll win the respect of your peers and the admiration of your friends and family.

Note: if you use the OOP way to call the API you can actually use the same kind of syntax if you have initialized the object on the remote server:

require_once ' /your/civi/folder/api/class.api.php';
$api = new civicrm_api3( array( ' server'=>' http://example.org' , ' api_key' =>'theusersecretkey' , ' key' =>' thesitesecretkey' ) );
$result = $api->Entity->Action ( $params );

API actions

Most entities will support the following actions:

 Action Description
 CREATE Insert one new record (Note: if you pass an 'id' as a parameter, one record will be modified)
 DELETE Delete one record (Note: requires an explicit 'id'  as a parameter. Note: If you want to skip the "recycle bin" for entities that support undelete (like Contacts) you should set $param[' skip_undelete' ] = 1)
 GET Search for records
 GETCOUNT Return the number of records found that match the criteria you passed as parameter(s). (Note: some queries are limited to 25 so you might always get that number as a maximum result.In that case you should really fix the API if you can.)
 GETFIELDSFetch entity metadata, i.e. the list of fields supported by the entity 
 GETSINGLE Search for records and return the only match. This returns the record in a simplified format that is easier to use and minimizes the IO required. If there are more records than 1 that match your criteria, an error is returned.
 GETVALUE Does a get and returns the single value that you need to specify: $param[' return' ]=> ' field name' 
 REPLACEReplace an old set of records with a new or modified set of records. For example, replace the set of phone numbers with another set of phone numbers. WARNING: replace uses an implicit delete - use with care and test well before you use it in production!
 UPDATE Update one or more fields for an existing record
 

Data returned

The returned data from the API will be an array (formatted in json/XML if you are using the REST).

The API does perform some internal validation and returns data based on (lack of) success:

$result[' is_error' ] = 0 (or 1 if there is an error)

$result[' error_message' ] = the error message if there is an error (as a string)

$result[' version' ] = 3 (or any other appropriate version)

$result[' count' ] = the number of records in the $values part of the $result array

$result[' values' ] = an array of records

$result[' id'] = the id of the record if there is only one result in $values 

Chaining of API calls

You can do more API calls in one go with the first call feeding into the second one etc. For example, you can create a contact and then nest the website create in the first call. Once the contact has been created it will use the created contact_id to then create the website. If the API can not complete the total of chained calls, the whole process is rolled back. An example:

civicrm('Contact', 'Create', array('version' => 3, 'contact_type' => 'Individual', 'display_name' => 'BA Baracus', 'api.website.create' => array('url' => 'Ateam.com'));

or if you have more websites:

civicrm('Contact', 'Create', array('version' => 3, 'contact_type' => 'Individual', 'display_name' => 'BA Baracus', 'api.website.create' => array(array('url' => 'Ateam.com', ), array('url' => 'warmbeer.com', ))); 

Options in the API

There are some special parameters you can pass into the API to perform additional sensible stuff, for example how many records you want returned. The following options should work on all API's:

 Option Description
 sortDetermines the way in which your returned records are ordered. Has to be a sort string that can be understood by MySQL (without the ORDER BY). So if I want to sort on last_name and  then on first_name starting with the last I should pass ' last_name, first_name DESC' 
 limitDetermines the number of results that are returned. In almost all API's there will be a default limit of 25 records returned. You can use this option to change that if you want more or less records returned. 
 offsetWorks in combination with limit as per standard MySQl. Check the MySQL documentation for details.
 return Determines what fields are returned in your result array. You should really only get the data that you actually need, for example only the display name, the gender and the birth date for a Contact.

 Note: the API development is an ongoing community effort. This means you might come across some unexpected behaviour with these options. We all hope you understand and fix them when required. 

The format of the options in a PHP call should be like this:

$params = array( ' option_group_id' => 1, ' version'  => 3, ' options'  => array( ' sort'  => ' label DESC' , ' limit'  => 1 ) ); 
$result = civicrm_api( ' option_value' , ' getsingle' , $params );

Note: the getsingle action in combination with limit=1 is sure to return you only one result. Getsingle all by itself returns an error if there are more than 1 records that match your set of criteria. 

Autocomplete with the API

If you create a profile for individual contacts that contains the current employer, you might want to add an autocomplete on that field, such as you have on the normal contact edit form. When a user starts to type the name of the current employer, the system will attempt to autocomplete the name from your database of organisation contacts. 

For security reasons, the Ajax interface is restricted to users who have access to CiviCRM - otherwise, it would be fairly easy for anyone to download all the contacts you have in your database. So that's the first thing we check for here: 

{if $session->get('userID') > 0}  <script type="text/javascript" src="/civicrm/{$config->resourceBase}js/rest.js"></script>{literal} <script> jQuery(document).ready(function($){   $('#current_employer').crmAutocomplete({params:{contact_type:'Organization'}}); }); </script> {/literal}  {/if} 

You might want to add additional filters. For instance in a profile "new volunteer from a member", you want to populate the list only with the organisations that belong to the group "members" (group id 42). 

The autocomplete uses the quicksearch function which is available in the Contact API (and roughly does the same as the search in the top left corner of standard CiviCRM).

$('#current_employer').crmAutocomplete({params:{contact_type:'Organization',group:42}});

Extending the API

It should be noted that it's extremely easy to extend the api if you want to add some funky features: add a Magic.php file under api/v3, create a function civicrm_magic_getpony and voila, you have civicrm_api ("magic","getpony"), the smarty, the ajax, the REST, and it's also directly usable from the api explorer at /civicrm/ajax/doc 

If you want to have a go at creating, extending or fixing a core API, make sure you check the wiki instruction and stick to the API Architecture standards.

Exampe of API usage

Migration can be a bit hard every now and then. Even if we have the standard CiviCRM import function, data quality at the source can be gruesome. So I personally create my own migration code using the API, and I will use some here as an example.

The first part is creating a specific migration group, after checking if it exists already and deleting it. This is done so all contacts created in the migration can be removed in one go if something goes wrong.

$groupTitle = " Migration ". date( " Ymd" , strtotime( ' now'  ) );
$groupName = " Special migration group" ;
$checkGroup = civicrm_api( ' Group' ,  ' Getcount',  array( 'version' =>'3', ' title' => $groupTitle;
if ( $checkGroup[' result' ] == 1 ) {
   civicrm_api( 'Group', 'Delete', array('version' => '3', 'id' => $checkGroup['id']));
}
civicrm_api( 'Group', 'Create', array('version' = '3', ' title' => $groupTitle, ' name' => $groupName ));

Second part of the example is creating an individual with the API, and adding a custom field which I know exists, but I do not know the id of the custom field in the specific site. Once again, I use the API to get the right custom field id. Obviously there are bits of code before this happens to manipulate the unstructured source data...

 $createInd = civicrm_api( 'Contact', ' Create'  array(
' version' => ' 3',
' contact_type' => ' Individual' ,
' first_name'  => $firstName,
' middle_name' => $middleName,
' last_name'  => $lastName,
' gender_id'  => $genderID,
' birth_date'  => $birthDate ));
if ( $createInd[' is_error'  != 0 ) {
// error handling
} else {
$contactID = $createInd[' id' ];
$customField = civicrm_api( 'CustomField', 'Getsingle', array(
'version' => '3',
'label' => $customFieldName ));
$columnName = "custom_".$customField['id'];
civicrm_api( 'CustomValue', 'Create', array(
'version'  => '3',
'entity_id' => $contactID,
$columnName => $sourceField));

So this example should give you an idea of how to go about. There are more examples in the API folder of your specific install, in the folder <your civicrm site>/civicrm/api/v3/examples.

 


Download this book


Get involved

CiviCRM documentation is community driven. You can help improve documentation.


Powered by Flossmanuals.