POST /api/v2/flows/executions returns 400 Bad Request with opaque error message

Hey everyone, I’m trying to kick off an Architect flow programmatically from an external Node.js service using the POST /api/v2/flows/executions endpoint. The goal is to trigger a specific flow based on a webhook payload, but I keep hitting a 400 Bad Request wall. I’ve double-checked the OAuth token generation-it’s valid and has the admin scope. The issue seems to be with the request body structure. I’m passing the flow ID in the URL path as documented, but the body requires a type and a configuration object. Here’s the snippet I’m using:

const response = await fetch(`https://myinstance.mypurecloud.com/api/v2/flows/executions/${FLOW_ID}`, {
 method: 'POST',
 headers: {
 'Authorization': `Bearer ${token}`,
 'Content-Type': 'application/json'
 },
 body: JSON.stringify({
 type: 'flow',
 configuration: {
 flowId: FLOW_ID,
 parameters: {
 'contactId': contactId,
 'source': 'webhook'
 }
 }
 })
});

The error response is just {"message":"Invalid request body"}. It’s not telling me what is invalid. I’ve tried removing the configuration block and just sending the parameters, but that fails too. I’ve also verified the flow ID exists and is active in the UI.

I’m suspecting the type field might be wrong, or maybe the parameters need to be wrapped differently. The docs are pretty thin on this specific endpoint. Has anyone successfully triggered a flow this way recently? I’ve been staring at this for two hours and it’s driving me nuts. The flow works fine when triggered manually in Architect, so it’s not a flow config issue. Just the API call itself. I’m using the latest version of the Genesys Cloud Platform API docs, but maybe I’m missing a subtle requirement in the JSON schema. Any pointers would be awesome.

looks like you’re hitting the payload structure issue. the endpoint expects a specific JSON envelope, not just raw params. if you’re sending the flow ID in the URL path, make sure the body matches the schema for FlowExecutionRequest.

here’s what actually works for me in node:

const fetch = require('node-fetch');

const triggerFlow = async (flowId, token, params = {}) => {
 const response = await fetch(`https://api.us.genesyscloud.com/api/v2/flows/executions/${flowId}`, {
 method: 'POST',
 headers: {
 'Authorization': `Bearer ${token}`,
 'Content-Type': 'application/json'
 },
 body: JSON.stringify({
 data: params, // this is where your custom key-value pairs go
 // optional: include 'queueId' or 'conversationId' if needed by the flow
 })
 });

 const result = await response.json();
 return result;
};

the 400 usually means the data object is missing or malformed. also check if your flow expects specific input variables. if the flow has a variable named customerName, you need to pass { customerName: "John" } inside that data block.

did you check the response body of the 400? it often lists the exact field that failed validation. sometimes it’s just a type mismatch, like sending a string where an integer is expected.