# AI Lead Qualifier — Score Leads & Write Openers (`rook-data-tools/ai-lead-qualifier`) Actor

Score any batch of leads against your ideal customer profile (1-10) and draft a personalized cold-open line for each. Feed it any lead scraper's output. Bring your own OpenAI-compatible key.

- **URL**: https://apify.com/rook-data-tools/ai-lead-qualifier.md
- **Developed by:** [Rook DataTools](https://apify.com/rook-data-tools) (community)
- **Categories:** Lead generation, AI
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## AI Lead Qualifier — Score Leads & Write Openers

**Turn a raw list of leads into a scored, prioritized outreach list — with a personalized
opening line already written for each one.** Point it at any batch of leads, describe your
ideal customer and your offer, and get back every lead scored 1–10 with a one-sentence
reason and a ready-to-send cold-open line.

![Real run: a public chamber directory turned into a ranked call list — 15 businesses → 12 emails added → AI-scored leads with written openers](https://raw.githubusercontent.com/willowridge1234/rook-data-tools-assets/main/pipeline-proof.png)



Not a scraper — this is the qualification layer that goes **after** scraping. Feed it the
output of any lead-scraper on Apify (including the Wild Apricot, MembershipWorks, and
ChamberMaster directory scrapers) and it turns hundreds of raw rows into a ranked call list.

### Bring your own key = you pay pennies here
The model runs on **your** OpenAI-compatible API key (OpenAI by default; works with Azure,
OpenRouter, Together, local servers — anything OpenAI-compatible). Because the model cost
is billed to your own account, this Actor charges only a few cents per lead for the
orchestration, prompting, parsing, and delivery.

### Input
```json
{
  "leads": [
    { "name": "Bluewater Bistro", "category": "Restaurant", "city": "Seattle" }
  ],
  "inputDatasetId": "PASTE_A_SCRAPER_RUN_DATASET_ID_optional",
  "icpDescription": "Independent restaurants and bars, not chains.",
  "offerDescription": "Modern restaurant POS with free install.",
  "scoreThreshold": 7,
  "onlyReturnQualified": false,
  "model": "gpt-4o-mini",
  "apiKey": "sk-your-own-key"
}
````

- **leads**: array of objects (any shape) or strings. And/or…
- **inputDatasetId**: qualify another Actor's output directly — paste its dataset ID.
- **icpDescription / offerDescription**: the sharper and more specific, the better the scores.
- **onlyReturnQualified**: return just the leads that meet your threshold.
- **model / apiBaseUrl / apiKey**: your provider and key (key stored as a secret).

### Output

Each input lead is returned unchanged, plus a `_qualification` block:

```json
{
  "name": "Bluewater Bistro",
  "category": "Restaurant",
  "city": "Seattle",
  "_qualification": {
    "score": 9,
    "reason": "Independent food-service business, strong ICP fit.",
    "opener": "Saw your spot listed locally — most independents here still run legacy POS; ours installs free before your next weekend rush.",
    "qualified": true,
    "model": "gpt-4o-mini",
    "at": "2026-07-23T21:40:00.000Z"
  }
}
```

### Typical workflow (the flywheel)

1. Run a directory/lead scraper → dataset of raw businesses.
2. Run **AI Lead Qualifier** with that `inputDatasetId` + your ICP + offer.
3. Export the qualified rows (with openers) to your CRM / Google Sheet / Slack.

### Notes

- Robust to messy model output — a malformed response never kills the run; it fails safe per lead.
- Concurrency is configurable (1–10) for speed vs. rate limits.
- Your API key is stored as a secret and used only to call your chosen model.
- No personal data is sent anywhere except your own model provider.

***

### 🔗 Part of a lead-generation suite (scrape → enrich → qualify)

This Actor works best chained with its companions on the same account:

1. **Directory scrapers** — get businesses/members (name + website) from
   Wild Apricot, MembershipWorks, or ChamberMaster / GrowthZone directories.
2. **Business Website Contact Extractor** — add the emails/phones the directories hide.
3. **AI Lead Qualifier** — score each lead against your ICP and write a personalized opener.

Pass a run's **dataset ID** into the next step. NOTE: cross-actor chaining needs your **apifyToken** in the input (Apify runs actors with limited permissions, so reading another run's dataset requires your token).

# Actor input Schema

## `leads` (type: `array`):

Leads to qualify — an array of objects (any shape: name, website, phone, category, etc.) or plain strings. Leave empty if you're using an Input dataset instead.

## `inputDatasetId` (type: `string`):

Qualify the output of another Actor run: paste its dataset ID (e.g. a directory scraper or the Website Contact Extractor). Combined with any inline leads. Requires 'apifyToken' below (Apify runs actors with limited permissions, so reading another run's dataset needs your token).

## `apifyToken` (type: `string`):

Your Apify API token — needed ONLY when using 'Input dataset ID' to read another actor run's output (chaining). Console → Settings → API. Stored as a secret. Not needed if you pass leads directly.

## `icpDescription` (type: `string`):

Describe your perfect customer in plain words. Be opinionated — specifics produce sharper scoring. e.g. 'Independent restaurants and bars in US metros, not chains, that likely lack a modern POS.'

## `offerDescription` (type: `string`):

What you sell, in one or two sentences. Used to write the personalized opener.

## `scoreThreshold` (type: `integer`):

Leads scoring at or above this (1-10) are marked qualified.

## `onlyReturnQualified` (type: `boolean`):

If on, only leads meeting the threshold are written to the output dataset.

## `model` (type: `string`):

Chat-completions model name on your provider (e.g. gpt-4o-mini, gpt-4o).

## `apiBaseUrl` (type: `string`):

OpenAI-compatible base URL. Default is OpenAI. Point it at Azure OpenAI, OpenRouter, Together, a local server, etc.

## `apiKey` (type: `string`):

Your OpenAI-compatible API key. Stored as a secret; used only to call the model on your behalf. This is why you pay only pennies per lead here — the model cost is billed to your own account.

## `maxLeads` (type: `integer`):

Hard cap. Controls cost.

## `concurrency` (type: `integer`):

How many leads to score in parallel (1-10).

## Actor input object example

```json
{
  "leads": [
    {
      "name": "Bluewater Bistro",
      "category": "Restaurant",
      "city": "Seattle",
      "website": "https://example-bistro.com"
    },
    {
      "name": "Acme Payroll Co",
      "category": "B2B services",
      "city": "Chicago"
    }
  ],
  "icpDescription": "Independent restaurants and bars in US metro areas — owner-operated, not chains — that would benefit from a modern point-of-sale system.",
  "offerDescription": "We sell an all-in-one restaurant POS with free installation and 0% processing for the first 3 months.",
  "scoreThreshold": 7,
  "onlyReturnQualified": false,
  "model": "gpt-4o-mini",
  "apiBaseUrl": "https://api.openai.com/v1",
  "maxLeads": 1000,
  "concurrency": 4
}
```

# 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 = {
    "leads": [
        {
            "name": "Bluewater Bistro",
            "category": "Restaurant",
            "city": "Seattle",
            "website": "https://example-bistro.com"
        },
        {
            "name": "Acme Payroll Co",
            "category": "B2B services",
            "city": "Chicago"
        }
    ],
    "icpDescription": "Independent restaurants and bars in US metro areas — owner-operated, not chains — that would benefit from a modern point-of-sale system.",
    "offerDescription": "We sell an all-in-one restaurant POS with free installation and 0% processing for the first 3 months."
};

// Run the Actor and wait for it to finish
const run = await client.actor("rook-data-tools/ai-lead-qualifier").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 = {
    "leads": [
        {
            "name": "Bluewater Bistro",
            "category": "Restaurant",
            "city": "Seattle",
            "website": "https://example-bistro.com",
        },
        {
            "name": "Acme Payroll Co",
            "category": "B2B services",
            "city": "Chicago",
        },
    ],
    "icpDescription": "Independent restaurants and bars in US metro areas — owner-operated, not chains — that would benefit from a modern point-of-sale system.",
    "offerDescription": "We sell an all-in-one restaurant POS with free installation and 0% processing for the first 3 months.",
}

# Run the Actor and wait for it to finish
run = client.actor("rook-data-tools/ai-lead-qualifier").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "leads": [
    {
      "name": "Bluewater Bistro",
      "category": "Restaurant",
      "city": "Seattle",
      "website": "https://example-bistro.com"
    },
    {
      "name": "Acme Payroll Co",
      "category": "B2B services",
      "city": "Chicago"
    }
  ],
  "icpDescription": "Independent restaurants and bars in US metro areas — owner-operated, not chains — that would benefit from a modern point-of-sale system.",
  "offerDescription": "We sell an all-in-one restaurant POS with free installation and 0% processing for the first 3 months."
}' |
apify call rook-data-tools/ai-lead-qualifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=rook-data-tools/ai-lead-qualifier",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "AI Lead Qualifier — Score Leads & Write Openers",
        "description": "Score any batch of leads against your ideal customer profile (1-10) and draft a personalized cold-open line for each. Feed it any lead scraper's output. Bring your own OpenAI-compatible key.",
        "version": "0.1",
        "x-build-id": "5Gnt19eXglPzDvfKh"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/rook-data-tools~ai-lead-qualifier/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-rook-data-tools-ai-lead-qualifier",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/rook-data-tools~ai-lead-qualifier/runs": {
            "post": {
                "operationId": "runs-sync-rook-data-tools-ai-lead-qualifier",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/rook-data-tools~ai-lead-qualifier/run-sync": {
            "post": {
                "operationId": "run-sync-rook-data-tools-ai-lead-qualifier",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "apiKey"
                ],
                "properties": {
                    "leads": {
                        "title": "Leads",
                        "type": "array",
                        "description": "Leads to qualify — an array of objects (any shape: name, website, phone, category, etc.) or plain strings. Leave empty if you're using an Input dataset instead."
                    },
                    "inputDatasetId": {
                        "title": "Input dataset ID (optional)",
                        "type": "string",
                        "description": "Qualify the output of another Actor run: paste its dataset ID (e.g. a directory scraper or the Website Contact Extractor). Combined with any inline leads. Requires 'apifyToken' below (Apify runs actors with limited permissions, so reading another run's dataset needs your token)."
                    },
                    "apifyToken": {
                        "title": "Apify API token (only for Input dataset ID)",
                        "type": "string",
                        "description": "Your Apify API token — needed ONLY when using 'Input dataset ID' to read another actor run's output (chaining). Console → Settings → API. Stored as a secret. Not needed if you pass leads directly."
                    },
                    "icpDescription": {
                        "title": "Ideal Customer Profile (ICP)",
                        "type": "string",
                        "description": "Describe your perfect customer in plain words. Be opinionated — specifics produce sharper scoring. e.g. 'Independent restaurants and bars in US metros, not chains, that likely lack a modern POS.'"
                    },
                    "offerDescription": {
                        "title": "Your offer",
                        "type": "string",
                        "description": "What you sell, in one or two sentences. Used to write the personalized opener."
                    },
                    "scoreThreshold": {
                        "title": "Qualified threshold",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Leads scoring at or above this (1-10) are marked qualified.",
                        "default": 7
                    },
                    "onlyReturnQualified": {
                        "title": "Only return qualified leads",
                        "type": "boolean",
                        "description": "If on, only leads meeting the threshold are written to the output dataset.",
                        "default": false
                    },
                    "model": {
                        "title": "Model",
                        "type": "string",
                        "description": "Chat-completions model name on your provider (e.g. gpt-4o-mini, gpt-4o).",
                        "default": "gpt-4o-mini"
                    },
                    "apiBaseUrl": {
                        "title": "API base URL",
                        "type": "string",
                        "description": "OpenAI-compatible base URL. Default is OpenAI. Point it at Azure OpenAI, OpenRouter, Together, a local server, etc.",
                        "default": "https://api.openai.com/v1"
                    },
                    "apiKey": {
                        "title": "API key (your own)",
                        "type": "string",
                        "description": "Your OpenAI-compatible API key. Stored as a secret; used only to call the model on your behalf. This is why you pay only pennies per lead here — the model cost is billed to your own account."
                    },
                    "maxLeads": {
                        "title": "Max leads per run",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Hard cap. Controls cost.",
                        "default": 1000
                    },
                    "concurrency": {
                        "title": "Concurrency",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "How many leads to score in parallel (1-10).",
                        "default": 4
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
