API documentation + state of the API

Publié
2011-11-16 15:16
Written by
Eileen - member of the CiviCRM community and Core Team member - about the Core Team

As many of you know with 3.4 & 4.0 a new API came out (APIv3). The new API had a number of improvements over the previous v2 including

  •  Consistent naming of entities & actions
  •  civicrm_api() wrapper that eliminated the need to do lots of 'require_once' & allowed us to move functionality into the wrapper rather than replicating it. (note that as long as civicrm is initialised you don't need any 'require_once' to call api functions using civicrm_api()).
  •  A consistent format for the results returned
  •   Consistent use of the 'id' param (& returning in in results using 'id')
  • A new API explorer to see the API functions.
  • wrapper functions such as getsingle, getvalue, getcount to allow you to get simpler result output
  • API chaining - the ability to pass results from one API call to another
  • Consistent handling of dates (based on strtotime so 'now' etc now supported)
  • Lots of bug fixes 
  • Many more tests

 

The API in 4.1 continues to be more of the same but we have continued to try to standardise & reduce the code.

 

Code driven documentation

 

One problem with a rapidly changing piece of code is that keeping the documentation up-to-date can be challenging. With APIv3 we have tried hard to keep the documentation & the code closely tied. So, the primary sources of documentation are the examples which are in the api/v3 folder of your install and the API explorer.

 

API explorer is based on the results of the 'getfields' function - which can be issued against any entity. e.g.

 

  • civicrm_api('email', 'getfields', array('version' =>3,));

 

Will tell you the fields for the Email entity. In 4.1 we have taken this a bit further & made it 'action' aware so

 

  • civicrm_api('email', 'getfields', array('version' =>3,'action' => 'get'));

 

returns different results to

 

  • civicrm_api('email', 'getfields', array('version' =>3,'action' => 'delete')); (or create)

 

You can see the different results in the phpdoc generated documentation

 

We've been very keen to push code generated documentation because it keeps the work on code & documenting closely tied. If you see an example in the examples directory it is there because it was generated by a test.

 

Likewise the results from the getfields function are dual purpose. They provide information to documenters but they are also implemented by the code. The api wrapper function (civicrm_api) queries getfields & if a field is designated as being 'api.default' (shows as default in the phpdoc link) then it is added to your array if needed. If it's set as 'api.required' (shows as 'Required' in the phpdoc) & you haven't passed it in you will get an error. These criteria are set in the _spec functions in the api.

 

There has been some debate in the API team as to how heavily to promote the phpdoc generated documentation. I have been keen to push it because it causes people also to note the comments that express limitations of particular API & can save time and because it causes people to see the code & hopefully engage with it. Another advantage is that we can embed links to the examples within it (although I haven't figured out how to link to those examples in subfolders).

 

However, Xavier, points out that as the only function in the api that you are 'allowed' to call from outside the api itself is 'civicrm_api' we shouldn't be promoting documentation that includes the function names. (actually civicrm_error is permitted too). It's a fair point.

 

Going forwards - validation

 

API validation varies from API to API. Some groan under the weight of excessive validation & others have none. I think it's most likely we will move validation to be based on 'getfields' results (e.g. if a field is an fk to contact we can check if the contact exists). But the question is how much validation we will do in the API & how we can allow people to opt out of it.

 

Some validation has already been moved out of the individual api. Checking for mandatory fields was orignally restructured by using a standard 'verify_mandatory' function & we've now mostly deprecated that in favour of a getfields approach. We have also 'sucked' date validation into the api wrapper layer already (so 'last saturday of first week of november next year' is now a valid paramater across all api date fields :-).

 

Standardisation

As many people have notice the formats for specifying which fields to return & the number of fields to return are not standard across the API. We are crawling closer to supporting the following across all api

 

$params['return'] = array(fields to return),

$params['options']['limit'] = no of rows to return

$params['options']['offset'] = starting row

$params['options']['sort'] = sort string

Filed under

Comments

I see you've (accidentally?) used $options instead of $params in that last bit. Is this a hint of what's to come... the missing 4th argument for civicrm_api()?

?action=get&entity=cookie&option.offset=0&option.limit=99999999

Great stuff!!! Hope to contribute a little during the eurosprint

On 4.1

civicrm_api('Contact', 'getactions', array('version' =>3,));

 

returns the list of actions available