# API key
Source: https://docs.pipecorn.com/api-reference/API-key
Where to generate the API key that authenticates every request.
## Get my API key
You need your personal API key to use the Pipecorn API, which you can generate [here](https://app.pipecorn.com/settings/apis/keys).
# Create a new list
Source: https://docs.pipecorn.com/api-reference/create-a-new-list
/api-reference/specs/list.json post /lists
Creates a new list in the system.
# Credits vs limits
Source: https://docs.pipecorn.com/api-reference/credits-vs-limits
Enrichment credits are a paid balance you spend. Plan limits are quotas included in your plan. They are tracked, exhausted, and refilled differently.
Pipecorn meters usage with two separate mechanisms that are easy to confuse,
partly because the `GET /credits` response uses the word "credits" for both.
This page tells them apart so you know which one a request draws on, which one
an error is about, and what actually unblocks you.
**One-line version.** A **credit** is a paid unit you spend on enrichment
(emails, phones, company and people data). A **limit** is a quota bundled
with your plan that caps how many profiles or companies you can extract per
day or month. Buying credits never raises a limit, and a limit resetting
never adds credits.
## Side by side
| | Enrichment credits | Plan limits |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| What it is | A prepaid balance owned by your workspace | Daily and monthly quotas included in your plan |
| What draws on it | Enrichment: waterfall email and phone, account and people enrichment, hiring and tech-stack lookups, WhatsApp validation | Extraction: pulling people profiles or importing companies from a search, a Sales Navigator URL, or a post |
| Unit | Credits per result (for example 3 per email, 30 per phone, 1 per enriched company) | One profile or one company per unit |
| How it goes down | Spent per successful result. A lookup that resolves nothing costs nothing | Consumed per extracted profile or imported company |
| How it goes back up | Buy credits, or wait for your plan renewal to add the plan's monthly allocation | Resets automatically: daily quotas every day, the monthly company quota every month |
| How to get more | [Top up](https://app.pipecorn.com/settings/subscriptions/credits) at any time | Upgrade your plan, or contact support |
| Where to check | `credits.enrichment` in [`GET /credits`](/api-reference/endpoints/miscellaneous/account-credits), or [`GET /credits_consumption`](/api-reference/endpoints/miscellaneous/credit-consumption) for a date range | `credits.daily_profile_scraping`, `credits.daily_company_import`, `credits.monthly_company_import` (remaining) and `limits.*` (ceiling) in `GET /credits` |
| Error when exhausted | `402 Payment Required`, `code: "insufficient_credits"`, with a `top_up_url` | `422 Unprocessable Entity`, message `"Can't proceed with the request. Plan limit reached."` |
Preview endpoints (`/leads/advanced_search/preview`, `/accounts/search/preview`,
`/intents/accounts/stack/preview`) draw on neither. They are free and never
return either error.
## Enrichment credits
Credits are the paid resource. Every endpoint that returns enriched data checks
your balance before doing any work and charges only for what it actually
returns:
* Waterfall enrichment: **3 credits** per email, **30 credits** per phone
([single](/api-reference/endpoints/enrichments/single),
[bulk](/api-reference/endpoints/enrichments/batch),
[synchronous](/api-reference/endpoints/contacts/sync_single_enrich))
* [Enrich account](/api-reference/endpoints/accounts/single) and
[Enrich people](/api-reference/endpoints/leads/single): **1 credit** per
resolved company or person
* [Company hiring](/api-reference/endpoints/accounts/company-hiring): **1 credit**
per job returned
* [Company stack](/api-reference/endpoints/accounts/company-stack),
[hiring intent](/api-reference/endpoints/signals/hiring) and
[tech-stack search](/api-reference/endpoints/signals/tech_stack) (**3 credits**
per imported company)
* WhatsApp validation
When the balance is too low the request is rejected up front with `402` and
nothing is spent, enqueued, or imported. Top up and replay the same request.
Credits belong to the workspace, so every member and every API key spends
from the same pool.
## Plan limits
Limits are quotas, not a balance. They come with your plan, reset on a fixed
schedule, and cannot be bought one at a time. There are two of them:
* **Profile scraping** (daily): how many people profiles you can extract per
day. Drawn on by lead extraction, such as
[search leads by filters](/api-reference/endpoints/leads/advanced_search),
[extract leads from a Sales Navigator URL](/api-reference/endpoints/extract/leads),
[leads in a company](/api-reference/endpoints/extract/leads_from_company), and
[post engagers](/api-reference/endpoints/signals/post_engagers).
* **Company import** (daily and monthly): how many companies you can import
per day and per month. Drawn on by account extraction, such as
[search accounts by filters](/api-reference/endpoints/accounts/search),
[extract accounts from a Sales Navigator URL](/api-reference/endpoints/extract/accounts),
[lookalike companies](/api-reference/endpoints/signals/company_lookalike), and
[growth signals](/api-reference/endpoints/signals/growth).
When a quota is used up the endpoint answers `422` with
`"Can't proceed with the request. Plan limit reached."`. Wait for the reset
or move to a plan with a higher allowance. Buying credits does nothing here.
In `GET /credits` the remaining quotas live under the `credits` key, next to
`credits.enrichment`, and the field descriptions call them "credits". Read
them as **remaining quota for the current period**, not as a spendable
balance. Only `credits.enrichment` is money you can top up. The `limits`
object gives each quota's ceiling so you can compute how much of the period
you have used.
```json theme={null}
{
"credits": {
"enrichment": 3000,
"daily_profile_scraping": 1500,
"daily_company_import": 1000,
"monthly_company_import": 10000
},
"limits": {
"daily_profile_scraping": 2500,
"daily_company_import": 1000,
"monthly_company_import": 10000
}
}
```
In this example the workspace has 3,000 enrichment credits to spend, and can
still extract 1,500 of its 2,500 daily profiles.
## Two other "limits" that are not plan limits
### Workspace weekly credit limit
A workspace admin can cap how many **enrichment credits** each member may
spend per week. This is a spending ceiling on credits, not a quota on
extraction. Hitting it returns `403 Forbidden` with
`code: "workspace_limit_exceeded"` and no `top_up_url`: the balance may be
fine, so buying credits does not help. An admin raises the member's weekly
allowance, or the limit resets at the end of the week.
### Rate limits
Requests per second or per minute, tracked per API key and per endpoint.
Exceeding one returns `429 Too Many Requests`. Rate limits are about request
pacing and have nothing to do with credits or quotas; back off and retry.
## Which one am I hitting?
Branch on the status code and, for `403`, on the `code` field.
| Response | What ran out | What unblocks it |
| --------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| `402` with `code: "insufficient_credits"` | Enrichment credit balance | Top up at `top_up_url`, or wait for plan renewal, then retry |
| `403` with `code: "workspace_limit_exceeded"` | Weekly credit spending cap for this member | Workspace admin raises the allowance, or the week resets |
| `403` with any other body | Nothing ran out: the API key lacks access to the endpoint | Use a key with the right permissions |
| `422` with `"Plan limit reached."` | Daily profile scraping or daily/monthly company import quota | Wait for the reset, or upgrade the plan |
| `429` | Request rate for this endpoint | Back off and retry |
For the exact response bodies and the list of endpoints that return each code,
see [Credit and limit errors](/api-reference/errors).
**History.** Until August 2026, enrich account and enrich people drew on the
company import and profile scraping quotas and failed with `422` when they
ran out. They are now priced in credits and answer `402` and `403` instead.
See the [changelog](/changelog).
# Company hiring (job postings)
Source: https://docs.pipecorn.com/api-reference/endpoints/accounts/company-hiring
POST /accounts/company_hiring
Retrieve the list of open job postings for a given company
Get the list of open job postings indexed for a company using one company identifier (domain, company name, or LinkedIn URL). Results are sourced from TheirStack.
## Credits and rate limits
* Credits: **1 credit per job returned**. You are only charged for the jobs actually returned, and never for more jobs than your available credits allow. A lookup that returns no jobs costs nothing.
* Rate limit: **5 requests per second** per user
If your balance cannot cover the lookup, the request is rejected with `402
Payment Required` and `code: "insufficient_credits"` before any job is fetched.
A workspace weekly credit limit returns `403 Forbidden` with
`code: "workspace_limit_exceeded"` instead. See
[Credit and limit errors](/api-reference/errors).
## Required identification
Provide at least one of:
* `company_domain`
* `company_name`
* `company_linkedin_url`
If none are provided, the API returns:
```json theme={null}
{
"error": 400,
"message": "Provide at least one of: company_domain, company_name, company_linkedin_url"
}
```
## Optional parameters
* `posted_within_days`: Only return jobs posted within the last N days. Must be one of the selectable look-back windows: `7`, `30`, `60`, `90`, or `180`. Defaults to `30` when omitted; any other value returns `422`.
* `limit`: Maximum number of jobs to return, a positive integer capped at **100**. Because billing is per job, use this to bound how many credits a single lookup can spend. Only enough pages to satisfy the limit are fetched.
* `full_description`: When `true`, return each job's full description. Defaults to `false`, in which case descriptions are truncated to a 300-character snippet.
* `job_title_keywords`: Array of strings. Only return jobs whose title matches one of these keywords.
* `excluded_job_title_keywords`: Array of strings. Exclude jobs whose title matches one of these keywords.
* `job_description_keywords`: Array of strings. Only return jobs whose description contains one of these keywords.
* `excluded_job_description_keywords`: Array of strings. Exclude jobs whose description contains one of these keywords.
* `job_country_codes`: Array of 2-letter ISO 3166-1 alpha-2 country codes (e.g. `US`, `FR`). Only return jobs located in these countries. Codes are case-insensitive.
* `excluded_job_country_codes`: Array of 2-letter ISO 3166-1 alpha-2 country codes. Exclude jobs located in these countries.
Each keyword filter must be an array of strings, otherwise the API returns `422`. Invalid country codes also return `422`.
## Example request
```json theme={null}
{
"company_domain": "notion.so",
"posted_within_days": 30,
"limit": 10,
"full_description": false,
"job_title_keywords": ["engineer", "developer"],
"excluded_job_title_keywords": ["intern"],
"job_country_codes": ["US", "FR"]
}
```
## Example response
The `truncated` flag is `true` when more jobs matched than were returned (because of the `limit`, the 100-job ceiling, or your available credits).
```json theme={null}
{
"total_jobs": 42,
"truncated": true,
"company": {
"name": "Acme",
"domain": "acme.com",
"linkedin_url": "https://linkedin.com/company/acme"
},
"jobs": [
{
"job_title": "Senior Backend Engineer",
"job_url": "https://example.com/jobs/1",
"job_location": "Paris France",
"employment_statuses": ["full_time"],
"date_posted": "2026-05-30",
"description": "Build cool stuff with Rails.",
"hiring_team": [
{
"name": "Alice Doe",
"title": "Engineering Manager",
"linkedin_url": "https://linkedin.com/in/alice"
}
]
}
]
}
```
# Company stack (technographics)
Source: https://docs.pipecorn.com/api-reference/endpoints/accounts/company-stack
POST /accounts/company_stack
Retrieve a company technology stack
Get a company's technology stack using one company identifier (domain, company name, or LinkedIn URL).
## Credits and rate limits
* Credits: **3 credits** per request
* Rate limit: **20 requests per second** per user
If your balance is below 3 credits, the request is rejected with `402 Payment
Required` and `code: "insufficient_credits"` before the provider is called. A
workspace weekly credit limit returns `403 Forbidden` with
`code: "workspace_limit_exceeded"` instead. See
[Credit and limit errors](/api-reference/errors).
## Required identification
Provide at least one of:
* `company_domain`
* `company_name`
* `company_linkedin_url`
If none are provided, the API returns:
```json theme={null}
{
"error": 400,
"message": "Provide at least one of: company_domain, company_name, company_linkedin_url"
}
```
## Example request
```json theme={null}
{
"company_name": "Notion",
"company_domain": "notion.so",
"company_linkedin": "https://www.linkedin.com/company/notionhq/"
}
```
## Example response
```json theme={null}
{
"technologies": ["Amazon Web Services", "React", "Segment"],
"technologies_with_confidence": [
{ "name": "Amazon Web Services", "confidence": 0.97 },
{ "name": "React", "confidence": 0.93 },
{ "name": "Segment", "confidence": 0.74 }
]
}
```
# # people at company
Source: https://docs.pipecorn.com/api-reference/endpoints/accounts/count-profiles
POST /accounts/count_profiles
Count matching profiles based on job titles and locations.
**Rate limit:** 2 requests per minute
# Count Profiles
The Count Profiles endpoint allows you to count the number of employee profiles matching specific criteria for a company. You can filter by job titles and locations to get precise counts of potential prospects.
## Required Parameters
You must provide one of the following to identify the target company:
* `company_linkedin_id`: The LinkedIn company identifier
* `company_linkedin_url`: The full URL of the company's LinkedIn profile (regular or Sales Navigator)
## Location IDs Reference
Location IDs used in this endpoint can be retrieved using the [Location Ids endpoint](/api-reference/endpoints/miscellaneous/location-ids). Simply provide a location name (e.g., "San Francisco") and the API will return all matching locations with their IDs.
## Request Example
```json theme={null}
{
"company_linkedin_id": "1234567", // Required if company_linkedin_url is not provided
"title_to_include": ["Software Engineer", "Developer"],
"title_to_exclude": ["Junior"],
"included_locations": ["105015875", "102221843"],
"excluded_locations": ["103644278"]
}
```
Alternative company identification:
```json theme={null}
{
"company_linkedin_url": "https://www.linkedin.com/company/microsoft", // Required if company_linkedin_id is not provided
// ... other parameters ...
}
```
## Response Example
```json theme={null}
{
"total": 26,
"title_to_include": ["Software Engineer", "Developer"],
"title_to_exclude": ["Junior"],
"included_locations": ["105015875", "102221843"],
"excluded_locations": ["103644278"]
}
```
## Understanding the Response
* `total`: The total number of profiles matching your criteria
* `title_to_include`: List of job titles that were included in the search
* `title_to_exclude`: List of job titles that were excluded from the search
* `included_locations`: List of Location IDs that were included
* `excluded_locations`: List of Location IDs that were excluded
## Tips
* Use location IDs to target specific geographic areas
* Combine title inclusions and exclusions to refine your search
* Keep your title filters relevant to ensure accurate results
# Department headcount
Source: https://docs.pipecorn.com/api-reference/endpoints/accounts/headcount
POST /accounts/headcount
Retrieve headcount information for specified departments or all departments if none specified.
By default the data comes live from LinkedIn (`live: true`) and includes 3/6/12-month evolution per department, as documented below. Set `live: false` to answer from Pipecorn's companies database (Elasticsearch) instead, with no integration required. The `live: false` response is a current snapshot only (no evolution) in a different shape:
```json
{
"total_headcount": 18769,
"departments": {
"Engineering": { "current_headcount": 8681 },
"Sales": { "current_headcount": 6258 }
}
}
```
**Rate limit:** 2 requests per minute
# Search accounts by filters
Source: https://docs.pipecorn.com/api-reference/endpoints/accounts/search
POST /accounts/search
Search and extract company accounts based on industry, location, size, and keyword filters
Search and extract company accounts using powerful filters including industry, location, company size, and keywords. This endpoint processes results asynchronously and sends enriched account data to your webhook URL.
## Overview
This endpoint allows you to search for companies based on various criteria without needing to provide a LinkedIn Sales Navigator URL. The process is asynchronous - you'll receive an immediate response with the import job details and a preview of matching accounts, and the complete enriched results will be sent to your webhook URL when processing is complete.
## Rate Limits
* **1 request per second** per user/IP address
## Search Filters
### Industries
Target or exclude specific industries using industry IDs. Multiple industry IDs are combined with OR logic.
**Parameters:**
* `included_industries`: Array of industry IDs to target
* `excluded_industries`: Array of industry IDs to exclude from results
For the complete list of industry IDs, see the [LinkedIn Industry List](https://docs.google.com/spreadsheets/d/1qTFPVfcSHnL5PU1AcQlzD8mCmfSICKJ4WuU-OBGhkdI/edit?gid=0#gid=0).
Common industry IDs include:
* `4` - Automotive
* `6` - Technology, Information and Internet
* `12` - Education
* `43` - Financial Services
* `96` - Software Development
### Locations
Use the [Location IDs endpoint](/api-reference/endpoints/miscellaneous/location-ids) to find valid location IDs. You can include or exclude specific locations:
* `included_locations`: Target specific countries, states, or cities
* `excluded_locations`: Exclude specific locations from results
### Company Size
Filter by employee count ranges:
* `1-10` - Startup/Very Small
* `11-50` - Small
* `51-200` - Medium
* `201-500` - Medium-Large
* `501-1000` - Large
* `1001-5000` - Very Large
* `5001-10000` - Enterprise
* `10001+` - Mega Corporation
Multiple size ranges can be used
### Keyword
Search for companies by keyword in their name or description. This is useful for targeting specific niches or technologies (e.g., "saas", "fintech", "healthcare").
### Revenue
Filter companies by their annual revenue range. Revenue values are specified in millions and can be combined with a currency code.
**Parameters:**
* `min_revenue`: Minimum annual revenue (in millions). Valid values: `0`, `0.5`, `1`, `2.5`, `5`, `10`, `20`, `50`, `100`, `500`, `1000`
* `max_revenue`: Maximum annual revenue (in millions). Valid values: `0.5`, `1`, `2.5`, `5`, `10`, `20`, `50`, `100`, `500`, `1000`, `1001` (where `1001` represents \$1B+)
* `revenue_currency`: Currency code for revenue values. Defaults to `USD` if not specified.
**Supported currencies:**
`USD`, `EUR`, `GBP`, `CAD`, `AUD`, `JPY`, `CNY`, `INR`, `BRL`, `SEK`, `NOK`, `DKK`, `SGD`, `HKD`, `NZD`, `THB`, `IDR`, `TRY`, `TWD`, `ILS`, `AED`, `RUB`
**Example:** To find companies with revenue between $10M-$50M:
```json theme={null}
{
"min_revenue": 10,
"max_revenue": 50,
"revenue_currency": "USD"
}
```
## Limits
By default, the endpoint will process up to 1,000 matching accounts. You can set a lower limit using the `limit` parameter. The minimum of your specified limit and 1,000 will be used.
## Streaming Mode
When `streaming` is set to `true`, results will be sent to your webhook in batches as they are processed, rather than all at once when complete. This is useful for large searches where you want to start processing results immediately.
## Response
The endpoint returns immediately with:
* A unique import job ID for tracking
* The total number of accounts that will be processed
* A preview of the first 10 matching accounts
The complete enriched results will be sent to your webhook URL when processing is complete.
## Example Use Cases
### Find SaaS companies in US tech hubs
```json theme={null}
{
"webhook_url": "https://your-webhook.com/accounts",
"name": "US Tech SaaS Companies",
"included_industries": ["6", "96"],
"included_locations": ["103644278"],
"company_size": ["51-200", "201-500"],
"keyword": "saas"
}
```
### Target European fintech startups
```json theme={null}
{
"webhook_url": "https://your-webhook.com/accounts",
"name": "European Fintech Startups",
"included_industries": ["43"],
"included_locations": ["100506914", "105015875", "101165590"],
"company_size": ["11-50", "51-200"],
"limit": 500
}
```
### Find large automotive companies excluding specific regions
```json theme={null}
{
"webhook_url": "https://your-webhook.com/accounts",
"name": "Global Automotive Giants",
"included_industries": ["4"],
"excluded_locations": ["102221843"],
"company_size": ["5001-10000", "10001+"]
}
```
### Find high-revenue tech companies in Europe
```json theme={null}
{
"webhook_url": "https://your-webhook.com/accounts",
"name": "High Revenue European Tech",
"included_industries": ["6", "96"],
"included_locations": ["100506914", "105015875"],
"min_revenue": 100,
"max_revenue": 1001,
"revenue_currency": "EUR"
}
```
# Preview
Source: https://docs.pipecorn.com/api-reference/endpoints/accounts/search_preview
POST /accounts/search/preview
Synchronously preview the first 25 matches and the total estimated count for a set of account search filters, without creating an import or consuming credits.
Run the same filters as [`POST /accounts/search`](/api-reference/endpoints/accounts/search) and get back a synchronous **preview**: the total estimated account count plus the first **25** matching companies. Use it to validate filters and size an audience before kicking off the real search.
## Overview
Compared to `POST /accounts/search`, the preview:
* Does **not** create an import job.
* Does **not** call your webhook.
* Does **not** consume credits.
* Does **not** require `webhook_url`.
The body accepts the exact same filter parameters as the regular account search — see [Search accounts by filters](/api-reference/endpoints/accounts/search) for the full reference (`included_industries`, `excluded_industries`, `included_locations`, `excluded_locations`, `company_size`, `keyword`, `min_revenue`, `max_revenue`, `revenue_currency`, …). `webhook_url`, `name`, `limit`, and `streaming` are accepted but ignored: the response always contains up to 25 accounts.
## Rate Limits
* **1 request per second** per user/IP address.
## Response
`200 OK` — returns immediately with:
```json theme={null}
{
"total_count": 4321,
"preview": [
{
"company_name": "Pipecorn",
"industry": "Technology, Information and Internet",
"linkedin_id": "104885158",
"linkedin_url": "https://www.linkedin.com/company/104885158"
}
]
}
```
| Field | Type | Notes |
| ------------- | ---------------- | --------------------------------------------------------------------------------------- |
| `total_count` | integer | Total estimated number of accounts matching the filters (not capped to 25). |
| `preview` | array of objects | Up to 25 matching accounts. Each entry contains the fields listed above when available. |
## Example
```json theme={null}
{
"included_industries": ["6", "96"],
"included_locations": ["103644278"],
"company_size": ["51-200", "201-500"],
"keyword": "saas"
}
```
# Enrich account
Source: https://docs.pipecorn.com/api-reference/endpoints/accounts/single
POST /accounts/single_enrich
Enrich a single company account with firmographic data.
**Credits:** 1 credit per enrichment. You are only charged when a company is actually resolved — a lookup that matches nothing costs nothing.
Identify the company with any of `company_linkedin_url`, `domain` or `name`. The more you provide, the more precisely the account is matched.
# Find Enrichment result
Source: https://docs.pipecorn.com/api-reference/endpoints/contacts/single_enrich
GET /contacts/{id}
Retrieve enrichment results for a single contact
# Synchronous Single Contact Enrichment
Source: https://docs.pipecorn.com/api-reference/endpoints/contacts/sync_single_enrich
sync-enrichments POST /contacts/single_enrich
Enrich a single contact with email, phone, and/or personal email data and get results instantly
Enrich a single contact with email, phone, and/or personal email data using our waterfall enrichment system. Unlike the async enrichment endpoint, this endpoint returns results **synchronously** in the response - no webhook polling required.
## Overview
This endpoint performs real-time waterfall enrichment across multiple data providers to find the most accurate email, phone number, and/or personal email for a contact. Results are returned immediately in the API response, making it ideal for interactive applications, Chrome extensions, and real-time workflows.
## Rate Limits
* **50 requests per second** per user
This generous rate limit makes it suitable for high-volume interactive use cases while protecting our infrastructure.
## Enrichment Types
You can specify which data points you want to enrich by passing the `enrichment_type` array parameter:
* `["email"]` - Find and validate professional email addresses only
* `["phone"]` - Find phone numbers only
* `["personal_email"]` - Find personal email addresses only (requires user consent — see below)
* Any combination, e.g. `["email", "phone"]`, `["email", "personal_email"]`, or `["email", "phone", "personal_email"]`
Requesting `personal_email` requires the authenticated user to have consented
to personal email enrichment in their account settings. If consent is missing,
the API responds with `422 Unprocessable Entity` and the message
`"You can't use the personal email enrichment feature without consenting with our terms of use"`.
This consent gate is required for GDPR compliance.
Requests including `phone` or `personal_email` must include `linkedin_url`.
### Waterfall Enrichment
When you request multiple enrichment types, our system uses a sophisticated waterfall approach:
1. Attempts to find the professional email from the most reliable providers first
2. Searches for personal email through dedicated personal-email providers (Pipecorn, LeadMagic, Airscale)
3. Searches for phone numbers using provider prioritization
4. Returns results as soon as all requested data points are found or all providers are exhausted
This approach maximizes data quality while minimizing enrichment time and cost.
## Response Format
### Success Response
When enrichment succeeds, you'll receive a 200 response with the enriched data:
**Email Only:**
```json theme={null}
{
"enrichment_id": "123e4567-e89b-12d3-a456-426614174000",
"first_name": "Mathieu",
"last_name": "Brun-Picard",
"linkedin_profile_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"status": "success",
"email": "mathieu@prontohq.com",
"email_status": "valid"
}
```
**Phone Only:**
```json theme={null}
{
"enrichment_id": "123e4567-e89b-12d3-a456-426614174000",
"first_name": "Mathieu",
"last_name": "Brun-Picard",
"linkedin_profile_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"status": "success",
"phones": [
"+33612345678"
],
"phone_status": "valid"
}
```
**Email and Phone:**
```json theme={null}
{
"enrichment_id": "123e4567-e89b-12d3-a456-426614174000",
"first_name": "Mathieu",
"last_name": "Brun-Picard",
"linkedin_profile_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"status": "success",
"email": "mathieu@prontohq.com",
"email_status": "valid",
"phones": [
"+33612345678"
],
"phone_status": "valid"
}
```
**Personal Email Only:**
```json theme={null}
{
"enrichment_id": "123e4567-e89b-12d3-a456-426614174000",
"first_name": "Mathieu",
"last_name": "Brun-Picard",
"linkedin_profile_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"status": "success",
"personal_email": "mathieu.bp@gmail.com",
"personal_email_status": "valid"
}
```
### Error Response
When no data is found, the response includes a message and empty data fields:
```json theme={null}
{
"enrichment_id": "123e4567-e89b-12d3-a456-426614174000",
"first_name": "Mathieu",
"last_name": "Brun-Picard",
"linkedin_profile_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"status": "error",
"message": "No email or phone found for this profile",
"email": null,
"email_status": "N/A",
"phones": [],
"phone_status": "not_found"
}
```
## Required Fields
`enrichment_type` is always required — an array containing any combination of
`"email"`, `"phone"`, and/or `"personal_email"`. The other required fields
depend on which types you request:
| `enrichment_type` value | Additional required fields |
| ----------------------- | ----------------------------------------------------------------------------------- |
| `"email"` | `firstname`, `lastname`, **and** one of `linkedin_url`, `domain`, or `company_name` |
| `"phone"` | `linkedin_url` |
| `"personal_email"` | `linkedin_url` |
`firstname`/`lastname` are only needed when you request `"email"`; phone and
personal email run off the `linkedin_url` alone.
When you request a combination, the requirements add up — but a single
`linkedin_url` satisfies the identifier requirement for all three types. For
example, `["email", "phone"]` needs `firstname`, `lastname`, and a
`linkedin_url` (the `linkedin_url` covers both the email and phone steps).
## Recommended Fields
Beyond the required fields, supplying more context improves accuracy:
* `linkedin_url` - LinkedIn profile URL (highly recommended for accuracy; on its own it satisfies every enrichment type)
* `domain` / `company_name` - Company context that improves professional email matching when you don't have a `linkedin_url`.
The more context you provide, the higher the accuracy of the enrichment.
## Custom Fields
You can include custom fields that will be returned in the response:
```json theme={null}
{
"firstname": "Mathieu",
"lastname": "Brun-Picard",
"linkedin_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"enrichment_type": ["email"],
"custom": {
"crm_id": "12345",
"campaign": "outbound_q1",
"segment": "enterprise"
}
}
```
These custom fields are passed through unchanged and returned in the `custom` field of the response, making it easy to correlate results with your internal systems.
## Email Status Values
The `email_status` field indicates the validation state of the email:
* `deliverable` - Email is deliverable
* `catch-all` - Email hasa catch-all status but was validated by our debouncing waterfall
* `N/A` - Email enrichment was not requested or no email was found
## Personal Email Status Values
The `personal_email_status` field indicates the validation state of the personal email:
* `valid` - Personal email was found and validated
* `invalid` - Personal email enrichment ran but the result is not deliverable
* `N/A` - Personal email enrichment was not requested or no personal email was found
## Phone Status Values
The `phone_status` field indicates whether valid phone numbers were found:
* `valid` - At least one valid phone number found
* `not_found` - No phone numbers found or phone enrichment not requested
## Pricing
Each enrichment request consumes credits based on the enrichment type requested and the providers used. Check your account credits using the [Account Credits endpoint](/api-reference/endpoints/miscellaneous/account-credits).
Credits are checked before the waterfall runs. If your balance cannot cover the
enrichment the request is rejected with `402 Payment Required` and
`code: "insufficient_credits"` (the response carries a `top_up_url`); if it
would exceed your workspace weekly credit limit, with `403 Forbidden` and
`code: "workspace_limit_exceeded"`. No provider is called and nothing is spent
in either case. See [Credit and limit errors](/api-reference/errors).
# Bulk Contact Enrichment
Source: https://docs.pipecorn.com/api-reference/endpoints/enrichments/batch
POST /contacts/bulk_enrich
Enrich up to 100 contacts in a single asynchronous batch
Enqueue up to **100 contacts** for waterfall enrichment in a single request.
The endpoint returns immediately with an `enrichment_id` for the bulk job;
each contact is enriched asynchronously and results are delivered to your
`webhook_url` as each contact completes.
## Constraints
* **Minimum:** 2 contacts per request. For a single contact, use the
[single async endpoint](/api-reference/endpoints/enrichments/single).
* **Maximum:** 100 contacts per request.
* A single `enrichment_type` applies to every contact in the batch.
## Enrichment Types
Pass `enrichment_type` as an array containing one of:
* `["email"]` — Find and validate professional emails
* `["phone"]` — Find phone numbers (requires `linkedin_url` on every contact)
* `["personal_email"]` — Find personal emails (requires `linkedin_url` **and** account-level consent — see below)
Requesting `personal_email` requires the authenticated user to have
consented to personal email enrichment in their account settings.
If consent is missing the entire batch is rejected with
`422 Unprocessable Entity`. This consent gate is required for GDPR compliance.
## Required Fields per contact
The required per-contact fields depend on the batch-wide `enrichment_type`:
| `enrichment_type` | Required fields per contact |
| -------------------- | ----------------------------------------------------------------------------------- |
| `["email"]` | `firstname`, `lastname`, **and** one of `linkedin_url`, `domain`, or `company_name` |
| `["phone"]` | `linkedin_url` |
| `["personal_email"]` | `linkedin_url` |
Phone and personal email batches run off each contact's `linkedin_url` alone,
so `firstname`/`lastname` are not required for those types.
## Receiving results
Provide `webhook_url` to receive results — we POST one payload per contact as
each one finishes. The webhook payload echoes the `custom` fields you sent
with that contact, so you can correlate results back to your records.
## Credits
Credits are checked up-front for the entire batch. If your balance is
insufficient the request is rejected with `402 Payment Required` and
`code: "insufficient_credits"`, and no contacts are enqueued — the response
carries a `top_up_url` you can send the user to. If the batch would exceed your
workspace weekly credit limit, the request is rejected with `403 Forbidden` and
`code: "workspace_limit_exceeded"` instead; buying credits does not lift that
limit. See [Credit and limit errors](/api-reference/errors).
# Asynchronous Single Contact Enrichment
Source: https://docs.pipecorn.com/api-reference/endpoints/enrichments/single
enrichments POST /contacts/single_enrich
Enrich a single contact record with email, phone, and / or personal email data
Enqueue a single contact for waterfall enrichment. The endpoint returns
immediately with an `enrichment_id` and `status: "pending"`; the waterfall
runs asynchronously in the background.
## When to use this endpoint
Use the async endpoint when:
* You can accept results via webhook, or you can poll for them later.
* You're enriching at scale and don't want to hold an HTTP connection per contact.
* You want to retain the enrichment result on the contact record for later retrieval via [`GET /contacts/{id}`](/api-reference/endpoints/contacts/single_enrich).
If you need results inline (Chrome extension, interactive UI, real-time
workflow), use the [synchronous endpoint](/api-reference/endpoints/contacts/sync_single_enrich) instead.
## Enrichment Types
Pass `enrichment_type` as an array containing one of:
* `["email"]` — Find and validate the professional email
* `["phone"]` — Find phone numbers (requires `linkedin_url`)
* `["personal_email"]` — Find a personal email (requires `linkedin_url` **and** account-level consent — see below)
Requesting `personal_email` requires the authenticated user to have
consented to personal email enrichment in their account settings.
If consent is missing, the API responds with `422 Unprocessable Entity`
and the message `"You can't use the personal email enrichment feature
without consenting with our terms of use"`. This consent gate is required
for GDPR compliance.
## Required Fields
`enrichment_type` is always required. The other required fields depend on its
value (the **Body** section below shows this per type):
| `enrichment_type` | Additional required fields |
| -------------------- | ----------------------------------------------------------------------------------- |
| `["email"]` | `firstname`, `lastname`, **and** one of `linkedin_url`, `domain`, or `company_name` |
| `["phone"]` | `linkedin_url` |
| `["personal_email"]` | `linkedin_url` |
Email enrichment needs the contact's name plus at least one identifier — a
`linkedin_url` on its own is enough, or company context (`domain` or
`company_name`). Phone and personal email enrichment run off the `linkedin_url`
alone, so `firstname`/`lastname` are not required for them.
## Receiving results
You have two options:
1. **Webhook** — pass `webhook_url` in the request. We POST the final result
to that URL once the waterfall completes.
2. **Polling** — call [`GET /contacts/{id}`](/api-reference/endpoints/contacts/single_enrich)
with the returned `enrichment_id`. While the waterfall is running the
`status` is `pending`; once it has completed (with or without data) the
`status` flips to `finished`.
## Custom Fields
Pass `custom: { ... }` in the request to attach arbitrary correlation data
(e.g. your CRM record ID). The same payload is echoed back on
`GET /contacts/{id}` and on the webhook callback.
## Pricing
Each enrichment consumes credits based on the requested `enrichment_type` and
the providers used. Check your account credits via the
[Account Credits endpoint](/api-reference/endpoints/miscellaneous/account-credits).
Credits are checked before the contact is enqueued. If your balance cannot cover
the enrichment the request is rejected with `402 Payment Required` and
`code: "insufficient_credits"` (the response carries a `top_up_url`); if it
would exceed your workspace weekly credit limit, with `403 Forbidden` and
`code: "workspace_limit_exceeded"`. Nothing is enqueued in either case. See
[Credit and limit errors](/api-reference/errors).
# Account search
Source: https://docs.pipecorn.com/api-reference/endpoints/extract/accounts
POST /accounts/
Extract company accounts from a LinkedIn Sales Navigator search URL and process them asynchronously.
**Rate limit:** 1 request per second
This endpoint creates an import job that will process the search results in the background. Results will be sent to the specified webhook URL when processing is complete.
Extract company accounts from LinkedIn Sales Navigator search results and process them asynchronously. This endpoint creates an import job that will process the search results in the background and send the results to your specified webhook URL when complete.
## Overview
This endpoint allows you to extract company data from LinkedIn Sales Navigator search URLs. The process is asynchronous - you'll receive an immediate response with the import job details, and the actual results will be sent to your webhook URL when processing is complete.
## Rate Limits
* **1 request per second** per user/IP address
# People search
Source: https://docs.pipecorn.com/api-reference/endpoints/extract/leads
POST /leads
Initiates a new lead search based on the provided parameters.
**Rate limit:** 1 request per second
## Scale Parameter
The `scale` parameter (boolean, optional) allows you to increase your volume of requests by omitting the following fields:
* `connections_count`
* `headline`
* Vanity LinkedIn profile URL (like `https://www.linkedin.com/in/mathieu-brun-picard/`)
When `scale` is set to `true`, you will still receive a LinkedIn profile URL, but it will use the user ID instead of the vanity URL format (like `https://linkedin.com/in/ACwAACaX8uYBfAh-5YxmfObz4mVOKYih3zxa-TM`).
# Find people at company
Source: https://docs.pipecorn.com/api-reference/endpoints/extract/leads_from_company
POST /leads/search
Searches for leads based on job titles and a company (LinkedIn company ID or URL). Optionally narrow results by location, LinkedIn **function** (department), and **seniority** level using the authorized ID lists below.
By default the search runs live through LinkedIn (`live: true`) and requires a connected integration. Set `live: false` to resolve the company and matching people from Pipecorn's people database (Elasticsearch) instead, with no LinkedIn call and no integration required.
# Find 2x people than with Clay
* Input : Job titles + Company
* Output : Live matching people data
# Prerequisites
## In Pipecorn
* A Pipecorn account with API access
* A valid **[sync](https://app.pipecorn.com/settings/extension)**
* Your Pipecorn **API key** ([How to get your API key](/api-reference/API-key))
## In Clay
A **Companies** table with at least:
* Company Name
* Domain
* Company LinkedIn URL (or LinkedIn Org ID)
These fields tell Pipecorn which company to search on LinkedIn.
# Step 1 — Create a Webhook Table in Clay
Pipecorn needs an endpoint to “deliver” the people it finds.
We’ll use a **Monitor Webhook** table.
1. In Clay, click **Add** → **Monitor Webhook**
2. Clay creates a new table with a **Webhook column**
3. Click the **Webhook column** → **Sources** → **Pull data from webhook**
4. Copy the **Webhook URL**
You will paste this URL into Pipecorn’s API request later.
# Step 2 — Add an HTTP API Column to Your Companies Table
1. Go back to your **Companies** table
2. Click **Add Column**
3. Choose **Add Enrichment**
4. Select **HTTP API**
This is the column that will call Pipecorn’s Find People API for each company.
# Step 3 — Configure the API Call
### Method
`POST`
### Endpoint
```
https://app.pipecorn.com/api/v2/leads/search
```
### Body (JSON)
Paste this JSON and customize it as needed:
```json theme={null}
{
"name": "Find people at {{Company Name}}",
"webhook_url": "PASTE_YOUR_WEBHOOK_URL_HERE",
"company_linkedin_url": "{{Company Linkedin URL}}",
"job_titles": [
"Head of Talent",
"HR Director",
"Talent Acquisition Manager"
],
"excluded_job_titles": [
"Intern"
],
"functions": ["12", "15"],
"seniority_levels": ["220", "300"],
"streaming": true,
"limit": 50
}
```
#### Using a saved Persona instead of inlining job titles
If you've already defined a Persona in Pipecorn, you can reference it by `persona_id`. Pipecorn will use that persona's included and excluded job titles automatically — do **not** pass `job_titles` or `excluded_job_titles` alongside `persona_id`.
```json theme={null}
{
"name": "Find people at {{Company Name}}",
"webhook_url": "PASTE_YOUR_WEBHOOK_URL_HERE",
"company_linkedin_url": "{{Company Linkedin URL}}",
"persona_id": "1f6b0f5a-2d8e-4c3a-9b8f-1a2b3c4d5e6f",
"streaming": true,
"limit": 50
}
```
> **At least one people filter is required.** The request must include at least one of `job_titles`, `excluded_job_titles`, `functions`, `seniority_levels`, `included_locations`, `excluded_locations`, or `persona_id`. Requests with none of these return `400`.
### Field explanations
* **name**: Label used inside Pipecorn
* **webhook\_url**: Clay webhook URL (Step 1)
* **company\_linkedin\_url**: Clay variable for the company’s LinkedIn profile
* **job\_titles**: The personas you want to target. If you pass `[*]` we will return every person in the company, regardless of their job title.
* **excluded\_job\_titles**: Optional list
* **persona\_id** (optional): UUID of a Pipecorn Persona. When provided, `job_titles` and `excluded_job_titles` are taken from the persona definition and **must not** be passed in the request — doing so returns `422`. Use this when you want a saved persona to drive the search instead of inlining job titles.
* **included\_locations** (optional): If used, we will return only leads with matching location. Location ids can be retrieved via this [endpoint](/api-reference/endpoints/miscellaneous/location-ids).
* **excluded\_locations** (optional): Location IDs to exclude (same ID source as above).
* **functions** (optional): Array of LinkedIn function IDs (department / job function). Only the IDs listed in [Authorized function IDs](#authorized-function-ids) are accepted. Multiple values use OR logic.
* **seniority\_levels** (optional): Array of LinkedIn seniority level IDs. Only the IDs listed in [Authorized seniority level IDs](#authorized-seniority-level-ids) are accepted. Multiple values use OR logic.
* **streaming**: Sends results to Clay row by row
* **limit**: Max number of people to return per company
* **live** (optional, boolean): Data source. Defaults to `true`, which searches LinkedIn in real time using your synced session. Set to `false` to resolve the company and matching people from Pipecorn's people database instead — no live LinkedIn call and no synced session required. A non-boolean value returns `422`.
If `functions` or `seniority_levels` is present, it must be a JSON array. Invalid IDs return `422` with a message listing the invalid values and the full set of valid IDs.
### Authorized function IDs
| ID | Label |
| -- | -------------------------------- |
| 1 | Accounting |
| 2 | Administrative |
| 3 | Arts and Design |
| 4 | Business Development |
| 5 | Community and Social Services |
| 6 | Consulting |
| 7 | Education |
| 8 | Engineering |
| 9 | Entrepreneurship |
| 10 | Finance |
| 11 | Healthcare Services |
| 12 | Human Resources |
| 13 | Information Technology |
| 14 | Legal |
| 15 | Marketing |
| 16 | Media and Communication |
| 17 | Military and Protective Services |
| 18 | Operations |
| 19 | Product Management |
| 20 | Program and Project Management |
| 21 | Purchasing |
| 22 | Quality Assurance |
| 23 | Real Estate |
| 24 | Research |
| 25 | Sales |
| 26 | Customer Success and Support |
### Authorized seniority level IDs
| ID | Label |
| --- | ------------------- |
| 100 | In Training |
| 110 | Entry Level |
| 120 | Senior |
| 130 | Strategic |
| 200 | Entry Level Manager |
| 210 | Experienced Manager |
| 220 | Director |
| 300 | Vice President |
| 310 | CXO |
| 320 | Owner / Partner |
Click **Save & Don’t Run**.
> **Clay JSON formatting errors?** Double-check commas, spacing, or [copy our template](https://app.clay.com/shared-workbook/share_0swi80wycWeW9mHM64p) to fix issues.
### Headers
| Key | Value |
| --------- | --------------------- |
| X-API-KEY | Your Pipecorn API key |
# Step 4 — Run Your First Find People Request
1. In your **Companies** table
2. Go to your new **HTTP API** column
3. Click the **▶️ Play** button on any company row
Pipecorn will immediately:
* query LinkedIn for your persona
* extract matching profiles
* stream the results into your Webhook table
# Step 5 — View and Use the Results
Go to your **Webhook table**.
You’ll see people appear row by row as Pipecorn finds them.
Click **Add Column** → search and add:
* `full_name`
* `title`
* `linkedin_url`
* `linkedin_id`
* `company_name`
* `status`
* `rejection_reasons`
You now have a **live Find People pipeline** inside Clay.
# FAQ
### Does this use my Clay credits?
No, Pipecorn handles the search, so you don’t use any Clay Find People credits.
### Is the data live?
Yes, by default Pipecorn searches in real-time using your synced session. If you'd rather not depend on a synced session — or want faster, integration-free results — pass `live: false` to search Pipecorn's people database instead.
### Can I run this at scale?
Yes, You can run it on thousands of companies. Pipecorn streams results progressively to avoid rate limits.
### What if my sync breaks?
Just re-sync your account in Pipecorn Settings.
# Need help?
If you need help customizing your Find people, please book a 15min set up with me : [https://zcal.co/mathieu-pipecorn/enterprise](https://zcal.co/mathieu-pipecorn/enterprise)
# Want to scale further ?
The `scale` parameter (boolean, optional) allows you to increase your volume of requests by omitting the following fields:
* `connections_count`
* `headline`
* Vanity LinkedIn profile URL (like `https://www.linkedin.com/in/mathieu-brun-picard/`)
When `scale` is set to `true`, you will still receive a LinkedIn profile URL, but it will use the user ID instead of the vanity URL format (like `https://linkedin.com/in/ACwAACaX8uYBfAh-5YxmfObz4mVOKYih3zxa-TM`).
# Search leads by filters
Source: https://docs.pipecorn.com/api-reference/endpoints/leads/advanced_search
POST /leads/advanced_search
Run a lead search with the full set of structured filters and stream enriched leads to your webhook.
Run a full lead search using structured filters. Pipecorn builds the underlying query for you, creates an asynchronous `Search`, and streams enriched leads to your `webhook_url`.
## Overview
Use this endpoint when you want to extract leads matching a precise persona definition (titles + seniority + function + tenure + company filters + signals). Pipecorn:
1. Validates and translates your filters into a search URL.
2. Estimates the number of matching profiles.
3. Enqueues the search and returns immediately with a `Search` record.
4. Streams leads to your webhook.
## Requirements
* A valid Sales Navigator **integration** must be connected on the authenticated user — **unless** you pass `live: false`, which serves the search from Pipecorn's people database and needs no integration.
* `webhook_url` is **required**.
* At least one filter or `keyword` must be provided.
## Live vs. database mode
By default (`live: true`) the search runs in real time through LinkedIn Sales Navigator. Set **`live: false`** to serve the count, preview, and streamed results entirely from Pipecorn's people database (Elasticsearch) instead — no Sales Navigator integration required.
Relationship and signal filters only exist in LinkedIn's graph, so they are **rejected with `422`** when `live: false`: `connections_of_profile`, `relationship`, `follows_your_company`, `viewed_your_profile`, `with_shared_experiences`, `posted_on_linkedin`, and `past_colleague`. Every other filter works in both modes.
The same `live` flag is accepted by the [preview endpoint](/api-reference/endpoints/leads/advanced_search_preview).
## Rate Limits
* **1 request per second** per user.
## Request body
### Top-level options
| Field | Type | Description |
| ------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `webhook_url` | string (HTTPS URL) | **Required.** Where Pipecorn sends the enriched leads. |
| `live` | boolean | Data source. `true` (default) searches LinkedIn Sales Navigator; `false` searches Pipecorn's people database with no integration required (see [Live vs. database mode](#live-vs-database-mode)). |
| `name` | string | Friendly name. Defaults to `Lead search - API -
`. |
| `keyword` | string | Free-text keyword. Spell correction is automatically enabled when set. |
| `limit` | integer | Cap on enriched leads. Effective value is `min(limit, MAX_RESULTS_COUNT)`. |
| `streaming` | boolean | If `true`, leads are pushed to the webhook as they are scraped. Default `false`. |
| `scale` | boolean | If `true`, skips some data retrieval, for higher volume. Default `false`. |
| `custom` | object | Arbitrary JSON stored on the search and echoed back in every webhook payload. |
### Title filters
| Field | Type | Notes |
| ---------------------- | ---------------- | ----------------------------------------------------- |
| `job_titles` | array of strings | Current titles to include (`CURRENT_TITLE` INCLUDED). |
| `excluded_job_titles` | array of strings | Current titles to exclude (`CURRENT_TITLE` EXCLUDED). |
| `past_titles` | array of strings | Past titles to include (`PAST_TITLE` INCLUDED). |
| `excluded_past_titles` | array of strings | Past titles to exclude (`PAST_TITLE` EXCLUDED). |
### Location filters
| Field | Type |
| -------------------- | --------------------------------- |
| `included_locations` | array of LinkedIn `geoRegion` IDs |
| `excluded_locations` | array of LinkedIn `geoRegion` IDs |
Resolve region names to IDs with the [Location IDs endpoint](/api-reference/endpoints/miscellaneous/location-ids).
### Industry filters
| Field | Type |
| --------------------- | ------------------------------ |
| `included_industries` | array of LinkedIn industry IDs |
| `excluded_industries` | array of LinkedIn industry IDs |
For the full list of industry IDs see the [LinkedIn Industry List](https://docs.google.com/spreadsheets/d/1qTFPVfcSHnL5PU1AcQlzD8mCmfSICKJ4WuU-OBGhkdI/edit?gid=0#gid=0). Common values:
* `4` Automotive
* `6` Technology, Information and Internet
* `12` Education
* `43` Financial Services
* `96` Software Development
### Company filters
| Field | Type | Notes |
| ---------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `included_companies` | array of ids or `{ id }` objects | Current company (`CURRENT_COMPANY` INCLUDED). `id` is the numeric LinkedIn organization id (the integer in `urn:li:organization:`). |
| `excluded_companies` | array of ids or `{ id }` objects | Current company to exclude (`CURRENT_COMPANY` EXCLUDED). |
| `past_companies` | array of ids or `{ id }` objects | Past company (`PAST_COMPANY` INCLUDED). |
| `company_headquarters` | array of `geoRegion` IDs | Filters by the lead's company HQ region (`COMPANY_HEADQUARTERS`). |
Each entry can be a plain LinkedIn organization id (string or integer) or an object with an `id` key (e.g. `"1441"`, `1441`, or `{ "id": "1441" }`). Other shapes return `422`.
### Function & seniority
| Field | Maps to | Valid IDs |
| ------------------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `functions` | `FUNCTION` | `1` Accounting · `2` Administrative · `3` Arts and Design · `4` Business Development · `5` Community and Social Services · `6` Consulting · `7` Education · `8` Engineering · `9` Entrepreneurship · `10` Finance · `11` Healthcare Services · `12` Human Resources · `13` Information Technology · `14` Legal · `15` Marketing · `16` Media and Communication · `17` Military and Protective Services · `18` Operations · `19` Product Management · `20` Program and Project Management · `21` Purchasing · `22` Quality Assurance · `23` Real Estate · `24` Research · `25` Sales · `26` Customer Success and Support |
| `seniority_levels` | `SENIORITY_LEVEL` | `100` In Training · `110` Entry Level · `120` Senior · `130` Strategic · `200` Entry Level Manager · `210` Experienced Manager · `220` Director · `300` Vice President · `310` CXO · `320` Owner / Partner |
Multiple IDs are combined with **OR** logic.
### Tenure filters
LinkedIn uses bucketed IDs `"1"`–`"8"` for these filters:
| Field | Maps to |
| --------------------------- | --------------------------- |
| `years_of_experience` | `YEARS_OF_EXPERIENCE` |
| `years_at_current_company` | `YEARS_AT_CURRENT_COMPANY` |
| `years_in_current_position` | `YEARS_IN_CURRENT_POSITION` |
Bucket meanings (same scale for all three): `"1"` Less than 1 year · `"2"` 1 to 2 years · `"3"` 3 to 5 years · `"4"` 6 to 10 years · `"5"` More than 10 years. Buckets `"6"`–`"8"` are reserved by LinkedIn.
### Company size & type
| Field | Maps to | Valid values (same strings as [account search](/api-reference/endpoints/accounts/search)) |
| -------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `company_size` | `COMPANY_HEADCOUNT` | `1-10` · `11-50` · `51-200` · `201-500` · `501-1000` · `1001-5000` · `5001-10000` · `10001+` (en-dashes in requests are normalized to hyphens on the server) |
| `company_type` | `COMPANY_TYPE` | `C` Public Company · `E` Educational Institution · `G` Government Agency · `N` Non-Profit · `P` Privately Held · `S` Self-Employed · `X` Self-Owned |
### Lists & relationship
| Field | Maps to | Value type |
| ------------------------ | -------------------------- | --------------------------------------------------------------------------------------------- |
| `included_account_lists` | `ACCOUNT_LIST` (INCLUDED) | array of account list IDs |
| `excluded_account_lists` | `ACCOUNT_LIST` (EXCLUDED) | array of account list IDs |
| `included_lead_lists` | `LEAD_LIST` (INCLUDED) | array of lead list IDs |
| `excluded_lead_lists` | `LEAD_LIST` (EXCLUDED) | array of lead list IDs |
| `relationship` | `RELATIONSHIP` | array of IDs: `F` 1st degree · `S` 2nd degree · `O` 3rd degree and beyond · `A` Group members |
| `recently_changed_jobs` | `RECENTLY_CHANGED_JOBS` | pass `["RPC"]` to enable — keeps only leads who started a new role in the **last 90 days** |
| `connections_of_profile` | `CONNECTION_OF` (INCLUDED) | single LinkedIn profile URL — returns 1st-degree connections of that profile |
`connections_of_profile` accepts any recognized LinkedIn profile URL:
* `https://www.linkedin.com/in/`
* `https://www.linkedin.com/in/`
* `https://www.linkedin.com/sales/lead/`
`recently_changed_jobs` is an on/off switch, not a list of options. `"RPC"` is
the only accepted value and it maps to Sales Navigator's *Changed jobs in the
last 90 days* filter: a lead matches when their current position started within
the 90 days before the search runs. The window is fixed. To target longer or
shorter tenures, use `years_in_current_position` instead.
The server resolves the URL to the target member's internal id via LinkedIn before building the search. Returns `422` if the URL is malformed or can't be resolved.
### Boolean signal filters
These send a single fixed value when truthy. Pass `true` to apply.
| Field | Maps to |
| ------------------------- | ------------------------------------- |
| `follows_your_company` | `FOLLOWS_YOUR_COMPANY` (id `CF`) |
| `viewed_your_profile` | `VIEW_YOUR_PROFILE` (id `VYP`) |
| `with_shared_experiences` | `WITH_SHARED_EXPERIENCES` (id `COMM`) |
| `posted_on_linkedin` | `POSTED_ON_LINKEDIN` (id `RPOL`) |
| `past_colleague` | `PAST_COLLEAGUE` (id `CL`) |
`viewed_your_profile` matches people who viewed the profile of the connected
LinkedIn account within the **last 30 days**. The window is fixed by LinkedIn
and cannot be widened; older views are not returned.
## Response
`201 Created` — returns immediately with the created `Search`:
```json theme={null}
{
"message": {
"id": "8e1dcba0-f0bb-4071-99fc-f18ba6559ccc",
"search_name": "EU SaaS VPs of Sales",
"search_url": "https://www.linkedin.com/sales/search/people?query=(filters%3AList(...))",
"expected_profiles_count": 842,
"created_at": "2026-05-04T12:34:56Z",
"custom": { "hubspot_id": "134567" }
}
}
```
Enriched leads are then POSTed to your `webhook_url` (one-shot at the end of the search, or per-batch when `streaming: true`).
## Errors
| Status | When |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request` | Missing `webhook_url`, invalid webhook URL format, or no filter/keyword provided. |
| `401 Unauthorized` | Invalid API key, or credentials missing/expired. |
| `403 Forbidden` | API key does not have access to this endpoint. |
| `422 Unprocessable Entity` | Invalid filter shape, or enum ID outside the authorized list (e.g. unknown `functions`, `seniority_levels`, `company_size`, etc.). |
| `429 Too Many Requests` | Per-user rate limit (1 req/s) or upstream LinkedIn rate limit. |
## Examples
### EU SaaS VPs of Sales
```json theme={null}
{
"name": "EU SaaS VPs of Sales",
"webhook_url": "https://hooks.example.com/leads",
"limit": 500,
"streaming": true,
"job_titles": ["VP of Sales", "Chief Revenue Officer"],
"seniority_levels": ["300", "310"],
"functions": ["25"],
"included_industries": ["96", "4"],
"included_locations": ["101452733", "105015875"],
"company_size": ["51-200", "201-500", "501-1000"],
"years_in_current_position": ["3", "4"],
"custom": { "hubspot_id": "134567" }
}
```
### Engineering leaders at specific companies who recently changed jobs
```json theme={null}
{
"name": "Eng leaders — recent movers",
"webhook_url": "https://hooks.example.com/leads",
"job_titles": ["VP Engineering", "Head of Engineering"],
"functions": ["8"],
"seniority_levels": ["220", "300"],
"included_companies": ["1441", { "id": "162479" }],
"recently_changed_jobs": ["RPC"]
}
```
### Target an account list while excluding an existing lead list
```json theme={null}
{
"webhook_url": "https://hooks.example.com/leads",
"job_titles": ["Head of Marketing"],
"included_account_lists": ["12345678"],
"excluded_lead_lists": ["87654321"]
}
```
### Past colleagues who posted on LinkedIn recently
```json theme={null}
{
"webhook_url": "https://hooks.example.com/leads",
"past_colleague": true,
"posted_on_linkedin": true,
"included_locations": ["103644278"]
}
```
### Keyword + tenure filter, scale mode
```json theme={null}
{
"webhook_url": "https://hooks.example.com/leads",
"keyword": "cybersecurity",
"years_of_experience": ["4", "5"],
"company_type": ["P", "C"],
"scale": true,
"limit": 1000
}
```
### 1st-degree connections of a target profile
```json theme={null}
{
"webhook_url": "https://hooks.example.com/leads",
"connections_of_profile": "https://www.linkedin.com/in/williamhgates",
"seniority_levels": ["300", "310"],
"functions": ["25"]
}
```
# Preview
Source: https://docs.pipecorn.com/api-reference/endpoints/leads/advanced_search_preview
POST /leads/advanced_search/preview
Synchronously preview the first 25 matches and the total estimated count for a set of advanced lead search filters, without creating a Search or consuming credits.
Run the same filters as [`POST /leads/advanced_search`](/api-reference/endpoints/leads/advanced_search) and get back a synchronous **preview**: the total estimated profile count plus the first **25** matching leads. Use it to validate filters and size an audience before kicking off the real search.
## Overview
Compared to `POST /leads/advanced_search`, the preview:
* Does **not** create a `Search` record.
* Does **not** call your webhook.
* Does **not** consume credits.
* Does **not** require `webhook_url`.
The body accepts the exact same filter parameters as the regular advanced search — see [Search leads by filters](/api-reference/endpoints/leads/advanced_search) for the full reference. `webhook_url`, `name`, `limit`, `streaming`, `scale`, and `custom` are accepted but ignored: the response always contains up to 25 leads.
## Requirements
* A valid **integration** must be connected on the authenticated user.
* At least one filter or `keyword` must be provided.
## Rate Limits
* **1 request per second** per user.
## Response
`200 OK` — returns immediately with:
```json theme={null}
{
"total_count": 1234,
"preview": [
{
"full_name": "Ada Lovelace",
"headline": "VP of Sales at Acme",
"current_company": "Acme",
"current_title": "VP of Sales",
"linkedin_id": "104885158",
"profile_url": "https://www.linkedin.com/in/urn:li:fs_salesProfile:(ACoAAAxxxx,NAME_SEARCH,abcde)"
}
]
}
```
| Field | Type | Notes |
| ------------- | ---------------- | ------------------------------------------------------------------------------------ |
| `total_count` | integer | Total estimated number of leads matching the filters (not capped to 25). |
| `preview` | array of objects | Up to 25 matching leads. Each entry contains the fields listed above when available. |
## Errors
| Status | When |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request` | No filter or `keyword` provided. |
| `401 Unauthorized` | Invalid API key, or credentials missing/expired. |
| `403 Forbidden` | API key does not have access to this endpoint. |
| `422 Unprocessable Entity` | Invalid filter shape, or enum ID outside the authorized list (e.g. unknown `functions`, `seniority_levels`, `company_size`, etc.). |
| `429 Too Many Requests` | Per-user rate limit (1 req/s) or upstream LinkedIn rate limit. |
## Example
```json theme={null}
{
"job_titles": ["VP of Sales", "Chief Revenue Officer"],
"seniority_levels": ["300", "310"],
"functions": ["25"],
"included_industries": ["96"],
"included_locations": ["101452733"]
}
```
# Enrich people
Source: https://docs.pipecorn.com/api-reference/endpoints/leads/single
POST /leads/single_enrich
Enrich a single person with profile and firmographic data.
**Credits:** 1 credit per enrichment. You are only charged when a person is actually resolved — a lookup that matches nothing costs nothing.
Identify the person either by `linkedin_url`, or by `first_name` + `last_name` + `company_name`.
This endpoint returns the profile only. Email and phone come from [waterfall enrichment](/api-reference/endpoints/contacts/single_enrich) and are never part of this response.
# Create a List
Source: https://docs.pipecorn.com/api-reference/endpoints/lists/create
POST /lists
Creates a new list in the system.
# Retrieve all Lists
Source: https://docs.pipecorn.com/api-reference/endpoints/lists/index
GET /lists
Retrieve all your lists
# Retrieve a List
Source: https://docs.pipecorn.com/api-reference/endpoints/lists/show
GET /lists/{id}
Retrieve a specific list by its ID
# Update a List
Source: https://docs.pipecorn.com/api-reference/endpoints/lists/update
PUT /lists/{id}
Updates a list in the system.
# Current credit balance
Source: https://docs.pipecorn.com/api-reference/endpoints/miscellaneous/account-credits
GET /credits
Get your current credit balance and usage information
# Credit consumption
Source: https://docs.pipecorn.com/api-reference/endpoints/miscellaneous/credit-consumption
GET /credits_consumption
Get your current credit balance and the credits consumed between two dates
# Account Info
Source: https://docs.pipecorn.com/api-reference/endpoints/miscellaneous/get-account-info
GET /account
Get your plan, the email address behind your API key, and your integration session status
## Example response
```json theme={null}
{
"account": {
"plan": "scale",
"email": "jane@acme.com"
},
"integrations": {
"linkedin_session_valid": true,
"sales_navigator_session_valid": true
}
}
```
`account.email` is the email address of the user the API key belongs to - use it
to confirm which Pipecorn account a key is authenticating as.
# Location Ids
Source: https://docs.pipecorn.com/api-reference/endpoints/miscellaneous/location-ids
POST /locations
Get the location id of a specific location
# Technology slug lookup
Source: https://docs.pipecorn.com/api-reference/endpoints/miscellaneous/technologies
GET /accounts/technologies
Resolve technology names to the slugs used by the tech-stack company search
Search the technology catalog (powered by TheirStack) and get back the slugs
used by the tech-stack company search endpoints.
## When to use it
The tech-stack search endpoints filter on technology **slugs**, not display
names. Call this endpoint to turn a human name (`"hubspot"`, `"shopify"`) into
the slug you pass in `stacks` / `excluded_stacks` on:
* [Preview companies by tech stack](/api-reference/endpoints/signals/tech_stack_preview)
* [Find companies by tech stack](/api-reference/endpoints/signals/tech_stack)
## Credits and rate limits
* Credits: **free** — no credits are spent
* Authentication: standard v2 scheme (`X-API-KEY`)
## Example request
```
GET /v2/accounts/technologies?query=hubspot
```
## Example response
```json theme={null}
{
"technologies": [
{
"slug": "hubspot",
"name": "HubSpot",
"category": "Marketing Automation",
"logo": "https://cdn.theirstack.com/logos/hubspot.png",
"description": "Inbound marketing, sales, and CRM platform."
}
]
}
```
`query` is required; an empty `query` returns `400`. Use the returned `slug`
values in `stacks` and `excluded_stacks`.
# List Personas
Source: https://docs.pipecorn.com/api-reference/endpoints/personas/index
GET /personas
Retrieves a list of all personas available in the system
# Get Persona
Source: https://docs.pipecorn.com/api-reference/endpoints/personas/show
GET /personas/{uuid}
Retrieves detailed information about a specific persona
# Delete a Search
Source: https://docs.pipecorn.com/api-reference/endpoints/searches/destroy
DELETE /searches/{id}
Deletes a specific search by its ID. This operation will permanently remove the search and all associated tasks from the system. Only the owner of the search can delete it.
## Description
Deletes a specific search by its ID. This operation will permanently remove the search and all associated tasks from the system. Only the owner of the search can delete it.
## Parameters
### Path Parameters
* **`id`** (required, string, UUID): The unique identifier of the search to delete
## Responses
### 200 OK
The search was successfully deleted.
```json theme={null}
{
"message": "Search deleted successfully"
}
```
### 401 Unauthorized
You are not authorized to delete this search. This may be because you do not own the search, or the search owner is not part of your workspace.
```json theme={null}
{
"error": "Unauthorized"
}
```
### 404 Not Found
The search with the specified ID does not exist.
```json theme={null}
{
"error": "Search not found"
}
```
### 422 Unprocessable Entity
The search deletion failed for an unknown reason.
```json theme={null}
{
"error": "Failed to delete search"
}
```
## Notes
* When a search is deleted, all related tasks are also deleted automatically
* This operation cannot be undone
* Only searches owned by the authenticated user or within the user's workspace can be deleted
# Retrieve all Searches
Source: https://docs.pipecorn.com/api-reference/endpoints/searches/index
GET /searches
Returns the searches the user has access to. By default only enriched searches are returned. Pass `enriched=false` to return all searches, enriched or not.
# Retrieve the details of a Search
Source: https://docs.pipecorn.com/api-reference/endpoints/searches/show
GET /searches/{id}
Returns a specific search and its leads by ID.
## Search Status
The search object includes a `status` field that indicates the current state of the search operation. The possible status values are:
### Active Statuses
* **`NOT_STARTED`**: The search has been created but has not yet begun processing
* **`ONGOING`**: The search is currently being processed and generating results
* **`FINISHED`**: The search has completed successfully and all results are available
### Error Statuses
* **`RATE_LIMITED`**: The search was interrupted due to rate limiting constraints
* **`UNAUTHORIZED`**: The search failed due to authentication issues
* **`FORBIDDEN`**: The search failed due to insufficient permissions
* **`ERROR`**: The search encountered an error during processing
When a search has a status of `FINISHED`, all leads are available and ready to be retrieved. For searches with error statuses, you may need to retry the search or check your API credentials and permissions.
# Extract comments from LinkedIn profile
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/comments
POST /intents/leads/comments
Extract comments left by a LinkedIn profile on other posts. Uses the voyagerFeedDashProfileUpdates endpoint and paginates until all comments are retrieved or the requested limit is reached.
Extract comments left by a LinkedIn profile on other posts. This endpoint paginates through the profile's feed activity and filters for comment-type elements, returning up to the specified limit.
## Use Cases
* Surface intent signals from prospects actively engaging with relevant content
* Identify which topics a lead is commenting on to personalise outreach
* Track engagement patterns of key prospects or customers
* Enrich lead profiles with recent activity data
## Parameters
### Required Parameters
* `linkedin_profile_url`: LinkedIn profile URL to extract comments from (e.g., `https://www.linkedin.com/in/mathieu-brun-picard/`)
* `limit`: Maximum number of comments to extract (minimum: 1)
## Response
The response includes an array of comments with the following fields:
* `id`: Numeric activity ID extracted from the URN
* `comment_url`: Full LinkedIn URL with `commentUrn` query parameter — links directly to the comment
* `author`: Full name of the commenter
* `author_url`: LinkedIn profile URL of the commenter (query params stripped)
* `comment_text`: Text content of the comment
* `commented_at`: ISO 8601 timestamp of when the comment was posted
* `urn`: LinkedIn URN identifying the comment (`urn:li:comment:(parentActivity,commentId)`)
## Example Request
```bash theme={null}
curl --request POST \
--url https://app.pipecorn.com/api/v2/intents/leads/comments \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key' \
--data '{
"linkedin_profile_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"limit": 10
}'
```
## Example Response
```json theme={null}
{
"comments": [
{
"id": "7241056783920183297",
"comment_url": "https://www.linkedin.com/feed/update/urn:li:activity:7241056783920183297?commentUrn=urn%3Ali%3Acomment%3A%28urn%3Ali%3Aactivity%3A7241056783920183297%2C7241089034521346049%29",
"author": "Mathieu Brun-Picard",
"author_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"comment_text": "Great point — we've been seeing the same pattern at Pipecorn. The signal quality improves significantly once you filter by recency and engagement depth.",
"commented_at": "2025-11-20T14:17:00Z",
"urn": "urn:li:comment:(urn:li:activity:7241056783920183297,7241089034521346049)"
},
{
"id": "7238912047563218945",
"comment_url": "https://www.linkedin.com/feed/update/urn:li:activity:7238912047563218945?commentUrn=urn%3Ali%3Acomment%3A%28urn%3Ali%3Aactivity%3A7238912047563218945%2C7238945301827563521%29",
"author": "Mathieu Brun-Picard",
"author_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"comment_text": "This is exactly why we built intent signals into Pipecorn. Knowing when a prospect is actively commenting on topics relevant to your product is a game changer for outbound timing.",
"commented_at": "2025-11-17T10:44:00Z",
"urn": "urn:li:comment:(urn:li:activity:7238912047563218945,7238945301827563521)"
}
]
}
```
## Notes
* This endpoint returns results synchronously (HTTP 200 OK) — no polling required
* Comments are detected from the profile's feed when the share URL contains `commentUrn` or `/comment/`, or when `parentUrn`/`baseUpdate` fields are present on the feed element
* The service paginates through the feed in pages of 20 until the limit is reached or the feed is exhausted
* `author_url` is returned with tracking query parameters stripped
# Find companies lookalikes
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/company_lookalike
POST /intents/accounts/lookalikes
Find companies that look like your target accounts. Provide one or more LinkedIn company URLs; the API uses them to generate a lookalike search and streams results to your webhook. Location IDs can be retrieved using the Location IDs endpoint.
Find companies that look like your target accounts. Send one or more LinkedIn company URLs; the API uses them (up to 3 for keyword generation) to build a lookalike search and delivers results to your webhook. The response includes an import `id`, `total` count, and a `preview` of the first 10 matching companies.
You must provide either `company_linkedin_url` or `company_linkedin_urls`, plus `webhook_url`. Optionally filter by `company_size`, `included_locations`, and `excluded_locations`, and cap results with `limit`.
## Location IDs Reference
Location IDs used in `included_locations` and `excluded_locations` can be retrieved using the [Location IDs endpoint](/api-reference/endpoints/miscellaneous/location-ids). Provide a location name (e.g. "San Francisco") and the API returns matching locations with their IDs.
# Find connections
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/connections
POST /intents/leads/connections
Returns mutual connections between your LinkedIn account and a target lead via LinkedIn Sales Navigator. Results are 1st-degree connections you share with the target. Requires a connected LinkedIn account with Sales Navigator access.
Find mutual connections between your LinkedIn account and a target lead via LinkedIn Sales Navigator.
Returns 1st-degree connections you share with the target.
### Use Cases
* Find mutual connections with a prospect before reaching out
* Discover shared alumni, colleagues, or group members with a target
## Notes
* Requires a connected LinkedIn account with Sales Navigator access
* Accepts public LinkedIn URLs, Sales Nav URLs, or internal URNs
# Find new hires
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/find_new_hires
POST /intents/leads/find_new_hires
Find people who recently changed jobs and match your ICP
Track when companies make new hires matching specific ICP.
This endpoint creates a weekly tracking task that will notify you through a webhook when matching new hires are found.
### Use Cases
* Monitor when competitors hire for specific roles
* Track hiring trends in your target market
* Identify companies expanding specific departments
* Get notified about potential customer expansion signals
## Location IDs Reference
Location IDs used in this endpoint can be retrieved using the [Location Ids endpoint](/api-reference/endpoints/miscellaneous/location-ids). Simply provide a location name (e.g., "San Francisco") and the API will return all matching locations with their IDs.
# Find companies growing
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/growth
POST /intents/accounts/growth
Start a LinkedIn account (company) search by growth criteria. Only documented fields are allowed; unknown keys return 422.
**Valid criteria (choose one mode):**
1. **Company-wide headcount growth:** Provide at least one of `min_headcount_growth_percentage` or `max_headcount_growth_percentage`. Do not send `department` in this mode.
2. **Department metrics:** Send `department` (LinkedIn function ID as a string, e.g. `"1"`) plus at least one of `min_department_headcount`, `max_department_headcount`, `min_department_headcount_growth_percentage`, or `max_department_headcount_growth_percentage`.
Department fields cannot be combined with company-wide headcount growth fields.
Find companies that are experiencing growth using company-wide headcount growth or department-level metrics. The search runs against LinkedIn account data; matching companies are imported and sent to your webhook.
Send parameters inside a top-level JSON object under the key `account`. Only documented fields are allowed; extra keys under `account` are rejected with a validation error.
## Growth criteria (pick one approach)
**1. Company-wide headcount growth**
Provide at least one of:
* `min_headcount_growth_percentage`
* `max_headcount_growth_percentage`
Do not send `department` in this mode. Company-wide headcount growth and department filters cannot be used together.
**2. Department-level metrics**
Always send `department` (a string ID for the LinkedIn function to target, for example `"1"`). Also include at least one of:
* `min_department_headcount` and/or `max_department_headcount`, or
* `min_department_headcount_growth_percentage` and/or `max_department_headcount_growth_percentage`
`department` alone is not enough. Department headcount or department growth fields without `department` are not allowed.
### Other fields (inside `account`)
* `webhook_url` (**required**): URL that receives results when processing completes.
* `streaming` (optional): Whether to stream results as they are processed.
* `limit` (optional): Maximum number of companies to import. If omitted, the import is still capped at **1000** companies even when the search finds more; the `total` field in the response reflects the full match count from the search when no limit is set.
### Filters
* `company_size`: Array of company size range strings (LinkedIn-style buckets). En-dash characters in values are normalized to hyphens on the server.
* `included_locations`: Array of location IDs to include.
* `excluded_locations`: Array of location IDs to exclude.
* `included_industries`: Array of industry IDs to include.
Allowed `company_size` values:
* `1-10`
* `11-50`
* `51-200`
* `201-500`
* `501-1000`
* `1001-5000`
* `5001-10000`
* `10001+`
For the complete list of industry IDs, see the [LinkedIn Industry List](https://docs.google.com/spreadsheets/d/1qTFPVfcSHnL5PU1AcQlzD8mCmfSICKJ4WuU-OBGhkdI/edit?gid=0#gid=0).
Common industry IDs include:
* `4` - Automotive
* `6` - Technology, Information and Internet
* `12` - Education
* `43` - Financial Services
* `96` - Software Development
### Department validation
`department` must be a string and must be one of the allowed LinkedIn function IDs used by the API.
## Response
Successful requests return **201 Created** with:
* `message`: Confirmation that the account search started and results will be sent to the webhook.
* `id`: UUID of the import job.
* `total`: If `limit` is set, this is the smaller of the search size and `limit`. If `limit` is omitted, this is the full search size (import volume may still be capped at 1000 as above).
* `preview`: Up to **10** sample companies, each with `company_name`, `industry`, `linkedin_id` (numeric ID from the result), and `linkedin_url` in the form `https://www.linkedin.com/company/{linkedin_id}`.
In development environments, responses may also include `account_url` for debugging.
## Example request
```json theme={null}
{
"webhook_url": "https://your-company.com/webhooks/growth",
"min_headcount_growth_percentage": 10,
"company_size": ["51-200"],
"included_locations": [103644278],
"streaming": false
}
```
## Example response
```json theme={null}
{
"message": "Account search started successfully. You will receive the results on your webhook shortly.",
"id": "5d4fabd2-e26d-47d1-b0de-4bf370f7b799",
"total": 150,
"preview": [
{
"company_name": "Acme Inc",
"industry": "Software Development",
"linkedin_id": "123456",
"linkedin_url": "https://www.linkedin.com/company/123456"
}
]
}
```
## Errors
* **401**: Not enough credits to create a list for the number of companies returned by the search (`Insufficient credits`), or Sales Navigator requirements are not met.
* **422**: Invalid combinations of growth parameters, disallowed extra parameters, invalid `department` type or value, or invalid optional filters (company size, locations, industries).
## Location IDs reference
Resolve IDs for `included_locations` and `excluded_locations` using the [Location Ids endpoint](/api-reference/endpoints/miscellaneous/location-ids).
# Find companies hiring
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/hiring
POST /intents/accounts/hiring
Start a company hiring-intent search based on job posting activity. Only documented fields are allowed; unknown keys return 422.
Find companies that are actively hiring based on their job posting activity. This endpoint allows you to track companies that are recruiting for specific roles, technologies, or departments.
## Credits
Each imported company costs **3 enrichment credits**, checked up-front against
the number of companies that would be imported. If your balance falls short the
request returns `402` with `code: "insufficient_credits"`, a `top_up_url`, and a
message reporting the shortfall (`"Not enough enrichment credits. You need 30
credits but only have 5 available."`) — and no import is created. A workspace
weekly credit limit returns `403` with `code: "workspace_limit_exceeded"`
instead. See [Credit and limit errors](/api-reference/errors).
## Parameters
### Required Parameters
* `webhook_url`: URL to receive hiring intent notifications
### Job Search Parameters
* `selected_keywords`: Array of keywords to include in job search
* `excluded_keywords`: Array of keywords to exclude from job search
* `selected_titles`: Array of job titles to include
* `excluded_titles`: Array of job titles to exclude
* `exclude_consulting_recruiting`: Boolean to exclude consulting and recruiting companies
* `exclude_internships`: Boolean to exclude internship positions
* `published_date`: Time range for job postings (e.g., "last\_24\_hours", "last\_7\_days", etc.)
### Location Parameters
* `included_locations`: Array of cities to include
* `excluded_locations`: Array of cities to exclude
> **Note**: You can specify cities by name (e.g., "New York", "San Francisco", "London", "Paris"). The system will automatically match cities and their surrounding areas.
### Company Filters
* `company_size`: Array of company size ranges to include
* `included_industries`: Array of industry IDs to include
Allowed `company_size` values:
* `1-10`
* `11-50`
* `51-200`
* `201-500`
* `501-1000`
* `1001-5000`
* `5001-10000`
* `10001+`
For the complete list of industry IDs, see the [LinkedIn Industry List](https://docs.google.com/spreadsheets/d/1qTFPVfcSHnL5PU1AcQlzD8mCmfSICKJ4WuU-OBGhkdI/edit?gid=0#gid=0).
Common industry IDs include:
* `4` - Automotive
* `6` - Technology, Information and Internet
* `12` - Education
* `43` - Financial Services
* `96` - Software Development
## Response
The response includes:
* A unique identifier for the hiring intent
* Number of matching job postings
* Optional message about the results
## Example Response
```json theme={null}
{
"preview_count": 13,
"message": "More than 100 results returned, we will only fetch the first 100 results and return it to your webhook",
"id": "5d4fabd2-e26d-47d1-b0de-4bf370f7b799"
}
```
## Notes
* Results will be delivered to your webhook URL as they become available
* If more than 100 results are found, only the first 100 will be processeds
# Post engagers
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/post_engagers
POST /intents/leads/posts_engagers
Start an asynchronous extraction of leads that engaged with a LinkedIn post.
Start an asynchronous extraction of leads that engaged with a LinkedIn post. You must provide:
* **post\_url** — A valid LinkedIn post URL (use the link from the **Share** button on the post).
* **webhook\_url** — URL where results will be sent when the job completes.
* **engagement\_type** — One of `reactions`, `comments`, or `all`.
Optionally filter by **persona** (UUID), set a **lead\_list\_name**, **company\_size**, or **exclude\_people\_from\_same\_company**. The API responds immediately with a `search_id` and `expected_profiles_count`; the actual engager profiles are delivered to your webhook.
# Extract posts from a LinkedIn profile or company page
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/posts
POST /intents/leads/posts
Returns up to the specified limit of posts for a LinkedIn person profile or company page. The URL is detected automatically: company page URLs use the organization feed; profile URLs use the member profile feed. Results can be narrowed with `posted_within`.
## Use Cases
* Monitor content published by key prospects, customers, or their companies
* Track thought leadership from individuals and brand pages
* Analyze posting patterns and content strategy
* Extract posts for further analysis or engagement tracking
## Parameters
### Required
* `linkedin_url`: LinkedIn profile URL (e.g. `https://www.linkedin.com/in/...`) or company page URL (e.g. `https://www.linkedin.com/company/...`)
* `limit`: Maximum number of posts to return (minimum: 1)
### Optional
* `posted_within`: `last_24_hours`, `last_7_days`, or `last_30_days`. Omit to return posts without this recency filter. Any other value returns `400`.
The Pipecorn account used for the request must have valid LinkedIn credentials connected.
## Response
The response is a JSON object with a `posts` array. Each post may include:
* `author`: Post author name
* `author_url`: LinkedIn URL of the author (profile or company)
* `content`: Post text content
* `id`: Post ID
* `urn`: LinkedIn URN for the post
* `base_url`: Base post URL
* `post_url`: Full post URL
* `published_at`: Date when the post was published (YYYY-MM-DD format)
* `engagement_count`: Total engagement on the post (reactions + comments)
* `reactions_count`: Number of reactions on the post
* `comments_count`: Number of comments on the post
If the company ID or profile cannot be resolved from the URL, the API returns `200` with an empty `posts` array.
## Example Request
```bash theme={null}
curl --request POST \
--url https://app.pipecorn.com/api/v2/intents/leads/posts \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key' \
--data '{
"linkedin_url": "https://www.linkedin.com/in/profile",
"limit": 5,
"posted_within": "last_7_days"
}'
```
For a company page, use the same field with the company URL, for example `"linkedin_url": "https://www.linkedin.com/company/example"`.
## Example Response
```json theme={null}
{
"posts": [
{
"author": "Author Name",
"author_url": "https://www.linkedin.com/in/author-profile",
"content": "Post content text...",
"id": "1234567890",
"urn": "urn:li:activity:1234567890",
"base_url": "https://www.linkedin.com/feed/update/...",
"post_url": "https://www.linkedin.com/posts/...",
"published_at": "2026-01-15",
"engagement_count": 142,
"reactions_count": 128,
"comments_count": 14
}
]
}
```
## Errors (400)
* Missing `limit`: `Missing required keys: limit`
* Missing `linkedin_url`: `Missing required keys: linkedin_url`
* Invalid `posted_within`: `Invalid posted_within. Use last_24_hours, last_7_days, last_30_days, or omit the key.`
## Notes
* Synchronous response (`200 OK`) with `{ "posts": [...] }`
* Recency filtering is applied after posts are fetched from LinkedIn
# Extract reactions from LinkedIn profile
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/reactions
POST /intents/leads/reactions
Extract reactions left by a LinkedIn profile on other posts. Paginates through the profile's feed activity and filters for reaction-type elements, returning up to the specified limit.
Extract the LinkedIn reactions left by a profile on other people's posts. This endpoint paginates through the profile's feed activity and filters for reaction-type elements, returning up to the specified limit.
## Use Cases
* Surface intent signals from prospects actively engaging with relevant content
* Identify which topics a lead is reacting to (celebrating, finding insightful, etc.) to personalise outreach
* Track engagement patterns of key prospects or customers
* Enrich lead profiles with recent activity data
## Parameters
### Required Parameters
* `linkedin_profile_url`: LinkedIn profile URL to extract reactions from (e.g., `https://www.linkedin.com/in/mathieu-brun-picard/`)
* `limit`: Maximum number of reactions to extract (minimum: 1)
## Response
The response includes an array of reactions with the following fields:
* `id`: Numeric activity ID extracted from the URN
* `reaction_type`: Type of reaction — one of `LIKE`, `CELEBRATE`, `INSIGHTFUL`, `FUNNY`, `SUPPORT`, `LOVE`
* `post_url`: Full LinkedIn URL of the post that was reacted to
* `author`: Full name of the post author
* `author_url`: LinkedIn profile URL of the post author
* `reacted_at`: Date when the reaction was made (`YYYY-MM-DD` format)
* `urn`: LinkedIn URN identifying the activity (`urn:li:activity:`)
## Example Request
```bash theme={null}
curl --request POST \
--url https://app.pipecorn.com/api/v2/intents/leads/reactions \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key' \
--data '{
"linkedin_profile_url": "https://www.linkedin.com/in/mathieu-brun-picard/",
"limit": 10
}'
```
## Example Response
```json theme={null}
{
"reactions": [
{
"id": "1234567890123456789",
"reaction_type": "CELEBRATE",
"post_url": "https://www.linkedin.com/posts/jane-smith_post-title-activity-1234567890123456789-abcd",
"author": "Jane Smith",
"author_url": "https://www.linkedin.com/in/jane-smith",
"reacted_at": "2026-03-11",
"urn": "urn:li:activity:1234567890123456789"
},
{
"id": "9876543210987654321",
"reaction_type": "INSIGHTFUL",
"post_url": "https://www.linkedin.com/posts/bob-jones_another-post-activity-9876543210987654321-efgh",
"author": "Bob Jones",
"author_url": "https://www.linkedin.com/in/bob-jones",
"reacted_at": "2026-03-10",
"urn": "urn:li:activity:9876543210987654321"
},
{
"id": "1122334455667788990",
"reaction_type": "LIKE",
"post_url": "https://www.linkedin.com/posts/alice-martin_third-post-activity-1122334455667788990-ijkl",
"author": "Alice Martin",
"author_url": "https://www.linkedin.com/in/alice-martin",
"reacted_at": "2026-03-09",
"urn": "urn:li:activity:1122334455667788990"
}
]
}
```
## Notes
* This endpoint returns results synchronously (HTTP 200 OK) — no polling required
* The service paginates through the profile's feed until the limit is reached or the feed is exhausted
* `reaction_type` reflects the LinkedIn reaction emoji: `LIKE` (👍), `CELEBRATE` (👏), `INSIGHTFUL` (💡), `FUNNY` (😄), `SUPPORT` (🤝), `LOVE` (❤️)
* `author_url` is returned with tracking query parameters stripped
# Find companies by tech stack
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/tech_stack
POST /intents/accounts/stack
Import companies using a given technology stack to your webhook
Import the companies matching a technology-stack query. This is the second
step of the two-step tech-stack search — run
[preview](/api-reference/endpoints/signals/tech_stack_preview) first to size
the segment for free, then extract to receive the full company records on your
webhook. Technographics are powered by TheirStack.
## Credits and rate limits
* Credits: **3 enrichment credits** per imported company
* Authentication: standard v2 scheme (`X-API-KEY`)
Extract is exempt from per-second rate limiting — the credit balance is its own
throttle. If the account lacks enough enrichment credits for the companies that
would be imported, the request returns `402` with `code: "insufficient_credits"`,
a `top_up_url`, and a message reporting the shortfall — and no import is
created. A workspace weekly credit limit returns `403` with
`code: "workspace_limit_exceeded"` instead. See
[Credit and limit errors](/api-reference/errors).
## Filters
Accepts the same filters as
[preview](/api-reference/endpoints/signals/tech_stack_preview)
(`stacks`, `stack_match`, `excluded_stacks`, `countries`,
`included_industries`, `excluded_industries`, `company_size`), plus:
* `webhook_url` **(required)** — where results are POSTed
* `limit` — caps how many companies are imported (and billed). Defaults to
1000, which is also the hard ceiling.
* `streaming` — when `true`, companies are POSTed one at a time instead of in a
single payload
* `name` — optional import name
Resolve technology names to slugs with the
[Technology slug lookup](/api-reference/endpoints/miscellaneous/technologies)
endpoint.
## Example request
```json theme={null}
{
"stacks": ["shopify"],
"stack_match": "and",
"countries": ["US"],
"limit": 200,
"webhook_url": "https://your-company.com/webhooks/stack"
}
```
## Example response
```json theme={null}
{
"message": {
"total_count": 200,
"total_available": 428,
"message": "Stack intent search started successfully. You will receive the results on your webhook shortly.",
"id": "b3f1c2d4-0000-0000-0000-000000000000"
}
}
```
* `total_available` is the full match count; `total_count` is what will be
imported (capped by `limit`, then the 1000 ceiling).
* When nothing matches, the response is `200` with `{ "total_count": 0, ... }`
and no import is created.
## Webhook payload
Companies are delivered to your `webhook_url` using the same field names as the
other company imports: `name`, `description`, `website`, `logo`, `industry`,
`location`, `linkedin_id`, `linkedin_url`, `employee_count`, `employee_range`.
Blank fields are omitted.
# Find companies by tech stack (preview)
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/tech_stack_preview
POST /intents/accounts/stack/preview
Count and preview companies using a given technology stack
Size a segment of companies by the technologies they use before spending any
credits. This is the free, first step of the two-step tech-stack search:
1. **Preview** (this endpoint) — returns the exact total match count plus a
blurred company sample. No credits.
2. **[Extract](/api-reference/endpoints/signals/tech_stack)** — starts an async
import and delivers the full company records to your webhook. Spends
enrichment credits.
Technographics are powered by TheirStack.
## Credits and rate limits
* Credits: **free** — no credits are spent
* Authentication: standard v2 scheme (`X-API-KEY`)
## Resolving technology slugs
`stacks` and `excluded_stacks` take technology **slugs**, not display names.
Resolve names to slugs with the
[Technology slug lookup](/api-reference/endpoints/miscellaneous/technologies)
endpoint.
## Example request
```json theme={null}
{
"stacks": ["shopify", "webflow"],
"stack_match": "or",
"countries": ["US", "FR"],
"included_industries": ["2190"],
"company_size": ["11-50", "51-200"]
}
```
## Example response
```json theme={null}
{
"total_count": 428,
"preview": [
{
"name": "Acme",
"domain": "acme.com",
"website": "https://acme.com",
"industry": "Software Development",
"location": "Paris France",
"city": "Paris",
"country": "France",
"linkedin_url": "https://linkedin.com/company/acme",
"technologies_found": [
{ "technology_name": "Shopify", "confidence": "high", "job_mentions": 3 }
]
}
]
}
```
Company identifiers in the preview may be blurred; `total_count` is exact.
For the complete list of industry IDs used by `included_industries` /
`excluded_industries`, see the
[LinkedIn Industry List](https://docs.google.com/spreadsheets/d/1qTFPVfcSHnL5PU1AcQlzD8mCmfSICKJ4WuU-OBGhkdI/edit?gid=0#gid=0).
# Track job changes
Source: https://docs.pipecorn.com/api-reference/endpoints/signals/track_job_changes
POST /intents/leads/track_job_changes
Track job changes for a list of LinkedIn profiles
This endpoint allows you to monitor job changes for a list of contacts on LinkedIn. When any of the tracked contacts changes their job, you'll receive a notification through the specified webhook URL.
## Use Cases
* Monitor when your champions or product users change jobs
* Track career movements of potential leads
* Stay informed about your network's professional changes
## Important Notes
* You can identify contacts either by their LinkedIn URL or by their name and current company
* The system checks for job changes monthly, so a change is reported in the monthly check that follows it rather than the day it happens
## Contact Identification
You can identify contacts in two ways:
1. **Using LinkedIn URL**
```json theme={null}
{
"linkedin_url": "https://www.linkedin.com/in/mathieu-brun-picard/"
}
```
2. **Using Name and Company**
```json theme={null}
{
"first_name": "Nicolas",
"last_name": "Fernandez Le Follic",
"company_name": "Pipecorn"
}
```
## Webhook Notifications
When a contact changes their job, you'll receive a webhook notification with details about the change. Make sure your webhook endpoint is ready to receive POST requests.
# Credit and limit errors
Source: https://docs.pipecorn.com/api-reference/errors
How the API reports an exhausted credit balance and workspace spending limits
Every endpoint that spends enrichment credits checks your balance before doing
any work. When that check fails, the API answers with a dedicated status code
and a machine-readable `code`, so your integration can tell "top up and retry"
apart from "this request will never succeed as-is".
## `402 Payment Required` — out of credits
The request was valid, but your workspace does not have enough enrichment
credits to pay for it. No credits are spent, and nothing is enqueued or
imported.
```json theme={null}
{
"error": "Not enough enrichment credits left",
"code": "insufficient_credits",
"top_up_url": "https://app.pipecorn.com/settings/subscriptions/credits"
}
```
| Field | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `error` | Human-readable message. Endpoints priced per result report the shortfall instead, e.g. `"Not enough enrichment credits. You need 30 credits but only have 5 available."` |
| `code` | Always `insufficient_credits`. |
| `top_up_url` | Absolute URL of your credits page. Send users there to buy credits, then replay the request. |
`402` is retryable: top up (or wait for your plan to renew) and send the same
request again.
You can also receive `402` after the pre-flight check passes, if a concurrent
request drains the balance before this one is charged. Treat it the same way.
## `403 Forbidden` — workspace weekly limit reached
Your workspace has a weekly enrichment credit limit and this request would
exceed it. The balance itself is irrelevant here, so no `top_up_url` is
returned — buying credits does not lift the limit.
```json theme={null}
{
"error": "You have reached your weekly enrichment credit limit for this workspace",
"code": "workspace_limit_exceeded"
}
```
To unblock, a workspace admin has to raise the member's weekly allowance, or
you wait for the limit to reset.
`403` is also returned when an API key does not have access to an endpoint.
Branch on `code`, not on the status alone: `workspace_limit_exceeded` is a
spending limit, anything else is a permission problem.
When both conditions apply — the balance is too low *and* the weekly limit is
reached — the API reports the balance first, with `402`.
## Endpoints that return these codes
* [`POST /contacts/single_enrich` (async)](/api-reference/endpoints/enrichments/single) and [`POST /contacts/bulk_enrich`](/api-reference/endpoints/enrichments/batch)
* [`POST /contacts/single_enrich` (synchronous)](/api-reference/endpoints/contacts/sync_single_enrich)
* [`POST /accounts/single_enrich`](/api-reference/endpoints/accounts/single)
* [`POST /leads/single_enrich`](/api-reference/endpoints/leads/single)
* [`POST /accounts/company_hiring`](/api-reference/endpoints/accounts/company-hiring)
* [`POST /accounts/company_stack`](/api-reference/endpoints/accounts/company-stack)
* [`POST /intents/accounts/hiring`](/api-reference/endpoints/signals/hiring)
* [`POST /intents/accounts/stack`](/api-reference/endpoints/signals/tech_stack)
* `POST /whatsapp_validations`
Preview endpoints are free and never return either code.
Every one of them checks credits up-front, so a rejected request never runs a
provider, creates an import, or enqueues an enrichment.
## Migrating from the previous behaviour
These conditions used to be reported as:
* `422 Unprocessable Entity` — waterfall enrichment (async, bulk, and
synchronous), WhatsApp validation, `POST /accounts/company_hiring`, and
`POST /accounts/company_stack`
* `422 Unprocessable Entity` with a plan-limit message — `POST /accounts/single_enrich`
(`"Not enough company import limits left"`) and `POST /leads/single_enrich`
(`"Not enough profile extraction limits left"`). Both are now priced in credits
and answer `402`/`403` instead; they no longer draw on those plan quotas at all.
* `401 Unauthorized` — `POST /intents/accounts/hiring` and
`POST /intents/accounts/stack`
These now answer `402` (or `403` for a workspace weekly limit). If your
integration detects an empty balance by matching on `422`/`401`, or by
string-matching the message, switch to the status code and `code` field. `422`
still covers validation errors and `401` still covers authentication, so the
old checks will silently stop firing.
# Docs for LLMs
Source: https://docs.pipecorn.com/api-reference/llms
Machine-readable versions of this documentation, including the whole site as a single file, for AI assistants and coding agents.
This documentation is published in formats that AI assistants can read
directly, so you can hand an LLM the full Pipecorn API reference instead of
pasting pages one at a time.
## The files
| File | What it contains | Use it when |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| [`llms-full.txt`](https://docs.pipecorn.com/llms-full.txt) | **Every page of this documentation concatenated into one file**, including endpoint references, error codes, and the [credits vs limits](/api-reference/credits-vs-limits) guide | You want the model to know the whole API in one shot |
| [`llms.txt`](https://docs.pipecorn.com/llms.txt) | A short index: one line per page with a link and a summary | You want a small context footprint and let the model fetch what it needs |
| [`agents.md`](https://docs.pipecorn.com/agents.md) | Agent-facing guide: which surface to use (MCP, REST, CLI), conventions to follow, auth | You are building an agent that acts on Pipecorn, not just reads about it |
Both `llms.txt` files follow the [llms.txt convention](https://llmstxt.org)
and are regenerated on every docs deploy, so they always match the pages you
see here.
```text theme={null}
https://docs.pipecorn.com/llms-full.txt
https://docs.pipecorn.com/llms.txt
https://docs.pipecorn.com/agents.md
```
## How to use them
Paste the `llms-full.txt` URL into the conversation and ask your question.
Both assistants fetch the file and answer from it. For long sessions,
attach it to a Project so it stays in context.
Ask Claude Code to read the file, or point it at the URL in a prompt:
```text theme={null}
Read https://docs.pipecorn.com/llms-full.txt, then write a script that
enriches the contacts in leads.csv with the Pipecorn bulk enrichment endpoint.
```
Add the URL to your project's `CLAUDE.md` if you integrate Pipecorn regularly.
Open **Settings → Features → Docs**, click **Add new doc**, and paste
`https://docs.pipecorn.com/llms-full.txt`. It then shows up under `@Docs`
in chat.
Fetch `llms-full.txt` at build time or on first use and put it in the
system prompt or a retrieval index. Fetch `llms.txt` instead when context
is tight, and let the agent follow links.
## Reading vs acting
These files let a model **read** about the API. If you want the model to
**call** Pipecorn (search companies, extract leads, enrich contacts) from a
chat, connect the [MCP server](/mcp/overview) instead. The two work well
together: the MCP server exposes the tools, and `llms-full.txt` explains the
concepts behind them, such as the difference between
[credits and limits](/api-reference/credits-vs-limits).
Machine-readable discovery for the MCP server lives at
[`/.well-known/mcp.json`](https://docs.pipecorn.com/.well-known/mcp.json).
# Main use cases
Source: https://docs.pipecorn.com/api-reference/main-use-cases
What you can build with the Pipecorn API: find people, enrich accounts, and run waterfall enrichment.
## How to use Pipecorn API
Find leads using live data in a specific company
-> 2x results than Clay
Enrich company accounts with specific data
-> # of SDR, Growth rate,...
Enrich contacts with email & phone
-> 20+ sources
## Get my API key
You need your personal API key to use the Pipecorn API, which you can generate [here](https://app.pipecorn.com/settings/apis/keys).
# API reference
Source: https://docs.pipecorn.com/api-reference/overview
Base URL, authentication, and a map of every Pipecorn REST endpoint: leads, accounts, waterfall enrichment, signals, searches, personas, lists, and utilities.
The Pipecorn REST API gives you programmatic access to the same data as the
[web app](https://app.pipecorn.com): search and extract leads, enrich
companies and contacts, pull buying signals, and manage Sales Navigator lists.
Every endpoint below is documented with its parameters, an interactive
request builder, and example responses.
| | |
| ------------------ | ---------------------------------------------------------------------------------------------------- |
| **Base URL** | `https://app.pipecorn.com/api/v2/` |
| **Authentication** | `X-API-KEY` header. Get a key from [API keys](https://app.pipecorn.com/settings/apis/keys) |
| **Format** | JSON request and response bodies |
| **Metering** | Enrichment spends [credits](/api-reference/credits-vs-limits); extraction counts against plan limits |
## Your first request
Check your credit balance and plan limits. This call is free and confirms your
key works.
```bash theme={null}
curl https://app.pipecorn.com/api/v2/credits \
-H "X-API-KEY: your_api_key"
```
If the key is wrong you get a `401`. See [Credit and limit errors](/api-reference/errors)
for the `402`, `403`, and `422` responses that metering can return.
## Endpoints
Search people by title, seniority, location, and industry. Extract leads
from a company or from Sales Navigator, and enrich a single person.
Search companies by firmographics, enrich a single account, and pull
headcount by department, tech stack, and open job postings.
Find verified business emails and phones through 20+ sources, one contact
at a time, in batches, or synchronously.
Hiring, growth, lookalike companies, tech-stack search, new hires, job
changes, and LinkedIn posts, comments, reactions, and engagers.
List, inspect, and delete the saved searches your extractions create.
Read the personas that define your ideal buyer profiles.
Create and update Sales Navigator lists and read their contents.
Credit balance and consumption, account information, location IDs, and
technology slugs.
## Before you build
* [Main use cases](/api-reference/main-use-cases) walks through the three
flows most integrations start with.
* [Authentication](/essentials/authentification) covers the header format and
key management.
* [Credits vs limits](/api-reference/credits-vs-limits) explains which
requests spend credits and which draw on plan quotas.
* Prefer not to write HTTP calls? The [CLI](/cli/overview) and the
[MCP server](/mcp/overview) wrap this API.
# Retrieve a specific list
Source: https://docs.pipecorn.com/api-reference/retrieve-a-specific-list
/api-reference/specs/list.json get /lists/{id}
Returns a specific list by its ID.
# Retrieve all lists
Source: https://docs.pipecorn.com/api-reference/retrieve-all-lists
/api-reference/specs/list.json get /lists
Returns all lists from the system that the user has access to.
# Update a list
Source: https://docs.pipecorn.com/api-reference/update-a-list
/api-reference/specs/list.json put /lists/{id}
Updates a list in the system.
# Changelog
Source: https://docs.pipecorn.com/changelog
Recent updates and improvements to the Pipecorn API.
## Week of August 23, 2026
### Updates
* **Enrich account and Enrich people are now credit-based.** [`POST /accounts/single_enrich`](/api-reference/endpoints/accounts/single) and [`POST /leads/single_enrich`](/api-reference/endpoints/leads/single) cost **1 credit per enrichment**, charged only when a company or person is actually resolved — a lookup that matches nothing costs nothing.
Two things change with it:
* **No more plan quotas on these endpoints.** They used to draw on your company import and profile extraction limits and fail with `422` when those ran out. They no longer touch either quota; an empty balance is now reported as [`402`](/api-reference/errors), and a workspace weekly limit as `403`.
* **No more rate limits.** The per-second and per-day caps are gone. A credit is a finite paid resource, so it is the only thing that throttles these endpoints.
* **Account info now returns your email.** [`GET /account`](/api-reference/endpoints/miscellaneous/get-account-info) includes `account.email`, the email address of the user the API key belongs to, so you can tell which Pipecorn account a key authenticates as without asking. The response also documents the `integrations` block (`linkedin_session_valid`, `sales_navigator_session_valid`) it has always returned.
```json theme={null}
{
"account": {
"plan": "scale",
"email": "jane@acme.com"
},
"integrations": {
"linkedin_session_valid": true,
"sales_navigator_session_valid": true
}
}
```
## Week of August 16, 2026
### Updates
* **`402` and `403` for credit and limit failures.** Running out of enrichment credits now returns `402 Payment Required` with a machine-readable `code` and a `top_up_url` pointing at your credits page, instead of `422` (waterfall enrichment, WhatsApp validation, [`POST /accounts/company_hiring`](/api-reference/endpoints/accounts/company-hiring), [`POST /accounts/company_stack`](/api-reference/endpoints/accounts/company-stack)) or `401` ([`POST /intents/accounts/hiring`](/api-reference/endpoints/signals/hiring), [`POST /intents/accounts/stack`](/api-reference/endpoints/signals/tech_stack)).
A workspace weekly credit limit is now reported separately as `403 Forbidden` with `code: "workspace_limit_exceeded"` and no `top_up_url` — buying credits does not lift it. The two used to collapse into the same response.
The [synchronous waterfall endpoint](/api-reference/endpoints/contacts/sync_single_enrich) also gained an up-front credit check. It previously only failed once the waterfall tried to charge, and it did not enforce workspace weekly limits at all; it now answers `402`/`403` before any provider is called, like every other credit-spending endpoint.
```json theme={null}
{
"error": "Not enough enrichment credits left",
"code": "insufficient_credits",
"top_up_url": "https://app.pipecorn.com/settings/subscriptions/credits"
}
```
If your integration detects an empty balance by matching on `422`/`401` or on the message text, switch to the status code and `code` field — `422` still covers validation errors and `401` still covers authentication, so the old checks will silently stop firing. Full details in [Credit and limit errors](/api-reference/errors).
## Week of July 26, 2026
### New features
* **Credit consumption over a date range.** [`GET /credits_consumption`](/api-reference/endpoints/miscellaneous/credit-consumption) returns your current credit balance alongside the total enrichment credits consumed between two dates. Pass `start_date` and `end_date` as `YYYY-MM-DD` query parameters (both inclusive, interpreted in UTC); the response echoes the range back and includes `credits_consumed`. Missing, malformed, or reversed dates return `422`.
## Week of July 12, 2026
### New features
* **Find companies by tech stack (technographics).** Search the company database by the technologies companies use, powered by TheirStack. It's a two-step flow so you can size a segment before spending credits:
* [`POST /intents/accounts/stack/preview`](/api-reference/endpoints/signals/tech_stack_preview) returns the exact match count plus a blurred company sample — free, no credits.
* [`POST /intents/accounts/stack`](/api-reference/endpoints/signals/tech_stack) starts an async import and delivers the full company records to your `webhook_url`, spending **3 enrichment credits per company**.
Both accept `stacks` / `excluded_stacks` (technology slugs), `stack_match` (`or` / `and`), `countries`, `included_industries` / `excluded_industries`, and `company_size`. Resolve technology names to the slugs these endpoints expect with the new [`GET /accounts/technologies`](/api-reference/endpoints/miscellaneous/technologies) lookup (free).
## Week of July 5, 2026
### Updates
* **Company hiring — per-job billing, filters, and limits.** [`POST /accounts/company_hiring`](/api-reference/endpoints/accounts/company-hiring) now charges **1 credit per job returned** (previously a flat 3 credits per request), and never returns more jobs than your available credits allow — a lookup that returns no jobs costs nothing. New optional parameters let you narrow and bound results:
* `limit` — cap the number of jobs returned (positive integer, max 100), which also caps the credits a single lookup can spend.
* `job_title_keywords` / `excluded_job_title_keywords`, `job_description_keywords` / `excluded_job_description_keywords` — include or exclude jobs by title and description keywords.
* `job_country_codes` / `excluded_job_country_codes` — include or exclude jobs by 2-letter ISO 3166-1 alpha-2 country code.
* `full_description` — return full job descriptions; by default descriptions are truncated to a 300-character snippet.
Responses now include a `truncated` boolean flagging when more jobs matched than were returned. The endpoint's rate limit is now **5 requests per second** (down from 20).
## Week of June 14, 2026
### Updates
* **`live` parameter — search and enrich from Pipecorn's database.** LinkedIn-backed endpoints now accept an optional `live` boolean (default `true`). Set `live: false` to serve results from Pipecorn's people and companies database (Elasticsearch) instead of calling LinkedIn / Sales Navigator in real time — no integration required, and no LinkedIn rate limits. Supported on:
* [`POST /leads/advanced_search`](/api-reference/endpoints/leads/advanced_search) and its [preview](/api-reference/endpoints/leads/advanced_search_preview)
* [`POST /leads/search`](/api-reference/endpoints/extract/leads_from_company) (Find people at company)
* [`POST /leads/single_enrich`](/api-reference/endpoints/leads/single)
* [`POST /accounts/search`](/api-reference/endpoints/accounts/search) and its [preview](/api-reference/endpoints/accounts/search_preview)
* [`POST /accounts/single_enrich`](/api-reference/endpoints/accounts/single)
* [`POST /accounts/headcount`](/api-reference/endpoints/accounts/headcount)
Database mode returns a Pipecorn-formatted response that can differ from the live LinkedIn payload (for example, `single_enrich` omits email/phone and `headcount` returns a current snapshot without 3/6/12-month evolution). On `POST /leads/advanced_search`, relationship/signal filters that only exist in LinkedIn's graph (`connections_of_profile`, `relationship`, `follows_your_company`, `viewed_your_profile`, `with_shared_experiences`, `posted_on_linkedin`, `past_colleague`) are rejected with `422` when `live: false`. A non-boolean `live` value returns `422`.
## Week of May 31, 2026
### New features
* **Company hiring (job postings).** The new [`POST /accounts/company_hiring`](/api-reference/endpoints/accounts/company-hiring) endpoint returns the list of open job postings indexed for a company. Identify the company with `company_domain`, `company_name`, or `company_linkedin_url`, and optionally narrow to recent posts with `posted_within_days`. Each job includes title, URL, location, employment status, posting date, description, hiring team, and company info. Costs 3 credits per request and is rate-limited to 20 requests per second.
## Week of May 10, 2026
### Updates
* **Filter leads by connections of a profile.** [`POST /leads/advanced_search`](/api-reference/endpoints/leads/advanced_search) and its [preview](/api-reference/endpoints/leads/advanced_search_preview) now accept `connections_of_profile`, a LinkedIn profile URL whose 1st-degree connections become the search audience. Combine it with the usual title, seniority, function, and company filters to mine a specific person's network.
* **Personal email enrichment.** Waterfall enrichment now supports `personal_email` as an `enrichment_type` on both the [async](/api-reference/endpoints/contacts/single_enrich) and [synchronous](/api-reference/endpoints/contacts/sync_single_enrich) waterfall endpoints (single and bulk). Combine it with `email` and `phone` in a single call to retrieve professional email, personal email, and phone in one waterfall. Requests with `personal_email` (or `phone`) must include `linkedin_url`, and personal email enrichment requires per-user GDPR consent — without it, the API returns `422`.
* **Scope phone lookups by country.** All [waterfall enrichment endpoints](/api-reference/endpoints/contacts/single_enrich) (sync, async single, and async bulk) now accept an optional `phone_country_codes` array. Pass ISO country codes to restrict phone results to specific regions and avoid spending credits on out-of-scope numbers.
* **Validation status on enriched emails.** Contact responses now include `email_status` (and `personal_email_status` once a personal email is found) so you can see at a glance whether each address is `valid`, `risky`, or `invalid` without a separate verification call. Returned by [`GET /contacts/{id}`](/api-reference/endpoints/contacts/single_enrich) and the synchronous waterfall.
* **Multiple phone numbers per contact.** The `phone` field in waterfall responses is now an array of E.164-formatted strings, so contacts with several numbers no longer have results truncated to one.
## Week of May 3, 2026
### New features
* **Advanced lead search.** The new [`POST /leads/advanced_search`](/api-reference/endpoints/leads/advanced_search) endpoint runs a full lead search from a structured filter set (titles, seniority, function, tenure, locations, industries, company size, signals, and more) and streams enriched leads to your webhook. No need to build a Sales Navigator URL yourself — Pipecorn translates the filters for you.
* **Search previews for leads and accounts.** Validate filters and size an audience before kicking off a full run. The new preview endpoints return synchronously with the total estimated count plus the first 25 matches, and don't consume credits or trigger webhooks:
* [`POST /leads/advanced_search/preview`](/api-reference/endpoints/leads/advanced_search_preview)
* [`POST /accounts/search/preview`](/api-reference/endpoints/accounts/search_preview)
### Updates
* **Engagement counts on LinkedIn posts.** [Extract posts](/api-reference/endpoints/signals/posts) responses now include `engagement_count`, `reactions_count`, and `comments_count` for each post, so you can rank or filter content by traction without a second call.
* **More MCP tools.** The [Pipecorn MCP server](/mcp/tools) now exposes `advanced_search_leads` for filter-based lead search, plus list management tools (`create_list`, `get_lists`, `get_list`, `update_list`) so AI assistants can build and update Sales Navigator lists on your behalf.
## Week of April 26, 2026
### New features
* **MCP server for AI assistants.** Connect any MCP-compatible AI assistant — including Claude Desktop, Claude Code, and Cursor — directly to Pipecorn. Once installed, your assistant can find companies, search leads, and enrich contacts from a chat interface using your existing API key. See the [MCP server guide](/mcp/overview) for installation instructions and example prompts.
* **Search by saved Persona on Find People in Company.** You can now pass a `persona_id` to the [Find People in Company](/api-reference/endpoints/extract/leads_from_company) endpoint to drive a search from a Persona you've already defined in Pipecorn. When `persona_id` is provided, included and excluded job titles are taken from the saved Persona — no need to inline them in the request.
Pass one or the other: combining `persona_id` with `job_titles` or `excluded_job_titles` returns a `422`. See the [Personas endpoints](/api-reference/endpoints/personas/index) to list available Persona IDs.
### Updates
* **More flexible people filters on Find People in Company.** [Find People in Company](/api-reference/endpoints/extract/leads_from_company) now accepts any one of `job_titles`, `excluded_job_titles`, `functions`, `seniority_levels`, `included_locations`, `excluded_locations`, or `persona_id` to satisfy the "at least one filter" requirement. Previously only `job_titles` or `persona_id` counted. Requests with none of these return `400`.
# Command reference
Source: https://docs.pipecorn.com/cli/commands
Every pipecorn CLI command with its arguments, flags, and examples.
Every command, argument and flag of the `pipecorn` CLI. Global flags (`--api-key`, `--format`, `--quiet`, `-o`) are accepted by every command; see the [overview](/cli/overview) for install and authentication.
This reference is generated from the CLI's command classes and mirrors the
[README of the `cli-pipecorn` repository](https://github.com/Pipecorn/cli-pipecorn). If a flag here
disagrees with `pipecorn help ` on your machine, the CLI is right and you likely need to update it.
## Authentication
### `pipecorn login [KEY]`
Save a Pipecorn API key locally after validating it against the API.
```
USAGE
$ pipecorn login [KEY] [--api-key ] [--format json|csv|table] [--quiet] [-o ] [--base-url
]
ARGUMENTS
[KEY] API key (omit to read from --api-key or env)
FLAGS
--api-key= [env: PIPECORN_API_KEY] API key value
--base-url= Override API base URL (default: https://app.pipecorn.com/api/v2)
GLOBAL FLAGS
-o, --output= Write output to a file instead of stdout
--format=