> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lusha.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> All notable changes to the Lusha API and MCP. We follow semantic versioning.

All notable changes to the Lusha API and MCP are documented here. We follow semantic versioning.

<Info>
  **Current Version: 2.16.0**
  Status: Production · Released: September 2026 · Stability: Stable (Tables API is Beta)
</Info>

<Update label="2026-09-23" description="v2.16.0 - Company ownership: direct and ultimate parent" tags={["Enrichment", "Lookalikes"]}>
  **Added**

  **`directParent` and `ultimateParent` on Company Enrichment** - Added two premium reveal fields exposing a company's ownership tree: its immediate parent, and the company at the top of the tree.

  * `POST /v3/companies/enrich` - request via `reveal: ["directParent", "ultimateParent"]`
  * `POST /v3/companies/search-and-enrich` - same `reveal` field, same tokens. Both fields must be requested explicitly; neither is returned by default
  * `POST /v3/companies/search` - both appear in the `canReveal` array, alongside fields like `monthlyWebsiteTraffic`, so you can check availability and cost before paying to reveal
  * Each returns an object with `lushaCompanyId`, `name`, `domain`, and (where held) `hqCountry`
  * Pass the returned `lushaCompanyId` back to Enrich Companies to retrieve the parent's full firmographic profile
  * Charged 1 credit per field when non-null; no charge when the company has no known parent
  * `null` when the company is independent or is itself the ultimate parent. For a company with a single level of ownership, `ultimateParent` matches `directParent`
  * Both fields are listed in the `has` and `canReveal` arrays on the enrich response

  **Changed**

  **Data Waterfall available on all paid plans** - Data Waterfall was previously limited to Pro plans and above. It is now available on every paid plan. No API change - this is a packaging change only, and the feature is still enabled per account under **Account Settings → Waterfall**.

  **Fixed**

  **Lookalikes: seed requirements corrected** - The 5–100 seed requirement on `POST /v3/contacts/lookalike` and `POST /v3/companies/lookalike` was documented only in prose and was absent from the schema, and the request examples on both endpoints sent fewer than 5 seeds, so copying them produced a `400`.

  * The minimum and maximum are now stated on the operation and on the `seeds` property, including that the count is across all identifier types combined
  * Request examples on both endpoints now send 6 seeds
  * `ContactIdentifiersBatch` was marked `nullable: true` while `seeds` was `required`, which is contradictory. `nullable` has been removed and `minProperties: 1` added, matching `CompanyIdentifiersBatch`
  * Behavior is unchanged - only the documentation was wrong

  **Search & Enrich Companies: `reveal` field documented** - `POST /v3/companies/search-and-enrich` accepts the same `reveal` field and the same tokens as Enrich Companies, but the request schema did not document it at all. `reveal` has been added to `V3CompaniesSearchAndEnrichRequest`. Behavior is unchanged - only the documentation was wrong.

  **Corrected**

  **2026-09-25** - This entry originally stated that `POST /v3/companies/search-and-enrich` takes no `reveal` field and returns every available premium data point automatically. That is not how the endpoint works: it accepts `reveal` exactly as Enrich Companies does, and `directParent` / `ultimateParent` are returned **only** when named in `reveal`. Any integration expecting ownership data without passing `reveal` will get none. The spec, the Search & Enrich tag description, and the request example have all been corrected.

  **Notes**

  * `ipoDate` and `stockSymbol` remain Tables-only columns and are still not returned by Enrich Companies
  * Ownership data is company-level and contains no personal information
</Update>

<Update label="2026-09-17" description="v2.15.0 - Company social links: Instagram, YouTube, TikTok" tags={["Enrichment"]}>
  **Added**

  **Instagram, YouTube, and TikTok on Enrich Companies** - Added `instagram`, `youtube`, and `tiktok` to the `socialLinks` object returned by `POST /v3/companies/enrich` (alongside the existing `linkedin`, `facebook`, and `x`).

  * Included automatically whenever Lusha holds the data - no `reveal` entry needed to unlock them
  * Free field - no additional credits charged
  * Available on all plans
  * Each is returned as a list of URLs rather than a single string, since a company can legitimately hold more than one profile on a network (multiple YouTube channels are common) - every value Lusha holds is returned
  * Omitted from the response entirely when no data is available for that network (never returned as `null` or an empty list)
  * Company-level data, contains no personal information, refreshed monthly

  **Notes**

  * Nested under `socialLinks` for consistency with the existing `linkedin`, `facebook`, and `x` fields, rather than returned as top-level siblings
  * Extends the pattern introduced for `facebook` and `x` in 2.10.0, with the added list shape to account for networks where a company can hold multiple profiles
