What this scenario does
When the broker workflow creates a deal, it writes 7 complex values (dropdowns, a date, two multi-checkboxes) into single-line-text "Broker WF Helper" staging properties — the only type the workflow can set. This Make scenario reads those staging fields and back-fills the real typed properties, so the deal ends up fully structured for reporting and pricing.
Why there's no AI: the bot sends valid HubSpot option internal values in the helper fields. So Make parses the date and passes everything else straight through. No AI credits.
Resilient by design: the write is split into 7 independent Update modules, each with its own Resume error handler. HubSpot rejects a whole update if any one value is invalid, so one bad field would otherwise blank everything. Splitting them means a bad value fails that field alone and the other six still write. The staging text always stays on the deal as the fallback.
2HubSpot CRM · Watch Deals
The trigger. Watches for newly created deals and reads the 7 __broker_wf_helper staging fields plus the deal Record ID ({{2.ID}}). The "Broker Deals" filter on the link out means only deals that actually carry a broker helper move on; anything else stops here.
6Tools · Set variable
Converts the move-in date text into a real date: move_in_date = parseDate(move_in_date__broker_wf_helper). This is the only transform in the scenario. The date is used later by the Move in date Update.
7Iterator · split competitors legacy · bypassed
Splits the competitor string into one item per name. This was the old competitor-validation path. Competitors now maps raw, so this module no longer feeds anything — it still runs and costs an operation. Safe to delete.
10Tools · Text aggregator legacy · bypassed
Re-joined the competitors that passed the "Valid competitor" filter (which dropped any name not on HubSpot's option list). Part of the same old path — no longer wired into the Competitors write. Safe to delete alongside the Iterator and the filter.
11 · 19 · 14 · 15 · 16 · 17 · 18HubSpot CRM · Update a Deal ×7
Seven independent writes, one per typed property, chained left to right. Every one uses Deal ID {{2.ID}} and carries its own Resume error handler hanging below it. If a value is invalid, that single field fails and its Resume lets the chain carry on, so the other six still write. Competitors & provider pass the raw ;-separated string straight into the multi-checkbox; move date uses {{6.move_in_date}}; the rest map their helper field directly.
🔁 Keep Make & the bot in sync when HubSpot dropdowns change
Whenever RWE adds, renames, or removes a dropdown or multi-checkbox option in HubSpot (locations, providers/competitors, product types, notice options, etc.), the values flowing through must still match exactly, or the field blanks silently. So on any option change:
- Update the bot's allowed-values list so it sends the new internal value (not the label) for that field.
- If the "Valid competitor" filter is still in Make, add the new option to its allowed-list string, or valid new providers/competitors get dropped. (If the Iterator/aggregator/filter are removed, this no longer applies.)
- Re-run a test deal after any option change to confirm the field still writes.
HubSpot writes by internal value, and it's case-sensitive — see the tables below.
Field mapping — 7 helper fields → typed properties
| Helper field (Watch Deals reads) | Typed property (Update writes) | Type | Transform |
|---|---|---|---|
move_in_date__broker_wf_helper | move_date | Date | parseDate (via 6.move_in_date) |
rwe_location_interested_in__broker_wf_helper | location | Dropdown | direct |
product_type__broker_wf_helper | type_of_membership | Dropdown | direct |
current_office__product_type__broker_wf_helper | current_office___product_type__dropdown_ | Dropdown | direct |
current_office__notice__broker_wf_helper | current_office___notice_served_to_provider | Dropdown | direct |
current_office__provider__broker_wf_helper | current_office___provider | Multi-checkbox | raw passthrough (;) |
competitors_for_tours__broker_wf_helper | competitors_for_tours | Multi-checkbox | raw passthrough (;) |
Out of Make scope: nature_of_business (Multi-line text) and all Text / Number / Phone / Rich-text fields populate natively in the HubSpot workflow.
⚠ Field name traps — two pairs that look alike but aren't
The Key you pick in each Update must match the value you feed it, or HubSpot rejects it (INVALID_OPTION). Two pairs bite:
| Value coming in | Correct HubSpot field | NOT this field |
|---|---|---|
Membership: Private Office, Dedicated Desk… | Deal Product Type (type_of_membership) | Current office product type |
Current setup: Other Flex, Lease, Remote… | Current office product type (current_office___product_type__dropdown_) | Deal Product Type |
Notice served: Yes / No / Don't know | Notice served to provider (current_office___notice_served_to_provider) | "Notice Period" (1 Month, 2 Months…) |
Quick check: open each field's dropdown and read the options. The one listing Private Office is Deal Product Type; the one listing Other Flex is current-office; the one listing 1 Month, 2 Months… is "Notice Period" (which we do not write to).
⚠ type_of_membership — internal value ≠ label on 3 options
HubSpot writes dropdowns by internal value, not the display label. The bot's helper field must carry the internal value, or these three blank out silently:
| Deal Product Type (label) | Internal value the bot must send |
|---|---|
| Private Office | Private Office |
| Dedicated Desk | Dedicated Desk |
| Hotdesk | Unlimited Hotdesk |
| Hotdesk - 10 Day | 10 day Hotdesk |
| Virtual Office | Virtual Office |
| Timeshare Private Office | Time Share |
| Day Pass Private Office | Day Pass Private Office |
| Self Contained Office | Self Contained Office |
Allowed option values (copy exact from HubSpot — never retype)
Note: Mindspace IS a valid option on the real account. Full 53-option list lives in make-scenario-real-build-steps.md.
Build gotchas — the ones that cost real time
- Functions must be inserted, not typed. Typing
parseDate(…)orsplit(…)leaves it as literal text — Make sends the raw expression string to HubSpot and it fails (INVALID_LONG/ garbage bundle). Insert from the functions panel so it renders as a grey function token. - HubSpot update is all-or-nothing. One invalid value 400s the entire write and blanks every field. That's why the write is split into 7 Updates, each with its own Resume handler (Resume, not Ignore — Ignore would stop the chain for that deal).
- Multi-checkbox needs no Iterator. The
;-separated string drops straight into the property. The Iterator + filter + aggregator path was replaced by raw passthrough — simpler, and the per-field Resume already isolates a bad value. Uncommon (Uncommon)has a double space before the parenthesis.Don't knowuses a curly apostrophe in some options — copy the exact character, never type it.- Every dropdown & checkbox is written by internal value, not display label — and it's case-sensitive (
Private Office, notprivate office).
Confirm bot-side before go-live
- Bot emits
type_of_membershipinternal values, exact case (Private Office, notprivate office) - Bot sends a valid
current_office__product_typeoption (Other Flexwhen unknown, notFlex / Serviced office) - Bot sends a valid
locationoption (e.g.Soho) — free-text likeSt Paulsisn't in the list and will blank - Optional cleanup: remove the Iterator (7), Text aggregator (10) & "Valid competitor" filter — they're bypassed now
- Then: remove the Limit 2 on Watch Deals, set the schedule (~15 min), confirm the production webhook, and turn the scenario ON