CiviCRM

Working with the API

CiviCRM provides an Application Programming Interface (API). This is a stable, coherent and standardised set of functions and it is the recommended way for any external programme to interact with CiviCRM.

CiviCRM is open source software, which means you can modify the source code or call methods and objects directly. But if you did, you would probably encounter difficulties when upgrading to a new version of CiviCRM because those methods and objects may have changed in the new version.

On the other hand, the API is designed to remain the same so it should behave identically across versions, or at the very least warn developers well in advance of a change. An API change between minor versions will be considered a regression bug and you should report it to the CiviCRM development team so they can fix it.

Most of the API functions are low level methods that allow you to interact with one of the entities in CiviCRM (contact, tag, group, activity, etc.). For each entity type, there are at least 3 actions: add (handles add and update), get (one specific entity), and delete. Some entities work slightly differently. Read the API docs in the wiki for the most up-to-date information:
http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+Public+APIs

Additionally, the API test directory http://svn.civicrm.org/civicrm/trunk/tests/phpunit/api/v2/ contains examples of most of the APIs, along with what parameters to use as input and what return parameters to expect.

There is an ongoing effort to better standardise the APIs, and help is certainly appreciated. If you're interested in lending a hand, post to the API section of the developer forum here: http://forum.civicrm.org/

How to use the API

The naming convention for API functions is civicrm_entityname_action. For instance, the function to create a contact is civicrm_contact_add, and the method to delete a group is civicrm_group_delete.

Every API function takes one single array of parameters as input. If the function needs a single parameter (e.g. the identifier of the group you want to delete), this will be an array containing a single item like so: array( 'id' => XX );

Every API function returns a single array. All the delete and add/modify functions contain an item "is_error". If the function couldn't delete or modify the entity as you requested, is_error = 1 and a second item error_message returns details about the error (eg. "DB Error: already exists"). If you have turned on debugging (see the Developer Tips & Tricks section), you have an extra item "debug_info" that contains a more detailed explanation (e.g. "INSERT INTO civicrm_tag (name) VALUES ('existing tag name') [nativecode=1062...").

They are at least 5 different ways of using an API function:

  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.

Tip: When using the API, be sure to verify the proper name of each parameter, which parameters are mandatory, and the structure of the resulting array. The easiest way to test the API is to make AJAX calls from a test web page. See the AJAX section below for more information.

*It's not really REST, but it's not SOAP either. It doesn't work for many API functions because it assumes a certain level of standardisation that just isn't in place yet (as of version 3.2). Test, test, test if you use the REST (REST, REST) interface, and don't hesitate to file bugs when things don't work the way they should.

Calling the API as a PHP function

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. The code below shows you how to do it using the API. 

Following the API convention described above, the function to call is civicrm_tag_create. The input parameters are: name, description, parent_id.

<?php
require_once 'civicrm.config.php';
require_once 'CRM/Core/Config.php';
require_once 'api/v2/Tag.php';

$param = array("name"=>"Topic of interest");
$result = civicrm_tag_create( $param );

if (civicrm_error( $result ))
  die ("Topic of interest already exists");

$parentid = $result['tag_id'];

$tags = array("Animal Protection", "...200 other tags", "Zen");

foreach ($tags as $tag) {
  $params = array("name"=>$tag, "description"=> "Example of Topic of interest",
      "parent_id" => $parentid);
  $result = civicrm_tag_create ($param);
  if (civicrm_error( $result )) {
        echo "\n ERROR creating $tag: ". $result['error_message'];
  } else {
        echo "\n Tag $name created with id:".$result['tag_id'];
  }
}

Some explanations:

  • civicrm_error is a helper function to test if the api returned an error (or not)
  • all the functions are in api/v2; the name of the file is the name of the entity (in CamelCase).

Tip: It is very easy to create a custom API class to add new methods to the API. Simply create a new file in api/v2/ with any name you want (and a .php extension) and put the functions in it. They should follow the naming convention explained above. Your new API functions will automatically be available.

Calling the API as Ajax back-end

With Ajax, you can retrieve data from the CiviCRM server asynchronously in the background without interfering with the display and behavior of the existing page. 

This section assumes you are familiar with over-riding templates and using jQuery. There is a chapter in this section on over-riding templates, and you can find more information on jQuery using any web search engine.

All the API functions are directly usable from an Ajax call and available to all logged-in users with CiviCRM access privileges. This is very useful to update a value in the database without having to reload the whole page (which might contain a long list of records, for example). You could use it on the  activities list page to set the status as "completed", on a list of participants to set the status as "attended", or to tag a contact in a search result, each time without having to reload the page.

Using the jQuery plug-in

The file js/rest.js contains a jQuery plug-in to make it simpler to call any CiviCRM API function.

The general syntax is $().crmAPI (entity,action,params)

For example, to dynamically create a tag, using JavaScript, in any page:

 $().crmAPI ("civicrm_tag", "create", {"name": "Wonky", "description": "Broken, please fix."});

Upon completion of the Ajax call, the default behaviour is to display a "Saved" message in a div with id "restmsg" (you will need to be sure this div exists in your page if you want to see the message). However, you might want to alter this default behaviour, for instance to change the colour of a row, the name in a field or to hide a button the user has clicked. This is done via a special parameter, "success", that is a function called when the Ajax API has returned the result. The next example shows how this is used.