</Update>

<Update label="2026-09-10" description="v2.14.0 - Tables: column catalog and add columns" tags={["Tables"]}>
  **Added**

  **Lusha column catalog** - Added a discovery endpoint listing every Lusha data column that can be added to a table.

  * `GET /v3/contacts/tables/columns` - 22 columns
  * `GET /v3/companies/tables/columns` - 46 columns

  No request body and no parameters. Each entry returns the column's `category`, `displayName` (e.g. "Job title"), `columnKey` (e.g. `jobTitle` - the key you pass when adding the column) and `type` (`string` / `number` / `object`).

  This is **not** the same as `GET /v3/{contacts|companies}/tables/{table_id}/columns`, which lists the columns a specific table already has. The catalog lists what's available to add.

  **Add columns to a table** - Added `POST /v3/{contacts|companies}/tables/{table_id}/columns` - adds up to 10 Lusha columns in one call and starts enriching them automatically.

  * Body is either `columns: [{ "columnKey": "jobTitle" }, ...]` or a single `columnKey` for one column
  * Keys come straight from the catalog endpoint
  * The response returns one entry per requested column with its own `status` (`added` / `failed`) and new `columnId`
  * Columns are handled independently - if one fails, the rest still go through
  * Most common failure is the column already being on the table, which returns the existing `columnId`, so the call is safe to re-run
  * Enrichment always runs on **all rows** in the table

  **Notes**

  * **Billing:** both endpoints are free today - credits aren't charged for the catalog or for adding columns yet
  * Enrichment kicked off by an add is asynchronous - poll Get Table for `isProcessing` and per-column row-status counts, then read values via Get Table Entities
  * Supersedes the Add Column pullback in 2.6.0. The endpoint returns in a different shape than the one documented in 2.5.0: it is catalog-key driven (`columnKey`) and accepts up to 10 columns per call, rather than the single-column `name` / `type` / `key` / `meta` body originally published. Since the 2.5.0 version was never functional, no working integration is affected
  * Adding columns is now reflected in the free-operations list on both the Contacts Tables and Companies Tables tag descriptions
</Update>

<Update label="2026-09-04" description="v2.8.0 - Buying Group, Signal Score, and Conversations" tags={["Buying Group", "Signals", "Conversations"]}>
  **Added**

  **Buying Group API** - Added `POST /v3/contacts/buying-group` - map the buying committee across up to 25 target companies.

  * Each returned contact is labelled with a persona role: `decision_maker`, `potential_champion`, or `end_user`
  * Pass `personas` to filter to specific roles, or omit it to return all three
  * `contactsLimit` caps contacts returned per company (default 60)
  * Results are free previews grouped by company, with `has` and `canReveal` per contact
  * Billed per contact returned, via the `buyingGroupContact` action

  **Signal Score API** - Added `POST /v3/contacts/signal-score` and `POST /v3/companies/signal-score` - a single `[0, 1]` buying-activity score per record, with the active signal breakdown behind it.

  * Accepts up to 100 records per call; identity is resolved server-side without revealing PII
  * Each result is a scored entry, a `NOT_FOUND` entry, or a new `NO_SCORE` entry
  * `NO_SCORE` added to the per-item error enum

  **Conversations API** - Added `POST /v3/account/conversations/search` and `GET /v3/account/conversations/{conversationId}/transcript`.

  * Search runs in keyword mode (supply `query`) or filter mode (omit `query`); the two do not combine
  * Search returns metadata, AI summary, action items, risks, objections, competitor mentions, coaching analysis, and chapters - transcripts are fetched separately
  * `summary`, `coaching`, and `chapters` are `null`/empty until the async pipeline completes

  **Removed**

  **Decision Makers API** - `POST /v3/contacts/decision-makers` has been retired and removed from the API reference. Use [Buying Group](/buying-group/overview), which covers the same use case with a broader persona set and per-contact relevance scoring.
</Update>

