If I do a civicrm_api3('contact', 'getsingle', ['id'=>123]) I get lots of data, including gender.

However when I try to set the gender like:

civicrm_api3('contact', 'create', ['id'=>123, 'gender'=>'Male'])

It reports no error, but neither does it do anything(!).

(Nb. I'm using v4.4.16 LTS)


Experimenting with the API explorer, I found that 'gender_id' => 'Male' worked.

| improve this answer | |
  • Do you know if this is a generalised case that works for all such ids (e.g. country_id)? Obvs I can test them one by one, but it would be useful to be able to rely on this behaviour. – artfulrobot Jul 31 '15 at 15:22
  • The latest version of the API explorer should help, as the API should still be fairly consistent between version 4.4 and the latest release at the moment: dmaster.demo.civicrm.org/civicrm/api login demo/demo – John Jul 31 '15 at 15:24
  • Thanks, John. Yes the new API explorer is v nice. related question – artfulrobot Jul 31 '15 at 16:09

The field name is gender_id not gender.

For a bit of history and explanation:

The contact api automatically takes a few fields (notably gender_id, prefix_id, suffix_id, state_province_id and a few others) and gives you the label as well as the id for convenience. However this is not consistent across all apis and is not something I would generally rely on.

In v4.4 a lot of work was done to standardize option lists and the upshot is that 'create' type actions will now accept either the id or the name of any option (not the translated label).

So civicrm_api3('contact', 'create', ['id'=>123, 'gender'=>'Male']) and civicrm_api3('contact', 'create', ['id'=>123, 'gender'=>2]) will do the same thing.

Come to think of it, it would be nice to accept either 'gender' or 'gender_id' since that's more consistent with the output. Here's a PR for that.

| improve this answer | |

Try using gender_id when creating the contact, rather than gender.

| improve this answer | |

I solved it by creating a lookup function (which can be used for any field that takes an id that you wouldn't know):

function getIdforLabel($entity, $field, $label) {

    $result = civicrm_api3($entity, 'getoptions', ['sequential' => 1, 'field' => $field]);
    if ($result['is_error']) {
      throw new \Exception("Failed to getoptions for $entity.$field");
    foreach ($result['values'] as $result) {
      if ($result['value'] == $label) {
        return $result['key'];
    throw new \Exception("Supplied value, '$label' is not a valid option.");

So then you can go:

$gender_id = getIdForLabel('contact', 'gender_id', 'Male');
civicrm_api3('contact', 'create', ['id'=>$contact_id, 'gender_id'=>$gender_id]);

Clearly davejenx's answer is simpler :-)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.