Skip to main content
Custom fields let each workspace store extra CRM data on contacts and companies. In the public API:
  • field definitions are exposed as read-only metadata
  • field values are stored in custom_data
  • updates to custom_data use partial merge semantics

1. Read field definitions

Use the dedicated definition endpoints to discover valid field keys and types before writing values.
curl -X GET "https://app.leonar.app/api/v1/contacts/custom-fields" \
  -H "Authorization: Bearer leo_your_api_key"
Example response:
{
  "data": [
    {
      "id": "cf2b8df3-1c85-4e5d-8f50-0c10b3994e90",
      "key": "crm_tier",
      "label": "CRM Tier",
      "type": "select",
      "options": [
        { "value": "enterprise", "label": "Enterprise" },
        { "value": "mid_market", "label": "Mid-market" }
      ],
      "is_required": false,
      "position": 0
    }
  ],
  "meta": {
    "total": 1,
    "limit": 1,
    "offset": 0,
    "has_more": false
  }
}

2. Read custom field values

Custom field values are returned in the custom_data object on contact and company responses.
{
  "data": {
    "id": "contact-uuid",
    "first_name": "Sophie",
    "custom_data": {
      "industry_code": "A12",
      "vip": true
    }
  }
}

3. Update custom field values

PUT /contacts/{id} and PUT /companies/{id} merge custom_data into the existing object:
  • sent keys are created or updated
  • keys set to null are removed
  • omitted keys are preserved
curl -X PUT "https://app.leonar.app/api/v1/contacts/contact-uuid" \
  -H "Authorization: Bearer leo_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "custom_data": {
      "industry_code": "A12",
      "vip": null
    }
  }'
If the contact already had:
{
  "custom_data": {
    "crm_owner": "alice",
    "vip": true
  }
}
the result becomes:
{
  "custom_data": {
    "crm_owner": "alice",
    "industry_code": "A12"
  }
}

4. Validation rules

The API validates custom_data against the workspace definitions:
  • unknown keys are rejected
  • select values must match an allowed option
  • multiselect values must all match allowed options
  • number, currency, boolean, date, datetime, url, and email values must match the field type
  • required fields cannot be removed with null
  1. Read definitions from /contacts/custom-fields or /companies/custom-fields
  2. Cache key, type, and options
  3. Read entities and inspect custom_data
  4. Send partial custom_data updates only for the keys you want to change