Skip to content

APIv4 Pseudoconstants (Option Lists)

Some fields in CiviCRM are linked to an option list (aka Pseudoconstant). These fields are typically shown to the user as checkboxes, radios, or a dropdown-select of options from the pseudoconstant list.

The API provides tools for working with such fields; so that downstream developers do not need to translate between database values and option properties.

Option list properties

Each option in the list consists of attributes like id, name, label, description, color and icon. For a complete list and description of each attribute see the framework chapter: Pseudoconstant (Option List) Reference.

Which fields have option lists?

To find out which fields have option lists for a particular entity, use the getFields action from the API or API Explorer, e.g.

civicrm_api4('Contact', 'getFields', [
  'where' => [['options', '!=', FALSE]],
])
This will return a list of all fields for a given entity (in this example, "Contact") which have an option list.

Retrieving an option list

If you need to retrieve the full option list for a field, use the getFields action and set the loadOptions parameter to an array of the above properties you would like to retrieve. Try it in the API explorer, e.g.

civicrm_api4('Contact', 'getFields', [
  'where' => [['name', '=', 'contact_type']],
  'loadOptions' => ['name', 'label', 'description'],
])->first();
This will load information about the contact_type field including the list of available options (names will be ['Individual', 'Household', 'Organization'], labels will be localized translations if the site is not in English).

Tip

Unless you are building a form and need to render an option list for the user to select, in most cases you will not need to query getFields to e.g. match option ids to labels. The syntax below can automatically perform such transformations.

Option transformations

When reading or writing data from the API, a special suffix tells the API to transform between option ids and other properties. For example:

Writing

Activity::create()
  ->addValue('activity_type_id:name', 'Meeting')
  ...

Using this syntax saves you from needing to look up the id of an activity type. It also makes your code more portable, as option ids can change from one database to another, but names are consistent.

Reading

Get operations use the same syntax to reverse the lookup and transform an option id to another property.

Activity::get()
  ->addSelect('*', 'activity_type_id:label', 'activity_type_id:icon')
  ...

This tells the API to return all fields (*) plus the label and icon of the activity type, giving the data needed for a user-facing display.

Option Lists or Joins

The syntax for option transformations looks very similar to implicit joins (the difference being a colon instead of a dot). Your choice of which to use depends on the field. For example, the Contact gender_id field has an option list but not a foreign key, so you must use the option syntax (gender_id:label). But the Event campaign_id field has a foreign key instead of an option list, so you would use a join (campaign_id.title).