curl --request GET \
--url https://openapi.enginy.ai/v1/companies/duplicates \
--header 'x-api-key: <api-key>'import requests
url = "https://openapi.enginy.ai/v1/companies/duplicates"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://openapi.enginy.ai/v1/companies/duplicates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://openapi.enginy.ai/v1/companies/duplicates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://openapi.enginy.ai/v1/companies/duplicates"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://openapi.enginy.ai/v1/companies/duplicates")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://openapi.enginy.ai/v1/companies/duplicates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"status": "success",
"message": "<string>",
"data": {
"groups": [
{
"values": {},
"companyIds": [
123
],
"size": 123
}
],
"nextCursor": "<string>"
}
}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_READRate limit: 100 requests per minute
curl --request GET \
--url https://openapi.enginy.ai/v1/companies/duplicates \
--header 'x-api-key: <api-key>'import requests
url = "https://openapi.enginy.ai/v1/companies/duplicates"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://openapi.enginy.ai/v1/companies/duplicates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://openapi.enginy.ai/v1/companies/duplicates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://openapi.enginy.ai/v1/companies/duplicates"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://openapi.enginy.ai/v1/companies/duplicates")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://openapi.enginy.ai/v1/companies/duplicates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"status": "success",
"message": "<string>",
"data": {
"groups": [
{
"values": {},
"companyIds": [
123
],
"size": 123
}
],
"nextCursor": "<string>"
}
}Authorizations
Query Parameters
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").
1 - 4 elementsdomain, companyLinkedInUrl, companyCRMId, name ["name", "domain"]
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.
The nextCursor of the previous page. Omit for the first page.
^\d+$Groups per page, at most 100.
1 <= x <= 100