Large organisations often have many contact records in CiviCRM and staff don't have time to update every detail of every record, even if they notice that the phone number doesn't work or the address isn't correct anymore. One solution is to allow them to flag the record for later follow-up if they suspect it may be inaccurate.

To make this as simple as possible, create a button that tags the contact "To be checked". We can modify the contact summary screen (CRM/Contact/Page/View/Summary.tpl) and add a button "To be checked", that adds the tag via an Ajax call to the API.

tobechecked_600x22.png

Here's what we added to the contact summary template to make this work (don't forget to create the "To be checked" tag):

{literal}
<script>
jQuery(document).ready(function($){
  $("#actions").append(''<li><a href="#" id="tobechecked" class="button"
     title="If the contact details need to be updated"><span>
          To be checked</span></a></li>');
   $("#tobechecked").click(function(){
     $().crmAPI ('entity_tag','add',{
                  tag_id       : 6
                 ,entity_table : 'civicrm_contact'
                 ,entity_id    : {/literal}{$contactId}{literal}
                 },{
                 success:function (){
                   $("#tobecheked").fadeOut('slow');
                 }
                 });
     return false;
   });

});
</script> {/literal}

A few points of explanation:

  • The initial {literal} is to tell Smarty (CiviCRM's templating engine) that it should ignore everything that comes next until it sees {/literal}. This is needed because JavaScript uses the curly brace character and Smarty will become very confused if we don't tell it to relax beforehand.
  • In this specific example, the tag "to be checked" had 6 as its id, so adjust appropriately if you're following along at home.
  • entity_id: {/literal}{$contactId}{literal} means that {$contactId} is a smarty tag (and is replaced by a number, the id of the contact
  • When the contact has been tagged, the function success is called, and it removes the "To be checked" button from the toolbar.
  • It might be even better to have the button create a new activity "To be checked" that is assigned to the person responsible for checking contacts. The API to call would be civicrm_activity_create. The details of the parameters for the actual implementation is an exercise left to the reader.

Ajax behind the scenes

It is useful to know what happens when you use the Ajax interface to help you debug problems with it.

The $().crmAPI call accesses a URL like this (for Drupal with clean URLs enabled):

http://eg.org/civicrm/ajax/rest?fnName=civicrm/<entity>/<action>&json=1&param1=xxx&param2=yyy...

To create a tag, for example, the following URL gets accessed:

http://eg.org/civicrm/ajax/rest?fnName=civicrm/tag/create&json=1&name=
     example&description=direct

Tip: In order to test an API function that you want to use in your PHP code, a template, or via the REST interface, you can use the Ajax interface to figure out the right parameters. For instance, if you want to fetch all the tags of a contact (method civicrm_entity_tag_get), log in to CiviCRM and then paste this URL into your browser:

http://example.org/civicrm/ajax/rest?fnName=civicrm/entity_tag/get&json=1

It should return {"is_error":1,"error_message":"entity_id is a required field."}. So you add the entity_id (which should be the contact id in this case). Now try this one:

http://example.org/civicrm/ajax/rest?fnName=civicrm/entity_tag/get&json=
    1&entity_id=1

... which returns:

[{"tag_id":"4"},{"tag_id":"3"},{"tag_id":"1"},{"tag_id":"14"}]

You can also now see the format of the returned data. This should give you a good idea of how to use this API function in other contexts.

Autocomplete and search contacts

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="../{$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).

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

Calling the API from a template

This section assumes you know how to find the template used to render a page and you know how to over-ride a template. Read the section on templating in the developer documentation if you're not sure.

On some templates, you might want to display more information than what is available by default, for example, displaying the list of groups a contact belongs to next to his or her tags.

You can use the API to fetch that information from within the template and assign it to a Smarty variable that you can then display just like any other variable.

The general syntax is {crmAPI var="new variable name" entity="entity name" action="action name" param1="xxx" param2="yyy"}

For example to fetch all groups the user id 42 belongs to and assign them to the variable groups:

{crmAPI entity="group_contact" action="get" var="groups" contact_id=42}

The following code adds the list of groups below the list of tags on the contact summary page (CRM/Contact/Page/View/Summary.tpl)

<tr>
  <td class="label">Groups</td>
  <td id="groups">
{crmAPI entity="group_contact" action="get" var="groups" contact_id=$contactId}
{foreach from=$groups item=group}
{$group.title},
{/foreach}
 </td>
</tr>

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.  

Access the REST API from other languages

The REST interface is language neutral (any language can use it as soon as it operates over HTTP requests), and 3 external libraries have been written by others in the CiviCRM community (and are in various states of completion):

  1. perl: http://search.cpan.org/~wmorgan/
  2. ruby: http://github.com/cap10morgan/civicrm-client-rest-ruby
  3. python: http://dev.plone.org/collective/browser/collective.civicrm.pycivicrm/trunk
Please refer to the documentation provided with each library to see how to use them (or complain to their authors if it is lacking).




your comment:
name :
comment :

If you can't read the word, click here
word :