# Bulk Email & Phone Validator – MX Check, Dedupe, Lead Score (`chris_elder/dataset-dedupe-enrich`) Actor

Clean and validate any contact or lead list: dedupe, email syntax + domain MX check, disposable/role/free-mail flags, E.164 phone formatting, website check and a 0–100 quality score. No SMTP mailbox probing. $0.60 per 1,000 rows; duplicates are free.

- **URL**: https://apify.com/chris_elder/dataset-dedupe-enrich.md
- **Developed by:** [Chris Elder](https://apify.com/chris_elder) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 cleaned rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bulk Email & Phone Validator – MX Check, Dedupe, Lead Score

**Clean and validate a contact or lead list in one run.** Upload a CSV, paste JSON or point at an Apify dataset, and this Actor removes duplicates, checks every email's syntax and domain **MX records**, flags role (`info@`), free-mail and **disposable** addresses, formats and validates phone numbers to **E.164**, checks each website is reachable, and gives every row a 0–100 quality score with a plain-English `issues` list.

It is a **validator, not an SMTP mailbox verifier**: it tells you which emails can never work (bad syntax, disposable, domain with no mail server) without probing inboxes, which is unreliable from cloud IPs and harms sender reputation.

Store page: [apify.com/chris_elder/dataset-dedupe-enrich](https://apify.com/chris_elder/dataset-dedupe-enrich)

✅ Pay per result: **$0.60 per 1,000 cleaned rows** · 🆓 Merged duplicates, dropped rows and input errors are never charged · 🔑 No API key

Formerly listed as *Dataset Dedupe & Enrich*. This is the **generalist** sibling of [Google Maps Lead Cleaner](https://apify.com/chris_elder/google-maps-lead-cleaner): same hygiene pipeline, but Store-positioned for *any* CSV / JSON / Apify dataset (CRM exports, form dumps, contact extractors, job boards), not only Maps scrapes.

### What it does

- 🧹 **Dedupes** by placeId (if present), else website domain+path, else phone, else name+address; merges contact fields from duplicates
- 📞 **E.164 phones** with national format, type and invalid list
- 📧 **Email hygiene**: split lists, fix `name @domain.com`, strip `mailto:`, syntax check
- 🌐 **Domain MX check** (cached per domain): no SMTP mailbox probing
- 🏷️ Role / free-mail / disposable flags; website alive check
- ⭐ **0–100 quality score** + `issues` list for sorting

**What it does not do:** SMTP / mailbox verification (unreliable from cloud IPs and bad for sender reputation).

### How to use it

Works with any columns: it auto-detects common names such as `email`/`emails`, `phone`/`phoneNumber`/`mobile`, `website`/`domain`/`homepage`, `name`/`company`/`title` and `address` (Apify CSV exports with `emails/0`, `emails/1` columns work too). Use `fieldMapping` if your headers are unusual.

1. Click **Try for free**: prefill has 8 public hotel contact rows (one duplicate, mistyped email, no-MX domain). A few seconds, about **$0.004**.
2. Or set `datasetId` / `csvUrl` / paste `items`.
3. Set `defaultCountry` (e.g. `US`) when phones lack country codes.
4. Download CSV/Excel/JSON from Storage. `RUN_SUMMARY` is in the key-value store.

```json
{
  "datasetId": "YOUR_DATASET_ID",
  "defaultCountry": "GB",
  "dedupeMode": "auto",
  "checkMx": true,
  "checkWebsites": true
}
```

### Real example output

Public run on 20 Oct 2026 (run `cQIQIxtnCC8uVeccQ`, `defaultCountry: "GB"`): 5 rows in, **4 rows out** (one duplicate merged, not charged). Fields trimmed for space.

Input rows:

```json
[
  { "title": "Apify", "email": "hello@apify.com", "website": "https://apify.com" },
  { "title": "Apify", "email": "HELLO@apify.com ", "website": "https://apify.com/" },
  { "title": "Throwaway Ltd", "email": "test123@mailinator.com", "phone": "07700 900123" },
  { "title": "No Mail Co", "email": "info@no-mx-domain-xyz123.com", "website": "https://no-mx-domain-xyz123.com" },
  { "title": "GOV.UK", "emails": "mailto:info@gov.uk; sales @gov.uk", "phone": "020 7946 0000", "website": "https://www.gov.uk" }
]
```

What came back:

| Row | Email result | Phone result | Website | Score | Issues |
|---|---|---|---|---|---|
| Apify (2 rows merged) | `hello@apify.com` → `valid-mx`, role address | none | alive (200) | 65 medium | email-role-address-only, missing-phone, missing-address |
| Throwaway Ltd | `test123@mailinator.com` → `disposable` | `07700 900123` → invalid (Ofcom drama range) | none | 5 low | no-usable-email, email-disposable, phone-invalid, no-contact-method |
| No Mail Co | `info@no-mx-domain-xyz123.com` → `no-mx` | none | `dns-not-found` | 5 low | email-domain-no-mx, website-unreachable, no-contact-method |
| GOV.UK | `mailto:` stripped and `sales @gov.uk` repaired; both → `no-mx-a-record` | `020 7946 0000` → `+442079460000` (fixed line) | alive (200) | 55 medium | email-domain-a-record-only, email-repaired, missing-address |

One output row in full shape (Apify):

```json
{
  "name": "Apify",
  "website": "https://apify.com/",
  "primaryEmail": "hello@apify.com",
  "primaryEmailStatus": "valid-mx",
  "primaryEmailIsRole": true,
  "phone": null,
  "invalidPhones": [],
  "websiteAlive": true,
  "websiteStatus": 200,
  "leadQuality": 65,
  "leadQualityLabel": "medium",
  "issues": ["email-role-address-only", "missing-phone", "missing-address"],
  "duplicatesMerged": 1,
  "mergedRowNumbers": [2],
  "emailDetails": [
    { "email": "hello@apify.com", "status": "valid-mx", "role": true, "freeMail": false, "disposable": false, "matchesWebsite": true,
      "mxHosts": ["aspmx.l.google.com", "alt1.aspmx.l.google.com", "alt2.aspmx.l.google.com"] }
  ]
}
```

### Email statuses

| Status | Meaning |
|---|---|
| `valid-mx` | Syntax OK and the domain publishes MX records |
| `no-mx-a-record` | No MX record; the domain only has an A record (mail may still be accepted, treat with care) |
| `no-mx` | Domain has no mail server: the address cannot receive email |
| `disposable` | Known throwaway-inbox domain |
| `invalid-syntax` | Not a valid email address |
| `placeholder` | Obvious placeholder or junk address |
| `unknown` | DNS lookup failed, so the domain could not be checked |
| `not-checked` | MX checking was switched off (`checkMx: false`) |

### Pricing

| Plan | Per cleaned row | Per 1,000 |
|---|---|---|
| Free / Bronze | $0.0006 | $0.60 |
| Silver | $0.0005 | $0.50 |
| Gold+ | $0.0004 | $0.40 |

Actor start is a tiny one-time fee. Duplicates merged into another row and rows you drop are **free**.

### Related Actors

- [Google Maps Lead Cleaner](https://apify.com/chris_elder/google-maps-lead-cleaner): same pipeline, Maps-shaped docs and examples
- [Dataset Transformer](https://apify.com/chris_elder/dataset-transformer): filter / flatten / rename / CSV (no MX or phone enrichment)
- [Website Contact Extractor](https://apify.com/chris_elder/website-contact-extractor): pull emails/phones from sites, then clean here

### Support

Built by GPT Shop Ltd. Questions: chris@gptshopltd.com

# Actor input Schema

## `datasetId` (type: `string`):

Apify dataset to clean (any scraper or contact extract). On Integrations tab set {{resource.defaultDatasetId}}. Use this OR items OR csvUrl.

## `items` (type: `array`):

Paste rows directly instead of datasetId. Prefill: 8 public hotel contact rows (OpenStreetMap-shaped) with one duplicate, a mistyped email and a domain without MX — proves general contact hygiene, not Maps-only.

## `csvUrl` (type: `string`):

Public link to a CSV (comma, semicolon or tab) or a JSON array, e.g. a Google Sheet published as CSV. Used when datasetId and items are empty.

## `fieldMapping` (type: `object`):

Only needed when your column names are unusual. Keys: name, website, phone, email, address, street, city, postalCode, state, countryCode, placeId. Values: your column name (dot paths like contact.email work). Example: {"name": "Company", "phone": "Tel"}. Common scraper and contact-extractor fields are detected automatically.

## `defaultCountry` (type: `string`):

2-letter ISO code (GB, US, DE, AU…) used to read national-format numbers like 020 7730 8191 when a row has no countryCode. Rows with countryCode use their own.

## `dedupeMode` (type: `string`):

auto = one row per place: Google placeId, else website (domain + page path), else phone, else name + address. company = one row per company website domain (merges chain branches). none = keep every row. Merged duplicates are free.

## `checkMx` (type: `boolean`):

Look up DNS MX records once per email domain (cached). Included in the price. This checks the domain can receive mail, not that the mailbox exists (no SMTP probing).

## `checkWebsites` (type: `boolean`):

One HEAD request per unique website (GET fallback), following redirects. Adds status, final URL and alive flag. Included in the price.

## `websiteTimeoutSecs` (type: `integer`):

Per website. 2–60.

## `dropRowsWithoutContact` (type: `boolean`):

Remove rows that have neither a usable email (domain has MX) nor a valid phone. Dropped rows are not charged.

## `minLeadQuality` (type: `integer`):

Drop rows scoring below this. 0 keeps everything. Dropped rows are not charged.

## `passthroughFields` (type: `array`):

Source fields copied to the output unchanged (dot paths allowed). Default keeps the Google Maps category, rating, review count and Maps URL.

## `includeEmailDetails` (type: `boolean`):

Adds emailDetails (status, role, free-mail, disposable, MX hosts) for every email found. Turn off for a narrower CSV.

## `includeOriginal` (type: `boolean`):

Adds the full source row under original.

## `maxRows` (type: `integer`):

Cap on input rows read (protects cost). Only cleaned rows written to the dataset are charged.

## Actor input object example

```json
{
  "items": [
    {
      "title": "Lime Tree Hotel",
      "categoryName": "Hotel",
      "website": "https://www.limetreehotel.co.uk/",
      "phone": "+44 20 7730 8191",
      "emails": [
        "info@limetreehotel.co.uk"
      ],
      "address": "135-137 Ebury Street, London, SW1W 9QU",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "The Warwick by Nestor",
      "categoryName": "Hotel",
      "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
      "phone": "+44 20 3868 6192",
      "emails": [
        "guest@nestorstay.com"
      ],
      "address": "94 Warwick Way, London, SW1V 1SB",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "The Warwick by Nestor",
      "categoryName": "Hotel",
      "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
      "phone": "+44 20 3868 6192",
      "emails": [
        "guest@nestorstay.com"
      ],
      "address": "94 Warwick Way, London, SW1V 1SB",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "The Trafalgar St. James London, Curio Collection by Hilton",
      "categoryName": "Hotel",
      "website": "https://www.hilton.com/en/hotels/lontsqq-the-trafalgar-st-james-london/",
      "phone": "+44 20 7870 2900",
      "emails": [
        "reservations@thetrafalgar.com"
      ],
      "address": "2 Spring Gardens, London, SW1A 2TS",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "Hilton",
      "categoryName": "Hotel",
      "website": "https://www.hilton.com/en/hotels/nyctshh-hilton-times-square/",
      "phone": "+1 212-913-9488",
      "emails": [
        "NYCTS_HOTEL @hilton.com"
      ],
      "address": "234 West 42nd Street, New York, 10036",
      "city": "New York",
      "countryCode": "US"
    },
    {
      "title": "Pod 39",
      "categoryName": "Hotel",
      "website": "https://www.thepodhotel.com/pod-39/",
      "phone": "+1-844-763-7666;+1-212-865-5700",
      "emails": [
        "info@podhotel39.com"
      ],
      "address": "145 East 39th Street, New York, 10016",
      "city": "New York",
      "countryCode": "US"
    },
    {
      "title": "Somerset Hotel",
      "categoryName": "Hotel",
      "website": "https://somersethotellondon.com",
      "phone": "+44 20 7723 0741",
      "emails": [
        "reservations@somersethotel.net"
      ],
      "address": "6 Dorset Square, London, NW1 6QA",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "Mandarin Oriental",
      "categoryName": "Hotel",
      "website": "https://www.mandarinoriental.com/en/new-york/manhattan",
      "phone": "+1-212-805-8800",
      "emails": [
        "MONYC-RESERVATIONS@MOHG.COM"
      ],
      "address": "80 Columbus Circle, New York, 10023",
      "city": "New York",
      "countryCode": "US"
    }
  ],
  "defaultCountry": "GB",
  "dedupeMode": "auto",
  "checkMx": true,
  "checkWebsites": true,
  "websiteTimeoutSecs": 10,
  "dropRowsWithoutContact": false,
  "minLeadQuality": 0,
  "passthroughFields": [
    "categoryName",
    "totalScore",
    "reviewsCount",
    "url"
  ],
  "includeEmailDetails": true,
  "includeOriginal": false,
  "maxRows": 100000
}
```

# Actor output Schema

## `leads` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "items": [
        {
            "title": "Lime Tree Hotel",
            "categoryName": "Hotel",
            "website": "https://www.limetreehotel.co.uk/",
            "phone": "+44 20 7730 8191",
            "emails": [
                "info@limetreehotel.co.uk"
            ],
            "address": "135-137 Ebury Street, London, SW1W 9QU",
            "city": "London",
            "countryCode": "GB"
        },
        {
            "title": "The Warwick by Nestor",
            "categoryName": "Hotel",
            "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
            "phone": "+44 20 3868 6192",
            "emails": [
                "guest@nestorstay.com"
            ],
            "address": "94 Warwick Way, London, SW1V 1SB",
            "city": "London",
            "countryCode": "GB"
        },
        {
            "title": "The Warwick by Nestor",
            "categoryName": "Hotel",
            "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
            "phone": "+44 20 3868 6192",
            "emails": [
                "guest@nestorstay.com"
            ],
            "address": "94 Warwick Way, London, SW1V 1SB",
            "city": "London",
            "countryCode": "GB"
        },
        {
            "title": "The Trafalgar St. James London, Curio Collection by Hilton",
            "categoryName": "Hotel",
            "website": "https://www.hilton.com/en/hotels/lontsqq-the-trafalgar-st-james-london/",
            "phone": "+44 20 7870 2900",
            "emails": [
                "reservations@thetrafalgar.com"
            ],
            "address": "2 Spring Gardens, London, SW1A 2TS",
            "city": "London",
            "countryCode": "GB"
        },
        {
            "title": "Hilton",
            "categoryName": "Hotel",
            "website": "https://www.hilton.com/en/hotels/nyctshh-hilton-times-square/",
            "phone": "+1 212-913-9488",
            "emails": [
                "NYCTS_HOTEL @hilton.com"
            ],
            "address": "234 West 42nd Street, New York, 10036",
            "city": "New York",
            "countryCode": "US"
        },
        {
            "title": "Pod 39",
            "categoryName": "Hotel",
            "website": "https://www.thepodhotel.com/pod-39/",
            "phone": "+1-844-763-7666;+1-212-865-5700",
            "emails": [
                "info@podhotel39.com"
            ],
            "address": "145 East 39th Street, New York, 10016",
            "city": "New York",
            "countryCode": "US"
        },
        {
            "title": "Somerset Hotel",
            "categoryName": "Hotel",
            "website": "https://somersethotellondon.com",
            "phone": "+44 20 7723 0741",
            "emails": [
                "reservations@somersethotel.net"
            ],
            "address": "6 Dorset Square, London, NW1 6QA",
            "city": "London",
            "countryCode": "GB"
        },
        {
            "title": "Mandarin Oriental",
            "categoryName": "Hotel",
            "website": "https://www.mandarinoriental.com/en/new-york/manhattan",
            "phone": "+1-212-805-8800",
            "emails": [
                "MONYC-RESERVATIONS@MOHG.COM"
            ],
            "address": "80 Columbus Circle, New York, 10023",
            "city": "New York",
            "countryCode": "US"
        }
    ],
    "defaultCountry": "GB"
};

// Run the Actor and wait for it to finish
const run = await client.actor("chris_elder/dataset-dedupe-enrich").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "items": [
        {
            "title": "Lime Tree Hotel",
            "categoryName": "Hotel",
            "website": "https://www.limetreehotel.co.uk/",
            "phone": "+44 20 7730 8191",
            "emails": ["info@limetreehotel.co.uk"],
            "address": "135-137 Ebury Street, London, SW1W 9QU",
            "city": "London",
            "countryCode": "GB",
        },
        {
            "title": "The Warwick by Nestor",
            "categoryName": "Hotel",
            "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
            "phone": "+44 20 3868 6192",
            "emails": ["guest@nestorstay.com"],
            "address": "94 Warwick Way, London, SW1V 1SB",
            "city": "London",
            "countryCode": "GB",
        },
        {
            "title": "The Warwick by Nestor",
            "categoryName": "Hotel",
            "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
            "phone": "+44 20 3868 6192",
            "emails": ["guest@nestorstay.com"],
            "address": "94 Warwick Way, London, SW1V 1SB",
            "city": "London",
            "countryCode": "GB",
        },
        {
            "title": "The Trafalgar St. James London, Curio Collection by Hilton",
            "categoryName": "Hotel",
            "website": "https://www.hilton.com/en/hotels/lontsqq-the-trafalgar-st-james-london/",
            "phone": "+44 20 7870 2900",
            "emails": ["reservations@thetrafalgar.com"],
            "address": "2 Spring Gardens, London, SW1A 2TS",
            "city": "London",
            "countryCode": "GB",
        },
        {
            "title": "Hilton",
            "categoryName": "Hotel",
            "website": "https://www.hilton.com/en/hotels/nyctshh-hilton-times-square/",
            "phone": "+1 212-913-9488",
            "emails": ["NYCTS_HOTEL @hilton.com"],
            "address": "234 West 42nd Street, New York, 10036",
            "city": "New York",
            "countryCode": "US",
        },
        {
            "title": "Pod 39",
            "categoryName": "Hotel",
            "website": "https://www.thepodhotel.com/pod-39/",
            "phone": "+1-844-763-7666;+1-212-865-5700",
            "emails": ["info@podhotel39.com"],
            "address": "145 East 39th Street, New York, 10016",
            "city": "New York",
            "countryCode": "US",
        },
        {
            "title": "Somerset Hotel",
            "categoryName": "Hotel",
            "website": "https://somersethotellondon.com",
            "phone": "+44 20 7723 0741",
            "emails": ["reservations@somersethotel.net"],
            "address": "6 Dorset Square, London, NW1 6QA",
            "city": "London",
            "countryCode": "GB",
        },
        {
            "title": "Mandarin Oriental",
            "categoryName": "Hotel",
            "website": "https://www.mandarinoriental.com/en/new-york/manhattan",
            "phone": "+1-212-805-8800",
            "emails": ["MONYC-RESERVATIONS@MOHG.COM"],
            "address": "80 Columbus Circle, New York, 10023",
            "city": "New York",
            "countryCode": "US",
        },
    ],
    "defaultCountry": "GB",
}

# Run the Actor and wait for it to finish
run = client.actor("chris_elder/dataset-dedupe-enrich").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "items": [
    {
      "title": "Lime Tree Hotel",
      "categoryName": "Hotel",
      "website": "https://www.limetreehotel.co.uk/",
      "phone": "+44 20 7730 8191",
      "emails": [
        "info@limetreehotel.co.uk"
      ],
      "address": "135-137 Ebury Street, London, SW1W 9QU",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "The Warwick by Nestor",
      "categoryName": "Hotel",
      "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
      "phone": "+44 20 3868 6192",
      "emails": [
        "guest@nestorstay.com"
      ],
      "address": "94 Warwick Way, London, SW1V 1SB",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "The Warwick by Nestor",
      "categoryName": "Hotel",
      "website": "https://nestorstay.com/properties/the-warwick-by-nestor/",
      "phone": "+44 20 3868 6192",
      "emails": [
        "guest@nestorstay.com"
      ],
      "address": "94 Warwick Way, London, SW1V 1SB",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "The Trafalgar St. James London, Curio Collection by Hilton",
      "categoryName": "Hotel",
      "website": "https://www.hilton.com/en/hotels/lontsqq-the-trafalgar-st-james-london/",
      "phone": "+44 20 7870 2900",
      "emails": [
        "reservations@thetrafalgar.com"
      ],
      "address": "2 Spring Gardens, London, SW1A 2TS",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "Hilton",
      "categoryName": "Hotel",
      "website": "https://www.hilton.com/en/hotels/nyctshh-hilton-times-square/",
      "phone": "+1 212-913-9488",
      "emails": [
        "NYCTS_HOTEL @hilton.com"
      ],
      "address": "234 West 42nd Street, New York, 10036",
      "city": "New York",
      "countryCode": "US"
    },
    {
      "title": "Pod 39",
      "categoryName": "Hotel",
      "website": "https://www.thepodhotel.com/pod-39/",
      "phone": "+1-844-763-7666;+1-212-865-5700",
      "emails": [
        "info@podhotel39.com"
      ],
      "address": "145 East 39th Street, New York, 10016",
      "city": "New York",
      "countryCode": "US"
    },
    {
      "title": "Somerset Hotel",
      "categoryName": "Hotel",
      "website": "https://somersethotellondon.com",
      "phone": "+44 20 7723 0741",
      "emails": [
        "reservations@somersethotel.net"
      ],
      "address": "6 Dorset Square, London, NW1 6QA",
      "city": "London",
      "countryCode": "GB"
    },
    {
      "title": "Mandarin Oriental",
      "categoryName": "Hotel",
      "website": "https://www.mandarinoriental.com/en/new-york/manhattan",
      "phone": "+1-212-805-8800",
      "emails": [
        "MONYC-RESERVATIONS@MOHG.COM"
      ],
      "address": "80 Columbus Circle, New York, 10023",
      "city": "New York",
      "countryCode": "US"
    }
  ],
  "defaultCountry": "GB"
}' |
apify call chris_elder/dataset-dedupe-enrich --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chris_elder/dataset-dedupe-enrich"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/BYWaa3e8tRIb42euE/builds/otL8dhozd6BboHW6N/openapi.json
