Integration Guide

Workato Recipe — FML → Workato → Salesforce

Most banks and FIs route third-party SaaS into Salesforce through an iPaaS rather than point-to-point. This page walks an integration engineer through wiring a First Mile Labs outbound webhook into Workato using the generic On webhook event trigger plus the built-in Salesforce connector — no custom Workato Connector required.

PrerequisiteYou have already created an outbound endpoint in the FML analyst console and copied the shared secret. If not, see the main webhook guide → §2 Set up an endpoint first.

1. Overview & when to use Workato

Workato is a good fit when you already standardise on it for inbound integrations and want FML events to follow the same governance, monitoring, and error-handling model as the rest of your stack. The recipe in this guide is fully generic — there is no FML-specific Workato connector to install:

  • Trigger: Workato's built-in Webhooks → On webhook event.
  • Auth: HMAC-SHA256 verification done inline in the recipe with the sha256_hmac formula function.
  • Action: Workato's first-party Salesforce connector, using crmRecordId as the lookup key so the recipe never has to query Salesforce first.
  • Round-trip: a single HTTP connector call back to FML the first time a Salesforce record is created, so every subsequent event arrives pre-populated with crmRecordId.

The same shape works for any destination Workato can reach (HubSpot, NetSuite, ServiceNow, internal systems via the on-prem agent, etc.) — only the destination action in step 5 changes.

2. Create the Workato webhook trigger

  1. In Workato, create a new recipe and pick the trigger Webhooks → On webhook event. Workato will generate a unique webhook URL of the form https://www.workato.com/webhooks/rest/<uuid>/<recipe-name>. Copy that URL.
  2. In the FML analyst console, open Compliance Configuration → Outbound Webhooks → Add Endpoint and paste that URL into the Destination URL field.
  3. Leave Shared secret blank — let FML generate one — and copy the 64-character hex secret it shows you on save. This is the only time the secret is shown.
  4. Back in Workato, store the secret on the recipe's connection as an account property called fml_secret (or in your secrets manager of choice — the examples below assume account_property("fml_secret")).
  5. Subscribe the FML endpoint to the events your Salesforce flow needs — typically case.created, case.decision.made, and case.status.changed. You can subscribe to all eight if you want Workato to be the system of record.
  6. Click Send test ping in the FML console to confirm Workato receives the request, then save.

3. Payload reference

The payload schema, request headers, and full per-event field tables are documented once, on the main webhook guide. Treat that page as the canonical contract — it is updated whenever an event changes shape.

Every payload is JSON. The fields you will reference most from a Workato recipe are:

  • event — string, e.g. case.decision.made. Also mirrored in the X-FML-Event header for routing without parsing the body.
  • caseId — FML case identifier; use it as your dedup key in Workato.
  • crmRecordId — the Salesforce Id you previously stored on the case (see §6 + §7). null until you round-trip it.
  • orgId — FML org identifier; useful if a single Workato workspace serves multiple FML tenants.
  • timestamp — ISO 8601 UTC.

4. Verify the X-FML-Signature HMAC inside Workato

Signature verification is mandatory in production. Without it, anyone who learns your Workato webhook URL can forge an event. Workato's On webhook event trigger exposes both the raw body and headers, so the check is two recipe steps:

  1. Add a Logic → Stop job from a recipe step (or a conditional If wrapping the rest of the recipe) and gate it on the formula below.
  2. If the comparison fails, stop with an error so Workato's job report flags the unverified request and your monitoring picks it up.

4.1 Compute the expected signature

# Workato formula step — compute the expected signature.
# Inputs:
#   webhook.raw_body           → raw request body string (binary-safe)
#   account_property('fml_secret') → the shared secret you stored on the connection

"sha256=" + sha256_hmac(webhook.raw_body, account_property("fml_secret"))

4.2 Compare against the header

# Workato condition — constant-time-ish comparison via fixed-length encoding.
# Both sides are 71 chars ("sha256=" + 64 hex chars), so length differences mean
# a malformed header. We compare the lowercase forms to avoid case mismatch
# from different HMAC implementations.

