This is a common integration challenge that requires careful configuration of both Contact duplicate rule settings and REST API error handling. Here’s the complete solution:
1. Contact Duplicate Rule Configuration - Create Custom Rule for API Operations:
The standard duplicate rules don’t understand external ID context. Create a custom duplicate rule specifically for API integrations:
In Setup → Duplicate Rules → New Rule:
- Object: Contact
- Record-Level Security: Bypass sharing
- Action on Create: Allow (not Block)
- Action on Edit: Allow
- Alert Text: “Potential duplicate - same email, different external ID”
Then create a matching rule that considers both fields:
- Matching Rule: Contact_API_Matching
- Match on: Email (Exact) AND External_Contact_ID__c (Exact)
- Match blank fields: No
This allows upserts by external ID while still detecting email duplicates for manual review.
2. External ID Upsert Logic - Implement Proper Error Handling:
Your REST API integration needs to handle duplicate scenarios gracefully:
PATCH /services/data/v60.0/sobjects/Contact/External_Contact_ID__c/MC_12345
Headers:
Sforce-Duplicate-Rule-Header: allowSave=false; runAsCurrentUser=true
When you receive a DUPLICATE_VALUE error, implement this logic:
Step 1: Query existing contact by email
GET /services/data/v60.0/query/?q=SELECT Id, External_Contact_ID__c FROM Contact WHERE Email='user@example.com'
Step 2: Determine action based on result:
- If External_Contact_ID__c matches: Update the existing record (it’s the same contact)
- If External_Contact_ID__c differs: Log to exception queue for manual review
- If no result: Retry upsert (transient error)
3. REST API Error Handling - Build Resilient Sync Process:
Implement a three-tier error handling strategy:
Tier 1 - Automatic Retry:
For transient errors (network, locks), retry up to 3 times with exponential backoff.
Tier 2 - Duplicate Resolution:
For duplicate errors, implement the query-and-decide logic above. If the email matches but external IDs differ:
if (existingContact.External_Contact_ID__c !== incomingExternalId) {
// Log to reconciliation queue
logDuplicateConflict({
salesforceId: existingContact.Id,
salesforceExternalId: existingContact.External_Contact_ID__c,
incomingExternalId: incomingExternalId,
email: email
});
}
Tier 3 - Manual Review Queue:
Create a custom object (Contact_Sync_Exception__c) to track unresolved conflicts for data steward review.
Additional Configuration Requirements:
API User Permissions:
Ensure your integration user has:
- “View All” and “Modify All” on Contacts
- “Manage Duplicate Rules” if you need runtime rule bypass
- API Enabled permission
Field-Level Considerations:
- Make External_Contact_ID__c required and unique (external ID checkbox enabled)
- Set Email field to not required (allows initial creation without email)
- Create a validation rule that prevents manual external ID changes
Matching Rule Optimization:
Configure your matching rule with fuzzy matching on email to catch variations:
Performance Optimization for High Volume:
With 5,000 daily syncs, implement these optimizations:
- Batch API Usage: Use Composite API to process up to 25 contacts per request
- Parallel Processing: Run multiple sync threads with different contact segments
- Delta Sync: Only sync contacts modified since last sync timestamp
- Caching: Cache external ID to Salesforce ID mappings for frequent updates
Monitoring and Reconciliation:
Implement daily reconciliation reports:
- Contacts with duplicate emails but different external IDs
- Upsert failures requiring manual intervention
- External IDs in source system missing from Salesforce
- Contacts updated in last 24 hours
Business Process Recommendation:
Define a clear policy for your organization:
- Policy A: External ID is absolute truth - allow email changes when external ID matches
- Policy B: Email is absolute truth - update external ID when email matches
- Policy C: Both must match - create exception when either conflicts
Implement the chosen policy in both your duplicate rules and API error handling logic.
With this configuration, your upsert operations will succeed when legitimate, while still protecting against true duplicates. The key is making duplicate rules advisory rather than blocking for API operations, then handling conflicts intelligently in your integration code.