# Biospace Jobs Scraper (`belcaidsaad/biospace-jobs-scraper`) Actor

This scraper finds biotech and pharma hiring managers who post on BioSpace.com — the specialist board most lead-gen tools ignore because it doesn't show up in Google Jobs aggregation.

- **URL**: https://apify.com/belcaidsaad/biospace-jobs-scraper.md
- **Developed by:** [Saad Belcaid](https://apify.com/belcaidsaad) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 5 total users, 4 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## BioSpace Jobs — The Niche Biotech Board Big Lead-Gen Misses

**Built for Jean (SSM) by [Saad Belcaid](https://x.com/saaborai).**

This scraper finds biotech and pharma hiring managers who post on BioSpace.com — the specialist board most lead-gen tools ignore because it doesn't show up in Google Jobs aggregation.

If you sell to biotech (CRO services, biostats, regulatory consulting, recruitment, lab services, software, equipment), the companies hiring on BioSpace are the ones nobody else is calling.

---

### The dumb-simple version

Big lead-gen tools (the ones every SDR spams) feed off Google Jobs. Google Jobs aggregates Indeed, LinkedIn, Glassdoor — but **not specialist boards like BioSpace**. So when a small biotech posts only on BioSpace, every lead-gen agency in your inbox misses them. You don't.

This scraper:

1. Reads BioSpace's job board (cookie-paginated, no scraping fragility — Madgex platform exposes job IDs cleanly)
2. Pulls the structured `JobPosting` data each listing publishes (title, company, location, description, dates)
3. **Tags every listing** with three classifiers — therapeutic area, drug modality, job function
4. Calculates hiring urgency from how long the role has been open
5. Optionally enriches each company's size via Apollo's free people-search endpoint
6. Outputs one row per listing with a one-line signal you can paste into a CRM

UK and US listings. No browser. No proxies. Just JSON-LD.

---

### Why hiring = buying

A biotech hiring a **VP of Clinical Operations** is buying CRO services within 90 days. A biotech hiring a **Head of Regulatory** is about to file an IND or BLA. A biotech hiring **Head of CMC** is scaling manufacturing — they need contract manufacturers, quality consultants, process equipment.

Every job posting is a demand signal with a 60-180 day decision window. Catch them while they're staffing up, before the role closes and the budget goes elsewhere.

---

### Read this before you run anything

**Don't scrape it all in one go. Run it daily.**

Yes, you *can* set `maxJobs: 5000` and pull all 3,000+ active BioSpace listings in one run. **Don't.** Here's why:

A biotech hiring manager who posted a role **today** picks up the phone. One who posted **30 days ago** has either filled the role, given up, or already heard from every other agency. The job's age is the dial.

| Day a role was posted | What's happening |
|---|---|
| Day 0–3 (`fresh`) | Hiring manager is excited. Calling now beats every competitor by 2 weeks. |
| Day 4–13 (`normal`) | Normal pipeline cadence. |
| Day 14–29 (`high`) | Recruiter is starting to sweat. Now they need help. |
| Day 30+ (`critical`) | They CAN'T fill it. They will pay anyone who can. **Hot.** |
| Day 60+ | Either filled or dead. Don't waste outreach. |

**Math: a daily drip is 10× more lead value than a quarterly bulk dump.**

200 fresh leads/day × 30 days = 6,000 leads, every single one in its hottest 2-week window. One bulk dump every quarter = 3,000 leads with mixed ages, half of them already cold. Daily wins.

There's exactly one reason to do a big bulk run: **the very first time**, to map the universe once and seed your CRM. After that, daily.

---

### Max-value playbook

#### THE main loop — daily drip (set this up first)

```yaml
maxJobs: 200
maxDaysOld: 7
politeDelayMs: 300
## leave filters empty for full coverage; narrow in the dataset
````

Schedule it: cron `0 9 * * 1-5` (9am UTC, Mon–Fri). Apify will run it every weekday morning. Each run pushes 100–250 fresh-this-week biotech listings into your dataset. Your CRM imports them. You call them while they're hot.

That's it. That's the system.

#### Triage in your CRM (or directly in the dataset)

| If you sell... | Filter rows by... |
|---|---|
| **CRO / clinical trial services** | `function_bucket = clinical_operations` AND `hiring_urgency ∈ {high, critical}` |
| **Regulatory consulting** | `function_bucket = regulatory_affairs` |
| **Biostats / data services** | `function_bucket ∈ {biostatistics, data_bioinformatics}` |
| **Manufacturing / CDMO** | `function_bucket = manufacturing_cmc` |
| **Recruitment / executive search** | `hiring_urgency = critical` (open 30+ days = stuck = will pay) |
| **Lab equipment / reagents** | `function_bucket = research` AND `modality ∈ {gene_therapy, cell_therapy, mrna_lnp}` |
| **Tax / legal / corp services** | `function_bucket ∈ {finance_legal, business_development}` |

#### Optional — one-time bulk seed

Only do this once, on day zero, to backfill your CRM with the existing universe. Then never again — the daily loop takes over.

```yaml
maxJobs: 5000
maxDaysOld: 30
politeDelayMs: 300
```

Wait ~45 min. Expect **2,500–3,500 rows**. Import to CRM. Then enable the daily schedule and forget this exists.

***

### Filter recipes (copy-paste)

#### "I want oncology biotech hiring this week"

```yaml
therapeuticAreas: ["oncology"]
maxDaysOld: 7
maxJobs: 300
```

#### "I want gene/cell therapy companies hiring at any function"

```yaml
modalities: ["gene_therapy", "cell_therapy", "mrna_lnp"]
maxJobs: 500
```

#### "I want struggling-to-fill clinical ops roles (sell CROs)"

```yaml
functionBuckets: ["clinical_operations"]
maxDaysOld: 60
## After: filter dataset by hiring_urgency = critical (30+ days open)
```

#### "I want UK biotech only"

```yaml
location: "United Kingdom"
maxJobs: 500
```

#### "I want commercial/BD roles at antibody companies (deal flow)"

```yaml
modalities: ["antibody_biologic"]
functionBuckets: ["business_development", "commercial"]
```

#### "I want CMC / manufacturing struggles (sell to operations)"

```yaml
functionBuckets: ["manufacturing_cmc", "quality"]
maxDaysOld: 45
```

***

### What each row tells you

| Field | Example |
|---|---|
| **`job_title`** | VP, Clinical Operations |
| **`company_name`** | Acme Therapeutics |
| `company_size` | 51-200 (with Apollo key) |
| `company_domain` | acmetx.com |
| **`therapeutic_area`** | oncology |
| **`modality`** | antibody\_biologic |
| **`function_bucket`** | clinical\_operations |
| `location` | Cambridge, Massachusetts, US |
| `locality`, `region`, `country`, `postal_code` | breakdown for filtering |
| `remote` | true / false |
| `employment_type` | FULL\_TIME |
| `salary_min`, `salary_max`, `salary_currency` | when listed |
| `date_posted`, `valid_through` | ISO dates |
| **`days_listed`** | 14 |
| **`hiring_urgency`** | fresh / normal / high / critical |
| `description_text` | full plain-text job description |
| `apply_url` | direct link to apply |
| **`signal`** | "Acme Therapeutics (antibody biologic, oncology) hiring clinical operations (VP, Clinical Operations) — open 14 days, struggling to fill" |
| `scraped_at` | ISO timestamp |

***

### Therapeutic areas (the dial for who they treat)

| Label | Catches |
|---|---|
| `oncology` | cancer, tumor, leukemia, lymphoma, melanoma, metastatic |
| `immunology` | autoimmune, lupus, allergy, asthma, atopic, psoriasis |
| `neurology_cns` | Alzheimer, Parkinson, ALS, MS, depression, epilepsy |
| `cardiovascular` | heart failure, coronary, thrombosis, hypertension |
| `metabolic` | diabetes, obesity, NASH, fatty liver, endocrine |
| `rare_disease` | orphan drug, ultra-rare |
| `ophthalmology` | retina, macular, glaucoma, vision |
| `gastroenterology` | Crohn, ulcerative colitis, IBD |
| `respiratory` | COPD, pulmonary |
| `dermatology` | skin disease |
| `infectious` | antiviral, antibiotic, HIV, hepatitis, COVID |
| `womens_health` | gynecology, fertility, menopause |
| `pediatric` | pediatric, neonatal |
| `hematology` | sickle cell, hemophilia, thalassemia |
| `nephrology` | renal, kidney, dialysis |
| `urology` | urology |

### Modalities (the dial for what they make)

| Label | Catches |
|---|---|
| `mrna_lnp` | mRNA, lipid nanoparticle |
| `gene_therapy` | AAV, CRISPR, gene editing, viral vector |
| `cell_therapy` | CAR-T, CAR-NK, allogeneic, autologous, TCR-T |
| `antibody_biologic` | mAb, bispecific, ADC, biosimilar |
| `vaccine` | vaccine, immunization, adjuvant |
| `small_molecule` | small molecule, kinase inhibitor, PROTAC |
| `oligonucleotide` | antisense, siRNA, ASO |
| `medical_device` | wearable, implantable |
| `diagnostic` | IVD, companion diagnostic, liquid biopsy |
| `digital_health` | digital therapeutic, SaMD |

### Function buckets (the dial for who you sell to)

| Label | Catches |
|---|---|
| `clinical_operations` | clinical trial, CRA, study manager |
| `regulatory_affairs` | RA, FDA submission, IND, BLA, NDA |
| `medical_affairs` | medical affairs, MSL |
| `biostatistics` | biostat, SAS programmer |
| `pharmacovigilance` | PV, drug safety |
| `quality` | QA, QC, GxP, GMP |
| `manufacturing_cmc` | CMC, process development, fermentation |
| `research` | research scientist, PI, discovery, preclinical |
| `business_development` | BD, licensing, alliance management |
| `commercial` | sales, marketing, market access, brand manager |
| `finance_legal` | CFO, general counsel, IP counsel |
| `data_bioinformatics` | bioinformatics, computational biology, ML |
| `hr_talent` | talent acquisition, HR, recruiter |

***

### Hiring urgency

| Urgency | Days listed | What it means |
|---|---|---|
| `fresh` | 0–2 | Just posted — ride the energy |
| `normal` | 3–13 | Active search |
| `high` | 14–29 | Recruiter struggling |
| `critical` | 30+ | They CAN'T fill this role — call them today |

`critical` rows are the ones to call first. A 30-day-open VP-level biotech role means the hiring manager is in pain. They will pick up your phone.

***

### Input options

| Field | Default | Description |
|---|---|---|
| `searchKeywords` | `""` | Free-text BioSpace search. e.g. "oncology", "CMC" |
| `location` | `""` | Location filter. e.g. "Cambridge, MA" |
| `maxJobs` | `200` | Cap on detail pages fetched per run |
| `maxDaysOld` | `14` | Drop listings older than N days. 0 = no age filter |
| `therapeuticAreas` | `[]` | Restrict to e.g. `["oncology","immunology"]` |
| `modalities` | `[]` | Restrict to e.g. `["gene_therapy","mrna_lnp"]` |
| `functionBuckets` | `[]` | Restrict to e.g. `["clinical_operations"]` |
| `apolloApiKey` | *(empty)* | Optional. Free Apollo key for company size enrichment |
| `politeDelayMs` | `400` | Throttle between detail fetches |

***

### How it works under the hood

- **Search**: hits `https://jobs.biospace.com/jobs/?Keywords=X&Page=N`. Each response sets a cookie `JobSearchResultIds=ID1|ID2|…|ID20` with the IDs on that page. We read the cookie — no HTML scraping needed for the listing page.
- **Detail**: each `/job/{ID}` page embeds a `<script type="application/ld+json">` block with the full schema.org `JobPosting` (title, company, location, description, dates, employment type, salary). We parse that — no DOM scrapes.
- **Classification**: deterministic keyword match on (title + description). Each rule's keyword list is curated. No AI in the hot path.
- **Enrichment**: if you pass an Apollo key, we hit `mixed_people/search` (the **free** Apollo endpoint, 0 credits) and read `organization.estimated_num_employees`. Per-company cache in memory, so no duplicate calls.
- **Polite throttling**: 400ms default delay between detail fetches. Tunable.

***

### Apollo enrichment (optional but worth it)

Add a free Apollo key to enrich every row with `company_size`, `company_domain`, `company_employee_count`. The endpoint we use (`mixed_people/search`) costs **0 credits** — Apollo's free tier is more than enough for tens of thousands of company lookups.

Sign up at [apollo.io](https://www.apollo.io) → Settings → API Keys → paste in the input.

Without it: every row still has therapeutic area, modality, function, urgency, and the signal sentence. Apollo just adds size and domain.

***

### Costs

- BioSpace: **free** (public job board, polite scraping)
- Apollo (optional): **free tier** is enough
- Apify compute: ~5–15 min per 200-job run × 1024 MB ≈ trivial CU

***

### Connector OS Station integration

Pipe the dataset into Station as the demand side. Each row's `signal` field plugs straight into the I Layer for evaluation against your supply network (CROs, regulatory consultants, biostats firms, etc.).

**Flow:** scrape → dataset → paste dataset ID into Station → match against your supply → scored introductions.

***

*Built by Saad Belcaid for Jean's SSM workflow. Data sourced from BioSpace.com (public listings) and Apollo's free People Search endpoint. Polite, no proxies, no DOM brittleness.*

# Actor input Schema

## `searchKeywords` (type: `string`):

Free-text search across BioSpace listings. e.g. 'oncology', 'clinical operations', 'CMC'. Leave empty to scrape all jobs.

## `location` (type: `string`):

City, state, or country filter. e.g. 'Cambridge, MA', 'San Diego', 'United Kingdom'. Empty = all locations.

## `maxJobs` (type: `integer`):

Cap the number of detail pages we fetch. 200 is a sensible first run.

## `maxDaysOld` (type: `integer`):

Drop listings older than N days. 14 = fresh hiring. 30 = include reposts. 0 = no age filter.

## `therapeuticAreas` (type: `array`):

Restrict to specific therapeutic areas. Empty = all. Choose from: oncology, immunology, neurology\_cns, cardiovascular, metabolic, rare\_disease, ophthalmology, gastroenterology, respiratory, dermatology, infectious, womens\_health, pediatric, hematology, nephrology, urology

## `modalities` (type: `array`):

Restrict to specific drug modalities. Empty = all. Choose from: mrna\_lnp, gene\_therapy, cell\_therapy, antibody\_biologic, vaccine, small\_molecule, oligonucleotide, medical\_device, diagnostic, digital\_health

## `functionBuckets` (type: `array`):

Restrict to specific function buckets. Empty = all. Choose from: clinical\_operations, regulatory\_affairs, medical\_affairs, biostatistics, pharmacovigilance, quality, manufacturing\_cmc, research, business\_development, commercial, finance\_legal, data\_bioinformatics, hr\_talent

## `apolloApiKey` (type: `string`):

Free Apollo key — gets you company size + domain on every row. Sign up at apollo.io, Settings → API Keys. Leave empty to skip enrichment.

## `politeDelayMs` (type: `integer`):

Throttle between detail fetches. 400ms is comfortable. Lower = faster but riskier.

## Actor input object example

```json
{
  "searchKeywords": "",
  "location": "",
  "maxJobs": 200,
  "maxDaysOld": 14,
  "therapeuticAreas": [],
  "modalities": [],
  "functionBuckets": [],
  "politeDelayMs": 400
}
```

# 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("belcaidsaad/biospace-jobs-scraper").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("belcaidsaad/biospace-jobs-scraper").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 '{}' |
apify call belcaidsaad/biospace-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=belcaidsaad/biospace-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Biospace Jobs Scraper",
        "description": "This scraper finds biotech and pharma hiring managers who post on BioSpace.com — the specialist board most lead-gen tools ignore because it doesn't show up in Google Jobs aggregation.",
        "version": "1.0",
        "x-build-id": "2hSfsGOzYrYmjSm0A"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/belcaidsaad~biospace-jobs-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-belcaidsaad-biospace-jobs-scraper",
                "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/belcaidsaad~biospace-jobs-scraper/runs": {
            "post": {
                "operationId": "runs-sync-belcaidsaad-biospace-jobs-scraper",
                "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/belcaidsaad~biospace-jobs-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-belcaidsaad-biospace-jobs-scraper",
                "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",
                "properties": {
                    "searchKeywords": {
                        "title": "Search Keywords",
                        "type": "string",
                        "description": "Free-text search across BioSpace listings. e.g. 'oncology', 'clinical operations', 'CMC'. Leave empty to scrape all jobs.",
                        "default": ""
                    },
                    "location": {
                        "title": "Location",
                        "type": "string",
                        "description": "City, state, or country filter. e.g. 'Cambridge, MA', 'San Diego', 'United Kingdom'. Empty = all locations.",
                        "default": ""
                    },
                    "maxJobs": {
                        "title": "Maximum Jobs",
                        "minimum": 10,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Cap the number of detail pages we fetch. 200 is a sensible first run.",
                        "default": 200
                    },
                    "maxDaysOld": {
                        "title": "Maximum Days Since Posting",
                        "minimum": 0,
                        "maximum": 365,
                        "type": "integer",
                        "description": "Drop listings older than N days. 14 = fresh hiring. 30 = include reposts. 0 = no age filter.",
                        "default": 14
                    },
                    "therapeuticAreas": {
                        "title": "Therapeutic Areas (filter)",
                        "type": "array",
                        "description": "Restrict to specific therapeutic areas. Empty = all. Choose from: oncology, immunology, neurology_cns, cardiovascular, metabolic, rare_disease, ophthalmology, gastroenterology, respiratory, dermatology, infectious, womens_health, pediatric, hematology, nephrology, urology",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "modalities": {
                        "title": "Modalities (filter)",
                        "type": "array",
                        "description": "Restrict to specific drug modalities. Empty = all. Choose from: mrna_lnp, gene_therapy, cell_therapy, antibody_biologic, vaccine, small_molecule, oligonucleotide, medical_device, diagnostic, digital_health",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "functionBuckets": {
                        "title": "Job Functions (filter)",
                        "type": "array",
                        "description": "Restrict to specific function buckets. Empty = all. Choose from: clinical_operations, regulatory_affairs, medical_affairs, biostatistics, pharmacovigilance, quality, manufacturing_cmc, research, business_development, commercial, finance_legal, data_bioinformatics, hr_talent",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "apolloApiKey": {
                        "title": "Apollo API Key (optional)",
                        "type": "string",
                        "description": "Free Apollo key — gets you company size + domain on every row. Sign up at apollo.io, Settings → API Keys. Leave empty to skip enrichment."
                    },
                    "politeDelayMs": {
                        "title": "Polite Delay Between Requests (ms)",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Throttle between detail fetches. 400ms is comfortable. Lower = faster but riskier.",
                        "default": 400
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
