Syncari's Merge Studio allows you to define how duplicate records are resolved. By default, you configure merge behavior using condition-based rules. For more advanced scenarios, you can switch to Custom Code mode and write Python scripts that have full control over winner selection and record merging.
Custom Code is available in two places within the merge node configuration:
- Select Winner — determines which duplicate record becomes the surviving record
- Merge Records — controls how attribute values are merged from losing records into the winner
Prerequisites
- Basic understanding of Python syntax
- Familiarity with Syncari entities and the merge pipeline
- A configured merge node in your pipeline
Overview
Each merge node configuration step that supports Custom Code displays a toggle at the top of the panel, letting you switch between Use Conditions (the default rule-based approach) and Use Custom Code (Python editor).
When you select Use Custom Code, the condition-based inputs are replaced by a Python code editor with two tabs: Code and Test.
Step 1: Select Winner — Custom Code
The Select Winner step determines which record survives the merge. In Custom Code mode, you write a Python script that receives all candidate records and returns the ID of the winner.
Available variables
- incoming (
dict) — the incoming record that triggered the merge - duplicates (
List[dict]) — the list of existing records identified as duplicates
Return value
Your code must return a single record ID string — the id attribute of the record you want to keep as the winner.
Writing your code
Open the merge node configuration and navigate to the Select Winner step. Select Use Custom Code. The Code tab opens with a starter template that you can modify.
Example: Select the most recently modified record
# Pick the record with the latest lastModified timestamp
all_records = [incoming] + duplicates
best = max(all_records, key=lambda r: r.get("lastModified", ""))
return best["id"]Example: Prefer a record from a specific source
# If any record comes from Salesforce, pick it; otherwise keep incoming
for record in [incoming] + duplicates:
if record.get("source") == "Salesforce":
return record["id"]
return incoming["id"]Step 2: Merge Records — Custom Code
After the winner is selected, the Merge Records step controls how attribute values from losing records are merged into the winner. In Custom Code mode, you write a Python script that receives the winner and losers, and returns the final merged record.
Available variables
- winner (
dict) — the record selected as the winner in the previous step - losers (
List[dict]) — the remaining records that will be merged into the winner
Return value
Your code must return a single dict — the final merged record. This is typically the winner dict with selected attributes updated from the losers.
Writing your code
Navigate to the Merge Records step and select Use Custom Code. The Code tab opens with a starter template.
Example: Fill empty attributes from losers
# For each attribute, if the winner's value is empty, take the first non-empty value from losers
for key in winner:
if not winner[key]:
for loser in losers:
if loser.get(key):
winner[key] = loser[key]
break
return winnerExample: Sum a numeric attribute across all records
# Combine revenue from all records into the winner
total = winner.get("annual_revenue", 0) or 0
for loser in losers:
total += loser.get("annual_revenue", 0) or 0
winner["annual_revenue"] = total
return winnerTesting your Custom Code
Both the Select Winner and Merge Records editors include a Test tab that lets you run your code against sample data before saving.
- Click the Test tab in the code editor
- The test panel shows two JSON input editors pre-populated with example data. Replace these with your own records or modify them as needed.
- Click Run Test to execute your code
- Review the result and logs in the output panels below
Select Winner test inputs
- incoming (dict) — a single JSON object representing the incoming record
- duplicates (List[dict]) — a JSON array of duplicate records
The result panel shows the record ID returned by your code.
Merge Records test inputs
- winner (dict) — a single JSON object representing the winning record
- losers (List[dict]) — a JSON array of losing records
The result panel shows the final merged record returned by your code.
Test result carry-over: Select Winner to Merge Policies
The test panels are connected across steps. When you run a successful Select Winner test, the result is automatically carried over to the Merge Records test inputs:
- The winning record from the Select Winner result is populated into the winner input of the Merge Policies test panel
- The remaining records (all candidates that were not selected as the winner) are populated into the losers input
This lets you test the full merge flow end-to-end without manually copying data between steps. The recommended workflow is:
- Write and test your Select Winner code first
- Click Run Test on the Select Winner step
- Navigate to the Merge Records step
- Open the Test tab — the winner and losers from your Select Winner test are already filled in
- Write your merge policy code and click Run Test to verify the final merged record
Viewing Custom Code results in Merge Logs
After a merge executes in your pipeline, you can inspect the Custom Code results in the merge transaction logs.
- Navigate to the Logs -> Merge page and find a merge transaction
- Expand the transaction to see the merge details. When Custom Code was used, the log displays:
- Whether Custom Code was used for Select Winner and/or Merge Policies
- Any errors returned by the code (highlighted in red)
- Any logs output (from
print()statements)
If a Custom Code script produces an error during a live merge, the error message is also shown in the transaction list's error column for quick identification.
Switching between Conditions and Custom Code
You can switch between Use Conditions and Use Custom Code at any time using the toggle at the top of each step. Your code and condition configurations are saved independently — switching modes does not discard either configuration.
Python environment reference
Your Custom Code runs in a sandboxed Python 3.11 environment. This means you can use modern Python 3.11 features such as exception groups, match/case pattern matching (introduced in 3.10), and fine-grained error locations in tracebacks.
What you can do
- Input variables are passed as standard Python
dictandlistobjects — use normal dictionary access (record["attribute"]) or.get()for safe access - Return value is required — use the
returnkeyword at the top level of your script (no need to wrap it in a function) - print() output is captured and shown in the Logs panel (test mode) or stored in the merge transaction logs (live execution)
- Standard Python built-ins are available (
sorted,max,min,len,enumerate,zip,filter,map, etc.) - Standard library modules for data manipulation such as
json,re,math,datetime, andcollectionscan be imported and used
What is not allowed
- No network access — the sandbox does not permit any outbound network calls. Functions like
urllib.request.urlopen(),http.client,socket, and third-party libraries such asrequestsare not available. Your code should operate solely on the input variables provided. - No file system access — reading from or writing to the file system is not permitted
- No subprocess or OS commands — modules like
subprocessandos.systemare blocked
Quick reference
| Step | Input variables | Must return |
|---|---|---|
| Select Winner | incoming (dict), duplicates (List[dict]) | A record ID string |
| Merge Records | winner (dict), losers (List[dict]) | A merged record dict |
Related to