How to merge two contacts in Dynamics CRM

If you are using the Dynamics CRM Destination SSIS component, perhaps you have noticed that it lacks the feature of merging two table rows - the masterid column won’t get updated, despite how hard you try. :wink: But don’t despair! Fortunately, this can be achieved using other means. Let’s begin and explore what they are.

Merging two contacts in Dynamics CRM

Overview

Dynamics CRM Destination uses older Dynamics 365 SOAP-based Web Services (it is in Microsoft’s plan to retire it in the future) to work with Dynamics CRM entities and therefore does not support merging two table rows. To merge two table rows we will have to use a newer Microsoft Dataverse Web API instead. It is a RESTful service, so it means we will deal with JSON files, which means we will have to use ZappySys Web API Destination or REST API Task connectors to perform the merge operation. By the way, you can accomplish this with ODBC PowerPack too - just create an ODBC data source based on ZappySys ODBC JSON Driver.

Now, let’s move on and enter the dark woods of the internals!

Registering the OAuth application in Microsoft Entra ID

First of all, you will have to register an OAuth app for Dataverse API to be used in OAuth Connection Manager. Just set Client Credentials Grant option and fill in all the required fields. When you accomplish that, you can be proud of yourself, because you are halfway out of the dark woods!

HTTP request

Once you have the authentication part covered, you can make a call to Dataverse merge endpoint by making a similar HTTP request:

POST [Organization URI]/api/data/v9.2/Merge HTTP/1.1
Content-Type: application/json; charset=utf-8
Accept: application/json

{
  "Target": {
    "contactid": "bb8055c0-aea7-ea11-a812-000d3a55d474",
    "@odata.type": "Microsoft.Dynamics.CRM.contact"
  },
  "Subordinate": {
    "contactid": "c38045c0-aea6-ea11-a812-000d3a55d474",
    "@odata.type": "Microsoft.Dynamics.CRM.contact"
  },
  "PerformParentingChecks": false
}

Just replace [Organization URI] with your organization URL and contactid field values with the real contact IDs you want to merge. In this HTTP request, Target becomes your master contact, and Subordinate - your child contact.

Now only one thing’s left - to make the actual HTTP request!

Making the HTTP request

In SSIS

In SSIS you can make the HTTP request using either Web API Destination or REST API Task. Use Web API Destination for bulk merging and REST API Task for a single contact merge. If you decide to go with a bulk-merging approach, you can use Template Transform to compose an HTTP body in a more convenient way.

In ODBC

If you like to perform similar update via ZappySys JSON Driver then here is how to do

  1. Create ODBC DSN using JSON Driver this way
  2. Edit DSN and click Load Connection String button. Paste the below string and click OK (Change ClientId, ClientSecret, TokenUrl, and DataPath as needed).
DRIVER={ZappySys JSON Driver};
DataPath='https://orgXXXXXX.api.crm.dynamics.com/api/data/v9.2/Merge';
DataConnectionType='OAuth';
AuthUrl='https://login.microsoftonline.com/common/oauth2/authorize';
TokenUrl='https://login.microsoftonline.com/XXXXXXXXXXXX/oauth2/token';
ReturnUrl='https://zappysys.com/oauth';
ExtraAttributesForTokenRequest='resource=https://orgXXXXXX.api.crm.dynamics.com';
ScopeSeparator='{space}';
OAuthVersion='OAuth2';
GrantType='ClientCredentials';
ClientId='45233d5a-xxxxxxxxxxxxxxx';
ClientSecret='SHQ8Q~xxxxxxxxxxx';
UseCustomApp=1;
  1. Run a query like below. Edit the URL / other information as per your need. SQL query would look in ODBC data source:
SELECT Status FROM [$]
WITH(
	 Src='https://orgXXXXXX.api.crm.dynamics.com/api/data/v9.2/Merge'
	,RequestData='{
  "Target": {
    "contactid": "bb8055c0-aea7-ea11-a812-000d3a55d474",
    "@odata.type": "Microsoft.Dynamics.CRM.contact"
  },
  "Subordinate": {
    "contactid": "c38045c0-aea6-ea11-a812-000d3a55d474",
    "@odata.type": "Microsoft.Dynamics.CRM.contact"
  },
  "PerformParentingChecks": false
}'
	,Header='Accept: application/json || Content-Type: application/json'
	,RequestMethod='POST'
	,Meta='Status:string'	
	,RawOutputDataRowTemplate='{Status:"Merged"}'
    ,EnableRawOutputModeSingleRow='true'
    ,Filter='$.Status'
)

Conclusion

It wasn’t easy, but you managed to leave the dark woods and reach the light!

It’s worth adding that it is possible to merge two rows of any Dataverse entity. You just have to replace
@odata.type field with an appropriate entity name. For the Dynamics CRM account entity @odata.type field would look like this:

 "@odata.type": "Microsoft.Dynamics.CRM.account"