Appearance
Data Adaptation
There are ways to adapt the data being read or written by the Common Model. For example, if one system displays data as a decimal number, but you want the data to show as a monetary value, you can transform that data as the Common Model reads and/or writes it. Adapting data is more likely to be done on the subscribing side, but it is possible to execute on both.
NOTE
Only available adaptation options will be displayed based on your configured Endpoints and Mapping Actions.
Advanced Tab
In the advanced settings, you can dictate when data gets transferred from the Common Model to other systems. For instance, on the subscribing side, you may want some functionality to only execute when a new record is created or only when data is updated. Also, data taken from the Common Model that is a string, but needs to be written to a Connector as a double or decimal value, changing the output, can be done here.
Read Action
| Setting | Description |
|---|---|
| FK System Override | When the data that is read from the Connector creates a Foreign Key on the Data Model, it will by default set the system of Connector. This override allows you to override the key as a value from another system. |
Write Action
| Setting | Description |
|---|---|
| FK System Override | When the data is written to the Connector, it will by default pull the Foreign Key value of the Connector it is writing to. This override allows you to override the key as a value from another system. |
| Supported Operations | By default, the map will execute for both Create and Updates; however, Supported Operations allows you to direct the map to only execute on a specific Write Operation, Create or Update. |
| Value Type | Converts the mapped value to a given type — numeric, date, etc. This is a conversion, not a display format, and it runs after any transforms on the map. See Value Formatting. |
| Supported Systems | By default, the map will execute for any system that posts a message that this Connector receives; however, Supported Systems allow you to only execute this map if the message came from a specific list of systems. |
| FK Use Label | By default, the Foreign Key map writes the value of the Foreign Key; however, this setting allows you to override the default and instead use the Label of the Foreign Key that is stored inside the Central Index. |
WARNING
Users should implement the Supported Systems functionality infrequently and only in necessary instances, as this will isolate the data transfer to that specific Mapping.
Transforms Tab
Transforms can be added to either subscribe or publish Mapping; however, they are more commonly used to modify the data being consumed by a system (on the subscribe side). Transforms can be strung together to manipulate data in multiple ways.
Transforms run in list order, and the Value Type setting on the Advanced tab is applied after all of them. That ordering matters whenever a transform produces your final wire format — see Value Formatting → Order of operations.
Transforms marked Recipes have worked examples under Transform Recipes.
| Transform | Description | Inputs |
|---|---|---|
| Addition | Adds a value to a property on the Data Model and outputs the result. | Add -- the value to be added |
| Auto-Number for Key | Generates a unique identifier for each child on a message (starts at 1, 2, and so on). | None (only used on primary key maps) |
| Business Logic Map | Adds conditional logic to a single property. Within a BizLogicMap, you can add Groups for more complex scenarios, where you can achieve And/Or scenarios, but between groups it supports only Or. For example, if the property value equals X or the property value equals Y, then return Z. Conditions are exact-match only — see the warning in its Recipes. | Group: And/Or, Operator, Value, Return Value. Else Return Value: If all of the groups return false, this value is returned from the map. |
| Business Logic Map - Simple | Adds conditional logic to a single property. This is the same concept as BizLogicMap, but only matches for equality and does not allow for more complex logic with groupings (e.g. if equals this value then return that value). Recipes | Comparison: The value you are comparing the property to be equivalent to; then Return: If the value of the property equals the value of the Comparison, then return this value. Return Null, Return Original Value, Else Return Value. |
| Compute Expression | This transform can be used to take in multiple properties and perform conditional logic or computation and return a value. Uses the syntax for .NET DataTable.Compute. Recipes | Expression |
| Convert From Base64 | Used to convert a property from a Base64 encoded string, typically in file upload scenarios. | None |
| Convert TimeZone to UTC | The inverse of Convert UTC To TimeZone: treats the incoming date/time as local to the chosen time zone and converts it to UTC. Typically used on a publish map when the source system stores local times. Accepts a date/time or a parseable date string. | Time Zone |
| Convert To Base64 | Encodes the value as a Base-64 string (UTF-8). | None |
| Convert UTC To TimeZone | Used to convert a date time that is in UTC format to a specific time zone, most likely on a subscriber. | Time Zone |
| CSV to List | A single property that is a character delimited list of values, split into a List. This transform will only work when mapping into values on the Common Model that is a list of strings. Recipes | Make Distinct, Trim Items, Character Separator |
| Date Change | Shifts a date/time by a fixed offset. Each unit is added independently and may be negative, so "-1 day, +2 hours" is a single transform. Useful for overlap windows on a read filter, or for aligning to a system that expects an inclusive end date. Recipes | Total Seconds, Total Minutes, Total Hours, Total Days, Total Months, Total Years |
| Date Only | Strips the time component, leaving midnight of the same date. Accepts a date/time or a parseable date string, so it doubles as a way to coerce a date string into a real date before a Formatting Template. | None |
| Default To Current Date | If the incoming property value is null, it will default to UTC date/time. Typically used on saves for a create record. | None |
| Default Value | If the incoming property value is null or empty, it will default to this value. Typically used on saves for a create record. Recipes | A predetermined value |
| Division | Takes a property on the Data Model and divides by a value; then, outputs the result. | A Divisor (the value of what you are dividing by) |
| Flatten Date/Time | Used to break a date apart into individual properties on a Save, or to combine them on a Read. For example: { "year": 2023, "month": 1, "day": 1 } | Include Time, Protocol, Year, Month, Day |
| Formatting Template | Takes one to many properties on the Data Model and does a string format; then, returns the result. The format of the template uses placeholders like {0}-{1}-{2}. The mapping engine replaces {0} with the value of the first property, and so on. Each placeholder can carry a format — {0:yyyy-MM-dd}, {0:D6}. See Value Formatting. Recipes | Template |
| From Epoch Time | Converts a Unix epoch timestamp in milliseconds into a UTC date/time. Pair with a Formatting Template to render it in the shape the target expects. | None |
| Invoke Instance Method (Deprecated) | Calls a named method on the incoming value by reflection. Deprecated — see the warning below. | Method Name, Parameters (type + value) |
| Invoke Static Method (Deprecated) | Calls a named static method on a named .NET class by reflection, passing the incoming value as the argument. Deprecated — see the warning below. | Class Name, Method Name, Parameter Types |
| Invoke Static Property | Returns the value of a named static property or field on a named .NET class. Ignores the incoming value. | Class Name, Property Name |
| JSON Contains | Executes a JSONPath. If it finds a value, it returns true, else returns false. Recipes | JSONPath |
| Math Truncate | Trims off all decimal values. | None |
| Multiplication | Multiplies a value to a property on the Data Model and outputs the result. | Multiplier (the value to be multiplied) |
| Parse to JSON | Takes a string value and generates a JSON object. | None |
| Regex Match | Pulls a value out of a string based on a pattern — for example, the month out of a date string, or an order number out of a description. Returns the first capture group ( ) of the match, not the whole match, and null when nothing matches. Recipes | Match Pattern |
| Regex Replace | Finds text matching a pattern and replaces it — reformatting (10 digits into a phone number), cleaning (stripping non-digits, collapsing spaces), or reordering parts of a value. A value that doesn't match passes through unchanged. Recipes | Match Pattern: tells it what to find in the string. Replace Pattern: tells it how to reformat the string based on what has matched. |
| Round | Applies rounding on a numeric property. Recipes | Behavior: Always round up, Always round down, Default. Precision. |
| String Join | Takes multiple values from a Publisher and writes them as a single, delimited string to the Subscriber. Recipes | Delimiter |
| Substring | Retrieves a portion of a string. For example, if a field can only accept 30 characters, Substring can be used to return only the first 30 characters of a property and remove the rest. | Starting Index: the position on the string you want to start with (e.g. the starting position is 0). Number of Characters. Recipes |
| Subtraction | Subtracts a value from a property on the Data Model and outputs the result. | Subtract -- the value being subtracted |
| To Epoch Time | Converts a date/time (or a parseable date string) into a Unix epoch timestamp in milliseconds. | None |
| To Lowercase | Lowercases the value. String input only — a non-string value raises an error, so place it after any transform that produces text. | None |
| To Title Case | Title-cases the value (e.g. acme holdings → Acme Holdings). String input only. | None |
| To Uppercase | Uppercases the value. String input only. | None |
| US State Abbreviation | Converts between US state names and their two-letter abbreviations, in either direction. Covers the 50 states, DC, and the USPS territories. Matching is case-insensitive; abbreviations come back uppercase and names in canonical casing. | Mode: Abbreviation → Full Name, or Full Name → Abbreviation. Return Original Value (default) or Else Return Value, used when no match is found. |
WARNING
Invoke Instance Method and Invoke Static Method are deprecated. They allow arbitrary .NET methods to be invoked from configuration and will be removed in a future release. Use a Compute Expression, a Business Logic Map, or a purpose-built transform instead.
TIP
Several of these transforms are the answer to "my format specifier isn't doing anything" — Date Only, Convert TimeZone to UTC, and From Epoch Time all coerce text or a number into a real date, which a Formatting Template can then format. See Value Formatting.
Transform Recipes
Worked examples for the transforms that take configuration. Each section below opens with how the transform behaves at the edges — what happens on no match, on a null, on the wrong type — followed by recipes you can copy. Every input → output pair shown was produced by the transform itself.
Leading and trailing spaces are trimmed
Transform fields drop leading and trailing whitespace when you leave them. A Delimiter of , is saved as ,, and a Replace Pattern can't be a lone space. Spaces inside a value are kept. In a regex, write \s or [ ] where you need a space at either end.
Regex Replace
Uses .NET regular expressions. Match Pattern finds the text, and Replace Pattern says what to put in its place.
- Every match is replaced, not just the first. Anchor with
^and$when the pattern should describe the whole value. - No match → the value passes through unchanged, type included. A match always produces text.
- In Replace Pattern,
$1,$2… insert what each( )group captured. Use${1}when a digit follows (${1}0), and$$for a literal$. Leave it blank to delete the match. - Case-sensitive by default. Start the pattern with
(?i)to ignore case. - Escape regex characters you mean literally:
.matches any character, so\.is a period. The same goes for( ) [ ] + * ? | ^ $ \. - Non-text values are converted to text first. A date becomes culture-dependent text like
3/9/2026 2:05:07 PM, so put a Formatting Template ahead of it to control that text.
Recipes
| Goal | Match Pattern | Replace Pattern | Input | Output |
|---|---|---|---|---|
| Format a 10-digit phone number, whatever punctuation it arrives with | ^\D*(\d{3})\D*(\d{3})\D*(\d{4})\D*$ | ($1) $2-$3 | 555.123.4567 | (555) 123-4567 |
| Strip everything except digits | \D | (blank) | (555) 123-4567 | 5551234567 |
| Insert dashes into a fixed-length ID | ^(\d{3})(\d{2})(\d{4})$ | $1-$2-$3 | 123456789 | 123-45-6789 |
Remove leading zeros (but keep a lone 0) | ^0+(?=\d) | (blank) | 000123 | 123 |
Reorder date text from MM/dd/yyyy to yyyy-MM-dd | ^(\d{2})/(\d{2})/(\d{4})$ | $3-$1-$2 | 03/09/2026 | 2026-03-09 |
| "Last, First" → "First Last" | ^\s*([^,]+?)\s*,\s*(.+?)\s*$ | $2 $1 | Doe, John | John Doe |
| Strip a fixed prefix | ^INV- | (blank) | INV-1042 | 1042 |
| Collapse runs of spaces to one | \s+(?=\s) | (blank) | Acme Holdings LLC | Acme Holdings LLC |
| Trim surrounding whitespace | ^\s+|\s+$ | (blank) | ␣␣Acme␣␣ | Acme |
| Mask all but the last four digits | \d(?=\d{4}) | * | 4111111111111111 | ************1111 |
| Normalize a suffix, ignoring case | (?i)\binc\.?$ | Inc. | Acme INC | Acme Inc. |
| Add a currency symbol | ^(\d+\.\d{2})$ | $$$1 | 19.99 | $19.99 |
| Blank out placeholder values | (?i)^\s*(n/?a|null|none|-)\s*$ | (blank) | N/A | (empty) |
Chaining: replace a placeholder with a real default
Source systems often send N/A, none, or - where they mean "no value". Two transforms in order:
- Regex Replace — Match
(?i)^\s*(n/?a|null|none|-)\s*$, Replace (blank).N/Abecomes empty;Nathandoesn't match and passes through. - Default Value — Value
Unknown. Fires on null or empty, so the blanked placeholder becomesUnknown.
Regex Match
Extracts part of a value. The thing to remember: it returns the first capture group ( ), not the whole match.
- Wrap what you want to keep in parentheses. A pattern with no group returns an empty string, even when it matches. To return the entire match, wrap the whole pattern:
(\d+). - Use
(?:…)to group without capturing, so alternatives don't steal group 1 — see the PO recipe below. - No match → null, unlike Regex Replace, which passes the value through. Follow with Default Value if you need a fallback.
- A full ISO timestamp read from JSON arrives as a date, not text, so text patterns like the month recipe below won't match it. Use a Formatting Template such as
{0:MM}instead. A date-only string like2026-03-09stays text.
Recipes
| Goal | Match Pattern | Input | Output |
|---|---|---|---|
Number after a # | #(\d+) | Order #12345 shipped | 12345 |
| Domain from an email address | @(.+)$ | jane@acme.com | acme.com |
| Month from an ISO date string | ^\d{4}-(\d{2}) | 2026-03-09 | 03 |
| Last four characters | (.{4})$ | 4111111111111111 | 1111 |
| First word | ^\s*(\S+) | ␣␣Jane Q Public | Jane |
| Last word | (\S+)\s*$ | Jane Q Public | Public |
| A reference that may follow either of two labels | (?:PO|Purchase Order)\s*#?\s*([\w-]+) | Purchase Order # A-77 | A-77 |
| ⚠ No capture group | \d+ | Order 12345 | (empty) |
| ✓ Same, with a group | (\d+) | Order 12345 | 12345 |
Formatting Template
Builds a string from one or more values with .NET composite formatting. Value Formatting is the full reference for format specifiers. The most important rule from it: a specifier like :D6 or :yyyy-MM-dd only applies to a real number or date — text passes through unformatted.
- On a multi-property map, the inner maps arrive as
{0},{1},{2}in the order listed. - A null or empty input is returned unchanged rather than rendered. A null inside a multi-property map renders as empty.
Recipes
| Goal | Template | Input | Output |
|---|---|---|---|
| Full name from two properties (multi-property map) | {0} {1} | John, Doe | John Doe |
| One-line address (multi-property map) | {0}, {1}, {2} {3} | Columbus, OH, 43215, US | Columbus, OH, 43215 US |
| Zero-padded document number | INV-{0:D6} | 42 (a number) | INV-000042 |
| ⚠ Same, but the value is text | INV-{0:D6} | "42" (text) | INV-42 |
| Date in the target's format | {0:yyyy-MM-dd} | a date | 2026-03-09 |
Chaining: format a value that arrives as text
When the specifier is ignored because the value is text, convert it first:
- Number as text → Compute Expression
Convert('{0}', 'System.Int32')→ Formatting TemplateINV-{0:D6}."42"becomesINV-000042. - Epoch milliseconds → From Epoch Time → Formatting Template
{0:yyyy-MM-dd}. - Date string → Date Only (or Convert TimeZone to UTC) → Formatting Template.
Compute Expression
Evaluates an expression after substituting each value into {0}, {1}, … as text. On a multi-property map, the inner maps fill the placeholders in order.
- Text values must be quoted in the expression: write
'{0}', not{0}. Unquoted text is read as a column name and fails with Cannot find column. Single quotes inside the value are escaped for you, soO'Brienis safe. - Numbers and booleans are left unquoted:
{0} * 2,IIF({0}, 'Yes', 'No'). - A null becomes the word
null. Unquoted, that is a real null, soIsNull({0}, 0)works. Inside quotes it becomes the text'null'. - Division is never integer division:
7 / 2is3.5. Substringhere counts from 1, unlike the Substring transform, which counts from 0.- Other useful functions:
IIF,IsNull,Len,Trim,Convert,LIKE(wildcards*or%), andIN (…).
Recipes
| Goal | Expression | Input | Output |
|---|---|---|---|
| Line total (multi-property: quantity, unit price) | {0} * {1} | 3, 19.99 | 59.97 |
| Sum two values where either may be null | IsNull({0}, 0) + IsNull({1}, 0) | 5, null | 5 |
| Label by sign | IIF({0} < 0, 'Credit', 'Debit') | -12.5 | Credit |
| Text to a flag | IIF('{0}' = 'Active', 1, 0) | Active | 1 |
| Bucket by a list of values | IIF('{0}' IN ('CA','OR','WA'), 'West', 'Other') | OR | West |
| Prefix test | IIF('{0}' LIKE 'TEST*', 'Y', 'N') | TEST-001 | Y |
| Two conditions across two properties | IIF({0} > 100 AND '{1}' = 'US', 'Domestic-Large', 'Other') | 150, US | Domestic-Large |
| Boolean to Yes/No | IIF({0}, 'Yes', 'No') | true | Yes |
| Concatenate text | '{0}' + ' ' + '{1}' | John, Doe | John Doe |
| Text to a number | Convert('{0}', 'System.Int32') | "41" | 41 |
| First three characters (1-based) | Substring('{0}', 1, 3) | ABCDEF | ABC |
Business Logic Map - Simple
A lookup table: if the value equals a Comparison, return its Return.
- Matching is exact and case-sensitive against the value as text:
Adoes not matcha. A boolean compares asTrueorFalse, capitalized. - No match returns Else Return Value, or the value itself when Return Original Value is on. A null input never matches a Comparison and goes to the else branch.
- The same Comparison can't be listed twice; the save is rejected.
Recipes
| Goal | Configuration | Input → Output |
|---|---|---|
| Translate codes to labels, with a catch-all | A → Active, I → Inactive; Else Return Value Unknown | A → Active, X → Unknown, a → Unknown |
| Override a few values and pass the rest through | Cancelled → Void; Return Original Value on | Cancelled → Void, Open → Open |
Boolean to Y/N | True → Y, False → N | true → Y |
Business Logic Map
Groups of conditions, each with a Return Value. Groups are checked in order and the first group that is true wins. Within a group, And binds tighter than Or. If no group is true, Else Return Value is returned.
Conditions are equality-only
The Operator on each condition is not currently evaluated. Every condition is an exact, case-sensitive equality test, whatever operator is selected. And because every condition tests the same value, And between two different values can never be true. In practice this transform maps several values to one result. Anything richer — not-equals, greater-than, contains — belongs in a Compute Expression.
Recipe: collapse many statuses into a few
| Group | Conditions | Return Value |
|---|---|---|
| 1 | New Or Pending Or In Progress | Open |
| 2 | Done Or Cancelled | Closed |
| Else | Other |
In Progress → Open, Cancelled → Closed, On Hold → Other.
Substring
- Starting Index counts from 0.
- Number of Characters must be set: at
0the result is empty. A value shorter than requested returns whatever is there. - A Starting Index past the end of the value raises an error. If values can be shorter than your prefix, use Regex Replace instead.
- It can't count from the end. For the last N characters, use Regex Match
(.{N})$.
Recipes
| Goal | Starting Index | Number of Characters | Input | Output |
|---|---|---|---|---|
| Truncate to a field's max length | 0 | 30 | Hi | Hi |
| First five characters | 0 | 5 | Hello world | Hello |
| Drop a fixed 4-character prefix | 4 | 1000 | INV-1042 | 1042 |
Round
| Rounding Behavior | Rule | 2.345 (Precision 2) | -2.349 (Precision 2) |
|---|---|---|---|
| Default | Nearest, halves away from zero | 2.35 | -2.35 |
| Always Round Up | Toward positive infinity (ceiling) | 2.35 | -2.34 |
| Always Round Down | Toward zero (truncate) | 2.34 | -2.34 |
Whole numbers read from JSON
Round accepts decimals, doubles, 32-bit integers, and numeric text. A whole number read from a JSON payload (42, not 42.0) arrives as a 64-bit integer and raises Invalid input type. That includes a field that is usually fractional but sometimes whole, like 2.5 one record and 3 the next.
Keeping trailing zeros
The result is a plain number, so trailing zeros are dropped: 2.50 comes out as 2.5. When the target needs a fixed number of decimals, follow Round with a Formatting Template {0:0.00}.
Date Change
Each unit is added independently, and any unit can be negative. Months and years respect calendar length: Jan 31 + 1 month is Feb 28.
Recipes
| Goal | Chain | Input | Output |
|---|---|---|---|
| Overlap window — reach one day further back | Date Change Days -1 | 2026-03-09 14:05:07 | 2026-03-08 14:05:07 |
| Inclusive end-of-day | Date Only → Date Change Days 1, Seconds -1 | 2026-03-09 14:05:07 | 2026-03-09 23:59:59 |
CSV to List and String Join
Inverses of each other: CSV to List splits one delimited string into a list, and String Join joins a list into one string.
- CSV to List always drops empty entries. A new transform starts with Trim Items on and Make Distinct off.
- String Join also accepts a JSON array that arrives as text, e.g.
["a","b"].
Recipes
| Goal | Configuration | Input | Output |
|---|---|---|---|
| Split a messy semicolon list | CSV to List, Separator ; | red; blue;;red␣ | ["red", "blue", "red"] |
| Same, without duplicates | CSV to List, Separator ;, Make Distinct on | red; blue;;red␣ | ["red", "blue"] |
| Join a list for a single text field | String Join, Delimiter | | ["a", "b", "c"] | a|b|c |
Default Value
Fires when the value is null or empty. A value of only spaces is not empty and passes through, so put a trim — Regex Replace ^\s+|\s+$ → (blank) — ahead of it if that matters. See also replacing placeholder values such as N/A.
JSON Contains
Returns true if the JSONPath selects anything, otherwise false.
- The input must be a JSON object or array. JSON that arrives as text always returns
false, so put Parse to JSON ahead of it. - An empty array selects nothing, so
$.tags[*]doubles as a "has any items" test.
Recipes
Against { "lines": [ { "type": "Freight", "amt": 10 }, { "type": "Item", "amt": 5 } ], "tags": [] }:
| Goal | JSONPath | Output |
|---|---|---|
| Has a freight line? | $.lines[?(@.type == 'Freight')] | true |
| Has a discount line? | $.lines[?(@.type == 'Discount')] | false |
| Any line over 8? | $.lines[?(@.amt > 8)] | true |
| Any tags at all? | $.tags[*] | false |
Behaviors Tab
Behaviors are advanced level options to assist developers in further isolating data transfers. They are unique overrides, used to adapt the data so that it behaves differently than it typically would.
| Behavior | Description |
|---|---|
| Allow Empty Fixed Value | Used primarily on Write Maps, it sets empty string on a field that we do not have mapped, but that needs to be included on the payload of a Save. |
| Bi-Directional Blocking Identifier | Used to select a field separate from the key that is unique and can be used to enforce bi-directional blocking on bi-directional endpoints. |
| Hide From Logging | Used to hide sensitive data (SSN, salaries, etc.) from the logs. |
| Allow Primary Key to Change | Used primarily on Read Maps to tell the engine it can update a value on a Primary Key in the Central Index. By default, Central prevents this from happening, so this acts as an override. |
| Map from Absolute Root | Used primarily on Read Maps, and mainly inside of nested maps, to path to the top level. |
| Map To Absolute Root | Used in nested lists to retrieve a value from the parent. |
| Skip if Null | Used primarily on Write maps, in instances where you want to ignore the map entirely if the incoming value on the property is null. |
Overrides
Overrides allow you to define different connector properties based on operations (Create vs Update). For example, you may want a different mapping behavior on creating a new record vs. updating an existing record.
See Also
- Action Mapping — Map endpoint actions to the Common Model
- Endpoint Configuration — Configure endpoint action inputs and parameterization
- Endpoint Settings — Configure processing behavior for endpoints
- Session Values — Extract and reuse values across multi-step API workflows
- Value Formatting — Format strings for placeholders and templates, with common examples