EventPerson Mapping - Advanced
this article covers the advanced eventperson field map options that go beyond the starter mapping making category roles mutually exclusive, migrating identifiers, and the fields the basic article only mentions in passing (items, program membership, and cancellation) new to eventperson ingests? start with the basic mapping and the mapping overview this article assumes you already know how a field map reads keymatch from your payload and writes to a type how it works an eventperson ingest creates or updates a person within a single event a field map is a list of rules; each rule reads a value from your payload (keymatch) and writes it to a jomablue field (type) keymatch is a path, so a value can sit anywhere in the payload, including inside nested objects (contact details email) a person is identified by organisation uid a match updates the existing person, otherwise a new one is created anything the mapping does not reference is ignored, so an over complete mapping never causes harm the mapping the complete mapping combines every technique in this article each section below explains one part of it \[ { "type" "organisation uid", "keymatch" "legacy id|contact id" }, { "type" "first name", "keymatch" "first name" }, { "type" "last name", "keymatch" "last name" }, { "type" "job title", "keymatch" "job title" }, { "type" "company", "keymatch" "company" }, { "type" "email", "keymatch" "email" }, { "type" "mobile", "keymatch" "mobile", "mobilecountry" "country" }, { "type" "cancelled", "keymatch" "status", "valuematch" "cancelled" }, { "type" "category", "keymatch" "category", "valuematch" "delegate", "maptoid" 1, "replaceexistingids" \[2, 3, 4, 5] }, { "type" "category", "keymatch" "category", "valuematch" "sponsor", "maptoid" 2, "replaceexistingids" \[1, 3, 4, 5] }, { "type" "category", "keymatch" "category", "valuematch" "speaker", "maptoid" 3, "replaceexistingids" \[1, 2, 4, 5] }, { "type" "category", "keymatch" "category", "valuematch" "staff", "maptoid" 4, "replaceexistingids" \[1, 2, 3, 5] }, { "type" "category", "keymatch" "category", "valuematch" "vip", "maptoid" 5, "replaceexistingids" \[1, 2, 3, 4] }, { "type" "item", "keymatch" "ticket type", "valuematch" "gala", "maptoid" 12 }, { "type" "program member", "keymatch" "memberships ", "programuidkeymatch" "program uid", "programnamekeymatch" "program name", "programmemberuidkeymatch" "member uid", "programmemberstatuskeymatch" "membership status", "programmemberarchivedkeymatch" "archived" }, { "type" "custom field", "keymatch" "custom fields ", "maptokey" " " } ] matching on more than one unique identifier the organisation uid rule can list several payload paths separated by | , oldest first { "type" "organisation uid", "keymatch" "legacy id|contact id" } the endpoint reads whichever of those paths are present in the payload this is useful when you change the identifier your system sends a person first created under legacy id is still matched when you start sending contact id, so they are updated in place rather than duplicated the right most path is treated as the current identifier assigning categories categories group people by role or type (delegate, sponsor, speaker, and so on) there are two ways to assign them, and a mapping should use one style only by value use value rules when your payload carries a role as text (for example "category" "speaker") each rule fires when the payload value equals its valuematch, and assigns the matching maptoid \[ { "type" "category", "keymatch" "category", "valuematch" "delegate", "maptoid" 1 }, { "type" "category", "keymatch" "category", "valuematch" "sponsor", "maptoid" 2 }, { "type" "category", "keymatch" "category", "valuematch" "speaker", "maptoid" 3 } ] if the path in keymatch holds an array rather than a single string, the rule fires when valuematch is one of the array's values that lets a payload send several roles at once (for example "roles" \["speaker", "vip"]) and have each matching rule assign its category by id use the wildcard form when your payload already carries jomablue category ids as an array { "type" "category", "keymatch" "categories ", "maptokey" " " } this reads the array at categories and assigns each entry as a category id only integer ids are accepted; anything else in the array is ignored category ids are specific to each instance, not each event a given id identifies the same category across every event in your instance the numbers used here are placeholders look up the real category ids from your instance, and set valuematch to the strings your system actually sends if an ingest assigns no category, the event's default category is applied replacing categories (mutually exclusive roles) by default categories are additive assigning one leaves any the person already has to make roles mutually exclusive, so a person ends up in exactly one, add replaceexistingids to each value rule listing the other ids in the set \[ { "type" "category", "keymatch" "category", "valuematch" "delegate", "maptoid" 1, "replaceexistingids" \[2, 3, 4, 5] }, { "type" "category", "keymatch" "category", "valuematch" "sponsor", "maptoid" 2, "replaceexistingids" \[1, 3, 4, 5] }, { "type" "category", "keymatch" "category", "valuematch" "speaker", "maptoid" 3, "replaceexistingids" \[1, 2, 4, 5] }, { "type" "category", "keymatch" "category", "valuematch" "staff", "maptoid" 4, "replaceexistingids" \[1, 2, 3, 5] }, { "type" "category", "keymatch" "category", "valuematch" "vip", "maptoid" 5, "replaceexistingids" \[1, 2, 3, 4] } ] when a rule assigns its category, the ids in its replaceexistingids are removed from the person a rule never lists its own maptoid any category the person holds that is not in the list is left untouched with the set above, sending "category" "speaker" assigns category 3 and removes 1, 2, 4, and 5 send "category" "sponsor" next time and the person moves from speaker to sponsor this is the technique to reach for when each person maps to a single role and re sends should overwrite the previous one assigning a single item the item type assigns a fixed item (a gala dinner ticket, a workshop place, a piece of merchandise) when a payload value is present { "type" "item", "keymatch" "add dinner ticket", "maptoid" 12 } the item with maptoid is assigned when the value at keymatch is present and truthy add valuematch to require a specific value { "type" "item", "keymatch" "ticket type", "valuematch" "gala", "maptoid" 12 } here the item is assigned only when ticket type equals gala unlike categories, assigning an item does not remove other items, and maptoid is required program and campaign membership the program member type links a person to a membership in one of your programs or campaigns it reads a nested object (or an array of them) and needs the program's uid and the membership's uid at minimum { "type" "program member", "keymatch" "memberships ", "programuidkeymatch" "program uid", "programnamekeymatch" "program name", "programmemberuidkeymatch" "member uid", "programmemberstatuskeymatch" "membership status", "programmemberarchivedkeymatch" "archived" } keymatch points at the membership object use a wildcard (memberships ) when the payload carries an array of memberships; the remaining paths are then read from each element programuidkeymatch and programmemberuidkeymatch are required a membership is only created when both resolve to a value programnamekeymatch , programmemberstatuskeymatch , and programmemberarchivedkeymatch are optional for a single membership, point keymatch at the object ("keymatch" "membership") and drop the wildcard cancellation status the cancelled type sets a person's registration status from a value in your payload { "type" "cancelled", "keymatch" "status", "valuematch" "cancelled" } when the value at keymatch equals valuematch, the person is marked cancelled any other non empty value marks them registered if the field is absent, the status is left unchanged valuematch is required, and defines which incoming value means cancelled custom fields named and wildcard the wildcard form maps every key inside an object to a custom field, reusing the payload's own keys { "type" "custom field", "keymatch" "custom fields ", "maptokey" " " } to map a single, specifically named field, use a fixed keymatch and maptokey { "type" "custom field", "keymatch" "tshirt size", "maptokey" "tshirt size" } you can combine both a wildcard rule for the bulk of the object plus named rules for values that live elsewhere in the payload custom field keys should be snake case mobile numbers and country mobile numbers are stored in international e164 format (for example +61402222111) the mobilecountry option controls how local formats are handled { "type" "mobile", "keymatch" "mobile", "mobilecountry" "country" } with mobilecountry the number is parsed using that country's rules and converted to e164, so local formats are accepted 0402 222 111 with country au becomes +61402222111 mobilecountry points at the payload path holding the country accepted values are iso 3166 alpha 2 (au) or alpha 3 (aus) codes, or country names without mobilecountry the number must already be in e164 format (starting with +) anything else is discarded if you only ever receive local numbers from one country, point mobilecountry at any payload field that reliably carries that country code worked example payload { "contact id" "crm 10432", "first name" "jordan", "last name" "avery", "job title" "head of partnerships", "company" "northwind labs", "email" "jordan avery\@northwindlabs com", "mobile" "0402 222 111", "country" "au", "status" "registered", "category" "speaker", "ticket type" "gala", "memberships" \[ { "program uid" "prog 2026", "program name" "ambassadors", "member uid" "m 88", "membership status" "active", "archived" false } ], "custom fields" { "dietary requirements" "vegetarian", "tshirt size" "l" } } resulting person field value organisation uid crm 10432 (read from contact id; matched if it exists, else created) name jordan avery job title / company head of partnerships, northwind labs email jordan avery\@northwindlabs com mobile +61402222111 (converted from local au format) status registered (not cancelled, so active) category speaker (id 3); ids 1, 2, 4, 5 removed if present item gala dinner ticket (id 12) program membership ambassadors (prog 2026), member m 88 custom fields dietary requirements = vegetarian, tshirt size = l send the same identifier again with different values and the person is updated in place send "category" "sponsor" next time and the person moves from speaker to sponsor validation before a payload is mapped, it can be checked against validation rules each rule targets a payload key (dot notation, including wildcards for arrays) and applies one or more checks separated by | a payload that fails is rejected before any person is created or updated { "organisation uid" "required|string", "first name" "required|string", "last name" "required|string", "email" "nullable|email", "mobile" "nullable|string", "category" "nullable|in\ delegate,sponsor,speaker,staff,vip", "status" "nullable|in\ registered,cancelled", "memberships program uid" "required with\ memberships|string", "memberships member uid" "required with\ memberships|string" } required rejects a payload where the field is missing or empty (the identifier and the names needed to create a person) nullable is only checked when present in limits a value to a fixed list, catching typos before they map to nothing required with requires a field only when a related field is present, so the membership identifiers are only enforced when memberships is sent match these keys to your own payload paths, and update the lists to your own values