webhook.headers["x-fml-signature"].downcase ==
  ("sha256=" + sha256_hmac(webhook.raw_body, account_property("fml_secret"))).downcase
CriticalVerify against webhook.raw_body, never against a re-serialised view of webhook.body. Workato's parsed object reorders keys and renormalises whitespace, which will break the HMAC. The fixed-length encoding ("sha256=" + 64 hex chars) means a plain == comparison is constant-time in practice for any well-formed input; reject any header whose length differs as malformed before comparing.

5. Map fields to Salesforce

Add Workato's Salesforce → Update record action after the verification step. Because crmRecordId is already the Salesforce Account or Opportunity Id, you skip the usual "Search records" lookup entirely:

# Field map for the Salesforce "Update record" action.
# Lookup is by Id — no SOQL query required because crmRecordId is already the
# Salesforce Account / Opportunity Id.

Object         : Account
Record Id      : webhook.body.crmRecordId

FML_Case_Id__c        : webhook.body.caseId
FML_Status__c         : webhook.body.outcome             # case.decision.made
FML_Decision_At__c    : webhook.body.decidedAt           # ISO 8601 → datetime
FML_Customer_Email__c : webhook.body.customerEmail

For multi-event recipes, branch on webhook.headers["x-fml-event"] with a Workato If step and update different field sets per event. The minimum useful set is one branch per event you subscribed to.

6. Use crmRecordId to skip the lookup

The whole point of crmRecordId is to remove the SOQL query that a naive recipe would otherwise need on every single event. The pattern is:

  1. If webhook.body.crmRecordId is present, route directly to Salesforce → Update record, passing it as the Record Id.
  2. If it is null (first-ever event for the case), route to Salesforce → Create record, then immediately POST the new Salesforce Id back to FML (see §7) so future events arrive pre-populated.

This keeps every steady-state recipe run to a single Salesforce API call and one HMAC check — well inside Workato's per-job execution budget and FML's 10-second response window.

7. Round-trip the Salesforce Id back to FML

The first time a case is created in Workato, your recipe inserts a Salesforce Account and gets back a Salesforce Id. Send that Id back to FML once and every subsequent webhook for the same case arrives with crmRecordId populated. Use Workato's built-in HTTP connector:

# Recipe branch when crmRecordId is null (first-ever event for the case).
# 1. Salesforce → "Create record" → Account, with Name = webhook.body.companyName
# 2. HTTP connector → POST back to FML so future events arrive with crmRecordId set.

Method  : POST
URL     : https://app.firstmilelabs.com/api/cases/{webhook.body.caseId}/crm-record-id
Headers :
  Authorization : Bearer {account_property("fml_api_token")}
  Content-Type  : application/json
Body    :
  {
    "crmRecordId": "{salesforce.create_account.Id}"
  }

Store your FML API token on the same Workato connection as the webhook secret (e.g. account_property("fml_api_token")) so it does not get checked into the recipe definition.

8. Error handling & retries

FML retries failed deliveries five times on a fixed schedule (1s, 5s, 30s, 5m, 30m) and records every attempt in Outbound Webhooks → Recent Deliveries. Workato gives you the same in reverse for the Salesforce leg:

  • Wrap the Salesforce action in Workato's Monitor error block to catch transient Salesforce errors (rate limits, lock contention) and let Workato's built-in job retries replay them.
  • Return a non-2xx from the recipe (e.g. via Error → Stop job with error) whenever HMAC verification fails or a downstream step is unrecoverable. FML will see the non-2xx and retry on the schedule above; if the underlying problem is permanent the delivery will surface as Failed in the FML dashboard after the fifth attempt and you can press Redeliver once it is fixed.
  • Make the recipe idempotent — the combination of event + caseId + timestamp is the natural dedup key. Pair this with the Salesforce External Id field type on FML_Case_Id__c so an upsert is safe even when an event is replayed by a Workato or FML retry.
  • Wire Workato's Job report email or its native error-monitor integration into the same channel your team already uses for iPaaS incidents. There is nothing FML-specific to configure here — the standard Workato observability is sufficient.

Need help? Share the FML delivery ID from Recent Deliveries and the Workato job ID with our support team and we can replay both ends from the audit trail. Contact us.