Skip to content

APIv4 Usage

API Input

Every API call consists of three elements: the entity, action, and parameters:

Entity: The "name" of the API. CiviCRM entities include Contacts, Activities, Contributions, Events, etc. Each API entity usually (but not always) corresponds to a table in the database (e.g. the Contact entity is the civicrm_contact table).

Supported Entities

The ongoing effort to port APIv3 entities to v4 is nearing completion. For updates or to help port a new entity, see this tracking issue.

Action: The "verb" of the API. The list of available actions varies for each entity, but most support a set of CRUD actions to create, get, update & delete, etc.

Parameters: Settings or data to pass to the api function. Each action accepts a different set of parameters.

Consider these samples with commonly-used actions and parameters for the Contact entity:

Action Parameters Description
create {"values":{"contact_type":"Individual", "first_name":"Jane", "last_name":"Doe"}} Create a new contact of type "Individual" with first name "Jane" and last name "Doe"
get {"where":[["last_name", "=", "Doe"]], "limit":25} Fetch the first 25 contacts with the last name "Doe"
delete {"where":[["id", "=", 42]]} Delete the contact with id "42"

API Explorer

For full, up-to-date details about specific entities, actions and parameters, use the API Explorer.

API Output

The API returns an array, with each item representing one record (also an array). In PHP, this output is contained in an ArrayObject, which can be accessed like an array using e.g. $result[0] or foreach ($result as ...).

See the php docs for a full list of methods ArrayObjects support

It also has the following methods in addition to or overriding the base ArrayObject:

  • $result->first(): returns the first item, or NULL if not found.
  • $result->single(): returns a single item, or throws an exception if not exactly one item was returned.
  • $result->last(): returns the last item, or NULL if not found.
  • $result->itemAt($index): returns the item at a given index, or NULL if not found.
  • $result->indexBy($field): reindexes the array by the value of a field.
  • $result->column($field): flattens the array, discarding all but a single field (call this second if using in conjunction with indexBy to create a key=>value array).
  • $result->count(): get the total number of results. See note below on use with LIMIT.


Sometimes you want to limit the number of results returned (e.g. when using a pager) but also need the full count of results outside the limit you have set. Adding row_count to the select clause will trigger the api to include the complete set of results in $result->count().


If you need to use functions such as is_array on the result you can cast it you cast it to an array, (array) $result, or use the getArrayCopy() method.


API Security

By default, APIv4 validates every action according to the permission level of the logged-in user. This can be disabled only when calling via PHP code. API Permissions are also able to be altered via hook.

More information on API Security can be found in the Security Documentation.

API Interfaces

The API is available in many environments (such as PHP, CLI, and JavaScript), and the notation differs slightly in each language. However, if you understand the canonical notation, then others will appear as small adaptations.

Use Outside of CiviCRM

If you're writing a Drupal module, a Joomla extension, a WordPress plugin, or a standalone script, then you may need to bootstrap CiviCRM before using the API.


This is the canonical API; all other environments are essentially wrappers around the PHP API.

There are two ways to call the api from PHP - which one you choose is a matter of convenience and personal preference. For example, you may prefer OOP syntax because IDE code editors provide autocompletion. Or if you need to work with the parameters as an array, traditional syntax will be more convenient.

APIv4 PHP Examples

Traditional (Procedural)

The function civicrm_api4($entity, $action, [$params], [$index]) accepts an array of parameters and returns the Result.

$result = civicrm_api4('Contact', 'get', [
  'where' => [
    ['last_name', '=', 'Adams'],
    // Option transformation.
    ['gender_id:name', '=', 'Male'],
    // Implicit join.
    ['employer_id.is_opt_out', '=', FALSE],
  'limit' => 25,

$index provides a convenient shorthand for reformatting the Result array. It has different modes depending on the variable type passed:

  • Integer: return a single result array; e.g. $index = 0 will return the first result, 1 will return the second, and -1 will return the last.
  • String: index the results by a field value; e.g. $index = "name" will return an associative array with the field 'name' as keys.
  • Non-associative array: return a single value from each result; e.g. $index = ['title'] will return a non-associative array of strings - the 'title' field from each result.
  • Associative array: a combination of the previous two modes; e.g. $index = ['name' => 'title'] will return an array of strings - the 'title' field keyed by the 'name' field.

Object-Oriented (OOP)

An Action class provides setter methods for each parameter. The execute() method returns the Result.

$result = \Civi\Api4\Contact::get()
  ->addWhere('last_name', '=', 'Adams')
  ->addWhere('gender_id:name', '=', 'Male')

Warning: Class names don't always match entity names!

For example, the entity "Case" is a reserved word in PHP and therefore could not be the name of a class, so it had to be named something else ("CiviCase"). Internally, calling civicrm_api4('Case', 'getFields') will translate to Civi\Api4\CiviCase::getFields. Custom data entities are another example. When writing generic functions that work with multiple entities, we strongly recommend against clever code like this: call_user_func(['\Civi\Api4\' . $entity, 'get'], ...), and suggest using this more reliable alternative: civicrm_api4($entity, 'get', ...).


The AJAX interface is automatically available for web-pages generated through CiviCRM (such as standard CiviCRM web-pages, CiviCRM extensions and custom CiviCRM templates).

Inputs are identical to the traditional PHP syntax:

CRM.api4('entity', 'action', [params], [index])

From an Angular app, use the service crmApi4() which has an identical signature but works within the $scope.digest lifecycle.

Both functions return a Promise, which resolves to a Result array.

CRM.api4('Contact', 'get', {
  where: [
    ['last_name', '=', 'Adams'],
  limit: 25
}).then(function(results) {
  // do something with results array
}, function(failure) {
  // handle failure

Use on Non-CiviCRM Pages

The AJAX interface could be made available to other parts of the same website (e.g. a Drupal module or WordPress widget) by calling Civi::resources()->addCoreResources() from PHP. Please note that the AJAX interface is subject to API Security and Same Origin Policy.

Command line


cv supports multiple input formats for APIv4. The API Explorer uses the JSON format in generated code:

cv api4 Contact.get '{"where":[["first_name", "=", "Alice"], ["last_name", "=", "Roberts"]]}'

This format may be cumbersome to enter manually, so the same API request could also be written like this:

cv api4 Contact.get +w 'first_name = "Alice"' +w 'last_name = "Roberts"'

For more examples, refer to the output of cv --help api4.


Adding version=4 to a drush command will cause v4 api to be called rather than v3.


APIv4 is not yet available as a wp-cli command.


APIv4 is not yet available via REST. This is being tracked in dev/core#1310.


Because Smarty is an older technology, there are no plans to port the APIv3 smarty function to APIv4.

Scheduled jobs

APIv4 is not yet available for scheduled jobs.