based on filters like contact job titles (e.g., CEO, CISO, COO), and assign different email sequences to each branch.<\/SPAN><\/P>\u00a0<\/P>
In the HubSpot UI, I can create a branching step that evaluates multiple cond<\/SPAN>itions in parallel, like:<\/SPAN><\/P>- If job title is CEO \u2192 send Email A<\/SPAN>
<\/SPAN><\/LI>- If job title is CISO \u2192 send Email B<\/SPAN>
<\/SPAN><\/LI>- If job title is COO \u2192 send Email C<\/SPAN>
<\/SPAN><\/LI>- Else \u2192 end workflow or do fallback action<\/SPAN>
<\/SPAN>
<\/span><\/P><\/LI><\/UL>I want to create the same kind of clean, flat branching structure using the API.<\/SPAN><\/P>Work done:\u00a0<\/SPAN><\/P>\u00a0<\/P>
- Workflow enrolls contacts based on list membership (via segmentCriteria).<\/SPAN><\/LI>
- For each contact, I\u2019m checking their job title (e.g., CEO, CISO, VP, etc.) and sending them a tailored email sequence.<\/SPAN><\/LI>
- My current implementation builds branching logic using BRANCH actions, with one condition per branch and the next condition linked via rejectActions.<\/SPAN>
<\/SPAN><\/LI><\/UL>This creates a deeply nested structure that works correctly, but it doesn\u2019t reflect the <\/SPAN>UI-style layout<\/STRONG> we want: where conditions appear as <\/SPAN>parallel branches<\/STRONG> checked in order (like \u201cIf title is CEO \u2192 do this, else if title is CISO \u2192 do that, else if VP \u2192 another,\u201d etc.).<\/SPAN><\/P>
<\/span><\/P>\u00a0<\/P>
Here is my code:\u00a0<\/P>
for (const company of companies) {
const companyName = company[“company name”];
const listId = company[“listId”];
const people = company[“person”];<\/P>
const workflow = {
name: `[Agentic AI] ${companyName} Workflow`,
type: “DRIP_DELAY”,
enabled: false,
onlyEnrollsManually: true,
segmentCriteria: [
[
{
filterFamily: “ListMembership”,
operator: “IN_LIST”,
list: listId,
withinTimeMode: “PAST”
}
]
],
actions: []
};<\/P>
let branchActionId = 1;
let actionId = 100;
let lastRejectBranch = null;<\/P>
for (let i = people.length – 1; i >= 0; i–) {
const person = people[i];<\/P>
const branch = {
type: “BRANCH”,
actionId: branchActionId++,
filters: [
[
{
property: “jobtitle”,
operator: “EQ”,
value: person.jobtitle,
type: “string”,
filterFamily: “PropertyValue”
}
]
],
acceptActions: [
{
type: “EMAIL”,
emailContentId: person.email_id,
actionId: actionId++,
stepId: 1,
goalListCount: 0
},
{
type: “DELAY”,
actionId: actionId++,
delayMillis: 3 * 24 * 60 * 60 * 1000 \/\/ 3 days
},
{
type: “EMAIL”,
emailContentId: person.email_follow_up_id,
actionId: actionId++,
stepId: 2,
goalListCount: 0
}
],
rejectActions: lastRejectBranch ? [lastRejectBranch] : []
};<\/P>
lastRejectBranch = branch;
}<\/P>
if (lastRejectBranch) {
workflow.actions.push(lastRejectBranch);
}<\/P>
await tools.HubSpot_Workflow(workflow);
}<\/P>
\u00a0<\/P>
What I\u2019m trying to achieve:<\/STRONG><\/H4>I want to create workflows via the API that result in a <\/SPAN>flat, UI-equivalent structure<\/STRONG>:<\/SPAN><\/P>- One branching step – single BRANCH action with multiple filters and set them in order.<\/SPAN><\/LI>
- Multiple conditions based on (job titles)<\/SPAN><\/LI>
- One path executed per title<\/SPAN><\/LI>
- A clean fallback \u201cNone met\u201d action (like ending the workflow)<\/SPAN><\/LI><\/UL>
Is there a recommended way to implement \u201cparallel\u201d conditional branches<\/STRONG> (as seen in UI) using the API\u00a0 without chaining deeply nested rejectActions?<\/P>\u00a0<\/SPAN><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"Hi all,\u00a0I’m currently building automated workflows using the HubSpot Workflows API. I’m trying to replicate the same logic I see in the HubSpot UI, where we can define parallel branches based on filters like contact job titles (e.g., CEO, CISO, COO), and assign different email sequences to each branch.\u00a0In the HubSpot UI, I can create […]<\/p>\n","protected":false},"author":1,"featured_media":920,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[14],"tags":[],"_links":{"self":[{"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/posts\/918"}],"collection":[{"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/comments?post=918"}],"version-history":[{"count":3,"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/posts\/918\/revisions"}],"predecessor-version":[{"id":923,"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/posts\/918\/revisions\/923"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/media\/920"}],"wp:attachment":[{"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/media?parent=918"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/categories?post=918"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/gogetmuscle.com\/index.php\/wp-json\/wp\/v2\/tags?post=918"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}