External Contacts: Preventing Duplicates Between MS Teams Direct Routing and Web Messaging

We’re using the Microsoft Teams integration for our back-office calls and Web Messaging for our customer support. We’ve noticed a significant issue with ‘External Contacts’ duplication.

If a customer calls us via a Teams Direct Routing number, a contact record is created based on their phone number. If that same customer later initiates a Web Messaging chat using their email address, Genesys creates a second contact record because it doesn’t see a link between the phone number and the email.

Is there a way to force a ‘Merge’ or a ‘Search’ during the Web Messaging initiation that checks both phone and email across all external contact sources, including the Teams-synced ones?

I’ve implemented several callback and contact-sync patterns. The native ‘Auto-Create’ for contacts in Web Messaging is fairly basic—it only looks at the primary identifier (Email or OpenID).

The ‘Best Practice’ is to disable the auto-create and use a Data Action in your Architect Inbound Message flow. The Data Action should call the GET /api/v2/externalcontacts/search endpoint. You can search by email, and if not found, search by phone number (if you collected it in the bot). If you find a match, you use the Set External Contact action in Architect to link the conversation to the existing ID. Only if both searches fail should you call the POST endpoint to create a new one.

From an automation perspective, I’ve seen this mess up our contact list uploads for outbound campaigns too. If you have duplicates, you might end up calling a customer who just finished a chat with you.

One tip for the search: make sure your phone numbers are in E.164 format. The MS Teams integration is very strict about formatting, and if your Web Messaging bot collects a number as ‘555-1212’ but Teams has it as ‘+15551212’, the search will fail even if you use a Data Action.

As a veteran architect, I’ve seen this ‘Identity Fragmentation’ in every major migration. The real problem is usually that the ‘Source of Truth’ isn’t Genesys—it’s likely your CRM.

Instead of trying to merge in Genesys, have your Architect flow query your CRM first. Use the CRM’s ID as the ‘External ID’ for the Genesys Contact. That way, regardless of whether they call or chat, they are always pinned to the same CRM record. Genesys Cloud’s External Contacts service will then handle the ‘Internal’ merge automatically based on that shared External ID.