Managing Duplicate Entities

A detailed guide to detecting, reviewing, and resolving duplicate customer records using FrankieOne's automated workflow step.

What are Duplicate Checks?

Duplicate checks are essential for maintaining data integrity, reducing fraud risk, and ensuring compliance. They prevent the creation of multiple records for the same individual within your system.

FrankieOne integrates this capability directly into your KYC workflow via a dedicated DUPLICATE step. This step provides:

  • Automated identification of possible duplicates using configurable, rules-based matching logic.
  • Manual review and resolution capabilities for operators to confirm or dismiss flagged duplicates.
  • Seamless integration with existing KYC processes to support both operational efficiency and regulatory compliance.

To implement duplicate checks, you must have the DUPLICATE step added to your KYC workflow. Speak with your FrankieOne representative to configure the duplicate step and its matching rules.


How Duplicate Checks Work

The process is designed to flag potential duplicates during onboarding and provide your team with the tools to resolve them.

1

1. Workflow Execution

When you execute a workflow for a new or updated entity, the DUPLICATE step runs. It compares the entity’s attributes (e.g., name, DOB, document number) against all other entities in your system based on your configured matching rules.

2

2. A 'HIT' is Returned

If a potential duplicate is found, the workflow step returns a result of HIT, and a DUPLICATE issue is created. This typically causes the overall workflow status to become REVIEW.

3

3. Detailed Results are Generated

For each potential duplicate found, a Process Result Object (PRO) is created. This PRO contains the granular details of the match, including which fields matched and the entityId of the potential duplicate.

4

4. Operator Review and Resolution

Your compliance team reviews the evidence within the PROs and makes a decision. They then resolve the match by calling the API to update the PRO’s manualStatus.

5

5. State and Relationships are Updated

Based on the operator’s resolution, the system updates the service profile states (e.g., marking one entity as DUPLICATE) and creates a permanent relationship between the two entities for future reference.


Implementation and API Guide

Step 1: Interpreting the Duplicate Check Result

When the DUPLICATE step returns a HIT, you need to parse the processResults within that step to understand the match. Each PRO will have class: "DUPLICATE".

The most important information is in the supplementaryData object.

1{
2 "processResultId": "01JNFWT5MKE75FMMZPWC7SDG2Z",
3 "result": "HIT",
4 "class": "DUPLICATE",
5 "stepName": "DUPLICATE",
6 "supplementaryData": {
7 "type": "DUPLICATE",
8 "duplicateEntityId": "98c545b6-7545-4337-85ce-30c64ef1ccff",
9 "matchedFields": [
10 {
11 "objectType": "NAME",
12 "objectId": "840268d6-d37e-43ad-a421-d35345472df4",
13 "duplicateObjectId": "4331b636-5cb2-46d6-bba1-03536232909b",
14 "matchStrength": 86
15 },
16 {
17 "objectType": "ADDRESS",
18 "objectId": "9c5fdaeb-056a-47c7-a36e-dcb59ddce5b3",
19 "duplicateObjectId": "c0d6872f-dd14-43f2-86b2-60e1e7ae24c4",
20 "matchStrength": 100
21 }
22 ],
23 "matchedRules": [
24 {
25 "name": "Given + Family name + Short form normalised address",
26 "strength": "HIGH"
27 }
28 ]
29 }
30}

Key supplementaryData Fields:

  • duplicateEntityId: The entityId of the existing profile that was matched.
  • matchedFields: An array detailing exactly which attributes matched between the two entities (e.g., NAME, ADDRESS). It includes the specific objectId for each attribute and the matchStrength.
  • matchedRules: Shows which configured rule was triggered to create this match.

Step 2: Resolving Duplicates

After reviewing the evidence, an operator must classify the match. This is done by sending a PATCH request with the processResultId and a manualStatus.

Endpoint:

1PATCH /v2/individuals/{entityId}/results/duplicate

Understanding the Manual Statuses The manualStatus you send should reflect the operator’s decision.

Operator’s DecisionmanualStatus to SendOutcome
”This is not a duplicate.”FALSE_POSITIVEThe potential match is dismissed. No relationship is created.
”This is a duplicate. Keep the new entity and mark the old one as the duplicate.”TRUE_POSITIVE_ACCEPTA relationship is created. The old entity’s service profile is marked as DUPLICATE.
”This is a duplicate. Keep the old entity and mark the new one as the duplicate.”TRUE_POSITIVE_REJECTA relationship is created. The new entity’s service profile is marked as DUPLICATE.
$curl -X PATCH \
>'{{baseHost}}/v2/individuals/{{entityId}}/results/duplicate' \
>-H 'api_key: YOUR_API_KEY' \
>-H 'X-Frankie-CustomerID: YOUR_CUSTOMER_ID' \
>-d '{
> "processResults": [
> "01JNFWT5MKE75FMMZPWC7SDG2Z"
> ],
> "manualStatus": "FALSE_POSITIVE",
> "comment": {
> "text": "Reviewed by operator. Confirmed different individuals with similar names."
> }
>}'

After resolving all duplicate-related issues, you should re-run the workflow. The DUPLICATE step will re-evaluate based on your resolutions, and the overall workflow status can then update from REVIEW to PASS.


Key Concepts: State and Relationships

  • Relationships: When a duplicate is confirmed (TRUE_POSITIVE_ACCEPT or TRUE_POSITIVE_REJECT), a permanent relationship is created between the two entities. You can see this in the response of GET /v2/individuals/{entityId} under the relationships.duplicates array.
  • DUPLICATE State: An entity’s service profile is moved to the DUPLICATE state when a relationship identifies it as such. An entity remains a duplicate as long as at least one relationship points to it. If all such relationships are removed (e.g., by being marked as FALSE_POSITIVE or if the source entity is deleted), its DUPLICATE state will be revoked.

Configuration (Reference)

The matching logic for the DUPLICATE step is highly configurable by the FrankieOne team.

1{
2 "ruleSets": {
3 "default": {
4 "rules": [
5 {
6 "name": "Document identifiers",
7 "matchFields": [ "DOC_PRIMARY_IDENTIFIER", "DOC_TYPE", "DOC_COUNTRY" ],
8 "method": "EXACT",
9 "riskFactor": "VERY_HIGH"
10 },
11 {
12 "name": "Given + Family name + Date of birth",
13 "matchFields": [ "GIVEN_NAME", "FAMILY_NAME", "DATE_OF_BIRTH" ],
14 "method": "EXACT",
15 "riskFactor": "VERY_HIGH"
16 }
17 ]
18 }
19 }
20}