{
  "apiVersion": 63,
  "status": "Active",
  "label": "HubSpot converted Lead identity handoff",
  "description": "After a converted Contact commits, move the finalized HubSpot contact identity from its exact active converted Lead only when that Lead still owns it, without changing the Contact's outbound-sync setting.",
  "runAtomically": true,
  "start": {
    "locationX": 40,
    "locationY": 0,
    "object": "Contact",
    "triggerType": "RecordAfterSave",
    "recordTriggerType": "CreateAndUpdate",
    "filterLogic": "1",
    "filters": [
      {
        "field": "HubSpot_Id__c",
        "operator": "IsNotBlank"
      }
    ],
    "scheduledPaths": [
      {
        "name": "AsyncAfterCommit",
        "label": "Hand off finalized converted Lead identity after Contact commit",
        "pathType": "AsyncAfterCommit",
        "connector": {
          "targetReference": "SkipHubSpotConnectorInbound"
        }
      }
    ]
  },
  "variables": [
    {"name": "durableAuthorityState", "dataType": "String"},
    {"name": "durableSourceObject", "dataType": "String"},
    {"name": "durableSourceRecordId", "dataType": "String"},
    {"name": "durableOwnerLifecycle", "dataType": "String"},
    {"name": "convertedLeadRemoteIdentityTransferred", "dataType": "Boolean"}
  ],
  "decisions": [
    {
      "name": "SkipHubSpotConnectorInbound",
      "label": "Skip HubSpot-originated updates",
      "locationX": 40,
      "locationY": 80,
      "rules": [
        {
          "name": "HubSpotConnectorInbound",
          "conditionLogic": "and",
          "conditions": [{
            "leftValueReference": "$SystemContext.ConnectorSyncOrigin",
            "operator": "EqualTo",
            "rightValue": {"stringValue": "hubspot-crm-connector"}
          }],
          "label": "Inbound Flow owns converted Lead reconciliation"
        }
      ],
      "defaultConnector": {"targetReference": "ResolveContactRemoteIdentity"}
    },
    {
      "name": "RouteAuthoritativeConvertedLead",
      "label": "Does this converted Lead still own the HubSpot identity?",
      "locationX": 40,
      "locationY": 160,
      "rules": [
        {
          "name": "FinalizedContactAuthority",
          "conditionLogic": "and",
          "conditions": [
            {"leftValueReference": "durableAuthorityState", "operator": "EqualTo", "rightValue": {"stringValue": "finalized"}},
            {"leftValueReference": "durableSourceObject", "operator": "EqualTo", "rightValue": {"stringValue": "Contact"}},
            {"leftValueReference": "durableSourceRecordId", "operator": "EqualTo", "rightValue": {"elementReference": "$Record.Id"}}
          ]
        },
        {
          "name": "FinalizedLeadAuthority",
          "conditionLogic": "and",
          "conditions": [
            {"leftValueReference": "durableAuthorityState", "operator": "EqualTo", "rightValue": {"stringValue": "finalized"}},
            {"leftValueReference": "durableSourceObject", "operator": "EqualTo", "rightValue": {"stringValue": "Lead"}},
            {"leftValueReference": "durableOwnerLifecycle", "operator": "EqualTo", "rightValue": {"stringValue": "active"}},
            {"leftValueReference": "durableSourceRecordId", "operator": "IsNotBlank"}
          ],
          "connector": {"targetReference": "FindConvertedLeadForContactHandoff"}
        }
      ],
      "defaultConnector": {"targetReference": "FailContactIdentityHandoff"}
    },
    {
      "name": "ConfirmConvertedLeadHandoffTarget",
      "label": "Does the authoritative Lead convert to this Contact?",
      "locationX": 40,
      "locationY": 240,
      "rules": [{
        "name": "ConvertedLeadTargetsContact",
        "conditionLogic": "and",
        "conditions": [{"leftValueReference": "$convertedLeadForContactHandoff.Id", "operator": "IsNotBlank"}],
        "connector": {"targetReference": "TransferConvertedLeadRemoteIdentityToContact"}
      }],
      "defaultConnector": {"targetReference": "FailContactIdentityHandoff"}
    },
    {
      "name": "ConfirmConvertedLeadIdentityHandoff",
      "label": "Did the converted Lead identity move to this Contact?",
      "locationX": 40,
      "locationY": 320,
      "rules": [{
        "name": "ConvertedLeadIdentityTransferSucceeded",
        "conditionLogic": "and",
        "conditions": [{"leftValueReference": "convertedLeadRemoteIdentityTransferred", "operator": "EqualTo", "rightValue": true}],
        "label": "Durable identity is now Contact-owned"
      }],
      "defaultConnector": {"targetReference": "FailContactIdentityHandoff"}
    }
  ],
  "recordLookups": [{
    "name": "FindConvertedLeadForContactHandoff",
    "label": "Find the exact converted Lead that still owns this identity",
    "locationX": 40,
    "locationY": 200,
    "object": "Lead",
    "filterLogic": "and",
    "filters": [
      {"field": "Id", "operator": "EqualTo", "value": {"elementReference": "durableSourceRecordId"}},
      {"field": "IsConverted", "operator": "EqualTo", "value": true},
      {"field": "ConvertedContactId", "operator": "EqualTo", "value": {"elementReference": "$Record.Id"}},
      {"field": "HubSpot_Id__c", "operator": "EqualTo", "value": {"elementReference": "$Record.HubSpot_Id__c"}}
    ],
    "outputReference": "$convertedLeadForContactHandoff",
    "getFirstRecordOnly": true,
    "connector": {"targetReference": "ConfirmConvertedLeadHandoffTarget"}
  }],
  "actionCalls": [
    {
      "name": "ResolveContactRemoteIdentity",
      "label": "Resolve authoritative durable HubSpot identity",
      "locationX": 40,
      "locationY": 120,
      "actionName": "resolveConnectorRemoteIdentity",
      "actionType": "resolveConnectorRemoteIdentity",
      "inputParameters": [
        {"name": "connectorOwnerKey", "value": {"stringValue": "pingcap-hubspot-companion"}},
        {"name": "destinationSlotId", "value": {"stringValue": "hubspot-contact"}},
        {"name": "remoteId", "value": {"elementReference": "$Record.HubSpot_Id__c"}}
      ],
      "outputParameters": [
        {"name": "authorityState", "value": {"elementReference": "durableAuthorityState"}},
        {"name": "sourceObject", "value": {"elementReference": "durableSourceObject"}},
        {"name": "sourceRecordId", "value": {"elementReference": "durableSourceRecordId"}},
        {"name": "ownerLifecycle", "value": {"elementReference": "durableOwnerLifecycle"}}
      ],
      "connector": {"targetReference": "RouteAuthoritativeConvertedLead"}
    },
    {
      "name": "TransferConvertedLeadRemoteIdentityToContact",
      "label": "Transfer converted Lead remote identity to this Contact",
      "locationX": 40,
      "locationY": 280,
      "actionName": "transferConnectorRemoteIdentity",
      "actionType": "transferConnectorRemoteIdentity",
      "inputParameters": [
        {"name": "sourceObject", "value": {"stringValue": "Lead"}},
        {"name": "sourceId", "value": {"elementReference": "$convertedLeadForContactHandoff.Id"}},
        {"name": "targetObject", "value": {"stringValue": "Contact"}},
        {"name": "targetId", "value": {"elementReference": "$Record.Id"}},
        {"name": "remoteIDField", "value": {"stringValue": "HubSpot_Id__c"}},
        {"name": "outputReference", "value": {"stringValue": "convertedLeadRemoteIdentityTransferred"}}
      ],
      "connector": {"targetReference": "ConfirmConvertedLeadIdentityHandoff"}
    }
  ],
  "customErrors": [{
    "name": "FailContactIdentityHandoff",
    "label": "Converted Lead HubSpot identity handoff failed",
    "locationX": 220,
    "locationY": 360,
    "customErrorMessages": [{
      "errorMessage": "HubSpot identity could not be handed from the converted Lead to this Contact",
      "statusCode": "HUBSPOT_CONTACT_CONVERTED_LEAD_IDENTITY_HANDOFF_FAILED"
    }]
  }]
}
