> ## Documentation Index
> Fetch the complete documentation index at: https://omni.fireflo.au/llms.txt
> Use this file to discover all available pages before exploring further.

# GET /v1/cdp/duplicates

> Pairs of contacts that look like the same person, with why and how sure.

Pairs of contacts that look like the same person, found every night, newest first. Dismissed pairs are left out.

<Note>Needs the `cdp.contacts:read` scope.</Note>

## Query parameters

| Field | Type | Required | Notes |
| :- | :- | :- | :- |
| `reason` | string | No | Only pairs found this way: `email`, `external_id`, `phone` or `name`. |
| `limit` | integer | No | 1 to 100; 50 by default. |
| `starting_after` | string | No | The last id of the previous page — `next` from it. |

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.fireflo.au/v1/cdp/duplicates?reason=email&limit=20" \
    -H "Authorization: Bearer $OMNI_API_KEY"
  ```

  ```python Python theme={null}
  import os

  import requests

  response = requests.get(
      "https://api.fireflo.au/v1/cdp/duplicates?reason=email&limit=20",
      headers={"Authorization": f"Bearer {os.environ['OMNI_API_KEY']}"},
  )
  print(response.status_code, response.json())
  ```

  ```javascript Node theme={null}
  const response = await fetch("https://api.fireflo.au/v1/cdp/duplicates?reason=email&limit=20", {
    headers: {
      Authorization: `Bearer ${process.env.OMNI_API_KEY}`,
    },
  });
  console.log(response.status, await response.json());
  ```
</CodeGroup>

## Response

`200 OK` — each pair's `id`, its two `contacts`, and why they look alike:

| `reason` | They share | `score` |
| :- | :- | :- |
| `external_id` | a customer id | 95 |
| `email` | an email address | 90 |
| `phone` | a number | 70 |
| `name` | a name and email domain | 60 |

`detail` is the value they share. `has_more` says whether there is another page, and `next` is the `starting_after` for it.

```json theme={null}
{
  "data": [
    {
      "id": 4821,
      "contacts": [
        {
          "id": "3f6b2a1e-8c4d-4e2a-9b7f-5d1c0e8a9f42",
          "name": "Asha Rao",
          "phone": "+919876543210"
        },
        {
          "id": "c2e9f4a7-1d3b-4a6c-8f5e-9b0d7c3a2e16",
          "name": "Asha R",
          "phone": "+919822001144"
        }
      ],
      "reason": "email",
      "detail": "asha@acme.in",
      "score": 90
    }
  ],
  "has_more": false,
  "next": null
}
```

## Errors

Every refusal is `{"error": {"code", "message", "field"}}`; `field` is there when one input is at fault.

| Status | Error code | When |
| :- | :- | :- |
| 400 | `invalid_request` | `limit` isn't 1 to 100, or `starting_after` isn't an id from this list (`field` names it). |
| 403 | `scope_missing` | The key doesn't have the `cdp.contacts:read` scope. |
| 404 | `module_off` | The account doesn't have Customer data on. |

Any request can also be refused for its key, its account or its rate (`key_required`, `invalid_key`, `account_suspended`, `plan_excludes_api`, `address_not_allowed`, `rate_limited`); see [the overview](/api-reference/overview).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.