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

# Find duplicate companies

> Find groups of duplicate companies: live companies of your workspace that share the same normalized value of ALL the `fields` you pick (1 to 4 of `domain`, `companyLinkedInUrl`, `companyCRMId`, `name`; AND: `fields=name,domain` groups only companies with the same name AND the same domain). A company with an empty value for any selected field never appears in a group. Returns `{ groups: [{ values, companyIds, size }], nextCursor }` where `values` maps each field to the shared normalized value, `companyIds` lists at most the 100 oldest ids of the group and `size` is the full count (when a group is large, narrow it by adding more `fields`), 100 groups per page at most, ordered by the lowest company id of each group. Only ids are returned: read the companies with `get_companies` or `get_a_single_company` to decide which copy to keep. Pass `listId` to look only for groups that touch a list. Companies you cannot access, blocklisted, merge-locked or deleted companies never appear. A search that takes too long answers 408: the workspace is too large to scan right now, so retry later (`listId` only filters the groups, it does not make the scan cheaper). To remove duplicates, show the user which companies will go and get their confirmation first, then call `delete_a_company` once per company: deleting cannot be undone from the product. If two duplicates carry different CRM ids, the duplicate lives in the CRM itself: tell the user to merge the records there, or a later CRM import can recreate the company.

    > **Required scope:** `COMPANIES_READ`
    >
    > **Rate limit:** 100 requests per minute



## OpenAPI

````yaml https://openapi.enginy.ai/definitions.json get /v1/companies/duplicates
openapi: 3.1.0
info:
  title: Enginy API
  version: 1.0.0
  description: Public API for Enginy platform
servers:
  - url: https://openapi.enginy.ai
    description: Configured server
security: []
tags:
  - name: AI Variables
    description: >-
      Manage AI variables and discover the entity fields you can reference in
      prompts and entity requests.
  - name: Inbox
    description: >-
      Inbox endpoints for listing contact threads, reading thread messages,
      managing tags, and sending manual replies.
  - name: Workflows
    description: >-
      Build, validate, publish, run, and inspect advanced (graph) workflows,
      plus the block/condition catalog needed to author a workflow plan.
paths:
  /v1/companies/duplicates:
    get:
      tags:
        - Companies
      summary: Find duplicate companies
      description: >-
        Find groups of duplicate companies: live companies of your workspace
        that share the same normalized value of ALL the `fields` you pick (1 to
        4 of `domain`, `companyLinkedInUrl`, `companyCRMId`, `name`; AND:
        `fields=name,domain` groups only companies with the same name AND the
        same domain). A company with an empty value for any selected field never
        appears in a group. Returns `{ groups: [{ values, companyIds, size }],
        nextCursor }` where `values` maps each field to the shared normalized
        value, `companyIds` lists at most the 100 oldest ids of the group and
        `size` is the full count (when a group is large, narrow it by adding
        more `fields`), 100 groups per page at most, ordered by the lowest
        company id of each group. Only ids are returned: read the companies with
        `get_companies` or `get_a_single_company` to decide which copy to keep.
        Pass `listId` to look only for groups that touch a list. Companies you
        cannot access, blocklisted, merge-locked or deleted companies never
        appear. A search that takes too long answers 408: the workspace is too
        large to scan right now, so retry later (`listId` only filters the
        groups, it does not make the scan cheaper). To remove duplicates, show
        the user which companies will go and get their confirmation first, then
        call `delete_a_company` once per company: deleting cannot be undone from
        the product. If two duplicates carry different CRM ids, the duplicate
        lives in the CRM itself: tell the user to merge the records there, or a
        later CRM import can recreate the company.

            > **Required scope:** `COMPANIES_READ`
            >
            > **Rate limit:** 100 requests per minute
      parameters:
        - schema:
            type: array
            items:
              type: string
              enum:
                - domain
                - companyLinkedInUrl
                - companyCRMId
                - name
            minItems: 1
            maxItems: 4
            description: >-
              The values two companies must ALL share to be duplicates (AND): 1
              to 4 different fields of `domain`, `companyLinkedInUrl`,
              `companyCRMId`, `name`. Comma-separated (`fields=name,domain`) or
              repeated (`fields=name&fields=domain`); through MCP, an array. A
              company whose value is empty for any selected field never matches.
              `domain` and `companyLinkedInUrl` compare normalized values (host
              without www, scheme and path; LinkedIn slug), `companyCRMId`
              compares CRM ids (a Salesforce 15-character id equals its
              18-character form), `name` ignores case, punctuation and extra
              spaces ("Acme, Inc." equals "acme inc" but not "Acme").
            example:
              - name
              - domain
          required: true
          description: >-
            The values two companies must ALL share to be duplicates (AND): 1 to
            4 different fields of `domain`, `companyLinkedInUrl`,
            `companyCRMId`, `name`. Comma-separated (`fields=name,domain`) or
            repeated (`fields=name&fields=domain`); through MCP, an array. A
            company whose value is empty for any selected field never matches.
            `domain` and `companyLinkedInUrl` compare normalized values (host
            without www, scheme and path; LinkedIn slug), `companyCRMId`
            compares CRM ids (a Salesforce 15-character id equals its
            18-character form), `name` ignores case, punctuation and extra
            spaces ("Acme, Inc." equals "acme inc" but not "Acme").
          name: fields
          in: query
        - schema:
            type: integer
            exclusiveMinimum: 0
            description: >-
              Only report groups with at least one company in this company list.
              Each group still names every copy in the workspace, including
              copies outside the list.
          required: false
          description: >-
            Only report groups with at least one company in this company list.
            Each group still names every copy in the workspace, including copies
            outside the list.
          name: listId
          in: query
        - schema:
            type: string
            pattern: ^\d+$
            description: The `nextCursor` of the previous page. Omit for the first page.
          required: false
          description: The `nextCursor` of the previous page. Omit for the first page.
          name: cursor
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 100
            description: Groups per page, at most 100.
          required: false
          description: Groups per page, at most 100.
          name: pageSize
          in: query
      responses:
        '200':
          description: A page of duplicate groups
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      groups:
                        type: array
                        items:
                          type: object
                          properties:
                            values:
                              type: object
                              additionalProperties:
                                type: string
                              description: >-
                                The normalized value the companies share for
                                each requested field, e.g. `{ "name": "acme
                                inc", "domain": "acme.com" }`.
                            companyIds:
                              type: array
                              items:
                                type: number
                              description: >-
                                Live companies sharing the value, lowest id
                                first: the 100 oldest at most. `size` is the
                                full count.
                            size:
                              type: integer
                              description: >-
                                How many companies share the value, at least 2;
                                can exceed `companyIds`.
                          required:
                            - values
                            - companyIds
                            - size
                      nextCursor:
                        type:
                          - string
                          - 'null'
                        description: >-
                          Pass as `cursor` for the next page; null on the last
                          page.
                    required:
                      - groups
                      - nextCursor
                required:
                  - status
                  - message
                  - data
        '400':
          description: >-
            Bad request - no fields, an unknown or repeated field, more than 4
            fields, or an invalid cursor or page size
        '404':
          description: List not found
        '408':
          description: >-
            The search took too long; the workspace is too large to scan right
            now, retry later
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key

````

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