A conversation is only useful if you know who it was with. Reference data is how the platform learns your customers, your people, your key accounts, and the competitors you track - and the attribution it produces is resolved once, then shared by every surface that reads the object.
A tenant may provide nothing and do attribution on their own systems. Enrichment then runs in unmapped mode: a valid object, mapping_status: "unmapped", association IDs absent rather than guessed, and the raw party addresses plus source_call_id preserved so you can join it yourself. Providing no reference data is a supported configuration, not a degraded one.
Attribution is stamped as stable identifiers. Current names, contacts, and details are resolved at read time through this surface. That is why a rename never rewrites history and why a bulk mapping correction does not mean reprocessing conversations.
Conversations are matched to your inventories by identifier and by tracked list - a number, an address, a handle, a name on a list you supplied. It is a lookup against data you control, which is what makes a wrong match something you can find and fix in your own records.
| Reference set | What it does |
|---|---|
| Customer inventory | Your customers and the addresses that reach them, so a conversation resolves to an account rather than to a number. |
| Employee roster | Your people and their addresses per channel, so a conversation resolves to a person and their conversations aggregate across channels. |
| Employee to customers | Which of your people is responsible for which customers. A one-to-many relationship, served live rather than stamped, because it changes often. |
| Manager to employees | Reporting structure, so a surface can be scoped to what a given manager is accountable for. |
| Customer groups | Grouping customers into the segments you actually manage, for per-group boards and comparisons. |
| Competitor and partner lists | The names you want tracked when they come up in a conversation. Matched against your list rather than inferred, so what counts as a competitor is your decision. |
| Do-not-process list | Addresses and lines that must never be analysed. Enforced before processing, so those conversations are never written rather than written and hidden. |
Every association is stamped as structured components plus an opaque URN, so you can read the parts or treat the whole string as a single join key.
{
"external_id": "cus_7Q2M4X",
"system_of_record": "tresic",
"identity_provider": null,
"urn": "tresic:master:cid/cus_7Q2M4X"
}
Exactly one source field is populated: identity_provider for a person, system_of_record for a customer, competitor, or partner. Both are extensible - adding a new source system is a data change, not a schema change, so bringing another CRM into the picture does not alter the contract you consume.
Your own account numbers, CRM record IDs, and internal user IDs are held as crosswalked attributes resolved by the stamped identifier - not baked into it. An identifier changing in one of your systems never re-keys a conversation record or forces anything to be reprocessed.
| Rule | Behaviour |
|---|---|
| Scope | Reference data is held per company by default, with optional per-location overrides. Resolution precedence is location override, then company default - so define once for a uniform tenant, and override only where a location genuinely differs. |
| Per platform and channel | How a conversation is matched depends on the source platform and the channel, because the identifiers differ: a phone number for voice, an address for email, a handle for chat. Inventories are address-typed so a match uses the identifier that fits the channel. Supporting another platform or channel is configuration on our side, not a change to the contract on yours. |
| Unmatched | That one identifier resolves to nothing and the ID is absent. The object stays valid and the rest of the attribution stands. |
| Partial | mapping_status: "partial". Some associations resolved and some did not. Aggregate on what is present rather than assuming a complete set. |
| Your own organisation | Your company naming itself on its own conversations never resolves to a customer. You supply your own name variants; we suppress them. |
| Business or consumer | A tenant whose customers are organisations and one whose customers are individuals need different resolution. It is an explicit setting rather than something inferred from whether company data happens to exist. |
Reference data can start as files you populate, move to being managed in the Admin Interface, and later arrive by continuous sync from your system of record. The interface you integrate against does not change when the backing store does.
That is the point of putting it behind a seam at all: the way a tenant maintains this data is an operational decision that will change over a multi-year deployment, and it should never be a reason to revisit code that reads conversations. The same holds for what we build - our own applications resolve names through this surface exactly as yours will.
Run the layer against conversations you already have, with your own customer and employee data behind it, and read what resolves.