# Email Validator & Verifier: Bulk MX & Disposable Check (`rod_analytics/bulk-email-verifier`) Actor

Bulk email validator and verifier for list cleaning: syntax, MX, disposable, role and typo checks. Verdict and 0-100 score per address. Paste emails, upload a CSV or pick a scraper dataset. No API key needed. Optional mailbox check with your own MillionVerifier key.

- **URL**: https://apify.com/rod_analytics/bulk-email-verifier.md
- **Developed by:** [Rod Services](https://apify.com/rod_analytics) (community)
- **Categories:** Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.21 / 1,000 results

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

**Email validator and bulk email verifier** that cleans your list before you send: syntax, MX records, disposable domains, role accounts and typos (gmial.com to gmail.com).
Each address gets a clear verdict, `deliverable`, `risky`, `undeliverable` or `unknown`, plus a 0-100 score. **$0.30 per 1,000 emails, no API key, no subscription.**

### What you get

- **One row per unique address** with `verdict`, `score`, `status`, `reason` and every flag behind them.
- **Syntax validation** per RFC 5321/5322, including quoted locals and international domains.
- **Domain and MX record check.** Dead domains, null MX and domains with no mail server are marked `undeliverable`.
- **Disposable email detection** from a list of 9,185 throwaway domains such as Mailinator and 10MinuteMail.
- **Typo suggestions** for common domains, with the fixed address in `didYouMean`.
- **Role account and free provider flags** for `info@`, `sales@`, Gmail, Outlook, GMX and about 110 more.
- **Three ways to feed it:** paste addresses, upload or link a CSV or text file, or pick the dataset of another Actor run, for example a Google Maps, Apollo or website contact scraper.
- **Optional mailbox check with your own [MillionVerifier](https://www.millionverifier.com) key.** Paste the key and every address that passes the DNS checks is also checked for an existing mailbox and for catch-all domains. It runs on your MillionVerifier credits, so you pay only the DNS-level price here. See [Mailbox check](#mailbox-check-with-your-millionverifier-key).
- **Fast.** 1,000 addresses finish in a few seconds. Each domain is looked up once and cached.

> **What `deliverable` means.** The address passed every check that ran. By default these are syntax, DNS, disposable, role and typo checks (`verificationLevel: "dns"`). They catch dead domains, typos and throwaway inboxes, but they do **not** prove that the mailbox itself exists. That is why DNS-level results score at most 80. With a mailbox check the same verdict is backed by an answer from the recipient mail server (`verificationLevel: "smtp"`, score up to 97).

### Quick start

1. Open the **Input** tab.
2. Paste addresses into **Email addresses**. Or upload a **CSV or text file**, or pick a **Dataset from another Actor**.
3. Click **Start**. The prefilled example with 5 addresses finishes in a few seconds.
4. Open the **Output** tab. Sort by `score` or filter by `verdict`, then export to CSV, Excel or JSON.

**Clean scraped leads in one step.** Run any lead scraper, copy the **Dataset ID** from its Storage tab, and paste it into **Dataset from another Actor**. The verifier reads the `email` field, or `emails` lists, from every row. Set **Email field in the dataset** if the column has another name, for example `contact.email`.

### Input example

```json
{
    "emails": ["info@apify.com", "example.user@gmial.com", "test@mailinator.com"],
    "emailsFileUrl": "https://example.com/contacts.csv",
    "datasetId": "aBcD1234eFgH5678i",
    "emailField": "emails",
    "millionVerifierApiKey": "<YOUR_MILLIONVERIFIER_KEY>"
}
```

| Field                   | Meaning                                                                                                                                                   |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `emails`                | Addresses to check. Blocks separated by new lines, commas or semicolons also work.                                                                        |
| `emailsFileUrl`         | CSV or text file, uploaded in the Console or given as a public link. Every cell with an `@` is used, so headers and other columns are ignored. Max 50 MB. |
| `datasetId`             | Dataset of another run. Dataset ID or the dataset picker.                                                                                                 |
| `emailField`            | Field that holds the address in that dataset. Lists and dot paths work. Empty: `email`, then `emails`.                                                    |
| `mailboxCheck`          | Default on. Runs the mailbox check when a MillionVerifier key is available. Turn off for DNS level results only.                                          |
| `millionVerifierApiKey` | Your own MillionVerifier API key. Stored encrypted, never logged. Optional.                                                                               |

All three sources can be combined. Duplicates are checked and billed once. `INFO@Example.com` and `info@example.com` count as one address. Plus tags are kept, so `jane+news@gmail.com` and `jane@gmail.com` are two.

### Output sample

```json
{
    "email": "info@apify.com",
    "verdict": "deliverable",
    "score": 70,
    "status": "valid",
    "reason": "mx_found",
    "verificationLevel": "dns",
    "isSyntaxValid": true,
    "hasMx": true,
    "mxHosts": ["aspmx.l.google.com", "alt1.aspmx.l.google.com"],
    "isDisposable": false,
    "isFreeProvider": false,
    "isRole": true,
    "isCatchAll": null,
    "catchAll": null,
    "mailboxCheck": "none",
    "mailboxResult": null,
    "mailboxDetail": null,
    "smtpChecked": false,
    "didYouMean": null,
    "domain": "apify.com",
    "checkedAt": "2026-10-05T12:54:10.311Z"
}
```

`mailboxCheck` tells who checked the mailbox: `none`, `millionverifier` or `smtp` (your own proxy). `mailboxResult` is `ok`, `invalid`, `catch_all`, `unknown` or `disposable`, and `null` when no mailbox check was made. `catchAll` mirrors `isCatchAll`. A run summary with counts per verdict, status, verification level and mailbox answer is saved as `SUMMARY` in the key-value store.

#### Verdict and score

| Verdict         | Typical score                | Reasons                                                                                                                | What to do                               |
| --------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| `deliverable`   | 80, or 70 for role mailboxes | `mx_found`: syntax fine, domain receives mail, not disposable, no typo                                                 | Keep. Mailbox not confirmed at DNS level |
| `deliverable`   | 97                           | `mailbox_exists`: confirmed by the mail server, only with a mailbox check                                              | Keep                                     |
| `risky`         | 10 to 55                     | `possible_typo`, `disposable`, `catch_all`, `mailbox_full`, `a_record_only`                                            | Fix the typo, or review and remove       |
| `undeliverable` | 0                            | `invalid_syntax`, `domain_not_found`, `null_mx`, `no_mail_server`, `mailbox_not_found`                                 | Remove                                   |
| `unknown`       | 30 to 60                     | `dns_error`, `mailbox_unknown`, `smtp_blocked`, `greylisted`, `smtp_temporary_error`, `smtp_unreachable`, `smtp_error` | Retry later                              |

`a_record_only` means the domain has no MX record and mail would go to its A record per RFC 5321. Many such domains do not accept mail, so they count as `risky`.

### Pricing

Pay per event. No monthly fee. Discounts apply automatically on paid Apify plans.

| Event                                      | Free plan | Bronze  | Silver  | Gold    |
| ------------------------------------------ | --------- | ------- | ------- | ------- |
| Address checked, per 1,000                 | $0.30     | $0.27   | $0.24   | $0.21   |
| Answer from your own SMTP proxy, per 1,000 | $0.40     | $0.36   | $0.32   | $0.28   |
| Run start, per run                         | $0.0005   | $0.0005 | $0.0005 | $0.0005 |

Examples on the Free plan: 1,000 addresses cost about $0.30, 100,000 cost about $30. The Apify free monthly credit covers thousands of checks. Set **Maximum cost per run** in the run options to cap spend: the run stops there and addresses past the cap are not charged.

**Mailbox check with your own MillionVerifier key costs nothing extra here.** You pay MillionVerifier for the credits, and this Actor charges only the DNS-level price per address. The price list also holds a "Mailbox verified" event of $3.00 per 1,000 (Bronze $2.70, Silver $2.40, Gold $2.10). It is reserved for a hosted mailbox check that is not switched on yet. **No run is charged this event today.**

### Use it from code, Make, Zapier or AI agents

Everything in the Input tab is also available through the Apify API, the JavaScript and Python clients, scheduling, webhooks and integrations such as Make, Zapier, n8n and Google Sheets. AI agents can call it through the Apify MCP server at `mcp.apify.com`. A typical API call:

```bash
curl -X POST "https://api.apify.com/v2/acts/rod_analytics~bulk-email-verifier/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <YOUR_APIFY_TOKEN>" -H "Content-Type: application/json" \
  -d '{"emails": ["jane@example.com", "john@gmial.com"]}'
```

### Mailbox check with your MillionVerifier key

A DNS-level check cannot see inside a mailbox. [MillionVerifier](https://www.millionverifier.com) can: it asks the recipient mail server whether the mailbox exists and whether the domain accepts every address. This Actor sends it only the addresses that already passed the syntax, MX, disposable and typo checks, once per unique address.

1. Create an account at millionverifier.com and buy credits. They do not expire.
2. Copy your API key from app.millionverifier.com/api.
3. Paste it into **MillionVerifier API key** in the Input tab and start the run.

What changes in the output:

| MillionVerifier says | Verdict                    | Reason                          | Score                      |
| -------------------- | -------------------------- | ------------------------------- | -------------------------- |
| `ok`                 | `deliverable`              | `mailbox_exists`                | 97 (87 for role mailboxes) |
| `invalid`            | `undeliverable`            | `mailbox_not_found`             | 0                          |
| `catch_all`          | `risky`                    | `catch_all`, `catchAll: true`   | 55                         |
| `unknown`            | `unknown`                  | `mailbox_unknown`               | 60                         |
| error or no answer   | unchanged DNS-level result | `mailboxDetail: "check_failed"` | unchanged                  |

Lists of 1,000 or more addresses are sent as files of up to 250,000 addresses and checked in the background. Smaller lists are checked one address at a time. If your key is wrong the run ends with a help row, `INVALID_API_KEY`, and you pay only the start fee. If your credits run out mid-run, the remaining addresses keep their DNS-level result. Your key is stored encrypted and never written to a log. We keep no copy of your addresses or the answers: they go only to your dataset.

Catch-all and accept-all domains, common on Microsoft 365 and Google Workspace, cannot be resolved by any verifier. They come back as `catch_all` and stay `risky`. The mailbox answer is a strong signal, not a guarantee, and no tool predicts every bounce.

### Optional: SMTP mailbox check with your own proxy

This is an advanced feature for users who run their own mail infrastructure. It is off by default and most users do not need it. If a working SOCKS5 proxy is set, it takes priority over the MillionVerifier check.

A mailbox check asks the recipient mail server whether the address exists, using only `EHLO`, `MAIL FROM`, `RCPT TO` and `QUIT`. **No email is ever sent.** It needs outbound TCP port 25, which **Apify blocks**, like most cloud providers. So on Apify it only works through your own SOCKS5 proxy:

1. Rent a small VPS where port 25 is open. Many hosts open it on request.
2. Set reverse DNS of its IP to a hostname you own, for example `verify.yourdomain.com`.
3. Run a SOCKS5 server such as Dante with a username and password.
4. In the **Bring your own SMTP proxy** section, fill `socksProxyUrl`, `heloHost` and `fromAddress`, then turn on `smtpCheck`.

The Actor tests port 25 before it starts, against four large mail servers. If none answers, it logs a warning, continues without your proxy check and charges no SMTP events. The probe results are in the `SUMMARY` record under `port25Probe`. With a working proxy it also detects catch-all domains with one extra random-address probe per domain. Even then no verifier is 100 % accurate: Yahoo and some Microsoft servers accept every address or block probes, so expect `catch_all` or `smtp_blocked` there. Keep **Max connections per mail server** at 1 or 2.

### Acceptable use

- **Only check lists you have a lawful basis to process**, for example your own customers or signups under GDPR. You are the data controller for the addresses you upload.
- **No spam.** Do not use this Actor to build lists for unsolicited email or to guess addresses. Be aware that cold email to German addresses needs prior consent (UWG section 7).
- Results stay in your own Apify storage. Delete datasets you no longer need.
- **Sub-processor.** With a mailbox check, the addresses that pass the DNS checks are sent to MillionVerifier, on your key. Without a key, nothing leaves the Actor. We store no addresses and log counts only.

### FAQ

**Does it confirm that the mailbox exists?** Not by default. The default checks prove that the address is well formed, the domain is live and receives mail, and it is not a throwaway or a typo. Those catch a large share of bounces from old, scraped or hand-typed lists. Mailbox confirmation needs your MillionVerifier key or your own SMTP proxy, see above.

**Why not just run SMTP checks from the Actor?** Apify blocks outbound port 25, like most cloud providers. We re-tested it on 2026-10-07: every large mail server timed out. That is why the mailbox check goes through MillionVerifier or your own proxy.

**Is the score a bounce probability?** No. It is a simple 0-100 confidence from the checks that ran: 97 for a confirmed mailbox, 80 for a clean address at DNS level, 0 for undeliverable. Role mailboxes get 10 points less.

**How big a list can I run?** Hundreds of thousands of addresses. Above about 200,000 addresses raise the run memory to 1 GB or more in the run options.

**Can I verify the output of a Google Maps or LinkedIn scraper?** Yes. Paste the run's dataset ID into **Dataset from another Actor**. Use **Email field in the dataset** if the addresses are not in `email` or `emails`.

**Where does the disposable list come from?** A pinned snapshot of [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains), CC0 licensed, 9,185 domains.

**Does it send emails?** No. There is no `DATA` command, even with the SMTP check on.

**What happens if my input is wrong?** The run still ends **SUCCEEDED** and you pay only the start fee. The status message explains the problem and the fix. The same help record is saved in the key-value store under `INPUT_ERROR`, with `error`, `errorCode`, `message` and `howToFix`. Codes: `EMPTY_INPUT`, `NO_EMAILS_FOUND`, `FILE_UNREADABLE`, `DATASET_UNREADABLE`, `INVALID_INPUT`, `INVALID_API_KEY` and `NO_MILLIONVERIFIER_CREDITS`. Addresses with bad syntax are not an input error: they come back as `undeliverable`.

**Found a bug or need a feature?** Open the **Issues** tab. Replies usually come within a day.

### Related Actors

| Actor                                                                                                               | What it does                                                            |
| ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| [Website Content Crawler to Markdown for RAG & LLMs](https://apify.com/rod_analytics/website-to-markdown)           | Crawl a site and get clean Markdown for RAG and LLMs                    |
| [PDF to Markdown & Text Extractor with OCR](https://apify.com/rod_analytics/doc-to-markdown)                        | Turn PDF, DOCX and scans into Markdown or text                          |
| [SEO Audit Tool: Site Crawler, Broken Links & Score](https://apify.com/rod_analytics/seo-site-audit)                | Crawl a site for broken links and SEO issues                            |
| [PageSpeed Insights & Lighthouse Bulk Checker](https://apify.com/rod_analytics/lighthouse-audit)                    | Core Web Vitals and Lighthouse scores for many URLs                     |
| [Tech Stack Detector: Wappalyzer & BuiltWith Alternative](https://apify.com/rod_analytics/tech-stack-detector)      | See which CMS, analytics and frameworks a site uses                     |
| [Bulk Domain Lookup: DNS, WHOIS, SPF, DMARC & SSL](https://apify.com/rod_analytics/domain-security-audit)           | DNS, mail security and SSL checks for domain lists                      |
| [Speech to Text: Audio, Video & Podcast Transcriber](https://apify.com/rod_analytics/media-transcriber)             | Transcribe audio, video and podcasts                                    |
| [Website Contact Scraper: Emails, Phones & Social Links](https://apify.com/rod_analytics/company-contact-extractor) | Emails, phones and social links from company websites                   |
| [Email Format Finder: Company Email Pattern Lookup](https://apify.com/rod_analytics/email-format-finder)            | Find the email pattern a company uses, with the source pages            |
| [Work Email Finder: Find Email by Name and Domain](https://apify.com/rod_analytics/work-email-finder)               | Find and verify the work email of a person from name and company domain |
| [VIES VAT Checker & EU Company Registry Lookup](https://apify.com/rod_analytics/eu-company-lookup)                  | Validate EU VAT numbers and look up companies                           |
| [Companies House Scraper: UK Company Search, No API Key](https://apify.com/rod_analytics/uk-companies-house)        | UK company profiles, officers and filings                               |
| [EU TED Tenders Scraper & Alerts: Public Procurement](https://apify.com/rod_analytics/ted-tenders)                  | EU public tenders with daily alerts                                     |
| [Greenhouse, Lever & Ashby Job Scraper: 8 ATS in One Feed](https://apify.com/rod_analytics/multi-ats-jobs-api)      | Jobs from 7 ATS platforms in one feed                                   |
| [GitHub Scraper: Repo Stats, Stars, Trending & Search](https://apify.com/rod_analytics/github-repo-stats)           | Stars, activity and trending GitHub repos                               |

# Changelog

This Actor's version history is a separate document: https://apify.com/rod_analytics/bulk-email-verifier/changelog.md

# Actor input Schema

## `emails` (type: `array`):

Addresses to check, one per item. You can also paste a block of addresses separated by new lines, commas or semicolons. Duplicates are checked and billed once.

## `emailsFileUrl` (type: `string`):

Optional. Upload a CSV or plain text file, or paste a public link to one, e.g. a Google Sheets "Publish to web" CSV link. Every cell that contains an @ is used, so header rows and other columns are ignored. Max 50 MB.

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

Optional. Pick the dataset of a finished run, e.g. Google Maps, Apollo, LinkedIn or a website contact scraper, and every address in it is checked. You can also paste a dataset ID.

## `emailField` (type: `string`):

Field that holds the address in the dataset rows. Lists like emails: \[...] and dot paths like contact.email work. Leave empty to use email, then emails.

## `mailboxCheck` (type: `boolean`):

After the DNS checks, ask MillionVerifier whether the mailbox exists and whether the domain accepts every address (catch-all). Runs only when a MillionVerifier API key is available, see the field below. Turn it off to get DNS level results only.

## `millionVerifierApiKey` (type: `string`):

Your own key from app.millionverifier.com/api. The check then runs on your MillionVerifier credits and only the DNS level price applies here. Stored encrypted. Leave empty to run DNS level checks only.

## `smtpCheck` (type: `boolean`):

Ask the recipient mail server whether the mailbox exists (EHLO, MAIL FROM, RCPT TO, QUIT). No email is sent. Needs the SOCKS5 proxy below. Without a working proxy the run continues with DNS level checks only, with no SMTP charges.

## `socksProxyUrl` (type: `string`):

socks5://user:password@host:port. The proxy host must allow outbound TCP port 25. Stored encrypted.

## `heloHost` (type: `string`):

Hostname sent in EHLO. Use a domain you control that matches the reverse DNS of the proxy IP. Defaults to the domain of the sender address.

## `fromAddress` (type: `string`):

Envelope sender used in MAIL FROM. Use an address on a domain you control. Defaults to verify@<HELO hostname>.

## `checkCatchAll` (type: `boolean`):

Only with the SMTP check. Sends one extra RCPT for a random address per domain. If the server accepts it, the domain accepts everything and results become risky.

## `smtpPort` (type: `integer`):

Port on the recipient MX. Keep 25 unless you know what you are doing.

## `greylistRetrySecs` (type: `integer`):

When a server answers with a temporary 4xx code, wait this long and try those addresses once more. 0 disables the retry.

## `maxConnectionsPerMx` (type: `integer`):

Parallel SMTP sessions to one MX host. Keep it low to avoid rate limits and blocks.

## `timeoutSecs` (type: `integer`):

Timeout for each DNS query and each SMTP step.

## `maxConcurrency` (type: `integer`):

How many domains are processed in parallel. Each domain uses at most one SMTP session at a time. DNS only runs use at least 20.

## Actor input object example

```json
{
  "emails": [
    "info@apify.com",
    "example.user@gmial.com",
    "test@mailinator.com",
    "hello@no-such-domain-4f7a2c.com",
    "not-an-email@"
  ],
  "mailboxCheck": true,
  "smtpCheck": false,
  "checkCatchAll": true,
  "smtpPort": 25,
  "greylistRetrySecs": 60,
  "maxConnectionsPerMx": 2,
  "timeoutSecs": 10,
  "maxConcurrency": 10
}
```

# Actor output Schema

## `results` (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 = {
    "emails": [
        "info@apify.com",
        "example.user@gmial.com",
        "test@mailinator.com",
        "hello@no-such-domain-4f7a2c.com",
        "not-an-email@"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rod_analytics/bulk-email-verifier").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 = { "emails": [
        "info@apify.com",
        "example.user@gmial.com",
        "test@mailinator.com",
        "hello@no-such-domain-4f7a2c.com",
        "not-an-email@",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("rod_analytics/bulk-email-verifier").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 '{
  "emails": [
    "info@apify.com",
    "example.user@gmial.com",
    "test@mailinator.com",
    "hello@no-such-domain-4f7a2c.com",
    "not-an-email@"
  ]
}' |
apify call rod_analytics/bulk-email-verifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rod_analytics/bulk-email-verifier"
        }
    }
}
```

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/KJb0YceLURY3ccPO4/builds/xbbcMHDdcaPKUuOPZ/openapi.json
