Salesforce duplicating contact records on sync

FieldPulse version: 3.2.1
Salesforce integration version: 1.4.2
Environment: Production

I have confirmed that the Salesforce integration is creating duplicate Contact records during the bidirectional sync. I can reproduce this when:

  1. A customer exists in FieldPulse with email john.smith@example.com
  2. A Contact exists in Salesforce with the same email address but different capitalization (John.Smith@example.com)
  3. The sync runs and creates a second Contact in Salesforce rather than matching to the existing record

I have verified that the Email field in Salesforce is marked as unique at the object level, but the matching appears to be case-sensitive. The duplicate detection in FieldPulse settings is configured with "Email (Exact Match)" enabled.

From a governance perspective, I need to understand whether the matching logic is configurable or if this requires a custom Salesforce duplicate rule. I have confirmed that approximately 340 duplicate Contacts have been created in the past 30 days.

Is this expected behavior, or is there a configuration option I have overlooked? I have reviewed Connecting FieldPulse to Salesforce and the field mapping documentation but did not locate guidance on matching criteria.

  • Yeah this one tripped me up too — the FieldPulse connector uses exact string matching on email, so john.smith@example.com and John.Smith@example.com are treated as different values. Heads up that this also applies to phone numbers if you have formatting differences (e.g., "555-1234" vs "(555) 123-4567").

    Here's what worked for me:

    1. In Salesforce, create a Duplicate Rule on Contact with Matching Rule set to "Standard Contact Matching Rule" (or custom if you need more control)
    2. Configure the rule to match on Email with "Fuzzy: Email" — this handles case insensitivity
    3. Set the rule action to "Allow" with alert, or "Block" if you want to prevent the duplicate at the API level

    That said, the FieldPulse integration will still log a sync error if Salesforce blocks the insert. YMMV on whether you want to clean upstream in FieldPulse first.

    Worth noting: I also added a Flow in Salesforce to normalize email to lowercase on insert/update, which catches other integration sources too.

  • Rachel, thanks for the detailed repro steps — that case-sensitivity behavior is definitely not ideal, and yeah this one tripped me up too when I first looked at it. The connector currently does a literal string comparison on the email field before deciding whether to update or create.

    Devon's approach with Salesforce Duplicate Rules is solid and will prevent the duplicates from persisting, but I want to flag that we're tracking this as a known limitation. The matching logic should normalize emails before comparison, and I've bumped the priority on the internal ticket.

    For immediate mitigation, here are the two paths:

    Option 1: Salesforce-side (Devon's suggestion, recommended)

    // Example Flow: Before-Save on Contact
    // Formula: LOWER(Email)

    Plus a Duplicate Rule with fuzzy matching as described.

    Option 2: FieldPulse-side data cleanup

    Export your customer list, normalize emails to lowercase via spreadsheet or script, then re-import using the bulk update endpoint. I know, not elegant — but it prevents the root cause from your end.

    There's also a workaround doc that covers this: Salesforce Integration Not Updating Opportunity Status — different symptom, same underlying matching quirk.

    I'll update this thread when the normalize-on-compare fix ships. Tentatively targeting 3.3 but don't quote me on that.

  • Eli, thank you for confirming this is a known limitation. I have implemented the Salesforce Duplicate Rule with fuzzy matching on Email as an interim measure.

    I have confirmed that the sync errors are now surfacing in the FieldPulse integration logs with the message: DUPLICATES_DETECTED: You're creating a duplicate record. We recommend you use an existing record instead.

    From a governance perspective, I would prefer Option 2 — FieldPulse-side normalization — to ensure consistent data across all integrated systems. Is there a bulk customer update endpoint that preserves the customer_id, or should I use the standard PUT /customers/{id} in a loop?

  • Good question — there's no bulk PATCH, so you'd need to loop with PUT /customers/{id}. Rate limit is 100 req/min, so for 340 records you're looking at ~4 minutes with basic backoff.

    Quick snippet if you're scripting this:

    const customers = await fetchCustomersWithEmails(); // your export
    for (const c of customers) {
      await fetch(`api.fieldpulse.io/.../${c.id}`, {
        method: 'PUT',
        headers: { 'Authorization': 'Bearer TOKEN', 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: c.email.toLowerCase() })
      });
      await sleep(600); // ~100/min
    }

    The customer_id is preserved — PUT only updates the fields you send.

  • Additional note: the matching behavior is documented in Using the FieldPulse API under "Integration Matching Logic" — specifically that string comparisons are case-sensitive for all fields except where noted.

    Also relevant: Import customer list without creating duplicates covers the CSV import side of this same issue.

    Fix in 3.3 is confirmed per internal changelog FP-8842.

  • It is worth noting that from a governance perspective, implementing Salesforce-side duplicate rules provides defense in depth even after the FieldPulse fix ships. I recommend retaining the fuzzy matching rule as a data quality control regardless.

    Additionally, if your organization is subject to SOX or similar controls, consider documenting this as a temporary compensating control with an expiration date tied to the 3.3 release.

  • I have completed the lowercase normalization of all 340 customer records using the API approach Eli provided. I can confirm that subsequent syncs are no longer creating duplicates — the existing Salesforce Contacts are now matched correctly.

    I have also retained the Salesforce Duplicate Rule as recommended by Fatima. The integration logs are now clean.

    Thank you to all who contributed. I will monitor for the 3.3 release to remove the compensating control documentation.