How to Configure Client Fields?
Configuring client fields lets you define custom fields and control their visibility for operators. Without custom fields, only a limited set of standard client-card fields is available.
When You'll Need This
- You need to add additional fields to the client card (for example, "Client Number", "Category", "Registration Date").
- Integration with external systems requires storing additional client information.
- You need to extend the standard client profile for your business processes.
What's Important to Know
- Client Fields (
/settings-page/client-fields): first block — custom field definitions (form + JSON); below — visibility toggles and optional visibility JSON. One Save button in the page header stores bothclient_fields_jsonandclient_card_fields— there is no second Save inside the visibility card. - Same visibility UI is also available under Field editor in the Client Card (
/settings-page/op-settings/client-fields, operator panel Settings menu): visibility only; save uses the op-settings header Save (batch operator-panel settings; needssettingspermission). See Field editor in the Client Card. - Standard fields — native OpClients columns:
phone,bot_id,bot_name,fullName(fromfull_name).clientType,whiteLabelin samples may be customextra_datakeys or legacy. - Custom field values are stored in the client's
extra_data. - Field form and JSON — basic inputs (key, type, label) plus optional properties; full list in the Client fields JSON reference. The field editor includes JSON examples snippets.
- Client Portal (self-registration): toggle Show on Client Portal registration adds the field to the
/registerform in Client Portal. Requiresportal_registration_enabledon the instance (instance settings, root). See Configure instance settings.
Before You Start
Step-by-step
1. Open Client Fields
- Open the Settings module via the menu or at
/settings-page. - In the side menu, expand Bots (Process Library).
- Click Client Fields (
/settings-page/client-fields).
2. Define fields and visibility
- In the first block, review or edit the field list and JSON (
custom_fields_json). Use Add field or edit JSON (reference). - In the second block, set visibility toggles for standard and custom fields.
- Optionally expand visibility JSON — same data as toggles; editors stay in sync.
- Click the single Save in the page header to persist both field definitions and visibility. A success notification appears after a successful save.
3. Alternative: visibility only in op-settings
Open Field editor in the Client Card (/settings-page/op-settings/client-fields) from operator panel Settings for the same visibility controls; use the on-page link to Client Fields for full field definition. Save with the op-settings header button. Details: Field editor in the Client Card.
JSON examples (same as the JSON examples block in the UI)
At the bottom of the Client Fields page, a selector offers five scenarios — the JSON below matches that content. Names in the UI are short; here each example explains what it is meant to demonstrate. Each block is the field object payload (under custom_fields_json when saved). Copy it, rename keys to match your project, then click Save in the page header.
Two levels of keys: outer keys (full_name, store_id, etc.) are your field names in client data; inner keys (type, label, association…) are schema parameters the UI understands. After each sample, a short list explains why each key is there.
Basic
Three standalone fields of different types: short text, date, and integer with a default value for loyalty points. Use it as a minimal starter without validation or cross-field logic.
{
"full_name": {
"type": "STRING",
"label": "Full name"
},
"birth_date": {
"type": "DATE",
"label": "Date of birth"
},
"loyalty_points": {
"type": "INTEGER",
"label": "Points",
"default": "0"
}
}
Keys and why: type — data type in the form; label — caption for operators; default — pre-filled value (here for the numeric field). Names like full_name, birth_date, loyalty_points are only examples — use your own keys.
Date / time + validation
Two time fields (type_string: time, HH:mm format). Both are required; the end field adds a cross-field check via validate: end time must be after start. That object is not exposed as separate toggles in the form — configure it in JSON.
{
"start_time": {
"type": "STRING",
"label": "Start",
"type_string": "time",
"format": "HH:mm",
"string_input": {},
"rules": ["required"]
},
"end_time": {
"type": "STRING",
"label": "End",
"type_string": "time",
"format": "HH:mm",
"string_input": {},
"rules": ["required"],
"validate": {
"required_field_not_empty": "start_time",
"rules": {
"type": "time",
"val_from_field": "start_time",
"action": "gt"
}
}
}
}
Keys and why: again type and label. For time-as-string fields: type_string: "time" tells the UI to treat input as time; format is the mask (HH:mm); string_input: {} enables the matching input widget. rules: ["required"] marks the field mandatory (also available from the form). The validate object is a cross-field rule: required_field_not_empty requires start_time to be set; nested rules compares end time to start_time with action gt (greater than — strictly later). Exact validate shapes depend on the scenario — use this snippet as the pattern.
Linked field
A field with association stores the linked record’s ID; a second field shows a human-readable label (e.g. name), is hidden in the quick-create popup, and is read-only. Typical “stored ID + display label for operators” pattern.
{
"store_id": {
"type": "INTEGER",
"label": "Store",
"association": {
"as": "store_name",
"model_field_label": "name",
"fetch_limit": 500
}
},
"store_name": {
"type": "STRING",
"label": "Store name",
"hidden_in_create_popup": true,
"non_editable": "true"
}
}
Keys and why: association describes a link to another entity: as — the other field key in this JSON that receives the display label; model_field_label — which field from the linked record to show; fetch_limit — how many rows can be loaded for the picker. On store_name: hidden_in_create_popup: true hides it in quick create; non_editable: "true" makes it read-only (the label is usually filled from store_id).
Row highlighting
Planned and actual time fields; one field uses sting_highlight so table rows get conditional colours based on comparing the two times. This is advanced behaviour and is wired only through JSON, not the field form.
{
"planned_finish": {
"type": "STRING",
"label": "Planned",
"type_string": "time",
"format": "HH:mm",
"string_input": {}
},
"actual_finish": {
"type": "STRING",
"label": "Actual",
"type_string": "time",
"format": "HH:mm",
"string_input": {},
"sting_highlight": {
"type": "STRING",
"highlight_rules": {
"type": "time",
"rules": [
{ "0": "actual_finish", "1": "planned_finish", "action": "gt", "color": "red" },
{ "0": "actual_finish", "1": "planned_finish", "action": "lte", "color": "green" }
]
}
}
}
}
Keys and why: for plain time fields — again type_string, format, string_input. sting_highlight (spelling as in the product) enables conditional row colouring; inside highlight_rules, type: "time" sets the comparison mode; the rules array lists conditions: "0" and "1" reference other field keys, action (gt, lte, …) is the comparison, color is the row colour when the condition matches.
Table totals + link
A numeric field with a footer total (total_sum), width, alignment, and sorting; a second string field uses display_type: link so the value opens as a URL. Flags like total_sum are set in JSON when the form does not offer them.
{
"amount": {
"type": "FLOAT",
"label": "Amount",
"width": "90",
"align": "end",
"sortable": "true",
"total_sum": true
},
"invoice_url": {
"type": "STRING",
"label": "Invoice",
"display_type": "link",
"width": "60"
}
}
Keys and why: for the clients table — width (column width in px), align (end is typical for numbers), sortable: "true" enables sorting; total_sum: true includes the field in the footer total. For the link column: display_type: "link" opens the cell value as a URL in a new tab (see also the reference).
What Happens Next
- Custom field definitions are stored in
client_fields_json(instance settings). - Visibility is stored in
client_card_fields(operator panel settings). - Operators see and fill fields according to the toggles / visibility JSON.
How to Verify Everything Worked
- On Client Fields, confirm fields and toggles match what you want.
- Open a client card in the operator panel and verify the right fields appear.
Related Materials
- Client fields JSON reference — all properties inside
custom_fields_json - Configure user fields
- Field editor in the Client Card (op-settings) — same visibility block, different save affordance
- Configure instance settings —
portal_registration_enabled,client_portal_url
Important Notes
- ⚠️ On Client Fields, one header Save writes both parts. On op-settings/client-fields, saving uses the op-settings header Save (
settingspermission). - ⚠️ Deleting fields: data in
extra_datamay be lost. - 💡 Backup: make a copy of the JSON before major changes.