we’ve got a Data Action failing when trying to create incidents in ServiceNow. it’s hitting a 422 Unprocessable Entity error. i think it’s something to do with how we’re mapping the participant.id field from the Genesys Cloud webhook payload.
The flow is pretty simple - conversation triggers an event, Data Action sends a POST to our ServiceNow incident table. we’re using the REST API, obviously. the endpoint is /api/now/table/incident. the payload looks mostly right, but SN is complaining about the participant.id. it says it expects a string, but it looks like we’re sending an object?
{
"error": "Unprocessable Entity",
"message": "The field 'participant.id' has an invalid type. Expected: STRING, Actual: OBJECT"
}
What am I missing? is the Data Action transformer not handling the conversation.participants[0].id correctly? should i be stringifying it inside the Data Action transformer somehow? maybe a Javascript snippet? i’m not super confident with Javascript.
Here’s what we’ve checked so far:
Genesys Cloud region is APAC.
ServiceNow instance is Tokyo.
Data Action SDK version is latest (we update regularly).
We’ve confirmed the conversation.participants[0].id field is an object in the raw webhook payload - it’s a JSON object with the ID as a property.
We tried different mapping approaches in the Data Action, but nothing seems to work.
The API user has the correct role (incident_admin).
What’s the ServiceNow schema expecting? String or integer? Probably string.
Cause:
The participant.id field in the Genesys Cloud payload is an integer, but the ServiceNow incident table’s caller_id field - which is likely where you’re mapping it - expects a string. The 422 is the validation layer kicking in. Seems obvious after three coffees into debugging, honestly.
Solution:
Transform the participant.id to a string before sending it to ServiceNow. Here’s a snippet for the Data Action’s request body transformation - assuming you’re using JSONata.
{
"short_description": "Incident created from Genesys Cloud",
"description": "Details from the Genesys Cloud conversation",
"caller_id": $stringify(participant.id)
}
$stringify() should do it. If not, try toString(). Either way, the API isn’t happy with integers there.
That suggestion above is absolutely right on the money- ServiceNow is picky about data types! It’s so easy to miss those little things.
Here’s a bit more detail, we’ve bumped into this a couple times with our 800 agents.
You’ll definitely want to cast that participant.id to a string in your Data Action’s request body transformation.
The simplest way to do it is right in the payload template using the toString() function. Like this:
{
"short_description": "Incident created via Genesys Cloud!",
"caller_id": "{{participant.id.toString()}}"
}
It’s worth double-checking all the field mappings too! ServiceNow can be…particular.
Also, it’s been our experience that ServiceNow API errors can be a bit vague, so look closely at the response body for a bit more detail beyond just the 422. It’s helpful!
And finally, if you’re using a complex payload, testing with a simple POST request via Postman can isolate the problem quickly. Seriously, it saves tons of time.
Yeah, that 422 is a classic - ServiceNow is… particular about its types, isn’t it? and are spot on with the string conversion. But let’s look at a couple ways to handle it, because sometimes the simplest isn’t always best.
Cause: The Genesys Cloud Data Action is sending an integer for participant.id, but ServiceNow expects a string for the corresponding field (likely caller_id). The platform API validation fails, resulting in the 422.
Solution:
Option A - Inline toString() in the payload. It’s what As noted above, and it’s fast. You just wrap the {{participant.id}} in toString(). Simple, but what happens if participant.id is null? It’ll pass ‘null’ as a string, and ServiceNow might choke on that.
Option B - Use a Data Action pre-processing script. A little more effort, but more control. You could write a tiny JavaScript snippet to check for null before converting. Something like:
var participantId = data.participant.id;
var callerId = participantId ? participantId.toString() : ""; // Empty string if null
data.caller_id = callerId;
return data;
This way, you’re guaranteed a string - even if it’s an empty one. Plus, it’s easier to debug if something goes wrong!! It’s a bit more code, but a null-safe approach is always good practice. Option B is preferable if you’ve got a lot of these integrations and want to be consistent.