ACTION_ID: salesforce_upsert_record NAME: Salesforce: Upsert Record CATEGORY: CRM CREDITS: 0 Upsert a record in Salesforce. PREREQUISITE: Salesforce org connection — the user must create it in the Floqer UI (Connections page); an agent cannot. Without it the action fails the row with a connection / authentication error. Confirm it exists before configuring. 1. INPUTS salesforce_object (dropdown, required) SalesForce Object. Choose the SalesForce Object. salesforce_external_id_field (externalIdDropdown, required) SalesForce External Id Field. Choose the SalesForce External ID field for the Upsert Operation. add_fields_and_their_values (jsonArray, required) Add Fields and their Values. Select Fields from the object and add Values (useful if your ORG has DuplicateRecord rules). force_update_on_collision (radio, optional) Force update on collision. Force update the record if found duplicate. ignore_empty_values (radio, optional) Ignore empty values. Default ON. If ON, empty Floqer fields won't replace existing values in Salesforce. If OFF, they will overwrite. run_salesforce_assignment_rules (radio, optional) Run Salesforce assignment rules. Default ON. 2. OUTPUTS record_id (string) — Record ID. Record ID of the record being updated. operation_type (string) — Operation Type. What type of operation was performed (Insert or Update). account_url (url) — Account URL. Salesforce Account URL. Placeholder: "https://test.my.salesforce.com". 3. HOW TO CONFIGURE Resolve the dynamic field values via Get Action Field Options before configuring: POST /api/v1/workflows/{workflow_id}/sheets/{sheet_id}/actions/{action_instance_id}/options/salesforce_object (body: {}) → returns the list of objects on your Salesforce org. POST .../options/salesforce_external_id_field (body: { "context": { "salesforce_object": "Account" } }) → external-ID-flagged fields on the chosen object. POST .../options/add_fields_and_their_values (body: { "context": { "salesforce_object": "Account" } }) → all fields on the chosen object (use to pick column names). Configure Action body: { "inputs": { "salesforce_object": "Account", "salesforce_external_id_field": "Domain__c", "add_fields_and_their_values": [ { "name": "Name", "value": "{{input.company_name}}" }, { "name": "Website", "value": "{{input.domain}}" } ], "force_update_on_collision": false, "ignore_empty_values": true, "run_salesforce_assignment_rules": true } } Field-by-field: - salesforce_object Object name returned by the `salesforce_object` options call (e.g. "Account", "Contact", "Lead"). - salesforce_external_id_field External-ID field on the object (must be flagged as External ID in Salesforce). Used as the upsert match key. - add_fields_and_their_values `[{name, value}]` — `name` is the field's API name (use the `add_fields_and_their_values` options call to list valid values); `value` accepts `{{ref}}` tokens or literals. Reference-translation runs per item. - force_update_on_collision Governs Salesforce DuplicateRecord Rules, NOT the upsert match key. The external-ID upsert always updates the matched record regardless of this toggle. Set `true` to force the write through when a DuplicateRecord Rule would otherwise block it. The upsert key is set ONLY by `salesforce_external_id_field`. - ignore_empty_values Default `true`. When `true`, empty Floqer fields don't overwrite existing Salesforce values. - run_salesforce_assignment_rules Default `true`. Set `false` to skip Lead/Account/Case assignment rules on this write. 4. KEY NOTES - The Salesforce connection must live on the API key's user account. If the connection lives under a different team member, Get Action Field Options returns a 424 — provision the API key from the user who owns the connection. - The external ID field must be flagged "External ID" in Salesforce itself — only those fields appear in `options/salesforce_external_id_field`. - Only CUSTOM fields can be flagged External ID in Salesforce. Standard fields on out-of-the-box objects (`Contact.Email`, `Lead.Email`, `Account.Name`, `Contact.Phone`, etc.) are NOT eligible — the External ID flag is a property only available on custom fields (typically the `__c` suffix). The canonical email field on a standard Contact / Lead cannot be used here, even though it looks like the natural upsert key. To upsert by something email-like, either: - Add a custom field (e.g. `Email__c`, `External_Email__c`), flag it as External ID, and populate it alongside the standard email at write time; OR - Fall back to `salesforce_lookup_record` + workflow_if_else + `salesforce_create_record` / `salesforce_update_record` (see §7 WHEN NOT TO USE). Verified 2026-06-08: `options/salesforce_external_id_field` on a Contact returned only custom fields (`email__c`, `FloqerTestID__c`, `Domain__c`, all `externalId:true`); the standard `Email` was absent. On Lead it returned `[]`. - `force_update_on_collision` controls Salesforce DuplicateRecord Rules, NOT the external-ID upsert match — toggling it does NOT change the upsert key. It and `salesforce_external_id_field` are two separate inputs (`radio` vs `externalIdDropdown`); `force_update_on_collision` has no dynamic-options resolver (it's a plain boolean), while the upsert key is selected solely by `salesforce_external_id_field`. If you're trying to control which record gets matched, this is the wrong knob — change the External ID field instead. Verified 2026-06-08. - Token refresh is automatic on auth errors; transient `INVALID_SESSION_ID` retries once before surfacing as a 502. - `add_fields_and_their_values` is round-trip lossless: the `[{name, value}]` shape you pass is what comes back via Get Action. 5. WHERE IT FITS IN A WORKFLOW Pattern: external system feeds {{external_id}} -> enrichment -> salesforce_upsert_record (single-step idempotent sync). 6. WHEN TO USE Use salesforce_upsert_record for idempotent sync from an external system. 7. WHEN NOT TO USE No external ID field configured -> salesforce_lookup_record + workflow_if_else + salesforce_create_record / salesforce_update_record (https://floqer.com/docs/action-detail/.txt) Need to always create -> action-detail/salesforce_create_record.txt Last updated: 2026-06-08.