# Universal B2B Lead Magnet & Intent Enricher (`stefano_seggio/actor-18-b2b-lead-magnet`) Actor

Discovers B2B leads via a customer seed list or OpenStreetMap Overpass (Google Maps excluded on ToS grounds), crawls each site for contact info, checks email plausibility via DNS/MX, supports BYOK Hunter.io/PDL enrichment, and optionally scores buying intent via Claude Haiku 4.5.

- **URL**: https://apify.com/stefano\_seggio/actor-18-b2b-lead-magnet.md
- **Developed by:** [Stefano Seggio](https://apify.com/stefano_seggio) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 basic leads

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/actors/running/actors-in-store.md#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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Universal B2B Lead Magnet & Intent Enricher — Apify Store Overview

**Actor:** `stefano_seggio/actor-18-b2b-lead-magnet`
**Actor ID:** `5QufcYxRkFNHM4h8K`
**Store URL:** https://apify.com/stefano\_seggio/actor-18-b2b-lead-magnet
**Version:** 1.1

***

### Executive Summary & Business Use Case

Universal B2B Lead Magnet & Intent Enricher turns either a list of company names/domains you already have or a geographic bounding box into structured, contact-plausibility-checked B2B leads. It runs in one of two discovery modes: **Mode A (`seedList`)**, where you supply the company names or website domains/URLs to enrich directly, and **Mode B (`osmOverpass`)**, where it discovers candidate businesses from OpenStreetMap's ODbL-licensed Overpass API inside a bounding box you define (`"south,west,north,east"` in decimal degrees). Deliberately absent from either mode is Google Maps: the actor's own documentation is explicit that Google's Maps/Earth Additional Terms and Maps Platform Terms both prohibit building a "business listings database" from Maps content, so discovery runs against OpenStreetMap's Overpass API instead — a source whose license explicitly permits bulk extraction — or against a list the customer already owns. For every candidate business, the actor crawls the site's own server-delivered HTML, extracts any `mailto:` links or regex-matched email addresses, and checks the plausibility of the associated domain with a live DNS MX-record lookup — a real, deliberately-configured mail-receiving path, not a guessed address pattern. Optionally, it layers on BYOK enrichment from Hunter.io and/or People Data Labs, and a Claude Haiku 4.5-scored buying-intent read of the business's own crawled site text.

Because the source data is a business's own public web presence (an OSM tag or a customer-supplied name/domain) rather than a valued financial record, the data this actor produces supports outreach-targeting and pipeline-building use cases, not valuation or transaction-monitoring ones. Three concrete uses fit the actual fields it returns: (1) **Sales development teams** building a first-touch outreach list from a target territory — run Mode B against a bounding box covering, say, a metro business district, and get back businesses with a live `website`, any `emailsFound`, and an `emailPlausible` flag to filter out dead-end contacts before an SDR ever touches the list. (2) **Marketing operations teams enriching an existing CRM export** — feed a seed list of account names/domains already sitting in a spreadsheet or CRM (Mode A) to attach verified-plausible contact emails and, when BYOK keys are supplied, deeper Hunter.io/People Data Labs firmographic data, without paying this actor's own price for enrichment services the customer already has a separate account for. (3) **Growth/RevOps teams prioritizing outbound sequencing by buying-intent signal** — enable `includeIntentScore` to get a 0–100 heuristic score (with a mandatory disclaimer that it is a heuristic LLM read of public text, never a verified fact) derived from hiring-page, funding-news, and tech-stack signals visible on the business's own site, letting reps triage a long list into "likely warmer" vs. "likely colder" without manually reading every homepage.

What this actor is deliberately not built for: it has no monetary `value` field populated (`value_native`, `value_currency`, and `value_usd_normalized` are always `null` per its own dataset schema — "Not applicable to this actor"), so it is not a deal-size or contract-value tool. It also has no registry-style status lifecycle — there is no tender-closed, listing-updated, or similar event a business's own website exposes the way a government registry does — so it is not a monitoring tool for change-over-time on a fixed set of records; its own CHANGELOG documents this as a deliberate design decision rather than a gap.

### Technical Features & V2 Architecture Highlights

**Cross-run lead deduplication via a named key-value store.** Per `CHANGELOG.md`, `src/state.ts` opens a NAMED key-value store — `Actor.openKeyValueStore('actor-18-b2b-lead-magnet-seen-leads')` — that persists which leads (identified by `record_id`) have already been discovered and charged for, across runs of this actor. This is real cross-run state, not an in-memory or single-run cache.

**`skipKnownLeads` — what it actually does.** Per the actor's own `input_schema.json`, when `skipKnownLeads` is enabled, "a lead already discovered (and charged for) in a prior run of this Actor is skipped before the enrichment waterfall runs — no repeat website crawl, no repeat BYOK/intent-score calls, and no repeat `basic_lead`/`enriched_lead` charge for the same business." Identity is a stable id derived from the OSM id (Mode B) or a normalized name+domain hash (Mode A), persisted in the named key-value store described above. Left off (the default), every run performs a full re-enrichment — useful when a business's own site content may have changed since the last run.

**`is_new` is a real, populated field — not the richer classification you'll see on registry-style actors in this fleet.** The dataset schema documents `is_new` as `true` if this exact business (by OSM id, or normalized name+domain for seed-list leads) was never seen in a prior run, `false` if it was — tracked in the named key-value store *regardless* of whether `skipKnownLeads` is enabled (that flag only controls whether an already-known lead is skipped from re-processing, not whether it is tracked at all). Per `CHANGELOG.md` 1.1.0, this field was previously always `null` and is now populated for real. Critically, this actor's own dataset schema is explicit that it does **not** implement the richer `NEW_LISTING`/`STATUS_CHANGE`/`UPDATED`/`CLOSED` delta-classification taxonomy some other actors in this fleet use: "a business's own listing has no observable status this actor tracks" — just seen-or-not-seen.

**`event_type` is a fixed constant here, not a set of states.** The dataset schema's own description for `event_type` reads: "Always `NEW_LISTING` — this actor has no cross-run delta-tracking concept." Every record this actor emits carries `event_type: "NEW_LISTING"`; there is no `UPDATED` or `CLOSED` value it ever writes, and per the CHANGELOG's own "Not added (and why)" section, that registry-style delta engine was deliberately not built for this domain: "a business's own web presence has no observable 'status' field the way a government tender or gazette entry does."

**18-field base envelope, confirmed by this actor's own CHANGELOG.** `CHANGELOG.md` 1.1.0 explicitly refers to `is_new` as "part of the 18-field UMS envelope" — confirming this actor shares the fleet's standard 18-field universal metadata shell (`record_id`, `event_type`, `scraped_at`, `is_new`, `source_url`, `recipient_or_defendant_name`, `entity_identifier_native`, `value_native`, `value_currency`, `value_usd_normalized`, `effective_date_iso`, `publish_date_iso`, `category_or_type`, `status_or_estado`, `awarding_or_regulating_agency`, `jurisdiction`, `source_document_url`, `reference_number`) on top of which this actor adds ten domain-specific fields (`discoverySource`, `website`, `emailsFound`, `emailPlausible`, `emailPlausibilityMethod`, `websiteContentUnavailable`, `byokEnrichment`, `intentScore`, `intentScoreRationale`, `intentScoreDisclaimer`) — 28 total fields per record.

**Compliance-by-construction discovery.** Discovery Mode B queries OpenStreetMap's public `overpass-api.de` mirror, which the input schema itself flags as "fair-use only — budget a self-hosted Overpass instance for production volume." Google Maps is excluded from the discovery layer entirely — not rate-limited or minimized, excluded — because of the ToS conflict described above. Per the README, "No CAPTCHA-solving, no fingerprint spoofing, no WAF/OAuth-gate bypass anywhere in this Actor," and a JS-rendered single-page site that can't be read from server-delivered HTML degrades to `websiteContentUnavailable: true` rather than escalating to a headless browser — a deliberate compliance-posture choice, not a missing feature.

**BYOK enrichment never touches this actor's own PPE price.** When `hunterApiKey` and/or `peopleDataLabsApiKey` are supplied, the actor calls each provider's API using the *customer's own key*, and that provider bills the customer's account directly — never this actor's own metered price. The `byokEnrichment` output field is `null` whenever neither key was supplied.

### Input Schema & JSON Configuration Example

| Field | Type | Default | Description |
|---|---|---|---|
| `discoveryMode` | string (enum: `seedList`, `osmOverpass`) | `seedList` | seedList (Mode A): enrich the company names/domains you supply directly - zero discovery-layer risk. osmOverpass (Mode B): discover candidate businesses from OpenStreetMap's Overpass API within a bounding box (ODbL-licensed - Google Maps is intentionally excluded from discovery because its Maps/Earth Additional ToS and Maps Platform ToS both prohibit building a business-listings/mailing-list database from Maps content). |
| `seedList` | array | `[]` | Company names or website domains/URLs to enrich directly. Required (non-empty) when discoveryMode is "seedList". Mixed entries are fine - each is heuristically read as either a bare name ("Acme Corp") or a domain/URL ("acme.com", "https://acme.com"). |
| `overpassBbox` | string | *(none)* | "south,west,north,east" in decimal degrees, e.g. "50.70,-1.90,50.90,-1.30". Required when discoveryMode is "osmOverpass". Queries the public overpass-api.de mirror, which is fair-use only - budget a self-hosted Overpass instance for production volume. |
| `maxLeads` | integer (min 1, max 5000) | `50` | Hard cap on how many candidates are enriched and charged this run. |
| `includeIntentScore` | boolean | `false` | When enabled, each lead gets one Claude Haiku 4.5 call scoring hiring-page, funding-news, and tech-stack signals read only from the business's own crawled site text (always paired with a mandatory disclaimer field - a heuristic read of public text, never a verified fact). Bills the enriched\_lead PPE event ($0.015/record) instead of basic\_lead ($0.002/record). Requires this Actor's own ANTHROPIC\_API\_KEY environment variable to be configured on the Actor - this is the operator's own compute cost (priced into the Enriched Lead rate), not a customer BYOK field. |
| `hunterApiKey` | string (secret) | *(none)* | Your own Hunter.io API key. When supplied, this actor calls Hunter.io's domain-search endpoint using YOUR key - Hunter.io bills your own account directly, never this actor's own PPE price. |
| `peopleDataLabsApiKey` | string (secret) | *(none)* | Your own People Data Labs API key, used and billed the same way as hunterApiKey - your own account is charged by People Data Labs directly. |
| `skipKnownLeads` | boolean | `false` | When enabled, a lead already discovered (and charged for) in a prior run of this Actor is skipped before the enrichment waterfall runs - no repeat website crawl, no repeat BYOK/intent-score calls, and no repeat basic\_lead/enriched\_lead charge for the same business. Identity is a stable id derived from the OSM id (Mode B) or normalized name+domain (Mode A), persisted in this Actor's own key-value store across runs. Leave off (default) for a full re-enrichment on every run, e.g. if a business's own site content may have changed since last time. |

No fields are marked `required` at the schema level (conditional requirements — `seedList` for Mode A, `overpassBbox` for Mode B — are enforced by description/runtime logic, not the JSON Schema `required` array).

**Example configuration — Mode A (seed list) with intent scoring and delta mode enabled:**

```json
{
  "discoveryMode": "seedList",
  "seedList": ["acme.com", "Beta Consulting LLC", "https://gamma-industries.example"],
  "maxLeads": 100,
  "includeIntentScore": true,
  "skipKnownLeads": true
}
```

**Example configuration — Mode B (OSM Overpass discovery), basic tier only:**

```json
{
  "discoveryMode": "osmOverpass",
  "overpassBbox": "50.70,-1.90,50.90,-1.30",
  "maxLeads": 200,
  "includeIntentScore": false,
  "skipKnownLeads": true
}
```

### Output Dataset Sample & Data Dictionary

| Field | Type | Description |
|---|---|---|
| `record_id` | string | `osm:<type>/<id>` for OSM-discovered leads; a deterministic `seed:<hash>` for seed-list leads - stable across runs for the same input. |
| `event_type` | string | Always `NEW_LISTING` - this actor has no cross-run delta-tracking concept. |
| `scraped_at` | string | ISO-8601 timestamp of this enrichment. |
| `is_new` | boolean | null | `true` if this exact business (identified by OSM id, or normalized name+domain for seed-list leads) was never seen in a prior run of this Actor; `false` if it was. Tracked in this Actor's own key-value store regardless of the skipKnownLeads input - that flag only controls whether an already-known lead is skipped, not whether it's tracked. Unlike a registry-monitoring actor, this is a simple seen/not-seen signal, not a richer NEW\_LISTING/STATUS\_CHANGE/UPDATED/CLOSED classification - a business's own listing has no observable status this actor tracks. |
| `source_url` | string | null | The business's own website, when known. |
| `recipient_or_defendant_name` | string | null | Business Name (fleet-standard UMS field name; holds the discovered/supplied business's name). |
| `entity_identifier_native` | string | null | Raw OSM type/id (e.g. `node/48213456`) for OSM discovery; null for seed-list leads (no native source id exists for a customer-typed name). |
| `value_native` | string | null | Not applicable to this actor - always null. |
| `value_currency` | string | null | Not applicable to this actor - always null. |
| `value_usd_normalized` | number | null | Not applicable to this actor - always null. |
| `effective_date_iso` | string | null | Not applicable to this actor - always null. |
| `publish_date_iso` | string | null | Not applicable to this actor - always null. |
| `category_or_type` | string | null | `business_listing_osm` or `business_listing_seed`. |
| `status_or_estado` | string | null | Not applicable to this actor - always null. |
| `awarding_or_regulating_agency` | string | null | Not applicable to this actor - always null. |
| `jurisdiction` | string | `OSM` for Overpass discovery; `GLOBAL` for seed-list leads (no single jurisdiction applies). |
| `source_document_url` | string | null | Not applicable to this actor - always null. |
| `reference_number` | string | null | Not applicable to this actor - always null. |
| `discoverySource` | string (enum: `seedList`, `osm`) | Which discovery mode produced this lead. |
| `website` | string | null | The resolved website URL used for the crawl. |
| `emailsFound` | array of string | `mailto:` links and regex-matched addresses found on the crawled page(s). |
| `emailPlausible` | boolean | null | `true` when the domain has a non-null MX record set (`dns.promises.resolveMx`). `null` when no domain was available to check. |
| `emailPlausibilityMethod` | string | null (enum: `mx_record_present`, `null_mx`, `mx_lookup_failed`, `no_domain`, `null`) | Which path produced the `emailPlausible` verdict. |
| `websiteContentUnavailable` | boolean | `true` when the site could not be fetched, is disallowed by robots.txt, or looks like a client-side-rendered SPA with no server-delivered content - this actor never escalates to a headless browser. |
| `byokEnrichment` | object | null | `null` when neither hunterApiKey nor peopleDataLabsApiKey was supplied. Otherwise per-provider used/data/error using the CUSTOMER's own key - billed by that vendor to the customer directly, never to this actor's own PPE price. Sub-fields: `hunterIo` (object | null), `peopleDataLabs` (object | null). |
| `intentScore` | number | null | 0-100 heuristic buying-intent score from Claude Haiku 4.5, only when includeIntentScore was enabled and the model call succeeded. |
| `intentScoreRationale` | string | null | Free-text rationale the model gave for the score above. |
| `intentScoreDisclaimer` | string | null | Mandatory whenever intent scoring was attempted - never omitted. States this is a heuristic LLM read of public text, not a verified fact. |

**Sample dataset record** (Mode A, seed-list lead, `includeIntentScore: true`, no BYOK keys supplied):

```json
{
  "record_id": "seed:3f9a1c2b8e7d4f0a",
  "event_type": "NEW_LISTING",
  "scraped_at": "2026-09-08T14:00:00.000Z",
  "is_new": true,
  "source_url": "https://acme.com",
  "recipient_or_defendant_name": "Acme",
  "entity_identifier_native": null,
  "value_native": null,
  "value_currency": null,
  "value_usd_normalized": null,
  "effective_date_iso": null,
  "publish_date_iso": null,
  "category_or_type": "business_listing_seed",
  "status_or_estado": null,
  "awarding_or_regulating_agency": null,
  "jurisdiction": "GLOBAL",
  "source_document_url": null,
  "reference_number": null,
  "discoverySource": "seedList",
  "website": "https://acme.com",
  "emailsFound": ["contact@acme.com"],
  "emailPlausible": true,
  "emailPlausibilityMethod": "mx_record_present",
  "websiteContentUnavailable": false,
  "byokEnrichment": null,
  "intentScore": 62,
  "intentScoreRationale": "Careers page lists 3 open roles; HubSpot tag present on homepage.",
  "intentScoreDisclaimer": "Heuristic LLM-derived estimate from public website text only. Not a verified fact."
}
```

### Multi-language Integration Snippets

#### cURL

```bash
curl "https://api.apify.com/v2/acts/stefano_seggio~actor-18-b2b-lead-magnet/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "discoveryMode": "seedList",
    "seedList": ["acme.com", "Beta Consulting LLC", "https://gamma-industries.example"],
    "maxLeads": 100,
    "includeIntentScore": true,
    "skipKnownLeads": true
  }'
```

#### Python (apify-client)

```python
from apify_client import ApifyClient

client = ApifyClient(token="<APIFY_TOKEN>")

run_input = {
    "discoveryMode": "seedList",
    "seedList": ["acme.com", "Beta Consulting LLC", "https://gamma-industries.example"],
    "maxLeads": 100,
    "includeIntentScore": True,
    "skipKnownLeads": True,
}

run = client.actor("stefano_seggio/actor-18-b2b-lead-magnet").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["recipient_or_defendant_name"], item["website"], item["intentScore"])
```

#### Node.js (apify-client)

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

const client = new ApifyClient({ token: '<APIFY_TOKEN>' });

const runInput = {
    discoveryMode: 'seedList',
    seedList: ['acme.com', 'Beta Consulting LLC', 'https://gamma-industries.example'],
    maxLeads: 100,
    includeIntentScore: true,
    skipKnownLeads: true,
};

const run = await client.actor('stefano_seggio/actor-18-b2b-lead-magnet').call(runInput);

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.log(item.recipient_or_defendant_name, item.website, item.intentScore);
});
```

### Pricing Model Explanation

This actor bills on a Pay-Per-Event (PPE) model with three named events:

| Event | Price | What triggers it in this actor |
|---|---|---|
| `apify-actor-start` | $0.00005 | Standard Apify per-run start fee, charged once when the actor run begins - independent of how many leads it goes on to process. |
| `basic_lead` | $0.002/record | Charged for each lead that completes discovery, the website crawl, and the DNS/MX email-plausibility check - the full waterfall *without* the Claude intent-scoring step. |
| `enriched_lead` | $0.015/record | Charged instead of `basic_lead` for each lead that also gets the Claude Haiku 4.5 buying-intent read (triggered by setting `includeIntentScore: true`). It covers everything `basic_lead` does, plus one model call per lead. |

**Why two tiers, and what actually separates them.** Per this actor's own README, the two tiers are never blended: `basic_lead` covers "Discovery + website crawl + DNS/MX check," while `enriched_lead` covers "Everything in basic\_lead plus the Claude intent score." The split is not "old vs. new" or "two different sub-sources" — every lead in a given run goes through the identical discovery-and-crawl waterfall regardless of tier; the *only* thing that moves a lead from `basic_lead` to `enriched_lead` is whether `includeIntentScore` triggered a Claude Haiku 4.5 call for that specific record. The README states this plainly: "The LLM step costs roughly 7x the rest of the waterfall combined - kept as a separate tier so a basic run never silently absorbs that cost." In other words, the pricing tier directly mirrors the one real cost driver in this actor's architecture: whether or not an LLM call happened for that lead.

**BYOK enrichment (Hunter.io, People Data Labs) is billed outside this actor entirely.** When `hunterApiKey` and/or `peopleDataLabsApiKey` are supplied, those providers bill the customer's own account directly for that usage — it is never folded into `basic_lead` or `enriched_lead` pricing, and using BYOK enrichment does not change which of the two tiers a lead is charged at.

**What `skipKnownLeads` means for your bill.** When `skipKnownLeads: true` is set on a recurring run, a lead already discovered (and already charged for) in a prior run of this actor is skipped *before* the enrichment waterfall runs at all — no repeat website crawl, no repeat BYOK or intent-score calls. Concretely, that means an already-known, unchanged business is never delivered as a dataset record and never triggers a `basic_lead` or `enriched_lead` chargeable event on that run — it is not billed at $0, it simply never becomes a billable event in the first place, because the actor's own named key-value store recognized it and routed it out of the waterfall before any chargeable work happened. The `apify-actor-start` fee is unaffected by this and is still charged once per run regardless of how many leads end up being skipped.

# Actor input Schema

## `discoveryMode` (type: `string`):

seedList (Mode A): enrich the company names/domains you supply directly - zero discovery-layer risk. osmOverpass (Mode B): discover candidate businesses from OpenStreetMap's Overpass API within a bounding box (ODbL-licensed - Google Maps is intentionally excluded from discovery because its Maps/Earth Additional ToS and Maps Platform ToS both prohibit building a business-listings/mailing-list database from Maps content).

## `seedList` (type: `array`):

Company names or website domains/URLs to enrich directly. Required (non-empty) when discoveryMode is "seedList". Mixed entries are fine - each is heuristically read as either a bare name ("Acme Corp") or a domain/URL ("acme.com", "https://acme.com").

## `overpassBbox` (type: `string`):

"south,west,north,east" in decimal degrees, e.g. "50.70,-1.90,50.90,-1.30". Required when discoveryMode is "osmOverpass". Queries the public overpass-api.de mirror, which is fair-use only - budget a self-hosted Overpass instance for production volume.

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

Hard cap on how many candidates are enriched and charged this run.

## `includeIntentScore` (type: `boolean`):

When enabled, each lead gets one Claude Haiku 4.5 call scoring hiring-page, funding-news, and tech-stack signals read only from the business's own crawled site text (always paired with a mandatory disclaimer field - a heuristic read of public text, never a verified fact). Bills the enriched\_lead PPE event ($0.015/record) instead of basic\_lead ($0.002/record). Requires this Actor's own ANTHROPIC\_API\_KEY environment variable to be configured on the Actor - this is the operator's own compute cost (priced into the Enriched Lead rate), not a customer BYOK field.

## `hunterApiKey` (type: `string`):

Your own Hunter.io API key. When supplied, this actor calls Hunter.io's domain-search endpoint using YOUR key - Hunter.io bills your own account directly, never this actor's own PPE price.

## `peopleDataLabsApiKey` (type: `string`):

Your own People Data Labs API key, used and billed the same way as hunterApiKey - your own account is charged by People Data Labs directly.

## `skipKnownLeads` (type: `boolean`):

When enabled, a lead already discovered (and charged for) in a prior run of this Actor is skipped before the enrichment waterfall runs - no repeat website crawl, no repeat BYOK/intent-score calls, and no repeat basic\_lead/enriched\_lead charge for the same business. Identity is a stable id derived from the OSM id (Mode B) or normalized name+domain (Mode A), persisted in this Actor's own key-value store across runs. Leave off (default) for a full re-enrichment on every run, e.g. if a business's own site content may have changed since last time.

## Actor input object example

```json
{
  "discoveryMode": "seedList",
  "seedList": [],
  "maxLeads": 50,
  "includeIntentScore": false,
  "skipKnownLeads": false
}
```

# Actor output Schema

## `results` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("stefano_seggio/actor-18-b2b-lead-magnet").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("stefano_seggio/actor-18-b2b-lead-magnet").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 '{}' |
apify call stefano_seggio/actor-18-b2b-lead-magnet --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stefano_seggio/actor-18-b2b-lead-magnet"
        }
    }
}

```

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/5QufcYxRkFNHM4h8K/builds/urw9ghhJ6SPQioHCy/openapi.json
