Key/Value Maps
Key/Value Maps are re-usable lookup tables for enum-like values that differ between epilot and an external system โ salutations, country codes, contract status codes, payment methods, tariff identifiers.
A typical example: epilot stores a contact's salutation as Mr. or Ms. / Mrs., while the ERP expects 1 or 2. Instead of repeating the same ? : chain in every mapping, declare the table once and look it up with $mapValue / $mapKey in any JSONata expression.
{
"Mr.": "1",
"Mr": "1",
"Ms. / Mrs.": "2",
"Company": "4"
}
How maps are storedโ
A map is an environment variable of type JSON โ a flat JSON object whose keys and values are strings (up to 32 KB). Maps are:
- Declared on an integration in the Integration Hub under the Maps tab (name, environment key, description, entries). The declaration travels with the integration, so the map is re-created when the integration is set up in another organization.
- Stored globally as an environment variable. Saving the integration writes the map to the environment; the environment value is what every lookup uses at runtime. If two integrations declare the same key, the last one saved wins.
- Editable in both places โ the Integration Hub shows the current environment value, and the variable also appears in Environments & Secrets with a JSON editor.
Because maps are ordinary environment variables, they are never secret, and they follow the same naming rules (salutation, erp.salutation, lima.contract_status, โฆ).
Using maps in JSONataโ
Wherever the Integration Toolkit or Webhooks evaluate JSONata, the organization's non-secret environment variables are available as $env, and two helper functions operate on map objects:
| Function | Direction | Returns |
|---|---|---|
$mapValue(map, key, default?) | key โ value | The value stored under key, or default when the key is missing |
$mapKey(map, value, default?) | value โ key | The first key whose value equals value, or default when nothing matches |
$mapValue($env.salutation, salutation, "!")
$mapKey($env.salutation, Person1Anredekennzeichen)
Rules worth knowing:
- Lookup keys are compared as strings โ
$mapValue($env.salutation, 1)and$mapValue($env.salutation, "1")are the same lookup. $mapKeycompares values with strict equality: a map value"1"does not match the number1. Coerce with$string()when the source field is numeric.- When no
defaultis given and nothing matches, the result isundefinedand the mapped attribute is simply omitted โ the same behaviour as any other undefined JSONata result. - If the first argument is not an object (for example the environment variable does not exist yet), the expression fails with
$mapValue: first argument must be an object/$mapKey: โฆ. In inbound use cases this surfaces as a mapping error in monitoring; in webhooks the delivery fails. - Values are read through the environments cache, so a change to a map becomes visible to running integrations within about 60 seconds.
Where $env, $mapValue and $mapKey are availableโ
- Inbound use cases โ every
jsonataExpressionfield mapping and entity-leveljsonataexpression, including the mapping simulation endpoint. - Outbound webhooks โ the payload transformation and multipart form-field expressions.
- Outbound file proxy โ request body templates and delivery expressions.
Recommended shape: one map, both directionsโ
Model each map as epilot value โ external value. The forward lookup ($mapValue) then serves outbound integrations and the reverse lookup ($mapKey) serves inbound ones, so one table covers both directions.
- Many-to-one is expressed with extra keys pointing at the same value (
"Mr": "1","Mr.": "1"). On the reverse lookup the first matching key wins, so list the canonical epilot value first. - Keep external codes in the values, not the keys. JavaScript orders integer-like object keys (
"0","1","10") numerically ahead of other keys, which would make "first match" in$mapKeydepend on the number, not on your ordering. Epilot values such as"Mr."keep the order you typed. - Defaults belong at the call site:
$mapValue($env.salutation, salutation, "!")โ the map stays a pure table and different mappings can choose different fallbacks. - No implicit normalisation. Lookups are exact; if the source system sends
herrorHerrinconsistently, normalise in the expression first:$mapKey($env.salutation, $trim($lowercase(Anrede)))against a map whose values are lower-cased.
Full exampleโ
Map salutation (declared on the ERP integration):
{ "Mr.": "1", "Mr": "1", "Ms. / Mrs.": "2", "Company": "4" }
Inbound field mapping โ ERP customer record to contact:
{
"attribute": "salutation",
"jsonataExpression": "Adressart = 'FIRMA' ? 'Company' : $mapKey($env.salutation, $string(Person1Anredekennzeichen))"
}
Outbound webhook payload transformation โ contact to ERP request:
{
"kundennummer": entity.customer_number,
"anredekennzeichen": $mapValue($env.salutation, entity.salutation, "!"),
"nachname": entity.last_name
}
Next Stepsโ
- Mapping โ all inbound field mapping types, including
env_var_reffor scalar environment values - Environments & Secrets โ variable types, naming, and API
- Environments & Secrets in Webhooks โ
{{ env.* }}and$envin webhooks