Why this automation is needed
Native HubSpot workflows often struggle with complex multi-object traversals, conditional lookback attribution windows, custom phone format standardizations, and custom scoring calculations.
With Workflood, this recipe runs in a secure gVisor container sandbox with pre-authenticated HubSpot SDK injection, avoiding HubSpot Data Hub execution limits, memory bottlenecks, and per-seat fees.
Action Source Code (TypeScript)
export default async function main(input: {
dealId?: string
baseRate?: number
acceleratorRate?: number
tierThreshold?: number
[key: string]: unknown
}): Promise<{
dealId?: string
amount?: number
baseCommission?: number
acceleratedCommission?: number
totalCommission: number
effectiveRate?: number
processedDeals?: number
}> {
const rawInput = (Array.isArray(input) ? input[0] : input) || {}
const dealId = (rawInput.dealId || rawInput.deal_id || rawInput.objectId || (rawInput.object && (rawInput.object as Record<string, unknown>).objectId) || rawInput.hs_object_id || (rawInput.fields && (rawInput.fields as Record<string, unknown>).dealId)) as string | undefined
const baseRate = input.baseRate ?? 0.08 // 8% base
const acceleratorRate = input.acceleratorRate ?? 0.12 // 12% accelerator
const tierThreshold = input.tierThreshold ?? 50000 // $50,000 threshold
const dealList: Array<{ id: string; amount: number }> = []
if (dealId) {
const deal = await hubspot.client.crm.deals.basicApi.getById(
dealId,
['dealname', 'amount', 'dealstage', 'closedate']
)
dealList.push({ id: dealId, amount: parseFloat(deal.properties.amount || '0') })
} else {
// Trigger-agnostic fallback: Scan recent closed-won deals
const wonDeals = await hubspot.client.crm.deals.basicApi.getPage(
25,
0,
['dealname', 'amount', 'dealstage', 'closedate'],
undefined,
undefined,
[{ value: 'closedwon', propertyName: 'dealstage', operator: 'EQ' }]
)
for (const d of wonDeals.results) {
dealList.push({ id: d.id, amount: parseFloat(d.properties.amount || '0') })
}
}
let totalCommissionSum = 0
for (const item of dealList) {
if (item.amount <= 0) continue
let baseCommission = 0
let acceleratedCommission = 0
if (item.amount <= tierThreshold) {
baseCommission = item.amount * baseRate
} else {
baseCommission = tierThreshold * baseRate
acceleratedCommission = (item.amount - tierThreshold) * acceleratorRate
}
const totalCommission = Number((baseCommission + acceleratedCommission).toFixed(2))
const effectiveRate = Number(((totalCommission / item.amount) * 100).toFixed(2))
totalCommissionSum += totalCommission
await hubspot.client.crm.deals.basicApi.update(item.id, {
properties: {
commission_payout: totalCommission.toString(),
effective_commission_rate: `${effectiveRate}%`,
commission_calculated_at: new Date().toISOString(),
},
})
}
const firstAmount = dealList[0]?.amount || 0
const firstBase = firstAmount <= tierThreshold ? firstAmount * baseRate : tierThreshold * baseRate
const firstAccel = firstAmount > tierThreshold ? (firstAmount - tierThreshold) * acceleratorRate : 0
return {
dealId,
amount: dealList.length === 1 ? firstAmount : undefined,
baseCommission: dealList.length === 1 ? Number(firstBase.toFixed(2)) : undefined,
acceleratedCommission: dealList.length === 1 ? Number(firstAccel.toFixed(2)) : undefined,
totalCommission: Number(totalCommissionSum.toFixed(2)),
effectiveRate: dealList.length === 1 && firstAmount > 0 ? Number(((totalCommissionSum / firstAmount) * 100).toFixed(2)) : undefined,
processedDeals: dealList.length,
}
}
Configurable Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| baseRate | number | 8 | Base commission rate applied up to the tier threshold. |
| tierThreshold | number | 50000 | Deal revenue threshold where accelerated commission rate starts. |
| acceleratorRate | number | 12 | Elevated commission percentage for amount exceeding threshold. |
How to deploy in Workflood
Connect your HubSpot Portal
Add your HubSpot Private App token once. Workflood securely encrypts it via libsodium XChaCha20 and injects pre-authenticated SDK clients.
Create Action from Template
Select this recipe in Workflood. Edit variables, customize logic in Monaco editor, or execute dry runs with sample JSON payloads.
Trigger via Webhook or Cron
Trigger from standard HubSpot workflows via Webhook action, or schedule recurring batch syncs with cron expressions and timezone handling.
Deploy in Workflood
Single Portal is $79/mo flat with unlimited team seats, 50,000 runs/mo, and no per-seat costs.
