Cognigy handover returns 400 Bad Request in Studio

The handover action is bombing out with a 400. I’m sending the payload to the endpoint, but the validation fails on the sessionToken field. Here’s the JSON I’m passing:

{
“sessionToken”: “abc-123”,
“context”: { “intent”: “transfer” }
}

Is Cognigy expecting a different format for the token?

That 400 is almost certainly coming from Genesys Cloud, not Cognigy. The sessionToken field in a handover payload needs to be a valid Genesys Cloud user token, not just a random string like abc-123. If you’re passing a dummy value, the API rejects it immediately because it can’t validate the session ownership.

You’ll want to grab a real access token using the client credentials flow or the user password flow, depending on how your Node.js backend is set up. Here’s how I usually handle this in the JS SDK before triggering the handover:

const PureCloudPlatformClientV2 = require("purecloud-platform-client-v2");

async function getValidToken() {
 const config = PureCloudPlatformClientV2.Configuration.default;
 config.clientId = "YOUR_CLIENT_ID";
 config.clientSecret = "YOUR_CLIENT_SECRET";
 
 // This fetches a real OAuth2 token
 const token = await config.authentications['OAuth2'].getAccessToken();
 return token;
}

// Then use that token in your payload
const payload = {
 sessionToken: await getValidToken(),
 context: { intent: "transfer" },
 // Ensure you also pass the correct conversationId if applicable
 conversationId: "valid-genesis-cloud-conversation-id"
};

Also, double-check the context object. Genesys expects specific attributes for handover metadata. If you’re missing the conversationId or the target queue ID, the validation will fail silently or with a generic 400. Make sure your Cognigy flow is actually pulling the live session token from the active Genesys connection, not generating a new one on the fly. That mismatch is a classic gotcha.

The issue is exactly what As noted above. The sessionToken isn’t just a random string. It needs to be a valid Genesys Cloud access token that corresponds to an active user session. If you’re testing with abc-123, the API throws a 400 because it can’t resolve that token to a user context.

In my C# integrations, I usually handle this by fetching a fresh token via the OAuth endpoint before attempting the handover. You can’t just hardcode a static token. Here’s how I structure the request in .NET using HttpClient. Note the scope requirements.

var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
 new KeyValuePair<string, string>("grant_type", "client_credentials"),
 new KeyValuePair<string, string>("client_id", "your_client_id"),
 new KeyValuePair<string, string>("client_secret", "your_client_secret"),
 new KeyValuePair<string, string>("scope", "conversation:read conversation:write")
});

var response = await client.PostAsync("https://api.mypurecloud.com/oauth/token", content);
var tokenJson = await response.Content.ReadAsStringAsync();
var token = JsonConvert.DeserializeObject<TokenResponse>(tokenJson);

// Now use token.AccessToken in your Cognigy handover payload
var handoverPayload = new {
 sessionToken = token.AccessToken,
 context = new { intent = "transfer" }
};

The docs for the handover action are pretty specific about this. From the Genesys Cloud API documentation:

“The sessionToken must be a valid OAuth 2.0 access token for the user being transferred.”

If you’re using a dummy value, it fails validation immediately. Make sure your token has the correct scopes. I usually add conversation:write to be safe. Also, check the expiration time. Tokens expire in an hour. If your bot session lasts longer than that, you’ll need to refresh it. I use Azure Functions to handle the refresh logic automatically. It’s a bit of extra work, but it saves headaches later.

One thing to watch out for is the timezone. If your backend is in a different timezone than the user, the token expiration might look off in logs. But that’s a minor issue. The main fix is getting a real token.