<Update label="2026-08-18" description="v2.12.0 - Prospecting contacts: per-company cap and exact totals" tags={["Prospecting"]}>
  **Added**

  **`maxContactsPerCompany` on Prospecting Contacts** - Added optional `options.maxContactsPerCompany` to `POST /v3/contacts/prospecting`.

  * Caps how many contacts are returned per company (accepts 1-20); omit for uncapped results
  * Caps contacts per company, **not** the page size - `pagination.size` still controls the page size

  **Exact-total pagination fields** - The `pagination` object on the Prospecting Contacts response can now include two optional fields:

  * `totalGuaranteed` - `true` when `total` is an exact count rather than an estimate
  * `totalDescription` - human-readable explanation of `total` (e.g. "Exact contact count (up to 2 per company)")

  Both keys are omitted from the response when not returned.

  **Notes**

  * Additive and backward compatible - existing requests are unaffected
  * The two pagination fields are scoped to the Prospecting Contacts response and do not appear on other paginated endpoints
</Update>

<Update label="2026-08-17" description="v2.11.0 - Open job postings on company enrichment" tags={["Enrichment"]}>
  **Added**

  **Open Job Postings on Enrich Companies** - Added four new independently revealable fields to `POST /v3/companies/enrich`, requested via the existing `reveal` array:

  * `openJobsTotal` - reveals the total open job count. In the response, this appears as the `total` field inside the `openJobs` object
  * `openJobsByDepartment` - reveals open job counts broken down by department. In the response, this appears as the `byDepartment` field inside the `openJobs` object
  * `openJobsByLocation` - reveals open job counts broken down by location. In the response, this appears as the `byLocation` field inside the `openJobs` object
  * `openJobsBySeniority` - reveals open job counts broken down by seniority level. In the response, this appears as the `bySeniority` field inside the `openJobs` object

  All four values are nested under a single `openJobs` object rather than returned as separate top-level fields, so a result with multiple sub-fields revealed reads as one grouped object. `openJobs` appears in `has[]` when any data exists for the company, and each of the four tokens appears in `canReveal[]`. A sub-field with no data is omitted from the response.

  **Notes**

  * Follows the same reveal pattern as `estimatedAnnualItSpend` and `monthlyWebsiteTraffic`
  * Department, location, and seniority vocabularies reuse the existing prospecting filter lists
</Update>

<Update label="2026-08-13" description="v2.10.0 - Company social links expansion" tags={["Enrichment"]}>
  **Added**

  **Facebook and X on Enrich Companies** - Added `facebook` and `x` to the `socialLinks` object returned by `POST /v3/companies/enrich` (alongside the existing `linkedin`).

  * Included automatically when available - no `reveal` entry needed to unlock them
  * Omitted from the response when not available (never returned as an empty string)
  * Free field - no additional credits charged
  * Available on all plans

  **Notes**

  * Nested under `socialLinks` for consistency with the existing `linkedin` field, rather than returned as top-level siblings
</Update>

<Update label="2026-08-05" description="v2.7.0 - LinkedIn Activity Intent Signal" tags={["Signals", "Prospecting"]}>
  **Added**

  **LinkedIn Activity Intent Signal** - Added `linkedinActivityIntent` as a new company signal type, available in Company Prospecting, Company Signals Lookup, and Signal Metadata/Discovery.

  * `POST /v3/companies/prospecting` - `filters.companies.include.signals.types` accepts `linkedinActivityIntent` (also selectable via `allSignals`). New optional `filterByIntentCategory` array narrows results to specific Bombora intent categories; omit to match all categories
  * `POST /v3/companies/signals` - `signalTypes` accepts `linkedinActivityIntent` (also via `allSignals`). New optional `filters.include.intentCategories` array applies the same category refinement
  * Each per-company result now includes a `linkedinActivityIntent` array of LinkedIn posts, with fields for publication date, signal category, detected Bombora topics, author, mentioned contacts/companies, post URL, an AI-generated summary, and engagement counts (likes, comments, shares)
  * `GET /v3/companies/signals/types` - `linkedinActivityIntent` now included in the returned list
  * `GET /v3/companies/signals/filters` - new `intentCategories` entry added to `availableFilters`
  * `GET /v3/companies/signals/filters/intentCategories` - new filter-value endpoint returning the full list of Bombora intent categories

  **Notes**

  * Legal limit: for `linkedinActivityIntent`, `startDate` is capped to a trailing 90-day window regardless of the value passed
  * Results cap: for `linkedinActivityIntent`, `maxResultsPerSignal` is capped at 50 per company regardless of the value passed
  * `activitySummary` is AI-generated and never contains the raw post text
  * `author`, `contactsMentioned`, and `companiesMentioned` resolve to Lusha IDs where possible; unresolved people or companies return `id: null`
  * The query parameter is not supported on `GET /v3/companies/signals/filters/intentCategories`; passing one returns 400
