Skip to main content

Lead Merge

When the same person is tracked under two or more separate lead records -- for example because they engaged from a work email and a personal email -- you can consolidate them into a single lead. Merging moves all events, aliases, sessions, and watch-list entries onto the target lead and soft-deletes the source leads.

POST /leads/merge/preview

Returns a read-only summary of what a merge would do without modifying any data. Use this to review the impact before committing to a merge.

When to Use This

  • Confirm the correct lead is being kept as the target before merging
  • See how many events and aliases would be moved
  • Identify whether the leads belong to different accounts, so you can decide which account to keep

Request Body

FieldTypeRequiredDescription
targetLeadIdstringYesThe lead that will survive the merge and receive all data
sourceLeadIdsarray of stringsYesOne or more lead IDs that will be absorbed into the target
{
"targetLeadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"sourceLeadIds": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"]
}

Response

FieldTypeDescription
target_lead_idstringThe target lead ID
source_lead_idsarrayThe source lead IDs to be absorbed
target_eventsintegerEvents currently on the target lead
total_eventsintegerEvents that would be moved from source leads
total_aliasesintegerAliases that would be moved from source leads
total_sessionsintegerSessions that would be moved from source leads
duplicate_aliasesintegerAliases on source leads that already exist on the target (will be de-duplicated; target's aliases win)
target_scorenumberCurrent total score on the target lead
source_scoresobjectCurrent score for each source lead, keyed by lead ID
account_conflictbooleantrue if sources and target belong to different accounts
accountsarrayAll unique accounts linked to the leads being merged
{
"target_lead_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source_lead_ids": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"],
"target_events": 14,
"total_events": 9,
"total_aliases": 2,
"total_sessions": 3,
"duplicate_aliases": 0,
"target_score": 85.0,
"source_scores": {
"b2c3d4e5-f6a7-8901-bcde-f12345678901": 42.0
},
"account_conflict": false,
"accounts": [
{
"account_id": "acc-123",
"account_name": "Acme Corp",
"lead_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
]
}

Example

curl -X POST "https://api.kenbun.io/leads/merge/preview" \
-H "Authorization: Basic <credentials>" \
-H "Content-Type: application/json" \
-d '{
"targetLeadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"sourceLeadIds": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"]
}'

Common Errors

StatusMeaningSolution
400Bad RequesttargetLeadId or sourceLeadIds is missing or malformed
401UnauthorizedCheck your API credentials

POST /leads/merge

Merges one or more source leads into a target lead. This action is permanent and cannot be undone. Use the preview endpoint first to confirm what will be affected.

What happens during a merge:

  • All engagement events from source leads are moved to the target lead. Each event retains its original_lead_id so you can always trace which lead it came from.
  • Aliases (email addresses, phone numbers, etc.) are moved to the target. If a source lead has an alias of the same type as one already on the target, the source's version is discarded and the target's alias is kept.
  • Sessions are reassigned to the target lead.
  • Watch-list entries are transferred to the target. If a team member already watches the target, the duplicate watch is removed.
  • Scores are recalculated on the target lead from all moved events.
  • Source leads are soft-deleted.
  • A lead_merged event is recorded on the target's activity timeline.
  • The merge is captured in the audit log with the user who performed it.

Request Body

FieldTypeRequiredDescription
targetLeadIdstringYesThe lead that will survive and receive all data
sourceLeadIdsarray of stringsYesLead IDs to absorb into the target
accountIdstringNoOverride the account linked to the merged lead
metadataSourceLeadIdstringNoCopy profile metadata from this lead (must be one of the leads being merged)
{
"targetLeadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"sourceLeadIds": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"]
}

Response

FieldTypeDescription
target_lead_idstringThe surviving lead's ID
merged_sourcesarrayLead IDs that were absorbed
moved_eventsintegerNumber of events transferred to the target
moved_aliasesintegerNumber of aliases transferred to the target
{
"target_lead_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"merged_sources": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"],
"moved_events": 9,
"moved_aliases": 2
}

Example

curl -X POST "https://api.kenbun.io/leads/merge" \
-H "Authorization: Basic <credentials>" \
-H "Content-Type: application/json" \
-d '{
"targetLeadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"sourceLeadIds": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"]
}'

Common Errors

StatusMeaningSolution
400Bad RequestMissing or invalid lead IDs, or no valid sources to merge
401UnauthorizedCheck your API credentials
404Not FoundOne or more lead IDs do not exist in the active OU

GET /leads/{leadId}/merge-history

Returns the merge history for a specific lead — both merges where this lead absorbed other leads, and merges where this lead was itself absorbed into another.

Request

ParameterTypeRequiredDescription
leadIdstringYesLead identifier (path parameter)

Response

FieldTypeDescription
mergeHistoryarrayList of merge records for this lead

Each merge record:

FieldTypeDescription
idstringUnique identifier for this merge record
target_lead_idstringThe lead that survived the merge
source_lead_idsarrayLead IDs that were absorbed
moved_eventsintegerNumber of events moved during the merge
user_emailstring or nullEmail of the user who performed the merge, or null for automated merges
created_attimestampWhen the merge occurred
merged_into_thisbooleantrue if this lead was the target (absorbed others); false if this lead was a source (merged out into another lead)
{
"mergeHistory": [
{
"id": "merge-abc123",
"target_lead_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source_lead_ids": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"],
"moved_events": 9,
"user_email": "jane@example.com",
"created_at": "2025-03-10T14:22:00Z",
"merged_into_this": true
}
]
}

Example

curl -X GET "https://api.kenbun.io/leads/a1b2c3d4-e5f6-7890-abcd-ef1234567890/merge-history" \
-H "Authorization: Basic <credentials>"

Common Errors

StatusMeaningSolution
401UnauthorizedCheck your API credentials
404Not FoundLead does not exist in the active OU

Notes

  • All three endpoints are OU-scoped to the active Organizational Unit. Leads from different OUs cannot be merged.
  • Merges are recorded in the Audit Log with the email of the user who initiated the action.
  • After a merge, events on the target lead may include an original_lead_id field indicating which source lead originally owned that event. This field is null for events that were never moved.
  • The merge operation is atomic -- if any step fails, no changes are saved.