Legacy Dev Forum Posts

 View Only

Sign Up

Data Action using External Contact Reverselookup API : If a field is blank

  • 1.  Data Action using External Contact Reverselookup API : If a field is blank

    Posted 06-05-2025 18:40

    Jonathan_Jones | 2018-02-21 12:52:17 UTC | #1

    Data Action using External Contact Reverselookup API : If a field is blank. Hi Everyone,

    So I finally created a data action that uses the purecloud api to do a reverse lookup and add the information into the agent script. The issue I've run into is that if the external contact field I'm pulling is empty it fails (let's say the customer gave us a cell# but not a work#). So how do I code my response in the data action to return any results even if it's blank or null? It works just fine if every field is filled in.

    Run Test Results:

    {

    "status": 400,

    "code": "invalid.extraction.into.translation.map",

    "message": "There was an issue extracting a value from the remote endpoint's response into the response translation map. Cause: Missing property in path $['contacts'][0]['cellPhone']",

    "messageParams": {},

    "contextId": "53dc3621-9156-4db4-86e2-6cf558e918a9",

    "details": [],

    "errors": []

    }

    Response Section:

    {

    "translationMap": {

    "firstName": "$.contacts[0].firstName",

    "lastName": "$.contacts[0].lastName",

    "title": "$.contacts[0].title",

    "workPhone": "$.contacts[0].workPhone.e164",

    "cellPhone": "$.contacts[0].cellPhone.e164",

    "homePhone": "$.contacts[0].homePhone.e164",

    "otherPhone": "$.contacts[0].otherPhone.e164",

    "workEmail": "$.contacts[0].workEmail",

    "personalEmail": "$.contacts[0].personalEmail",

    "otherEmail": "$.contacts[0].otherEmail",

    "address1": "$.contacts[0].address.address1",

    "address2": "$.contacts[0].address.address2",

    "city": "$.contacts[0].address.city",

    "state": "$.contacts[0].address.state",

    "postalCode": "$.contacts[0].address.postalCode",

    "countryCode": "$.contacts[0].address.countryCode"

    },

    "successTemplate": "{\"firstName\": ${firstName}, \"lastName\": ${lastName}, \"title\": ${title}, \"workPhone\": ${workPhone}, \"cellPhone\": ${cellPhone}, \"homePhone\": ${homePhone}, \"otherPhone\": ${otherPhone}, \"workEmail\": ${workEmail}, \"personalEmail\": ${personalEmail}, \"otherEmail\": ${otherEmail}, \"address1\": ${address1}, \"address2\": ${address2}, \"city\": ${city}, \"state\": ${state}, \"postalCode\": ${postalCode}, \"countryCode\": ${countryCode}}"

    }


    anon28066628 | 2018-02-20 14:59:42 UTC | #2

    Currently if a field is asked for in the translationMap, it must be present.

    An alternative is passing the entire raw response through to Architect (leave the translationMap at default), or selecting the entire object instead of individual fields ($.contacts[0]). The success schema and Architect will deal with missing fields -- however, the response must be flattenable.


    Jonathan_Jones | 2018-02-20 17:02:41 UTC | #3

    Thanks for the reply, Could you provide me an example of what you mean here, because I think I’ve tried using the rawresults and it errored out for me as well. I’m actually pushing this data to variables in the inbound call flow, that then gets presented in the agents screen pop.


    Jonathan_Jones | 2018-02-20 17:19:27 UTC | #4

    Also is there any way to maybe work around this, like if NULL or Empty, fill in with a dummy variable like a "." or something like that, so that when it goes to the translationMap there is something present?


    anon28066628 | 2018-02-20 17:41:12 UTC | #5

    Default placeholders don't exist for the actions, but you could fill empty fields with "." in Salesforce.

    For the translationMap, try $.contacts[0]. If you get an error, please post the details of the error.


    Jonathan_Jones | 2018-02-20 18:03:35 UTC | #6

    Good morning, I'll give that a try, just as an fyi, this isn't calling to salesforce, this is the purecloud reverselookup api call. I was hoping not to have to put dummy data in the external contacts, since that would just be a bad practice to have bad data in your master file, especially if you need to export it to another system one day.


    Jonathan_Jones | 2018-02-20 21:31:22 UTC | #7

    Ok, so I've removed the required request in the output contract, and then change the response to { _ "translationMap": {},_ _ "successTemplate": "${rawResult}"_ } Now I get this feedback. "contacts.address.city": [ _ "Burnaby"_ _ ],_ _ "contacts.address.state": [_ _ "British Columbia"_ _ ],_

    But I can't use this data in my inbound call flow because it isn't in usable string variables, so what's my next step?


    anon28066628 | 2018-02-20 22:21:20 UTC | #8

    Are you using the test feature with the Data Actions interface? Does the action complete execution successfully, and is the final output flattenable (ie did you check the Flatten box and was the last step of the Test 'flatten')?


    Jonathan_Jones | 2018-02-20 23:04:26 UTC | #9

    I'm assuming this is what you mean. It has the flatten output option. So can I now call contacts.title as a variable in my inbound call flow?


    Jonathan_Jones | 2018-02-20 23:50:13 UTC | #10

    So I published the new data action, went to the script, added it to a link, in the link setup it asks me to define a variable, so I create a string variable. I then called into the ivr and got the screen pop, click the link to trigger the Data Action, I get a response of undefined. Now when I did this with my previous data action that had the translationMap setup, I worked. So using the raw results translationMap, it doesn't seem like it's passing any data along?


    anon28066628 | 2018-02-21 14:00:29 UTC | #11

    Are you able to get the variables in the IVR with the data action?


    Jonathan_Jones | 2018-02-22 00:28:13 UTC | #12

    Got swamped today, hopefully will have time to look at this tomorrow and get you some feedback.


    Jonathan_Jones | 2018-02-22 00:34:23 UTC | #13

    Input Contract { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Search External Contact", "description": "Info of External Contact", "type": "object", "required": [ "lookupVal" ], "properties": { "lookupVal": { "type": "string" } } } Output Contract { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Get Store Data from External Contact", "description": "Return Data External Contact", "type": "object", "properties": { "id": { "type": "string" }, "firstName": { "type": "string" }, "lastName": { "type": "string" }, "title": { "type": "string" }, "workPhone": { "type": "string" }, "cellPhone": { "type": "string" }, "homePhone": { "type": "string" }, "otherPhone": { "type": "string" }, "workEmail": { "type": "string" }, "personalEmail": { "type": "string" }, "otherEmail": { "type": "string" }, "address1": { "type": "string" }, "address2": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" }, "postalCode": { "type": "string" }, "countryCode": { "type": "string" } } } Request { "requestUrlTemplate": "/api/v2/externalcontacts/reversewhitepageslookup?lookupVal=${input.lookupVal}", "requestType": "GET", "headers": { "UserAgent": "PureCloudIntegrations/1.0", "Content-Type": "application/x-www-form-urlencoded" }, "requestTemplate": "${input.rawRequest}" } Response { "translationMap": {}, "successTemplate": "${rawResult}" } Test Output (Fake Data) { "contacts.cellPhone.e164": [ "+12508016666" ], "contacts.lastName": [ "Test3" ], "contacts.homePhone.userInput": [ "+1 250-801-7777" ], "contacts.address.state": [ "British Columbia" ], "contacts.address.address2": [ "Test Address Line 2" ], "contacts.address.address1": [ "1540 Kalamalka Lake Rd" ], "contacts.workPhone.countryCode": [ "CA" ], "contacts.cellPhone.countryCode": [ "CA" ], "contacts.address.postalCode": [ "V1B3W8" ], "contacts.personalEmail": [ "testpersonal@kaltire.com" ], "contacts.modifyDate": [ "2018-02-16T23:59:33Z" ], "contacts.middleName": [ "Test2" ], "contacts.otherPhone.acceptsSMS": [ false ], "contacts.otherPhone.e164": [ "+12508018888" ], "contacts.title": [ "Kaltire Tester" ], "contacts.otherPhone.display": [ "+1 250-801-8888" ], "contacts.homePhone.display": [ "+1 250-801-7777" ], "contacts.homePhone.e164": [ "+12508017777" ], "contacts.address.city": [ "Coldstream" ], "contacts.workEmail": [ "testwork@kaltire.com" ], "contacts.otherPhone.countryCode": [ "CA" ], "contacts.homePhone.countryCode": [ "CA" ], "contacts.cellPhone.userInput": [ "+1 250-801-6666" ], "contacts.otherPhone.userInput": [ "+1 250-801-8888" ], "contacts.firstName": [ "Test1" ], "contacts.cellPhone.acceptsSMS": [ false ], "contacts.createDate": [ "2017-09-14T17:05:42Z" ], "contacts.homePhone.acceptsSMS": [ false ], "contacts.address.countryCode": [ "CA" ], "contacts.workPhone.acceptsSMS": [ false ], "contacts.cellPhone.display": [ "+1 250-801-6666" ], "contacts.otherEmail": [ "test_other@kaltire.com" }


    anon28066628 | 2018-02-23 15:01:32 UTC | #14

    Hi Jonathan, your outputs aren't strings, but rather arrays of strings. Your output contract needs to look like this:

    { "type": "object", "additionalProperties": true, "properties": { "contacts.title": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.workPhone.display": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.lastName": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.address.city": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.address.state": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.workPhone.userInput": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.workEmail": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.id": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.workPhone.e164": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.workPhone.countryCode": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.address.address1": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.address.postalCode": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.modifyDate": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.personalEmail": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.firstName": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.middleName": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.createDate": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.address.countryCode": { "type": "array", "additionalItems": false, "items": { "type": "string" } }, "contacts.workPhone.acceptsSMS": { "type": "array", "additionalItems": false, "items": { "type": "boolean" } }, "contacts.selfUri": { "type": "array", "additionalItems": false, "items": { "type": "string" } } } }


    Jonathan_Jones | 2018-02-26 20:53:33 UTC | #15

    Thank you for the correction. I'll give this a try and see what I get when I run it.


    Jonathan_Jones | 2018-03-16 20:00:06 UTC | #16

    Still haven't been able to circle back on this yet. Hopefully next week.


    SergioRota | 2018-03-29 15:11:59 UTC | #17

    Hi, I have the same problem

    I have a Custom Action to retrieve counts of callbacks (nOffered, tAnswered, tWait, tFlowOut, tTalk, tHandle). If a one of this count don't has value, the custom action fails


    IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII


    anon28066628, post:14, topic:2512
    Hi Jonathan, your outputs aren’t strings, but rather arrays of strings. Your output contract needs to look like this:

    I don't understand how apply this method in my action


    IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII


    Can I insert a default value for my Output contract properties? Like this:

    I tested It but the error remains

    Thanks Sergio


    anon28066628 | 2018-03-29 16:57:03 UTC | #18

    Hi Sergio, it's not the output contract causing the problem, but rather the translation map. I'm assuming you're grabbing a specific field like $.results[0].data[0].metrics.... etc. etc.

    When the fields that are present vary, you cannot target them directly with the translation map. Instead, you have to get the higher level object, such as $.results[0].data.

    The success / output schema can and will ignore missing fields if they're not in the "required" array in the schema. Similarly, the output schema will ignore additional fields if "additionalProperties" is not set to false.


    SergioRota | 2018-03-30 08:37:15 UTC | #19

    Thanks Smith,

    I Tried this method: (following your answer)

    1) Change Config Response:

    { "translationMap": {}, "successTemplate": "${rawResult}" }

    2) Change the Contract Output:

    Test Custom Action:

    But in Architect I don't retrieve nothing :confused:

    Sergio


    Jason_Mathison | 2018-03-30 11:51:46 UTC | #20

    First for @Jonathan_Jones, I have entered a ticket in our internal system to allow users to set a fallback value when one or more translation map values can't be set. I wrote it up that the user could set a single value for all translation map entries, not have a separate value for each. Let me know if that doesn't seem like a reasonable approach. The issue ID is BPIVR-1537.

    @SergioRota results.data.metrics[0].stats.count doesn't exist in your pasted output, so nothing showed up in architect.

    Is your goal to get the '1' from results.data.metrics.stats.count?


    SergioRota | 2018-03-30 13:14:49 UTC | #21

    Jason_Mathison, post:20, topic:2512
    Is your goal to get the '1' from results.data.metrics.stats.count?

    Yes! I tried also this method:

    In Architect no values retrieved

    Sergio


    anon28066628 | 2018-03-30 13:29:08 UTC | #22

    Hi Sergio, can you paste a sample of your Execute output please? (The raw response from the webservice.)

    The sample expression I gave above ($.results[0].data[0].metrics...) was intended as part of the translationMap, not the success schema. If the translation map and response template pass an object through to the success schema, the schema will be flattened and give a flattened representation of that object. You shouldn't see array indices in a success schema.


    SergioRota | 2018-03-30 14:02:50 UTC | #23

    anon28066628, post:22, topic:2512
    Hi Sergio, can you paste a sample of your Execute output please? (The raw response from the webservice.)

    Surely!

    to sum up

    My goal is: retrieve this information about callbacks: nOffered, tAnswered, tFlowout, tAcd But, if one of these information doesn't have value, the action has to retrieve the other values (now my action goes in error)

    EXECUTE (in case of all fields with values)

    { "results": [ { "group": { "mediaType": "callback" }, "data": [ { "interval": "2018-03-28T00:00:00.000Z/2018-03-30T00:00:00.000Z", "metrics": [ { "metric": "nOffered", "stats": { "count": 10 } }, { "metric": "nOverSla", "stats": { "count": 3 } }, { "metric": "tAcd", "stats": { "max": 81746259, "min": 3177, "count": 9, "sum": 85005993 } }, { "metric": "tAnswered", "stats": { "max": 81746259, "min": 3177, "count": 8, "sum": 84966285 } }, { "metric": "tFlowOut", "stats": { "max": 39708, "min": 39708, "count": 1, "sum": 39708 } }, { "metric": "tHandle", "stats": { "max": 11516, "min": 2819, "count": 8, "sum": 49866 } }, { "metric": "tTalk", "stats": { "max": 11516, "min": 1819, "count": 8, "sum": 40866 } }, { "metric": "tTalkComplete", "stats": { "max": 11516, "min": 1819, "count": 8, "sum": 40866 } }, { "metric": "tWait", "stats": { "max": 81746259, "min": 3177, "count": 8, "sum": 84966285 } } ] } ] } ] }

    If a field (es. nOffered) doesn't have value, this error occurs

    { "status": 400, "code": "invalid.extraction.into.translation.map", "message": "There was an issue extracting a value from the remote endpoint's response into the response translation map. Cause: No results for path: $['results'][0]['data'][0]['metrics'][8]['stats']['count']", "messageParams": {}, "contextId": "282ddf2d-ddb8-4c57-8a76-7e4d71a126ad", "details": [], "errors": [] }

    in this case I have this EXECUTE:

    { "results": [ { "group": { "mediaType": "callback" }, "data": [ { "interval": "2018-03-30T00:00:00.000Z/2018-03-31T00:00:00.000Z", "metrics": [ { "metric": "nOverSla", "stats": { "count": 1 } }, { "metric": "tAcd", "stats": { "max": 70221212, "min": 70221212, "count": 1, "sum": 70221212 } }, { "metric": "tAnswered", "stats": { "max": 70221212, "min": 70221212, "count": 1, "sum": 70221212 } }, { "metric": "tHandle", "stats": { "max": 16018, "min": 16018, "count": 1, "sum": 16018 } }, { "metric": "tTalk", "stats": { "max": 4018, "min": 4018, "count": 1, "sum": 4018 } }, { "metric": "tTalkComplete", "stats": { "max": 4018, "min": 4018, "count": 1, "sum": 4018 } }, { "metric": "tWait", "stats": { "max": 70221212, "min": 70221212, "count": 1, "sum": 70221212 } } ] } ] } ] }

    Thanks Sergio


    anon28066628 | 2018-03-30 17:03:46 UTC | #24

    Try this config:

    Request config:

    { "headers": {}, "requestUrlTemplate": "https://demo4653912.mockable.io/sergio", "requestTemplate": "${input.rawRequest}", "requestType": "GET" }

    Response config:

    { "translationMap": { "metrics": "$.results[0].data[0].metrics" }, "successTemplate": "{\"metrics\": ${metrics}}" }

    The translationMap gets the entire metrics array. It doesn't matter if fields are present or not now, because the metrics object itself is always there. The successTemplate wraps the selected metrics array into a proper json object, because the output schema requires it.

    Output contract:

    { "type": "object", "definitions": {}, "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "metrics": { "type": "array", "items": { "type": "object", "properties": { "metric": { "type": "string" }, "stats": { "type": "object", "properties": { "max": { "type": "integer" }, "min": { "type": "integer" }, "count": { "type": "integer" }, "sum": { "type": "integer" } } } } } } } }

    With this output contract, the action looks like this in Architect. Use the fields you want and leave the others blank. Note the type of the variable is "String Collection".

    The flattened output looks like this:

    { "metrics.metric": [ "nOffered", "nOverSla", "tAcd", "tAnswered", "tHandle", "tTalk", "tTalkComplete", "tWait" ], "metrics.stats.count": [ 10, 3, 9, 8, 8, 8, 8, 8 ], "metrics.stats.max": [ null, null, 81746259, 81746259, 11516, 11516, 11516, 81746259 ], "metrics.stats.sum": [ null, null, 85005993, 84966285, 49866, 40866, 40866, 84966285 ], "metrics.stats.min": [ null, null, 3177, 3177, 2819, 1819, 1819, 3177 ] }

    Note that the flattening process "stripes" the values across the Collections. You'll need a loop to iterate the "metric" collection, looking for the stat you want by name, and choose the corresponding values from the other collections in a parallel manner. Notice also that fields not present in some objects are returned as "null" so the Collections will always be equal length.


    SergioRota | 2018-04-03 10:00:27 UTC | #25

    THANKS!!!!!!!

    I tried your configuration and the Action runs very well! And I can retrieve single informations :smiley:


    system | 2018-05-04 08:29:13 UTC | #26

    This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.


    This post was migrated from the old Developer Forum.

    ref: 2512