</Update>

<Update label="2026-07-27" description="v2.6.0 - Waterfall Reveal for Contact Enrichment" tags={["Enrichment"]}>
  **Added**

  **Waterfall Reveal on Enrich Contacts** - Added optional `waterfallEnabled` field to `POST /v3/contacts/enrich`. When Lusha's own data has no match for a field, the request falls through to your enabled third-party providers to try to fill the gap - extra reach on hard-to-match contacts, on top of standard enrichment.

  * If Data Waterfall is enabled on your account, with specific providers turned on under **Account > Waterfall**, the waterfall runs automatically on every Enrich Contacts call - no need to pass anything to trigger it
  * Pass `waterfallEnabled: false` to opt a specific call out
  * `reveal` still controls which fields come back; `waterfallEnabled` only controls whether the fallback runs for this call at all
  * Provider order isn't configurable - Lusha manages that internally
  * Use of Data Waterfall is subject to Lusha's Supplementary Terms

  **Notes**

  * Billing: A field resolved via waterfall is charged at the enabled provider's own credit rate for that field - not a flat rate. Rates vary by provider (visible under Account > Waterfall) and can be higher than a standard Lusha-only reveal
  * `waterfallEnabled` defaults to `true` once Data Waterfall is turned on for your account; it's backward compatible - accounts without Data Waterfall enabled see no change in behavior

  **Removed**

  **Tables: Add Column endpoint pulled back** - `POST /v3/{contacts|companies}/tables/{table_id}/columns` - documented as shipped in 2.5.0, but the action is not yet functional and has been removed from both Contacts Tables and Companies Tables pending further work. Columns can still be listed, run, and removed; only adding a new column via API is unavailable for now. No changes to existing columns or table data.
</Update>

