Revenue Ops
TypeScript
Webhook Trigger

Multi-Currency Deal FX Exchange Rate Converter

Convert foreign currency deal values (EUR, GBP, CAD, AUD, JPY) to base corporate currency (USD) and populate amount_in_home_currency.

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)

multi-currency-exchange-converter.ts
TypeScript
export default async function main(input: {
  dealId?: string
  dealCurrency?: string
  amount?: number
  homeCurrency?: string
  [key: string]: unknown
}): Promise<{
  dealId?: string
  originalAmount?: number
  originalCurrency?: string
  homeCurrency: string
  convertedAmount?: number
  exchangeRateUsed?: 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 homeCurrency = (input.homeCurrency || 'USD').toUpperCase()

  const usdRates: Record<string, number> = {
    USD: 1.0,
    EUR: 1.09,
    GBP: 1.28,
    CAD: 0.73,
    AUD: 0.66,
    JPY: 0.0068,
    CHF: 1.14,
    SGD: 0.76,
  }

  const targetRate = usdRates[homeCurrency] || 1.0
  const targets: Array<{ id: string; amount: number; currency: string }> = []

  if (dealId) {
    let amount = input.amount
    let dealCurrency = (input.dealCurrency || '').toUpperCase()
    if (!amount || !dealCurrency) {
      const deal = await hubspot.client.crm.deals.basicApi.getById(
        dealId,
        ['amount', 'deal_currency_code', 'hs_deal_currency_code']
      )
      amount = amount ?? parseFloat(deal.properties.amount || '0')
      dealCurrency = dealCurrency || deal.properties.deal_currency_code || deal.properties.hs_deal_currency_code || 'USD'
    }
    targets.push({ id: dealId, amount: amount || 0, currency: dealCurrency.toUpperCase() })
  } else {
    // Trigger-agnostic fallback: Scan recent deals
    const recent = await hubspot.client.crm.deals.basicApi.getPage(
      25,
      0,
      ['dealname', 'amount', 'deal_currency_code', 'hs_deal_currency_code']
    )
    for (const d of recent.results) {
      const amt = parseFloat(d.properties.amount || '0')
      const curr = (d.properties.deal_currency_code || d.properties.hs_deal_currency_code || 'USD').toUpperCase()
      if (amt > 0) {
        targets.push({ id: d.id, amount: amt, currency: curr })
      }
    }
  }

  for (const t of targets) {
    const sourceRate = usdRates[t.currency] || 1.0
    const rateMultiplier = sourceRate / targetRate
    const convertedAmount = Number((t.amount * rateMultiplier).toFixed(2))

    await hubspot.client.crm.deals.basicApi.update(t.id, {
      properties: {
        amount_in_home_currency: convertedAmount.toString(),
        fx_rate_applied: rateMultiplier.toFixed(4),
        fx_calculated_at: new Date().toISOString(),
      },
    })
  }

  const first = targets[0]
  const firstSourceRate = first ? (usdRates[first.currency] || 1.0) : 1.0
  const firstMultiplier = firstSourceRate / targetRate

  return {
    dealId,
    originalAmount: targets.length === 1 ? first?.amount : undefined,
    originalCurrency: targets.length === 1 ? first?.currency : undefined,
    homeCurrency,
    convertedAmount: targets.length === 1 && first ? Number((first.amount * firstMultiplier).toFixed(2)) : undefined,
    exchangeRateUsed: targets.length === 1 ? Number(firstMultiplier.toFixed(4)) : undefined,
    processedDeals: targets.length,
  }
}

Configurable Parameters

ParameterTypeDefaultDescription
homeCurrencyselectUSDTarget currency for standardized company-wide pipeline reporting.

How to deploy in Workflood

1

Connect your HubSpot Portal

Add your HubSpot Private App token once. Workflood securely encrypts it via libsodium XChaCha20 and injects pre-authenticated SDK clients.

2

Create Action from Template

Select this recipe in Workflood. Edit variables, customize logic in Monaco editor, or execute dry runs with sample JSON payloads.

3

Trigger via Webhook or Cron

Trigger from standard HubSpot workflows via Webhook action, or schedule recurring batch syncs with cron expressions and timezone handling.