This guide explains how to sync custom fields between Xurrent and remote systems using Exalate.
Overview
Xurrent custom fields are defined in UI Extensions attached to Request Templates. Each template can have its own set of custom fields with different types and validation rules.
Prerequisites
- API token must have
ui_extensionspermission to read custom field definitions - Know the
templateIdof the request (available asentity.templateIdorreplica.templateId)
Outgoing Sync (Xurrent → Remote System)
To send custom fields from Xurrent to the remote system:
// Send all custom fields
replica.customFields = entity.customFields
// Send specific custom fields by name
replica.customFields."Distribution Center" = entity.customFields."Distribution Center"
replica.customFields."Story Points" = entity.customFields."Story Points"
//Send specific custom fields by name
replica.customFields."Story Points" = entity.customFields."story_points"
// Access custom field value directly
replica.myCustomValue = entity.customFields."Priority Level"?.value
Converting Select Field IDs to Labels
Xurrent API returns internal IDs for select fields (e.g., value_1). To get the display label:
// Get display label for a select field value
def internalValue = entity.customFields."Company"?.value // Returns: "value_2"
def displayLabel = nodeHelper.getCustomFieldValueLabel(entity.templateId, "company", internalValue)
// Returns: "Acme Corporation"
replica.companyName = displayLabel
Incoming Sync (Remote System → Xurrent)
To receive custom fields from the remote system and set them in Xurrent:
Method 1: Using nodeHelper.getCustomField() (Mandatory)
This method validates field names and values automatically:
// Text fields
entity.customFields."Description" = nodeHelper.getCustomField(entity.templateId, "Description", "Task details here")
// Number fields
entity.customFields."Story Points" = nodeHelper.getCustomField(entity.templateId, "Story Points", 5)
entity.customFields."Cost Estimate" = nodeHelper.getCustomField(entity.templateId, "Cost Estimate", 1234.56)
// Select fields (can use display label OR internal ID)
entity.customFields."Priority" = nodeHelper.getCustomField(entity.templateId, "Priority", "High")
entity.customFields."Company" = nodeHelper.getCustomField(entity.templateId, "Company", "value_1") // Internal ID also works
entity.customFields."company" = nodeHelper.getCustomField(entity.templateId, "company", "value_2") // Internal ID for field name and value also works
// Date fields (must use YYYY-MM-DD format)
entity.customFields."Due Date" = nodeHelper.getCustomField(entity.templateId, "Due Date", "2025-12-31")
// DateTime fields (must use UTC format)
entity.customFields."Meeting Time" = nodeHelper.getCustomField(entity.templateId, "Meeting Time", "2025-12-31T14:30:00Z")
// Time fields (must use HH:mm format)
entity.customFields."Start Time" = nodeHelper.getCustomField(entity.templateId, "Start Time", "09:30")
// Email fields
entity.customFields."Contact Email" = nodeHelper.getCustomField(entity.templateId, "Contact Email", "john.doe@company.com")
// Rich text fields
entity.customFields."Custom Description" = nodeHelper.getCustomField(entity.templateId, "Custom Description", "**Bold** and __italic__ text")
entity.customFields."Custom Description" = nodeHelper.getCustomField(entity.templateId, "Custom Description", nodeHelper.convertJiraWikiToXurrent(replica.description)) // in case the remote is jira
entity.customFields."Custom Description" = nodeHelper.getCustomField(entity.templateId, "Custom Description", nodeHelper.convertHTMLToXurrent(replica.description)) // in case the remote is system which supports HTML fomatting
// Clear/reset a field (set to null or empty)
entity.customFields."Optional Field" = nodeHelper.getCustomField(entity.templateId, "Optional Field", null)
entity.customFields."Optional Field" = nodeHelper.getCustomField(entity.templateId, "Optional Field", "")
Supported Field Types
| Type | Format | Example Value |
|---|---|---|
text | Any string | "Task details here" |
text area | Any multiline string | "Task details here for more details" |
rich_text | Xurrent rich text format | "**bold** and __italic__" |
number | Integer or decimal | 42 or 1234.56 |
checkbox | boolean value | true or false |
select | Option label or internal ID | "High" or "value_1" |
date | YYYY-MM-DD | "2025-12-31" |
date_time | YYYY-MM-DDTHH:mm:ssZ (UTC) | "2025-12-31T14:30:00Z" |
time | HH:mm | "09:30" |
email | Valid email address | "user@example.com" |
Validation Rules and Expected Errors
Select Fields
Values must match an existing option (by label or internal ID).
// Valid
entity.customFields."Priority" = nodeHelper.getCustomField(templateId, "Priority", "High")
entity.customFields."Priority" = nodeHelper.getCustomField(templateId, "Priority", "value_1")
// Invalid - throws error
entity.customFields."Priority" = nodeHelper.getCustomField(templateId, "Priority", "SuperHigh")
Error:
Invalid value 'SuperHigh' for custom field 'Priority'.
Available options: "Low" (id: value_1), "Medium" (id: value_2), "High" (id: value_3)
Number Fields
Values must be valid integers or decimals.
// Valid
entity.customFields."Points" = nodeHelper.getCustomField(templateId, "Points", 5)
entity.customFields."Points" = nodeHelper.getCustomField(templateId, "Points", "5")
entity.customFields."Cost" = nodeHelper.getCustomField(templateId, "Cost", 123.45)
// Invalid - throws error
entity.customFields."Points" = nodeHelper.getCustomField(templateId, "Points", "five")
Error:
Invalid number value 'five' for custom field 'Points'.
Expected a valid number (integer or decimal).
Email Fields
Values must be valid email addresses.
// Valid
entity.customFields."Contact" = nodeHelper.getCustomField(templateId, "Contact", "user@example.com")
// Invalid - throws error
entity.customFields."Contact" = nodeHelper.getCustomField(templateId, "Contact", "not-an-email")
Error:
Invalid email format 'not-an-email' for custom field 'Contact'.
Expected a valid email address (e.g., user@example.com).
DateTime Fields
Values must be in UTC format: YYYY-MM-DDTHH:mm:ssZ
// Valid
entity.customFields."Meeting" = nodeHelper.getCustomField(templateId, "Meeting", "2025-12-31T14:30:00Z")
entity.customFields."Meeting" = nodeHelper.getCustomField(templateId, "Meeting", "2025-12-31T14:30:00.123Z")
// Invalid - throws error
entity.customFields."Meeting" = nodeHelper.getCustomField(templateId, "Meeting", "2025-12-31 14:30:00")
entity.customFields."Meeting" = nodeHelper.getCustomField(templateId, "Meeting", "12/31/2025")
Error:
Invalid datetime format '2025-12-31 14:30:00' for custom field 'Meeting'.
Expected UTC format: yyyy-MM-ddTHH:mm:ssZ (e.g., 2025-12-02T10:11:00Z).
Note: Xurrent expects datetime in UTC. The UI will display in user's timezone based on profile settings.
Date Fields
Values must be in format: YYYY-MM-DD
// Valid
entity.customFields."Due Date" = nodeHelper.getCustomField(templateId, "Due Date", "2025-12-31")
// Invalid - throws error
entity.customFields."Due Date" = nodeHelper.getCustomField(templateId, "Due Date", "12/31/2025")
entity.customFields."Due Date" = nodeHelper.getCustomField(templateId, "Due Date", "31-12-2025")
Error:
Invalid date format '12/31/2025' for custom field 'Due Date'.
Expected format: yyyy-MM-dd (e.g., 2025-12-03).
Time Fields
Values must be in format: HH:mm
// Valid
entity.customFields."Start Time" = nodeHelper.getCustomField(templateId, "Start Time", "09:30")
entity.customFields."Start Time" = nodeHelper.getCustomField(templateId, "Start Time", "14:00")
// Invalid - throws error
entity.customFields."Start Time" = nodeHelper.getCustomField(templateId, "Start Time", "9:30 AM")
entity.customFields."Start Time" = nodeHelper.getCustomField(templateId, "Start Time", "9:30")
Error:
Invalid time format '9:30 AM' for custom field 'Start Time'.
Expected format: HH:mm (e.g., 12:30 or 09:05).
Field Not Found
When the field name doesn't exist in the template:
entity.customFields."NonExistent" = nodeHelper.getCustomField(templateId, "NonExistent", "value")
Error:
Custom field 'NonExistent' not found in template 12345.
Available fields: "Priority" (id: priority), "Description" (id: description), "Due Date" (id: due_date)
No Custom Field Definitions
When the template has no UI extension or API token lacks permissions:
entity.customFields."Field" = nodeHelper.getCustomField(templateId, "Field", "value")
Error:
No custom field definitions found for template 12345.
Ensure the template has a UI extension with custom fields defined,
and your API token has permission to access ui_extensions.
Helper Methods Reference
getCustomField(templateId, fieldName, value)
Creates a validated custom field object.
def cf = nodeHelper.getCustomField(entity.templateId, "Priority", "High")
entity.customFields."Priority" = cf
Troubleshooting
"No custom field definitions found"
- Verify the template has a UI extension attached
- Check API token has
ui_extensionspermission - Verify the templateId is correct
"Invalid value 'X' for custom field"
- For select fields, check available options in Xurrent UI
- Use the exact option label or internal ID
- Check for typos or extra whitespace
DateTime displaying wrong time
- Xurrent expects UTC format (
Zsuffix) - The UI displays time in user's timezone based on profile settings
- Always send UTC, Xurrent handles timezone conversion
Important Notes
- Date Format: Date fields must use
YYYY-MM-DDformat - DateTime Format: DateTime fields must use UTC format
YYYY-MM-DDTHH:mm:ssZ - Time Format: Time fields must use
HH:mmformat (24-hour, zero-padded) - Select Fields: Values must match existing options exactly (label or internal ID)
- Null/Empty Values: Setting null or empty string clears/resets the field
- Permissions: API token needs
ui_extensionspermission for field validation
More information
Have more questions? Ask the community