> **Building with AI coding agents?** If you're using an AI coding agent, install the official Scalekit plugin. It gives your agent full awareness of the Scalekit API — reducing hallucinations and enabling faster, more accurate code generation.
>
> - **Claude Code**: `/plugin marketplace add scalekit-inc/claude-code-authstack` then `/plugin install <auth-type>@scalekit-auth-stack`
> - **GitHub Copilot CLI**: `copilot plugin marketplace add scalekit-inc/github-copilot-authstack` then `copilot plugin install <auth-type>@scalekit-auth-stack`
> - **Codex**: run the bash installer, restart, then open Plugin Directory and enable `<auth-type>`
> - **Skills CLI** (Windsurf, Cline, 40+ agents): `npx skills add scalekit-inc/skills --list` then `--skill <skill-name>`
>
> `<auth-type>` / `<skill-name>`: `agentkit`, `full-stack-auth`, `mcp-auth`, `modular-sso`, `modular-scim` — [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# HarvestAPI

**Authentication:** API Key
**Categories:** Crm, Sales
## What you can do

Connect this agent connector to let your agent:

- **Search search** — Search LinkedIn for leads using advanced filters including company, job title, location, seniority, industry, and experience
- **Get get** — Retrieve reactions made by a LinkedIn profile
- **Profile scrape** — Scrape a LinkedIn profile by URL or public identifier, returning contact details, employment history, education, skills, and more
- **Job scrape** — Retrieve full job listing details from LinkedIn by job URL or job ID
- **Company scrape** — Scrape a LinkedIn company page for overview, headcount, employee count range, follower count, locations, specialities, industries, and funding data
- **Profiles bulk scrape** — Batch scrape multiple LinkedIn profiles in a single request using the HarvestAPI Apify scraper

## Authentication

This connector uses **API Key** authentication. Your users provide their HarvestAPI API key once, and Scalekit stores and manages it securely. Your agent code never handles keys directly — you only pass a `connectionName` and a user `identifier`.

Before calling this connector from your code, create the HarvestAPI connection in **AgentKit** > **Connections** and copy the exact **Connection name** from that connection into your code. The value in code must match the dashboard exactly.

## Set up the connector

Register your HarvestAPI key with Scalekit so it can authenticate LinkedIn data requests on your behalf. You'll need an API key from your HarvestAPI dashboard.

> note
>
> HarvestAPI uses a pay-as-you-go credit model. Each scrape or search request consumes credits from your HarvestAPI account. Monitor your credit balance at [harvest-api.com/admin](https://harvest-api.com/admin) to avoid unexpected request failures.

1. ### Generate an API key

   - Sign in to your [HarvestAPI dashboard](https://harvest-api.com/admin/api-keys).

   - Click **Create API key**, give it a descriptive name (e.g., `My Agent`), and click **Create**.

   - Copy the generated API key. **It is shown only once** — store it securely before navigating away.

      > Image: Screenshot

2. ### Create a connection in Scalekit

   In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections** > **Create Connection**. Find **HarvestAPI** and click **Create**.

   > Image: Screenshot

3. ### Add a connected account

   Open the connection you just created and click the **Connected Accounts** tab → **Add account**. Fill in the required fields:

   - **Your User's ID** — a unique identifier for the user in your system
   - **API Key** — the key you copied in step 1

   > Image: Screenshot

   Click **Save**.

## Code examples

Once a connected account is set up, call LinkedIn data tools on behalf of any user — Scalekit injects the stored API key into every request automatically.

## Proxy API Calls

  ### Node.js

```typescript

const connectionName = 'harvestapi';  // connection name from Scalekit dashboard
const identifier = 'user_123';        // must match the identifier used when adding the connected account

// Get credentials from app.scalekit.com → Developers → API Credentials
const scalekit = new ScalekitClient(
  process.env.SCALEKIT_ENV_URL,
  process.env.SCALEKIT_CLIENT_ID,
  process.env.SCALEKIT_CLIENT_SECRET
);
const actions = scalekit.actions;

// Scrape a LinkedIn profile by URL
const profile = await actions.request({
  connectionName,
  identifier,
  path: '/linkedin/profile',
  method: 'GET',
  queryParams: { url: 'https://www.linkedin.com/in/satyanadella' },
});
console.log(profile.data);

// Search LinkedIn for people by title and location
const people = await actions.request({
  connectionName,
  identifier,
  path: '/linkedin/lead-search',
  method: 'GET',
  queryParams: { title: 'VP of Engineering', location: 'San Francisco, CA' },
});
console.log(people.data);

// Scrape a LinkedIn company page
const company = await actions.request({
  connectionName,
  identifier,
  path: '/linkedin/company',
  method: 'GET',
  queryParams: { url: 'https://www.linkedin.com/company/openai' },
});
console.log(company.data);

// Search LinkedIn job listings by keyword and location
const jobs = await actions.request({
  connectionName,
  identifier,
  path: '/linkedin/job-search',
  method: 'GET',
  queryParams: { keywords: 'machine learning engineer', location: 'New York, NY' },
});
console.log(jobs.data);

// Scrape a single job listing by URL
const job = await actions.request({
  connectionName,
  identifier,
  path: '/linkedin/job',
  method: 'GET',
  queryParams: { url: 'https://www.linkedin.com/jobs/view/1234567890' },
});
console.log(job.data);

// Bulk scrape multiple LinkedIn profiles in one request
const bulk = await actions.request({
  connectionName,
  identifier,
  path: '/v2/acts/harvestapi~linkedin-profile-scraper/run-sync-get-dataset-items',
  method: 'POST',
  body: {
    urls: [
      'https://www.linkedin.com/in/satyanadella',
      'https://www.linkedin.com/in/jeffweiner08',
      'https://www.linkedin.com/in/reidhoffman',
    ],
  },
});
console.log(bulk.data);
```

  ### Python

```python

from dotenv import load_dotenv
load_dotenv()

connection_name = "harvestapi"  # connection name from Scalekit dashboard
identifier = "user_123"         # must match the identifier used when adding the connected account

# Get credentials from app.scalekit.com → Developers → API Credentials
scalekit_client = scalekit.client.ScalekitClient(
    client_id=os.getenv("SCALEKIT_CLIENT_ID"),
    client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
    env_url=os.getenv("SCALEKIT_ENV_URL"),
)

# Scrape a LinkedIn profile by URL
profile = scalekit_client.actions.request(
    connection_name=connection_name,
    identifier=identifier,
    path="/linkedin/profile",
    method="GET",
    params={"url": "https://www.linkedin.com/in/satyanadella"}
)
print(profile)

# Search LinkedIn for people by title and location
people = scalekit_client.actions.request(
    connection_name=connection_name,
    identifier=identifier,
    path="/linkedin/lead-search",
    method="GET",
    params={"title": "VP of Engineering", "location": "San Francisco, CA"}
)
print(people)

# Scrape a LinkedIn company page
company = scalekit_client.actions.request(
    connection_name=connection_name,
    identifier=identifier,
    path="/linkedin/company",
    method="GET",
    params={"url": "https://www.linkedin.com/company/openai"}
)
print(company)

# Search LinkedIn job listings by keyword and location
jobs = scalekit_client.actions.request(
    connection_name=connection_name,
    identifier=identifier,
    path="/linkedin/job-search",
    method="GET",
    params={"keywords": "machine learning engineer", "location": "New York, NY"}
)
print(jobs)

# Scrape a single job listing by URL
job = scalekit_client.actions.request(
    connection_name=connection_name,
    identifier=identifier,
    path="/linkedin/job",
    method="GET",
    params={"url": "https://www.linkedin.com/jobs/view/1234567890"}
)
print(job)

# Bulk scrape multiple LinkedIn profiles in one request
bulk = scalekit_client.actions.request(
    connection_name=connection_name,
    identifier=identifier,
    path="/v2/acts/harvestapi~linkedin-profile-scraper/run-sync-get-dataset-items",
    method="POST",
    json={
        "urls": [
            "https://www.linkedin.com/in/satyanadella",
            "https://www.linkedin.com/in/jeffweiner08",
            "https://www.linkedin.com/in/reidhoffman"
        ]
    }
)
print(bulk)
```

## Tool list

Use the exact tool names from the **Tool list** below when you call `execute_tool`. If you're not sure which name to use, list the tools available for the current user first.

## Tool list

### `harvestapi_bulk_scrape_profiles`

Batch scrape multiple LinkedIn profiles in a single request using the HarvestAPI Apify scraper. Accepts a JSON array of LinkedIn profile URLs. Pricing: $4 per 1,000 profiles, $10 per 1,000 with email. Requires an Apify API token from https://console.apify.com/settings/integrations.

Parameters:

- `apify_token` (`string`, required): Your Apify API token from https://console.apify.com/settings/integrations.
- `profile_urls` (`array`, required): JSON array of LinkedIn profile URLs to scrape in bulk.
- `find_email` (`boolean`, optional): When true, attempts email discovery for all profiles. Costs $10 per 1,000 instead of $4.

### `harvestapi_get_ad`

Retrieve details of a specific LinkedIn ad by ad ID or URL.

Parameters:

- `ad_id` (`string`, optional): The unique identifier of the LinkedIn Ad.
- `url` (`string`, optional): The URL of the LinkedIn Ad.

### `harvestapi_get_comment_reactions`

Retrieve reactions on a specific LinkedIn comment by its URL.

Parameters:

- `url` (`string`, required): URL of the LinkedIn comment.
- `page` (`integer`, optional): Page number for pagination (default: 1).

### `harvestapi_get_company`

Retrieve the Harvest company (account) information for the authenticated user, including company name, base URI, plan type, clock format, currency, and weekly capacity settings.

Parameters:

- `account_id` (`string`, required): Your Harvest account ID, returned during OAuth as the Harvest-Account-Id header.

### `harvestapi_get_company_posts`

Retrieve posts published by a LinkedIn company page. Returns paginated post content, engagement metrics, and timestamps.

Parameters:

- `company` (`string`, optional): LinkedIn company URL. Provide this or company_universal_name.
- `company_universal_name` (`string`, optional): LinkedIn company universal name (slug from company URL).
- `page` (`integer`, optional): Page number for pagination (default: 1).

### `harvestapi_get_group`

Retrieve details of a LinkedIn group including name, description, member count, and activity by URL or group ID.

Parameters:

- `group_id` (`string`, optional): LinkedIn group ID. Provide this or url.
- `url` (`string`, optional): LinkedIn group URL. Provide this or group_id.

### `harvestapi_get_post`

Retrieve a specific LinkedIn post by its URL. Returns full post content, author details, and engagement metrics.

Parameters:

- `url` (`string`, required): The LinkedIn post URL.

### `harvestapi_get_post_comments`

Retrieve all comments on a LinkedIn post by its URL. Returns comment text, author details, and timestamps.

Parameters:

- `post` (`string`, required): The LinkedIn post URL to retrieve comments for.

### `harvestapi_get_post_reactions`

Retrieve all reactions on a LinkedIn post by its URL. Returns reaction type and reactor profile details.

Parameters:

- `post` (`string`, required): The LinkedIn post URL to retrieve reactions for.

### `harvestapi_get_profile_comments`

Retrieve comments made by a LinkedIn profile. Returns paginated results with comment content and timestamps.

Parameters:

- `page` (`integer`, optional): Page number for pagination (default: 1).
- `pagination_token` (`string`, optional): Required for pages > 1. Use token from previous page response.
- `posted_limit` (`string`, optional): Filter by maximum posted date. Options: '24h', 'week', 'month'.
- `profile` (`string`, optional): URL of the LinkedIn profile.
- `profile_id` (`string`, optional): Profile ID of the LinkedIn profile. Faster than URL lookup.

### `harvestapi_get_profile_posts`

Retrieve posts made by a specific LinkedIn profile. Returns paginated post content, engagement data, and timestamps.

Parameters:

- `page` (`integer`, optional): Page number for pagination (default: 1).
- `profile` (`string`, optional): LinkedIn profile URL. Provide this or profile_id.
- `profile_id` (`string`, optional): LinkedIn profile ID. Provide this or profile.
- `profile_public_identifier` (`string`, optional): LinkedIn public identifier (slug from profile URL).

### `harvestapi_get_profile_reactions`

Retrieve reactions made by a LinkedIn profile. Returns paginated results.

Parameters:

- `page` (`integer`, optional): Page number for pagination (default: 1).
- `pagination_token` (`string`, optional): Required for pages > 1. Use token from previous page response.
- `profile` (`string`, optional): URL of the LinkedIn profile.
- `profile_id` (`string`, optional): Profile ID of the LinkedIn profile. Faster than URL lookup.

### `harvestapi_scrape_company`

Scrape a LinkedIn company page for overview, headcount, employee count range, follower count, locations, specialities, industries, and funding data. Provide one of: company_url, universal_name, or search (company name).

Parameters:

- `company_url` (`string`, optional): Full LinkedIn company page URL. Provide this, universal_name, or search.
- `search` (`string`, optional): Company name to look up on LinkedIn. Returns the most relevant result. Provide this, company_url, or universal_name.
- `universal_name` (`string`, optional): Company universal name from the LinkedIn URL slug. Provide this, company_url, or search.

### `harvestapi_scrape_job`

Retrieve full job listing details from LinkedIn by job URL or job ID. Returns title, company, description, requirements, salary, location, workplace type, employment type, applicant count, and application details. Provide one of: job_url or job_id.

Parameters:

- `job_id` (`string`, optional): LinkedIn numeric job ID from the posting URL. Provide this or job_url.
- `job_url` (`string`, optional): Full LinkedIn job posting URL. Provide this or job_id.

### `harvestapi_scrape_profile`

Scrape a LinkedIn profile by URL or public identifier, returning contact details, employment history, education, skills, and more. Provide either profile_url or public_identifier. Use main=true for a simplified profile at fewer credits. Optionally find email with find_email=true (costs extra credits). Processing time ~2.6s (main) or ~4.9s (full).

Parameters:

- `find_email` (`boolean`, optional): When true, attempts to find the profile's email address via SMTP verification. Costs extra credits.
- `include_about_profile` (`boolean`, optional): When true, includes the 'About' section of the LinkedIn profile in the response.
- `main` (`boolean`, optional): When true, returns a simplified profile with fewer fields. Charges fewer credits than a full scrape.
- `profile_id` (`string`, optional): LinkedIn numeric profile ID. Can be used instead of profile_url or public_identifier.
- `profile_url` (`string`, optional): Full LinkedIn profile URL. Provide this or public_identifier or profile_id.
- `public_identifier` (`string`, optional): LinkedIn profile public identifier (the slug in the URL). Provide this or profile_url or profile_id.
- `skip_smtp` (`boolean`, optional): When true, skips SMTP verification when finding email. Faster but less accurate.

### `harvestapi_search_ads`

Search the LinkedIn Ad Library for ads by keyword, advertiser, country, and date range. Useful for competitive research and ad intelligence.

Parameters:

- `account_owner` (`string`, optional): LinkedIn company URL of the advertiser.
- `countries` (`string`, optional): Country codes to filter ads by, comma-separated. e.g. 'US,GB'.
- `date_option` (`string`, optional): Predefined date filter option.
- `enddate` (`string`, optional): End date for ad search in YYYY-MM-DD format.
- `keyword` (`string`, optional): Keyword to search for in ads.
- `startdate` (`string`, optional): Start date for ad search in YYYY-MM-DD format.

### `harvestapi_search_companies`

Search LinkedIn for companies using keyword, location, and company size filters. Returns paginated results with company name, description, and LinkedIn URL.

Parameters:

- `company_size` (`string`, optional): Company size range filter e.g. '1-10', '11-50', '51-200'.
- `location` (`string`, optional): Location to filter companies by.
- `page` (`integer`, optional): Page number for pagination (default: 1).
- `search` (`string`, optional): Keyword to search for companies.

### `harvestapi_search_geo`

Search for LinkedIn geo IDs by location name. Returns matching geographic location IDs used for filtering people and job searches by location.

Parameters:

- `search` (`string`, required): Location name to search for geo IDs.

### `harvestapi_search_groups`

Search LinkedIn groups by keyword. Returns paginated results with group name, description, and member count.

Parameters:

- `search` (`string`, required): Keyword to search for groups.
- `page` (`integer`, optional): Page number for pagination (default: 1).

### `harvestapi_search_jobs`

Search LinkedIn job listings by keyword, location, company, workplace type, employment type, experience level, and salary. Returns paginated job listings with title, company, location, and LinkedIn URL.

Parameters:

- `company_id` (`string`, optional): Filter by LinkedIn company ID(s), comma-separated.
- `easy_apply` (`boolean`, optional): When true, filter to jobs with LinkedIn Easy Apply only.
- `employment_type` (`string`, optional): Filter by employment type. Accepted values: full-time, part-time, contract, temporary, internship (comma-separated).
- `experience_level` (`string`, optional): Filter by experience level. Accepted values: internship, entry, associate, mid-senior, director, executive (comma-separated).
- `location` (`string`, optional): Filter by job location text (city, country, or region).
- `page` (`integer`, optional): Page number for pagination (default: 1).
- `posted_limit` (`string`, optional): Filter by recency of posting. Accepted values: 24h, week, month.
- `salary` (`string`, optional): Minimum salary filter. Accepted values: 40k+, 60k+, 80k+, 100k+, 120k+, 140k+, 160k+, 180k+, 200k+.
- `search` (`string`, optional): Job title or keyword to search for.
- `sort_by` (`string`, optional): Sort results by relevance or date.
- `workplace_type` (`string`, optional): Filter by workplace type. Accepted values: office, hybrid, remote (comma-separated).

### `harvestapi_search_leads`

Search LinkedIn for leads using advanced filters including company, job title, location, seniority, industry, and experience. Supports LinkedIn Sales Navigator URLs.

Parameters:

- `company_headcount` (`string`, optional): Filter by company size e.g. '1-10', '11-50', '51-200'.
- `current_companies` (`string`, optional): Filter by current company IDs or URLs (max 50, comma-separated).
- `current_job_titles` (`string`, optional): Filter by current job titles (max 70, comma-separated).
- `first_names` (`string`, optional): Filter by first names (max 70, comma-separated).
- `geo_ids` (`string`, optional): LinkedIn Geo IDs for location filtering. Overrides locations.
- `industry_ids` (`string`, optional): Filter by industry IDs (max 70, comma-separated).
- `last_names` (`string`, optional): Filter by last names (max 70, comma-separated).
- `locations` (`string`, optional): Location text filter (max 70, comma-separated).
- `page` (`integer`, optional): Page number for pagination (default: 1, max: 100).
- `past_companies` (`string`, optional): Filter by past company IDs or URLs (max 50, comma-separated).
- `past_job_titles` (`string`, optional): Filter by past job titles (max 70, comma-separated).
- `recently_changed_jobs` (`boolean`, optional): Filter for people who recently changed jobs.
- `sales_nav_url` (`string`, optional): LinkedIn Sales Navigator URL to use as search override.
- `search` (`string`, optional): Search query supporting LinkedIn operators.
- `seniority_level_ids` (`string`, optional): Filter by seniority level IDs (comma-separated).
- `years_of_experience_ids` (`string`, optional): Filter by years of total experience IDs.

### `harvestapi_search_people`

Search LinkedIn for people using filters such as job title, current company, location, and industry. Uses LinkedIn Lead Search for unmasked results. Returns paginated profiles with name, title, location, and LinkedIn URL. All parameters are optional and comma-separated for multiple values.

Parameters:

- `company_headcount` (`string`, optional): Company headcount range filter, comma-separated (e.g. '1-10,11-50').
- `current_companies` (`string`, optional): Current company IDs or LinkedIn URLs, comma-separated (max 50).
- `current_job_titles` (`string`, optional): Current job titles, comma-separated (max 70). e.g. 'CTO,VP Engineering'
- `first_names` (`string`, optional): First names to filter by, comma-separated (max 70).
- `industry_ids` (`string`, optional): LinkedIn industry IDs, comma-separated (max 70).
- `last_names` (`string`, optional): Last names to filter by, comma-separated (max 70).
- `locations` (`string`, optional): Location text, comma-separated (max 70). e.g. 'San Francisco,New York'
- `page` (`integer`, optional): Page number for pagination (default: 1, max: 100).
- `search` (`string`, optional): Fuzzy keyword search across name, title, and company. Supports LinkedIn search operators.
- `seniority_level_ids` (`string`, optional): LinkedIn seniority level IDs, comma-separated.

### `harvestapi_search_posts`

Search LinkedIn posts by keyword, company, profile, or group. Supports filtering by post age and sorting. Returns paginated results with post content, author, and engagement data.

Parameters:

- `authors_company` (`string`, optional): Filter posts by the author's current company URL.
- `company` (`string`, optional): LinkedIn company URL to filter posts by.
- `company_id` (`string`, optional): LinkedIn company ID to filter posts by.
- `group` (`string`, optional): LinkedIn group URL to filter posts by.
- `page` (`integer`, optional): Page number for pagination (default: 1).
- `posted_limit` (`string`, optional): Filter by post age. e.g. 'past-24h', 'past-week', 'past-month'.
- `profile` (`string`, optional): LinkedIn profile URL to filter posts by.
- `profile_id` (`string`, optional): LinkedIn profile ID to filter posts by.
- `search` (`string`, optional): Keyword to search for in posts.
- `sort_by` (`string`, optional): Sort results by 'relevance' or 'date'.

### `harvestapi_search_services`

Search LinkedIn profiles offering services by name, location, or geo ID. Returns paginated results.

Parameters:

- `search` (`string`, required): Search profiles by service name or keyword.
- `geo_id` (`string`, optional): Filter by LinkedIn Geo ID. Overrides the location parameter.
- `location` (`string`, optional): Filter by location text.
- `page` (`integer`, optional): Page number for pagination (default: 1).


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