<Update label="2026-07-21" description="v2.5.0 - Tables API" tags={["Tables"]}>
  **Added**

  **Contacts Tables & Companies Tables APIs** - Added 24 new endpoints (12 per entity type) for creating and managing persistent tables of contacts or companies:

  * `POST /v3/{contacts|companies}/tables` - create a table
  * `POST /v3/{contacts|companies}/tables/list` - list tables owned by a user
  * `GET /v3/{contacts|companies}/tables/{table_id}` - get table status (metadata + entity/column counts + processing state)
  * `PATCH /v3/{contacts|companies}/tables/{table_id}` - update name, visibility, or archive state
  * `DELETE /v3/{contacts|companies}/tables/{table_id}` - permanently delete a table
  * `GET /v3/{contacts|companies}/tables/{table_id}/entities` - read a page of rows with column values and per-cell status
  * `POST /v3/{contacts|companies}/tables/{table_id}/entities` - add up to 500 entity IDs to a table
  * `DELETE /v3/{contacts|companies}/tables/{table_id}/entities` - remove entity IDs from a table
  * `GET /v3/{contacts|companies}/tables/{table_id}/columns` - list columns with aggregated row-status counts
  * `POST /v3/{contacts|companies}/tables/{table_id}/columns` - add a column (`lusha`, `crm`, `signal`, `ai`, or `score` type)
  * `DELETE /v3/{contacts|companies}/tables/{table_id}/columns/{column_id}` - remove a column
  * `POST /v3/{contacts|companies}/tables/{table_id}/columns/{column_id}/run` - run a column across some or all rows (async)

  Tables are two-way synced with the Workspace UI - a table created via API appears there immediately, and vice versa. Each table response includes a `workspaceUrl` deep link.

  **`tableId` opt-in on 4 existing endpoint pairs** - Added an optional `tableId` field to the request body of both the contacts and companies variants of:

  * Prospecting (`POST /v3/{contacts|companies}/prospecting`)
  * Enrich (`POST /v3/{contacts|companies}/enrich`)
  * Signals (`POST /v3/{contacts|companies}/signals`)
  * Lookalike (`POST /v3/{contacts|companies}/lookalike`)

  When `tableId` is passed, matching results are also saved into that table. The primary response is unchanged and always succeeds even if the table write fails; a new `tableWrite` object is added to the response confirming what happened on the table side (`added`, `alreadyPresent`, `columnsCreated`, `rowsProcessed`, `rowsCharged`, `rowsAlreadyPaidInTable`, `creditsCharged`). Not supported on the Search-only preview endpoints.

  **Notes**

  * Ownership: every table-route call requires `owner.email`, which must resolve to an existing user on the account tied to your API key. It travels in the request body (`owner: { email }`) on POST/PATCH calls, and as a `?email=` query parameter on GET/DELETE calls that carry no body
  * Entity IDs accept either the encrypted Lusha token (`v{N}.…`, as returned by Search/Enrich/Get Entities) or the legacy numeric ID - `personId` for contacts, `lushaCompanyId` for companies. An ID that is neither a valid token nor numeric returns 400. Get Entities now returns each row's `id` as the encrypted token (previously returned the raw numeric ID), closing the read/write asymmetry
  * Limits: up to 500 entity IDs per add/remove call, 50,000 entities per table, 500 tables per account
  * Billing: creating, listing, updating, and deleting tables is free, as is listing, adding, and removing columns. Adding contacts to a table is free; adding companies is charged per newly-added company (deduped, so duplicates aren't re-charged). Reading rows (`GET .../entities`) is charged per row returned. Running a column is charged per row per the column's credit tier - company-enrichment columns charge once per company per table, so re-running an already-paid company is free
  * Run Column is asynchronous - the call kicks off the run and returns immediately; poll Get Table Status for per-column row-progress and the credits actually charged
  * Adding entity IDs that can't be resolved is not an error - the call returns 200 with the unresolved IDs listed in `invalidIds`
  * Contacts tables support an optional `companyIds` field on Add Entities (index-aligned with `entityIds`) to pair each contact with its company for enrichment; not applicable to companies tables
</Update>

<Update label="2026-06-08" description="v2.4.0 - Decision Makers API" tags={["Decision Makers"]}>
  **Added**

  **Decision Makers API** - Added `POST /v3/contacts/decision-makers` - resolve companies to their most relevant contacts for outreach.

  * Supply companies by domain or Lusha company id (exactly one per entry); up to N companies per request
  * Optional `clientReferenceId` per entry is echoed back in the matching result for correlation
  * Results are grouped per company with decision makers ranked by relevance (highest first)
  * Each decision maker is returned as a free contact preview: name, title, location, LinkedIn, seniority, department, `has`, and `canReveal`
  * Pass the returned contact `id` values to Enrich Contacts (`POST /v3/contacts/enrich`) to reveal emails and phones
  * Companies that cannot be matched return a per-item `NOT_FOUND` error without failing the entire request

  **Notes**

  * Free for MVP (`creditsCharged: 0` on all responses)
  * Encrypted company IDs (`vN.…`) are supported; legacy numeric IDs are accepted during the transition window
  * Decision makers are returned as `V3ContactPreview` objects - the same shape as Search Contacts results
</Update>

<Update label="2026-06-02" description="v2.3.0 - Website Visitors API" tags={["Website Visitors"]}>
  **Added**

  **Website Visitors API** - Added `POST /v3/companies/website-visits` - identify and filter companies that have visited your tracked domains.

  * Filter by engagement score band (`cold`, `warm`, `hot`) via `filters.scoreBands`
  * Filter by session metrics: `totalSessions`, `uniqueVisitors`, `avgSessionMinutes`, `daysVisited`, `highIntentPageviews`, `daysSinceLastVisit`
  * Filter by score range via `filters.score` (min/max, 1–100)
  * Filter by geography via `filters.visitorCountries` with include and exclude arrays (ISO 3166-1 alpha-2 codes)
  * Sort results by any metric field via `sort.by` and `sort.order` (`asc` or `desc`)
  * Paginate via `pagination.limit` (max 150) and `pagination.offset`
  * Date range window cannot exceed 3 months

  Domains must be configured for tracking in the Lusha dashboard before use. If any requested domain is not configured, the entire request fails with 400. Each result includes a V3 company firmographic preview (same shape as Search Companies) plus behavioral visit metrics. Pass the returned company `id` to Enrich Companies for full firmographic data.

  **Notes**

  * `startDate` and `endDate` are required; the window between them must not exceed 3 months
  * Both dates must be in `YYYY-MM-DD` format
  * Each result includes `score`, `scoreBand`, `totalSessions`, `uniqueVisitors`, `avgSessionMinutes`, `daysVisited`, `highIntentPageviews`, `daysSinceLastVisit`, `lastVisit`, and `visitorCountry`
</Update>

<Update label="2026-03-10" description="v2.2.0 - Signal Sub-Filters, Lookalikes V3 Expansion & Doc Improvements" tags={["Signals", "Lookalikes", "Webhooks"]}>
  **Added**

  **Signal Sub-Filters for Company Bulk Enrich** - Added optional `signalsFilters` parameter to `POST /bulk/company/v2` to narrow signal results within requested signal types:

  * `newsEventTypes` - filter news signals by specific event types (e.g. Partnership, New Customer, Executive Hire)
  * `hiringByDepartments` - filter `surgeInHiringByDepartment` signals by department
  * `hiringByLocations` - filter `surgeInHiringByLocation` signals by country/state
  * Multi-value filters use OR logic; values are not case-sensitive
  * Sending `state` without `country` in `hiringByLocations` returns HTTP 400

  **Signal Sub-Filters for Company Signals API** - Added optional `filters.include` block to:

  * `POST /api/signals/companies`
  * `POST /api/signals/companies/search`

  Supports the same sub-filter options as above (`newsEventTypes`, `hiringByDepartments`, `hiringByLocations`).

  **Company Lookalikes V3** - Added `POST /v3/companies/lookalike` - mirrors the contact lookalikes pattern introduced in v2.1.0:

  * Session-based deduplication via `dedupeSessionId`
  * Seed inputs via `domains` and `linkedinUrls`
  * `exclude` parameter to suppress known accounts
  * Returns `domain`, `linkedinUrl`, `name`, `employeeCount`, `industry`, and `location` per result

  **Webhooks: Opt-Out Subscription Endpoint** - Added `POST /api/subscriptions/opt-out` - subscribe to real-time notifications when a contact opts out of data processing. Delivers contact identity, opt-out date, and specific data points (emails/phones) that must be removed. Supports multi-tenant setups via `partnerClientId`.

  **Changed**

  * Contact Lookalikes V3 - Result field `id` renamed to `contactId`; nested company field `id` renamed to `companyId` for clarity
  * Signals API - `maxResultsPerSignal` is now optional across all 4 signal endpoints (previously required in v2.1.0). When omitted: returns all available signals if no `startDate` is provided, or all signals from `startDate` onward if provided

  **Removed**

  **Webhooks URL Verification** - Removed the challenge/response URL verification step from webhook subscription creation. Webhook URLs are no longer verified via a GET challenge request when creating or updating subscriptions.

  **Notes**

  * Signal sub-filters reduce response size and credit usage by narrowing results within a signal type without requiring separate requests
  * `maxResultsPerSignal` remains available as an optional cap when you want to limit results per signal type
</Update>

<Update label="2026-02-26" description="v2.1.0 - Contact Lookalikes V3 & Signals Rate Control" tags={["Lookalikes", "Signals"]}>
  **Added**

  **Contact Lookalikes V3** - Replaced `POST /api/recommendations/contacts` with a redesigned endpoint:

  * `POST /v3/lookalike/contacts` - returns contact lookalikes based on seed contacts
  * Supports multiple seed identifier types: `linkedinUrls`, `emails`, `contactIds`, and `contacts` (name + company)
  * Session-based deduplication via `dedupeSessionId` - omit on first request, reuse on subsequent calls
  * Session history persists for 30 days from last activity
  * `exclude` parameter supports up to 500 contacts across all identifier types
  * Seeds require 5-100 total identifiers across all arrays
  * Returns `id`, `firstName`, `lastName`, `socialLinks`, `company`, `jobTitle`, and `location` per result

  **Signal Rate Control** - Added `maxResultsPerSignal` (required at time of release) to all 4 Signals API endpoints:

  * `POST /api/signals/contacts`
  * `POST /api/signals/contacts/search`
  * `POST /api/signals/companies`
  * `POST /api/signals/companies/search`

  **Changed**

  * Contact Lookalikes - Endpoint path changed from `/api/recommendations/contacts` to `/v3/lookalike/contacts`. Request and response schemas fully replaced - not backwards compatible.
  * Signals API - `maxResultsPerSignal` added as a required parameter. Limits the number of signal instances returned per signal type per entity, starting from `startDate`.

  **Notes**

  * The new contact lookalikes endpoint aligns with the existing company lookalikes pattern
  * `maxResultsPerSignal` helps control response size and credit consumption, especially when requesting `allSignals` over long date ranges
</Update>

<Update label="2026-02-18" description="v1.8.0 - Company Data Points & News Signal Expansion" tags={["Enrichment", "Signals"]}>
  **Added**

  **New Company Data Fields** - Added 7 new data points to Company API V2 (Single & Bulk) and Prospecting Company Enrich API:

  * `linkedinFollowers` - LinkedIn followers count
  * `emailDomain` - company email domain
  * `companyLocations` - array of all known company site locations (not just HQ), each with `city`, `continent`, `country`, `country_iso2`, `location_coordinates`, `state`, `state_code`
  * `alternativeName` - normalized alternative company name
  * `companyType` - type of company (e.g. "Private company")
  * `lushaPopularityTier` - Lusha popularity tier

  **New Person Data Fields** - Added LinkedIn enrichment fields to Person API V2 (Single & Bulk) and Prospecting Contact Enrich API:

  * `xUrl` - Twitter/X profile URL (`data.socialLinks.xUrl`)
  * `linkedinFollowersCount` - LinkedIn followers count
  * `linkedinConnectionsCount` - LinkedIn connections count
  * `linkedinCertifications` - professional certifications from LinkedIn
  * `linkedinCourses` - courses listed on LinkedIn
  * `linkedinAwards` - honors and awards from LinkedIn
  * `linkedinSkills` - skills listed on LinkedIn profile

  **Company Size Enhancements**

  * `companySize` object (Single Enrich) now returns `min`, `max`, and `employeesInLinkedin`
  * `employeesInLinkedin` added as a flat field to the bulk response

  **New News Event Signal Types** - Replaced the generic `newsEvent` signal with 7 granular categories, available across Signals API, Prospecting API, and Webhooks:

  * `riskNews` - litigations and security news
  * `commercialActivityNews` - launches, partnerships, and go-to-market activity
  * `corporateStrategyNews` - M\&A, restructuring, or strategic direction changes
  * `financialEventsNews` - funding, IPOs, and financial performance events
  * `peopleNews` - hiring, layoffs, or leadership changes
  * `marketIntelligenceNews` - event participation, recognition, competitor activity
  * `productActivityNews` - product launch, development, and integration news

  **Changed**

  * Company API V2 (Single Enrich) - `companySize` now returns an object with `min`, `max`, and `employeesInLinkedin` instead of a simple range array
  * Prospecting Company Search - New news signal types now available as search filters
  * Prospecting Company Enrich - Response now includes all signal types including new news signal categories
  * Webhooks - New news signal types are now subscribable event types for company subscriptions

  **Notes**

  * `companyLocations` differs from the existing HQ location field - it returns all known company site locations
  * The new news signal types replace the previous generic `newsEvent` signal
  * All 7 news signal types share the same response schema: `companyId`, `companyName`, `domain`, `signalId`, `eventType`, `eventSummary`, `articlePublishedDate`, `articleTitle`, `articleHighlight`, `eventEffectiveDate`, `articleUrl`
</Update>

<Update label="2026-01-26" description="v1.7.0 - Webhooks API Release" tags={["Webhooks"]}>
  **Added**

  **New Webhooks API** - Introduced real-time event notifications for contact and company signals via webhooks.

  * `POST /api/subscriptions` - create webhook subscriptions (bulk, up to 25 per request) for contact and company signals
  * `GET /api/subscriptions` - list all active webhook subscriptions
  * `GET /api/subscriptions/{id}` - retrieve a specific subscription
  * `PATCH /api/subscriptions/{id}` - update subscription settings
  * `POST /api/subscriptions/delete` - delete subscriptions (bulk supported)
  * `POST /api/subscriptions/{id}/test` - test delivery with mock payload (no credits consumed)
  * `GET /api/audit-logs` - webhook delivery logs
  * `GET /api/audit-logs/stats` - delivery statistics
  * `GET /api/account/secret` - retrieve webhook secret
  * `POST /api/account/secret/regenerate` - regenerate webhook secret

  Features include real-time delivery, event filtering by signal type, HMAC-SHA256 signature verification, automatic retry with exponential backoff (max 3 attempts), and delivery audit logs retained for 90 days (successful) and 180 days (failed).

  **Notes**

  * Webhooks are a push-based alternative to polling the Signals API
  * Ideal for time-sensitive workflows like triggering outreach on job changes
  * Premium feature - standard credit charges apply for signal detection; retries do not incur additional charges
</Update>

<Update label="2025-01-05" description="v1.6.0 - Prospecting API Signal Filtering" tags={["Prospecting", "Signals"]}>
  **Added**

  **Signal Filtering for Prospecting Search** - Enhanced Prospecting APIs with signal-based filtering.

  * `POST /prospecting/contact/search` - can now filter contacts by `promotion`, `companyChange`, `allSignals`
  * `POST /prospecting/company/search` - can now filter companies by `headcountGrowth`, `newJobsOpen`, `newsEvent`, `allSignals`
  * `startDate` parameter added for time-based filtering
  * Search responses now include a `signalTypes` array indicating detected signals per result

  **Notes**

  * Premium feature - credits are charged for each signal type that returns results
  * Works in conjunction with the Signals API for retrieving detailed signal metadata
</Update>

<Update label="2025-10-15" description="v1.5.0 - Recommendations API Release" tags={["Recommendations"]}>
  **Added**

  * `POST /api/recommendations/contacts` - AI-powered recommendations for similar contacts
  * `POST /api/recommendations/companies` - AI-powered recommendations for similar companies

  Enables prospect expansion by surfacing net-new contacts and companies with similar attributes to your known leads. Can be used as a downstream step after enrichment, prospecting, or CRM triggers.

  **Notes**

  * These endpoints were superseded by the redesigned Lookalikes V3 endpoints in v2.1.0
</Update>

<Update label="2025-09-30" description="v1.4.0 - Enhanced Search Capabilities" tags={["Prospecting"]}>
  **Added**

  **New `searchText` Filter** - Free-text search capability for Prospecting APIs, available in both include and exclude sections:

  * `POST /prospecting/contact/search` - supports `searchText` in contacts and companies filter sections
  * `POST /prospecting/company/search` - supports `searchText` in companies filter section
  * Enables natural language queries like "finance marketing in Germany DE"
  * Searches across multiple fields simultaneously

  **Changed**

  * `ContactFilters` and `CompanyFilters` schemas updated to include optional `searchText` property
</Update>

<Update label="2025-09-10" description="v1.3.0 - Signals API Expansion" tags={["Signals", "Enrichment"]}>
  **Added**

  **New Signals Endpoints**

  * `POST /signals/contacts` - retrieve contact signals by IDs
  * `POST /signals/companies` - retrieve company signals by IDs
  * `POST /signals/contacts/search` - retrieve contact signals by identifiers (LinkedIn URL, email, or name + company/domain)
  * `POST /signals/companies/search` - retrieve company signals by identifiers (domain, company name, or ID)
  * `GET /signals/filters/:objectType` - view available signal filter types for contact or company

  All signal endpoints support `startDate` (optional, defaults to last 6 months).

  **Partial Profile Filter** - Added `partialProfile` boolean parameter to contact enrichment APIs for simplified contact profiles.

  **Changed**

  * Enrichment APIs (`v2/person` and `v2/company`, single and bulk) now always return `person_id` and `company_id` where applicable
  * Signal filters can now be used as filters in existing enrichment API calls
</Update>

## Format Reference

```markdown theme={null}
## [Version] - YYYY-MM-DD - Title

### Added
New features and endpoints

### Changed
Updates to existing functionality

### Fixed
Bug fixes and corrections

### Removed
Deprecated features

### Notes
Additional context
```

## Notifications

* **Email**: Subscribe for release notifications
* **Support**: [support@lusha.com](mailto:support@lusha.com)

## API Versioning

| Version | Status  | Support Level                   |
| ------- | ------- | ------------------------------- |
| 2.7.x   | Current | Full support (Tables API: Beta) |
| 2.x     | Recent  | Full support                    |
| 1.x     | Legacy  | Security only                   |
