Create and Modify Custom Fields

Overview of creating and updating custom fields.

Overview

In Zylo, customizable fields can be created for applications, contracts, payments, and users. These fields (referred to commonly as "Custom Fields") allow for users to create their own updateable and filterable fields that are attached to an application, contract, payment, or user.

Creating a payments-, contracts-, or users-scoped custom field requires the corresponding custom fields feature to be enabled for your company; see Choosing the entity_type below. Applications-scoped custom fields are unaffected.

Below is a table describing how each type of custom field:

TypeDescription
booleanEquivalent to the Yes/No type as seen in the Zylo App.
choiceEquivalent to the Dropdown type as seen in the Zylo App.
multichoiceEquivalent to the Multi-Select type as seen in the Zylo App. Its value is an array of selected options rather than a single value.
currencyChoose this to have the field treated and validated as a currency
dateChoose this to have the field treated and validated as a date
emailChoose this to have the field treated and validated as an email
numberChoose this to have the field treated and validated as a number
textChoose this to have the field treated and validated as text

Note on the options Property

When retrieving a Custom Field from either the List or the By ID routes the individual record's options will have varying shapes:

If boolean type

{
  ...
  "type": "boolean",
  "options": {
    "default": "Yes",
    "options": [
      "Yes",
      "No",
      "Not Specified (-)"
    ]
  },
  ...
}

If choice type

{
  ...
  "type": "choice",
  "options": {
    "default": "value1",
    "options": [
      "value1",
      "value2",
      "value3"
    ],
    "disabled_options": []
  },
  ...
}

If multichoice type

{
  ...
  "type": "multichoice",
  "options": {
    "default": "value1",
    "options": [
      "value1",
      "value2",
      "value3"
    ],
    "disabled_options": []
  },
  ...
}

For all other types; currency, date, email, number, and text

{
  ...
  "type": "text",
  "options": {},
  ...
}

Creating a Custom field

Naming

A custom field's display name is what a user sets; the name used in queries and filters (custom_fields.<slug>) is derived from it automatically. The slug is the display name lowercased, with spaces changed to underscores, hyphens preserved, and other special characters removed — for example, QA Choice P0-3 becomes custom_fields.qa_choice_p0-3.

Choosing the entity_type

The entity_type property controls which resource the custom field applies to. It accepts applications, contracts, payments, or users, and defaults to applications when omitted.

{
  ...
  "entity_type": "applications", // or "contracts" / "payments" / "users" (feature-gated — see below)
  ...
}

entity_type is set at creation only and cannot be changed afterward — a field's scope is fixed for the life of the field.

Creating a payments-, contracts-, or users-scoped custom field requires the corresponding custom fields feature to be enabled for your company. When the feature is not enabled, a request with that entity_type is rejected; applications-scoped fields are unaffected.

Choosing the boolean type

When creating a boolean type the options top level property must take the shape:

{
  ...
  "type": "boolean",
  "options": {
    "default": "Yes", // or "No" or "Not Specified (-)"
    "options": [
      "Yes",
      "No",
      "Not Specified (-)"
    ]
  },
  ...
}

The options array must contain the values Yes, No, Not Specified (-), or a subset of those three.

The default may be omitted, null, or empty string ''. However if one of those values are pass the default will be set to Not Specified (-).

Choosing the choice type

When creating a choice type the options top level property must take the shape:

{
  ...
  "type": "choice",
  "options": {
    "default": "value1", // or "value2" or "value3"
    "options": [
      "value1",
      "value2",
      "value3"
    ]
  },
  ...
}

The default may be omitted, null, or empty string ''. However if any other value then it must be present in the options array.

Each entry in options must be a non-empty, non-whitespace-only string and cannot contain a semicolon (;) — semicolons are reserved as the delimiter for multichoice values in CSV import.

NOTE: the disabled_options array cannot be modified through the API.

Choosing the multichoice type

When creating a multichoice type the options top level property must take the same shape as choice:

{
  ...
  "type": "multichoice",
  "options": {
    "default": "value1", // or "value2" or "value3"
    "options": [
      "value1",
      "value2",
      "value3"
    ]
  },
  ...
}

The default may be omitted, null, or empty string ''. However if any other value then it must be present in the options array.

Unlike choice, a multichoice field's value (as set on an application or payment via its custom_fields object) is an array of selected options rather than a single string, e.g. "regions": ["value1", "value2"]. Each item in the array must be present in the field's options array.

This holds even when a record has no explicit selection: a record with no value set for the field returns an array containing the field's default (or an empty array [] if default is null/omitted) — never a bare string or null.

NOTE: the disabled_options array cannot be modified through the API.

Choosing currency, date, email, number, and text types

When choosing one of these types the options property can be omitted, null, or an empty object {}.

Updating a Custom field

Currently only the description, is_enabled, and position are the only properties that can be updated at this time via PATCH. In particular, entity_type and type cannot be changed after a field is created via PATCH — see below for the one exception to type.

Changing a field's type

type cannot be changed via PATCH. The one exception — migrating a choice field to multichoice — is a dedicated action: POST /v2/customFields/{customFieldId}/convertToMultichoice. This is a one-way migration — a multichoice field cannot be changed back to choice, and no other type change is permitted (e.g. text to number). choice and multichoice share the same options shape, so the options object itself needs no changes.

Existing values are migrated automatically as part of this request: every existing value for the field is converted from a single selection into a single-element array (e.g. "Medium" becomes ["Medium"]), so reads immediately reflect the new array shape. A value that was already an array is left as-is.