Companies providing customer care often require multiple supporting IT systems to achieve the high standards they strive for. This implies usage of telephony services, contact center platforms, CRM and WFM solutions, etc.
Using 5 – 10 separate solutions to handle a single client interaction may become confusing and time-consuming for agents. How many times a customer called in to open a service ticket, but the responding agent was too busy filling in collateral data that he or she was not able to fully attend to customer’s request?
In this blog post, I try to help with the outlined problem by showing how to create a CRM case programmatically, using Amazon Connect and Microsoft Dynamics 365. At the time I am writing this article there are no out-of-the-box integrations for the two solutions.
Use case details are available from my previous blog posts:
- Self-service Contact Center with Amazon Connect and Amazon Lex
- Process Amazon Connect self-service data with Lambda and SES
High-level overview
- Customer calls into a service desk number hosted by Amazon Connect, to open a service case
- Customer speaks briefly regarding the issue that needs to be reported (handled by built-in Amazon Connect and Amazon Lex integration)
- Caller’s data is processed with a Lambda function
- Microsoft Dynamics Case gets created based on caller’s input data
- Caller receives feedback on success or failure
Prerequisites
Please, be aware, there are a number of preceding steps that need to be taken before you can auto-create records in Dynamics CRM. The steps outlined below are not covered in this post as the list is quite extensive. By all means, I’d be happy to share the details – let me know if this interests you in the comments section below.
- Authenticate to Microsoft Dynamics 365 with the Web API
- Configure permissions
- Create additional Lambda function that returns Dynamics Account ID (or Contact ID) based on Amazon Connect caller’s phone number
- Introduce robust error handling
- Create additional logic to allow callers to check in on their case status
Create a Dynamics CRM Case from AWS Lambda
If you made it this far, you have completed most of the hard work and now comes the fun part. You can get creative and design a cutting-edge self-service flow in no time! Let’s take a look at the AWS Lambda function that creates a Microsoft Dynamics CRM case record.
First, we collect basic CRM-related data (Web API authentication token and Dynamics CRM base URL). Next, we make sure there is a Dynamics Account or Contact record related to Amazon Connect caller’s phone number. This is important as the Dynamics CRM case we are creating needs to be bound either to a Dynamics Account or Contact. For simplicity, this is hardcoded in the sample function, however, a good approach would be to invoke another Lambda function to return an Account Id or Contact Id to this function.
Next, we build out the header and body of the web request we send to Microsoft Dynamics Web API, asking to create a new case.
Dynamics 365 cases keep track of your customer’s support requests and issues. Web API exposes case records through Incident entity type.
The part when it all comes together is when we pass Amazon Connect/ Lex data to the Dynamics Web API, using the incident.title and incident.description parameters. Note: as outlined above, to create a Dynamics case, it’s mandatory to bind it either to an Account or Contact, using @odata.bind notation. See incident[“customerid_account@odata.bind”] within the sample code.
You may have noticed the Web API implements OData v4.0 – more details are available through the Dynamics 365 API Documentation.
Last, we send out the request to the Web API and process the received response. We pass this information back to the caller, to let him or her know if the case was successfully created.
const https = require('https'); exports.handler = (event, context, callback) => { // Dynamics API authentication token and CRM base URL var token = 'xxxxx'; const dynamicsLookupHost = "company.crm.dynamics.com"; // Dynamics Account ID or Contact ID var accountId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // Caller's phone number var callerPhoneNumber = "xxxxxxxxxx"; // Amazon Lex response parameters var lexResponseContent = "message"; jsonLexResponse = { "sessionAttributes": { "key1": "your custom attribute value1", "key2": "your custom attribute value2" }, "dialogAction": { "type": "Close", "fulfillmentState": "Fulfilled", "message": { "contentType": "PlainText", "content": lexResponseContent } } }; //Building Dynamics API request var callRequestHeaders = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json; charset=utf-8', 'OData-MaxVersion': '4.0', 'OData-Version': '4.0', 'Accept': 'application/json' }; var options = { host: dynamicsLookupHost, path: "/api/data/v8.2/incidents", method: "POST", headers: callRequestHeaders }; var incident = {}; incident.title = "" + event.currentIntent.slots.caseTitle; incident.statuscode = 1; // 1 -> In Progress incident state incident.description = "" + event.currentIntent.slots.caseDescription + "\nCaller:" + callerPhoneNumber; incident.severitycode = 1; // 1 -> Normal priority incident.caseorigincode = 1; // 1 -> Case opened by phone incident["customerid_account@odata.bind"] = "accounts(" + accountId + ")"; var incidentRequestBody = JSON.stringify(incident); console.log('Attempting to create a Case in Dynamics CRM...'); var incidentRequestHttpsClient = https.request(options, function (response) { var insertIncidentResponse = ""; response.on('data', function (dataChunk) { insertIncidentResponse += dataChunk; }); response.on('end', function () { jsonLexResponse.dialogAction.message.content = "Successfully created new Dynamics Incident."; callback(null, jsonLexResponse); }); }); incidentRequestHttpsClient.on('error', function (e) { callback(e); }); incidentRequestHttpsClient.write(incidentRequestBody); incidentRequestHttpsClient.end(); }; Function repository: CreateDynamicsIncidentRecordFromLambda
It’s a good practice to test the Lambda functions before linking them to Amazon Connect contact flows or Lex bots. This function can be invoked using the following sample JSON event:
{ "currentIntent": { "dialogState": "ReadyForFulfillment", "intentName": "OpenDynamicsIncident", "message": null, "responseCard": null, "slotToElicit": null, "slots": { "caseDescription": "Not able to find delivery contact", "caseTitle": "Delivery issue" }, "confirmationStatus": "confirmed" } }
End result
That’s it! Here is a sample of a programmatically created case in Dynamics CRM, using data collected from Amazon Connect self-service call. Notice how Case Title and Description got populated based on Amazon Connect caller’s input? Additionally, Customer section was populated based on binding to an existing Account.
If you’re interested to see more, schedule a demo or contact us here.