Contact Keys and Customer Identity
You keep GadgetSphere’s customer list — about 85,000 records, most of them walk-ins created at a till in under a minute — and twice a week someone asks why the same person has three customer records, or why a phone number typed at GS-KV-01 did not find the customer the web store already knows.
Both questions are about the contact key: the identity record BigLedger keeps behind a customer, and the rules it uses to decide that a phone number, e-mail or ID number belongs to somebody it has already met. By the end of this page you will know what the key is, exactly when and how BigLedger looks one up, why the match is stricter than people expect, and what to do about duplicates. Fifteen minutes to read; the procedure at the end takes ten.
The procedure at a glance. Agree one phone format for the group first: the match is exact, so the format is the policy (Before you start).
- Find out whether the two records share a key: query the key API with each variant exactly as stored (Step 1).
- Make the phone and e-mail match exactly, with the e-mail in lower case, and save; the background job merges the keys (Step 2).
- Decide whether the two records should also become one customer, with Entity Merging (Step 3).
Meet GadgetSphere
A customer buys a laptop online from GadgetSphere Online (GSO) and gives the web store 012-345 6789 and Someone@example.com. A month later she walks into GS-KV-03 for a charger; the cashier creates a customer record and types 0123456789. Two customer records now exist for one person — one made by the web store, one at the counter — and whether BigLedger knows they are the same person depends entirely on what was typed.
What a contact key is
A contact key is a small record — phone, e-mail, ID number and type, name — that stands for one person or organisation regardless of how many records mention them. Three kinds of record hang off it:
| Record | What it is | How it points at the key |
|---|---|---|
| Customer / supplier | The master-data record documents are raised against | A key reference on the record, plus a key-to-entity link |
| Contact | One observation of the person from one source — a web-store sign-up, a marketplace order, an inbound e-mail, a contact-centre call, a CRM contact you typed | A key reference on the contact (not enforced), plus a contact-to-customer link |
| Membership card | The loyalty membership | A key reference on the card, plus a key-to-member link |
A key can be linked to many customers, and after a merge a customer to more than one key. The links’ type and probability columns are never written, so do not build a report on them.
A key linked to several customers is not how BigLedger expects a group to look. The customer record belongs to no single company: one record serves GS, GSO and GSD at once, each company attached to it on the record’s Company Linking tab with its own customer code. So one person buying from all three companies is normally one customer record, and three records for her are duplicates — unless someone keeps them apart on purpose.
Contacts also carry a source. The platform seeds exactly one source, AI_LEDGER, into every tenant; it is the source stamped by the Unified Contact Center, inbound e-mail and sales leads. Only those three routes stamp it, so most contacts have no source at all — the ones created by the matching jobs below never get one.
Keys are not a feature you switch on. The save path below mints one for any customer or supplier record that carries a phone number, an ID number or an e-mail address, so by the time you go looking, most of your entity records already have one.
When BigLedger looks a key up
Two passes run when a customer is saved, and they use different rules. Knowing both explains every “why didn’t it match” you will meet.
Pass 1 — the moment a customer or supplier is saved
If the record has no key yet and at least one of phone, ID number or e-mail is filled in, the save itself looks for an existing key:
- the ID number is compared with the key’s ID number or its Ref 2 (the field an older integration used for the identification number);
- the e-mail with the key’s e-mail;
- the phone with the key’s phone.
Any one field matching is enough. The comparison is exact: no trimming, no lower-casing, no stripping of +60, spaces or dashes. If several keys match, the oldest wins. If none matches, a new key is created together with a contact that shares its guid, and the record is stamped with it.
For GadgetSphere: 0123456789 at the till and 012-345 6789 on the web store are two different strings, so the cashier’s save creates a second key. someone@example.com and Someone@example.com likewise.
Pass 2 — a few minutes later, for customers only
Saving a customer (not a supplier) also queues a background job. It looks, this time, at contacts rather than keys, by e-mail (compared lower-cased on the stored side) and by phone (exact), and does one of three things:
| It finds | It does |
|---|---|
| No contact | Keeps the key pass 1 gave the customer; if the customer somehow has none, tries a second “similar key” lookup and otherwise creates key, contact and both link rows |
| Exactly one contact | Updates that contact’s key with the customer’s details and links the customer to it |
| More than one contact | Merges: every contact is re-pointed at the oldest contact’s key; the customer, its membership, sales leads, contact-centre links and link rows are re-keyed; the other keys are deleted |
Two details of this pass decide whether your duplicates merge:
- The e-mail comparison lower-cases the stored value but binds the typed value as is, so a customer saved with
Someone@example.comdoes not find a contact stored assomeone@example.com. Save e-mails in lower case. - The “similar key” lookup in the no-contact branch binds its ID-number and phone parameters to the e-mail value, so only its e-mail branch can ever match. In practice that branch finds nothing for a phone-only walk-in.
Beyond 1,000 candidate contacts the job logs an error and merges the oldest 1,000 onto one key, which matters where a placeholder phone number has been typed on thousands of records (see Common mistakes).
Contacts saved directly
A contact created through the CRM API or the Unified Contact Center goes through a third, contact-side pass with the most forgiving rule of the three: e-mail, ID number and Ref 2 are compared lower-cased on both sides, phone exactly, and, when both carry a Ref 2, candidates whose Ref 2 differs are dropped. A contact with none of e-mail, phone, ID number or Ref 2 is rejected outright (CONTACT_HDR_SHOULD_HAVE_AT_LEAST_ONE_VALUE_SET…). A contact saved without a key gets one created.
What the key is used for today
Be clear about what the key does not do, because the name suggests more than the product does:
- The POS does not search by key. The cashier’s customer search sends the phone number as a criteria on the customer query — it finds customers whose own phone equals what was typed. A key that links the web-store customer to the phone does not surface the web-store customer at the till; only a customer record with that exact phone does. The cash bill never records the key: the action that would fill it is never dispatched.
- Keys are read through the key API (query by phone, e-mail or ID number, exact-match, permission
TNT_API_CRM_CONTACT_KEY_READ), and through the membership and contact-centre screens that hang records off a key. There is no key screen in the customer, POS or membership applets. - Membership cards are keyed the same way: creating or editing a card queues a member merge job that mirrors pass 2 and stamps the key on the card. This is what lets a member’s points follow the person rather than one customer record.
- Deleting a customer keeps its key and soft-deletes only the two link rows, so the identity survives for the contacts and memberships still attached to it.
So in practice: many keys belong to contacts and members and link to no customer; a key linked to two or more customers is almost always a duplicate; and a phone number or e-mail written two ways sits on two keys, one per variant.
Before you start
- You have the customer maintenance permission set that includes Entity Merging (see the Customer Maintenance applet).
- You can call the key API, or have someone who can:
TNT_API_CRM_CONTACT_KEY_READ. - Agree one phone format for the group before you touch anything — digits only, no country code, is the least error-prone at a till (
0123456789). The match is exact, so the format is the policy.
Step 1: Find out whether the two records share a key
By the end of this step you know whether BigLedger already treats the web-store customer and the walk-in as one person.
Customer Maintenance → Customer listing → open each record; then look the key up through the key API by phone.
Open the GSO record and the GS-KV-03 record and compare the phone and e-mail exactly as stored. Then query the key API with each variant you find. One key returned for both variants means the records are already linked and you are done. Two keys — one per variant — is the usual answer, and it means every screen that walks the key (membership, contact centre) sees two people.
The most common failure: querying with a normalised number and getting nothing. The API is as exact as the save: query with the string as stored.
Step 2: Make the records match, then let the job merge them
By the end of this step both customer records carry the same key.
Customer Maintenance → open the newer record → Edit → set the phone and e-mail to exactly the values on the older record → Save.
Saving a customer whose key already exists does not re-run pass 1 (it only runs when the record has no key), but it does queue pass 2, which now finds the older contact by e-mail (lower case!) or phone and, finding more than one contact, merges everything onto the oldest key and deletes the newer one. Give the queue a few minutes, then repeat the Step 1 query: one key, both records.
The most common failure: the e-mail was saved with a capital letter and the phone was left in the old format, so pass 2 finds nothing and both keys survive. Lower-case the e-mail, match the phone exactly, save again.
Step 3: Decide whether you also want one customer record
By the end of this step you have decided whether the two records should become one, and who does it.
Customer Maintenance → Entity Merging.
One key tells the identity screens that the records are one person; it does not make them one account. The records still carry separate invoices, separate statements and separate balances.
If they really are the same person, merge them — and the company each record was created for is no reason not to. A customer record is not tied to one company, and Entity Merging works across the whole group: it has no company filter, it re-points every document and link that names a duplicate — including its Company Linking rows and its key links — onto the survivor, and sets the duplicates inactive. After the merge, the survivor is the one record GS and GSO both bill. Pick the survivor and the duplicates, then check Entity Merge Processing for the job’s status.
Keep two records only when you mean to, such as a company and its director who share a phone. Duplicate customers covers how to decide and how to check a merge.
What success looks like
GET …/contact-keys/query?phone=0123456789 returns one key. Open both customer records: both show the same phone and e-mail, as stored — or, if you merged them in Step 3, only the survivor is active. Create a test customer with the same phone and save it: it picks up the same key at save time (pass 1) without waiting for the job. Delete the test customer. Ten minutes.
Common mistakes
| Mistake | What you see | Fix |
|---|---|---|
Different phone formats across channels (+6012…, 012-…, 012 …) | One person, one key per format | Pick one format; store digits only; fix the web-store and marketplace mappings to send it that way |
| Mixed-case e-mail on a customer record | Pass 2 never finds the existing contact | Save e-mails in lower case |
Placeholder phone numbers at the till (0000000000, 0123456789) | Thousands of customers on one key; each merge takes the oldest 1,000 matches and logs an error | Make phone optional at the till rather than fake (NOT_MANDATORY_PHONE_NO on the customer applet) and clean the placeholders |
| Expecting the POS to find the web-store customer through the key | Search by phone finds nothing at the till | The till searches customer records, not keys. Keep one customer record for the person with the phone in the format the till types, rather than creating a second record at the counter |
| Typing the registration number into ID type | The type column holds a number; the ID number column is empty; nothing matches | ID type is a label (NRIC, PASSPORT, BRN); the number goes in ID number |
| Deleting a duplicate customer that has invoices | The record cannot go; the key stays either way | Use Entity Merging for records with history |
| Keeping one customer record per company for the same person | One key, several customer records; her statement, credit and history split by company | A customer record serves the whole group — attach the companies on Company Linking and merge the duplicates with Entity Merging, which works across companies |
Related documentation
- Duplicate customers — deciding which records are one person, what Entity Merging changes for good, and how to check the result
- Customer Maintenance applet — the customer record, Entity Merging and the
NOT_MANDATORY_PHONE_NOswitch - Unified Contact Center applet — where contacts with the
AI_LEDGERsource come from - Membership module — the membership card that hangs off the same key
- POS General applet — the customer search at the till
- Credit limits and terms — the other thing a customer record carries that a key does not