# Lusha API Documentation

<blockquote class="callout">

 **This is the Lusha API V3 documentation.** 
 
 V3 introduces a new search-then-enrich pattern, bulk operations, AI-powered lookalikes, and richer filter capabilities. All endpoints are under `https://api.lusha.com/v3/`.

  For more information on V3, refer to the [Migration Guide](/tutorials/v3-migration-guide).

</blockquote>

  --- 

Lusha provides a RESTful API for querying a comprehensive dataset of business profiles and company information. Built for teams running prospecting, enrichment, automation, and analytics workflows that need accurate, continuously updated business data. The API supports both real-time and bulk use cases.

Use the Lusha API to **search for new prospects**, **enrich existing records**, **react to real-world changes**, and **expand coverage** with AI-powered lookalike recommendations.

> All API requests must be made over **HTTPS**. All responses are returned in **JSON** format.

--- 
## Available Endpoints

| Category | Description |
|---|---|
| [**Search**](#tag/Search) | Find contacts or companies using known identifiers |
| [**Enrich**](#tag/Enrich) | Retrieve full profile data for contacts or companies by ID |
| [**Search & Enrich**](#tag/Search-and-Enrich) | Find and retrieve full contact or company data in a single call |
| [**Prospecting**](#tag/Prospecting) | Filter-based search across contacts and companies |
| [**Lookalikes**](#tag/Lookalikes) | AI-powered recommendations for similar contacts and companies |
| [**Signals**](#tag/Signals) | Real-world activity data for contacts and companies |
| [**Decision Makers**](#tag/Decision-Makers) | Find the most relevant decision makers across your target accounts |
| [**Website Visits**](#tag/Website-Visits) | Companies ranked by website-visit signals for your tracked domains |
| [**Filters**](#tag/Filters) | Discover valid filter values for prospecting |
| [**Webhooks**](#tag/Webhooks) | Real-time signal notifications via HTTP callbacks |
| [**Account**](#tag/Account) | Usage, credits, rate limits, and pricing |

---

## Data Source and Privacy

**Lusha is a search platform.** The data provided is not created or directly managed by Lusha. It is sourced from publicly available information and trusted business partners.

For more details on how we collect and handle data, see our [Privacy Policy](https://lusha.com/legal/privacy-notice/).

---

## Authentication

All API requests require an **API key** linked to your Lusha account and plan. Pass your key in the `api_key` request header on every call.

> Generate and manage your API key in the [Lusha dashboard](https://dashboard.lusha.com/enrich/api).

Store your API key securely and use it only in **server-side environments**.

---

## Rate Limiting

Lusha enforces rate limits on a per-plan basis to ensure fair usage and platform stability. Limits are applied across multiple time windows (per minute, per hour, and per day), and vary depending on your account plan.

Rate limits for the **Credit Usage API** differ from standard endpoint limits.

> **Note:** To check your current plan's limits, visit the [Lusha Help Center](https://info.lusha.com/en/articles/163856-all-there-is-to-know-about-lusha-s-api) or contact your account manager.

**Rate Limit Response Headers**

| Header | Description |
|--------|-------------|
| `x-rate-limit-daily` | Total requests allowed per day |
| `x-daily-requests-left` | Requests remaining in your daily quota |
| `x-daily-usage` | Requests made in the current daily period |
| `x-rate-limit-hourly` | Total requests allowed per hour |
| `x-hourly-requests-left` | Requests remaining in your hourly quota |
| `x-hourly-usage` | Requests made in the current hourly period |
| `x-rate-limit-minute` | Total requests allowed per minute |
| `x-minute-requests-left` | Requests remaining in the current minute window |
| `x-minute-usage` | Requests made in the current minute window |

---
## Error Codes

Lusha uses standard HTTP status codes to indicate the result of each request.

| Code | Name | Description |
|------|------|-------------|
| `200` | OK | Request was successful |
| `400` | Bad Request | Request is malformed or missing required fields |
| `401` | Unauthorized | API key is missing or invalid |
| `402` | Payment Required | Insufficient credits or payment needed |
| `403` | Forbidden | Account is inactive. Contact support@lusha.com |
| `404` | Not Found | Endpoint or resource does not exist |
| `429` | Too Many Requests | Rate limit or daily quota exceeded |
| `451` | Unavailable For Legal Reasons | Request blocked due to GDPR regulations |
| `499` | Client Closed Request | Request timed out before completing |
| `5XX` | Server Error | Issue on Lusha's end. Retry with exponential backoff |

**Error Response Format**

```json
{
  "statusCode": 400,
  "message": "Invalid request parameters"
}
```

**Tips for Handling Errors**

- Verify your API key is correct and active
- Read the `message` field for specific troubleshooting details
- For `429` errors, wait before retrying
- For `5XX` errors, use exponential backoff before retrying


License: Proprietary

## Servers

Production server
```
https://api.lusha.com
```

## Security

### ApiKeyAuth

Your Lusha API key. You can find this in your Lusha dashboard under API settings.
Include this key in the `api_key` header for all requests.


Type: apiKey
In: header
Name: api_key

## Download OpenAPI description

[Lusha API Documentation](https://docs.lusha.com/_bundle/apis/@v3/openapi.yaml)

## Search

**Search APIs:** Find contacts or companies using known identifiers.

Look up contacts by `id`, `linkedinUrl`, `email`, or `firstName` + `lastName` + `companyName`/`companyDomain`. Look up companies by `id`, `name`, or `domain`.

Returns a non-PII preview of each profile with a `has` field listing available data points and a `canReveal` field showing what can be unlocked via Enrich.

> **Billing:** Charged per successful result via the `api_search` action.


### Search Contacts

 - [POST /v3/contacts/search](https://docs.lusha.com/apis/openapi/search/searchcontacts.md): Look up contacts by identifier. Returns a non-PII preview of each profile — no emails or phone numbers.

Accepted identifiers (one required per contact):
- Lusha contact id
- linkedinUrl
- email
- firstName + lastName + companyName or companyDomain

Up to 100 contacts per request. Each result includes:
- has — data points available on this profile
- canReveal — what you can unlock via Enrich Contacts, and the credit cost

Pass a signals filter to narrow results to contacts with recent activity (e.g. promotion, job change).

> Billing: Charged per successful result via the api_search action.

### Search Companies

 - [POST /v3/companies/search](https://docs.lusha.com/apis/openapi/search/searchcompanies.md): Look up companies by identifier. Returns a preview of each company profile.

Accepted identifiers (at least one required per company):
- Lusha company id
- name
- domain

Up to 100 companies per request. Each result includes a has field listing the data available via Enrich Companies.

Pass a signals filter to narrow results to companies showing specific activity (e.g. headcount growth, hiring surge).

> Billing: Charged per successful result via the api_search action.

## Enrich

**Enrich APIs:** Retrieve full profile data for contacts or companies by ID.

Pass IDs from Search results to reveal emails, phones, and full firmographic data.

> **Billing:** Charged per revealed field via per-datapoint pricing (`revealEmail`, `revealPhone`, `reveal_company`).


### Enrich Contacts

 - [POST /v3/contacts/enrich](https://docs.lusha.com/apis/openapi/enrich/enrichcontacts.md): Reveal full contact data for contacts you've already found via Search Contacts.

Pass up to 100 contact ids (from the search response). Use the reveal field to control what gets unlocked:
- emails — work and personal email addresses
- phones — mobile and direct phone numbers
- Omit reveal to get both by default

> Tip: If canReveal.credits is 0 in the search response, that data has already been revealed for your account — re-enriching it is free.

> Billing: Charged per revealed field (email or phone) via per-datapoint pricing.

### Enrich Companies

 - [POST /v3/companies/enrich](https://docs.lusha.com/apis/openapi/enrich/enrichcompanies.md): Reveal full company data for companies you've already found via Search Companies.

Pass up to 100 company ids (from the search response). Each enriched result includes:
- Firmographics: size, revenue range, year founded, company type
- Industry: primary industry, sub-industry, SIC/NAICS codes
- Locations: HQ and additional office sites
- Technologies, funding rounds, buyer intent topics
- LinkedIn followers, logo URL, social links

> Billing: Charged per successful result via the reveal_company action.

## Search & Enrich

**Search & Enrich APIs:** Find and retrieve full contact or company data in a single call.

Combines Search and Enrich into one request. Provide identifiers and control what gets revealed via the `reveal` field.

> **Billing:** Two charges apply — one for the search (`api_search`) and one per revealed field.


### Search and Enrich Contacts

 - [POST /v3/contacts/search-and-enrich](https://docs.lusha.com/apis/openapi/search-and-enrich/searchandenrichcontacts.md): Find contacts and reveal their full data in a single call. Combines Search and Enrich into one request.

Provide contact identifiers the same way you would for Search Contacts. Use the reveal field to control what gets unlocked (emails, phones, or both).

Up to 100 contacts per request.

> Billing: Two charges apply — one for the search (api_search) and one per revealed field. The billing.creditsCharged in the response reflects the total.

### Search and Enrich Companies

 - [POST /v3/companies/search-and-enrich](https://docs.lusha.com/apis/openapi/search-and-enrich/searchandenrichcompanies.md): Find companies and reveal their full data in a single call. Combines Search and Enrich into one request.

Provide company identifiers the same way you would for Search Companies. Up to 100 companies per request.

> Billing: Same as Enrich Companies — charged per successful result via the reveal_company action.

## Prospecting

**Prospecting APIs:** Filter-based search for contacts and companies.

Use prospecting to find new records that match your Ideal Customer Profile (ICP). Apply rich filters across:

- **Contact attributes:** title, seniority, location, signals
- **Company attributes:** size, revenue, industry, technologies, intent

Results are paginated: up to **1,000 pages x 50 results = 50,000 results** per query.

> **Billing:** Uses the capture/charge model with `api_search` actions. Signal charges apply additionally.


### Prospecting Contacts

 - [POST /v3/contacts/prospecting](https://docs.lusha.com/apis/openapi/prospecting/prospectingcontacts.md): Search for contacts that match your Ideal Customer Profile using rich filter criteria.

Filter by contact attributes:
- Job title, seniority, department
- Location (city, state, country, continent)
- Existing data points (e.g. only contacts with a known work email)
- Signal activity (promotion, job change)

Filter by company attributes:
- Size, revenue, industry, technologies
- Location, intent topics, funding

Results are paginated up to 50,000 total (1,000 pages × 50 results). Use the returned contact id values with Enrich Contacts to reveal emails and phones.

> Billing: Charged per result via api_search. If signals are requested, an additional charge applies per matched signal per result.

### Prospecting Companies

 - [POST /v3/companies/prospecting](https://docs.lusha.com/apis/openapi/prospecting/prospectingcompanies.md): Search for companies that match your target market using rich filter criteria.

Filter by:
- Size, revenue range, industry, sub-industry
- Technologies in use
- Locations (HQ country, state, city)
- SIC and NAICS codes
- Buyer intent topics
- Signal activity (headcount changes, hiring surges, news events)

Results are paginated up to 50,000 total. Use the returned company id values with Enrich Companies to get full firmographic data.

> Billing: Charged per result via api_search. If signals are requested, an additional charge applies per matched signal per result.

## Lookalikes

**Lookalike APIs:** Use AI-powered recommendations to discover contacts and companies similar to your best existing customers. The Contact Lookalikes and Company Lookalikes endpoints return paginated results you can pipe directly into Enrich for full data.


### Contact Lookalikes

 - [POST /v3/contacts/lookalike](https://docs.lusha.com/apis/openapi/lookalikes/getcontactlookalikes.md): Find contacts similar to a set of seed contacts using AI-powered recommendations.

Provide 5-100 seed contacts via LinkedIn URLs, emails, Lusha IDs, or name + company. The API returns contacts who share similar roles, seniority, and company profiles.

Pagination without duplicates:
On your first request, omit dedupeSessionId — the server generates one and returns it. Pass it on every subsequent request to get more results without repeating contacts already seen. Sessions are retained for 30 days.

Use the exclude field to always filter out specific contacts (e.g. existing customers).

Results are lightweight previews. Use Enrich Contacts with the returned id to get emails and phones.

> Billing: Charged per result via the lookalikeContact action.

### Company Lookalikes

 - [POST /v3/companies/lookalike](https://docs.lusha.com/apis/openapi/lookalikes/getcompanylookalikes.md): Find companies similar to a set of seed companies using AI-powered recommendations.

Provide 5-100 seed companies via domains or LinkedIn URLs. The API returns companies with similar size, industry, and profile.

Pagination without duplicates:
On your first request, omit dedupeSessionId — the server generates one and returns it. Pass it on every subsequent request to get more results without repeating companies already seen. Sessions are retained for 30 days.

Use the exclude field to always filter out specific companies (e.g. existing customers or competitors).

Results are lightweight previews. Use Enrich Companies with the returned id to get full firmographic data.

> Billing: Charged per result via the lookalikeCompany action.

## Signals

Real-world activity data for contacts and companies.

Signals are available as standalone endpoints or as an optional `signals` filter on Search and Prospecting endpoints.

**Contact signal types:** `promotion`, `companyChange`, `allSignals`

**Company signal types:** `headcountIncrease1m/3m/6m/12m`, `headcountDecrease1m/3m/6m/12m`, `surgeInHiring`, `surgeInHiringByDepartment`, `surgeInHiringByLocation`, `websiteTrafficIncrease`, `websiteTrafficDecrease`, `itSpendIncrease`, `itSpendDecrease`, `riskNews`, `commercialActivityNews`, `corporateStrategyNews`, `financialEventsNews`, `peopleNews`, `marketIntelligenceNews`, `productActivityNews`, `allSignals`

Credits are charged per matched signal per result via `showSignalsContact` or `showSignalsCompany`.


### Contact Signals

 - [POST /v3/contacts/signals](https://docs.lusha.com/apis/openapi/signals/getcontactsignals.md): Retrieve signal events for a list of contacts — job changes and promotions.

Pass up to 100 contact ids. Use signalTypes to specify which events to return (promotion, companyChange, or allSignals). Optionally set a startDate to limit results to recent activity.

> Billing: Charged per matched signal per result via the showSignalsContact action.

### Company Signals

 - [POST /v3/companies/signals](https://docs.lusha.com/apis/openapi/signals/getcompanysignals.md): Retrieve signal events for a list of companies — hiring activity, headcount changes, web traffic, IT spend, and news.

Pass up to 100 company ids. Use signalTypes to specify which signals to return (or use allSignals). Optionally set a startDate to limit results to recent activity.

> Billing: Charged per matched signal per result via the showSignalsCompany action.

### Get Contact Signal Types

 - [GET /v3/contacts/signals/types](https://docs.lusha.com/apis/openapi/signals/getcontactsignaltypes.md): Returns the full list of supported signal types for contacts.

### Get Company Signal Types

 - [GET /v3/companies/signals/types](https://docs.lusha.com/apis/openapi/signals/getcompanysignaltypes.md): Returns the full list of supported signal types for companies.

### Get Company Signal Filters (Discovery)

 - [GET /v3/companies/signals/filters](https://docs.lusha.com/apis/openapi/signals/getcompanysignalfilters.md): Returns all available filter types for company signals and whether each requires a search query.

### Get Company Signal Filter Values

 - [GET /v3/companies/signals/filters/{filterType}](https://docs.lusha.com/apis/openapi/signals/getcompanysignalfiltervalues.md): Returns valid values for a single company signal filter type.

| Filter type | Query required? |
|---|---|
| newsEventTypes | No |
| hiringByDepartments | No |
| hiringByLocations | Yes (2-256 chars) |

## Decision Makers

Supply companies by domain or Lusha ID and get back the most relevant decision makers per company, ranked by fit. Results are free contact previews — pass the returned id values to Enrich Contacts to reveal emails and phones. 


### Get Decision Makers

 - [POST /v3/contacts/decision-makers](https://docs.lusha.com/apis/openapi/decision-makers/getdecisionmakers.md): Resolve each supplied company to a Lusha company ID, rank the most relevant decision makers per company using the buying-committee-ranker model, and return them grouped per company.

Results are free previews — name, title, company, location, LinkedIn, seniority, and department — with has and canReveal fields. Reveal emails and phones separately via Enrich Contacts.

Accepted company identifiers (exactly one required per entry):
- domain — resolved to a Lusha company ID server-side
- id — encrypted Lusha company ID (vN.…); legacy numeric IDs accepted during transition

## Website Visits

Retrieve companies ranked by website-visit signals for your tracked domains.

 Domains must be configured for tracking in the dashboard. Each result combines a V3 company firmographic preview with behavioral visit metrics (score, sessions, unique visitors, avg session length, and more).


### Get Website Visits

 - [POST /v3/companies/website-visits](https://docs.lusha.com/apis/openapi/website-visits/getwebsitevisits.md): Returns companies ranked by website-visit signals for your tracked domains and date range.

Domains must be configured for tracking in the Lusha dashboard — they are resolved to site IDs server-side. Each result combines a V3 company firmographic preview (same shape as Search Companies) with behavioral visit metrics.

Notes:
- Date range must be ≤ 3 months
- If any requested domain is not configured for tracking, the entire request fails with 400
- limit accepts 1–150

## Filters

**Filter APIs:** Retrieve available filter values for prospecting.

Use the discovery endpoints to list all available filter types, then fetch valid values for a specific filter type before building a prospecting request.

**Contact filter types:** `departments`, `seniority`, `existingDataPoints`, `countries`, `locations`

**Company filter types:** `names`, `sizes`, `revenues`, `locations`, `sics`, `naics`, `industriesLabels`, `intentTopics`, `technologies`


### Get Contact Filter Types (Discovery)

 - [GET /v3/contacts/prospecting/filters](https://docs.lusha.com/apis/openapi/filters/getcontactfiltertypes.md): Returns all available filter types for contact prospecting and whether each requires a search query.

### Get Contact Filter Values

 - [GET /v3/contacts/prospecting/filters/{filterType}](https://docs.lusha.com/apis/openapi/filters/getcontactfiltervalues.md): Returns valid values for a single contact filter type.

| Filter type | Query required? |
|---|---|
| departments | No |
| seniority | No |
| existingDataPoints | No |
| countries | No |
| locations | Yes (2-256 chars) |

### Get Company Filter Types (Discovery)

 - [GET /v3/companies/prospecting/filters](https://docs.lusha.com/apis/openapi/filters/getcompanyfiltertypes.md): Returns all available filter types for company prospecting and whether each requires a search query.

### Get Company Filter Values

 - [GET /v3/companies/prospecting/filters/{filterType}](https://docs.lusha.com/apis/openapi/filters/getcompanyfiltervalues.md): Returns valid values for a single company filter type.

| Filter type | Query required? |
|---|---|
| sizes | No |
| revenues | No |
| sics | No |
| naics | No |
| intentTopics | No |
| industriesLabels | No |
| names | Yes (2-256 chars) |
| technologies | Yes (2-256 chars) |
| locations | Yes (2-256 chars) |

## Webhooks

Subscribe to real-time notifications when contacts change jobs or companies experience key business events.

Webhooks deliver HTTP POST requests to your endpoints when signals occur - from promotions and job changes to company growth.

> For a full list of available signals, refer to [**Signal Options**](https://docs.lusha.com/apis/openapi/signals/getsignaloptions).
---
**Key Features:**
- Real-time contact & company signal notifications
- Bulk subscription management (up to 25 items per request)
- Secure delivery with HMAC-SHA256 signatures
- Delivery monitoring with audit logs

 **Available Endpoints:**

| Method | Endpoint | Purpose |
|--------|----------|---------|
| POST | `/api/subscriptions` | Create subscriptions (bulk supported) |
| GET | `/api/subscriptions` | List all subscriptions |
| GET | `/api/subscriptions/{id}` | Get subscription by ID |
| PATCH | `/api/subscriptions/{id}` | Update subscription |
| POST | `/api/subscriptions/delete` | Delete subscriptions (bulk supported) |
| POST | `/api/subscriptions/{id}/test` | Test subscription delivery |
| GET | `/api/audit-logs` | Get webhook delivery logs |
| GET | `/api/audit-logs/stats` | Get delivery statistics |
| GET | `/api/account/secret` | Get account webhook secret |
| POST | `/api/account/secret/regenerate` | Regenerate account secret |
| POST | `/api/subscriptions/opt-out` | Subscribe to contact opt-out notifications |

> **Webhook Delivery Acknowledgment:** When receiving webhook deliveries (POST requests), your endpoint must acknowledge with a specific response format. See the [Create Subscription](#operation/createSubscription) endpoint for the required acknowledgment structure.
      ---

<details>
<summary><strong>Rate Limits</strong></summary>

| Operation | Limit |
|-----------|-------|
| API Requests | 100 requests/minute per account |
| Create Subscriptions | 25 items per request |
| Delete Subscriptions | 25 items per request |

</details>

---

<details>
<summary><strong>Security & Verification</strong></summary>

**HTTPS Requirement:**
- Production webhook URLs **must** use HTTPS
- HTTP URLs are not accepted

**Signature Verification:**

All webhook deliveries include an `X-Lusha-Signature` header containing an HMAC-SHA256 signature. Verify this signature to ensure the request is from Lusha:

1. Extract the `X-Lusha-Signature` and `X-Lusha-Timestamp` headers
2. Concatenate: `timestamp + "." + JSON.stringify(payload)`
3. Compute HMAC-SHA256 using your webhook secret
4. Compare the computed signature with the received signature

**Example (Node.js):**
```javascript
const crypto = require('crypto');

function verifySignature(payload, signature, timestamp, secret) {
  const signedPayload = `${timestamp}.${JSON.stringify(payload)}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}
```

> **Security Best Practice:** Always verify webhook signatures to prevent spoofed requests.

</details>

---

<details>
<summary><strong>Credits & Billing</strong></summary>

**Credit Charges:**
- Credits are charged when signals are detected and delivered to your webhook
- The `creditsCharged` field in the webhook payload indicates how many credits were used
- Credits are deducted from your account balance per signal type

**No Duplicate Charges:**
- Each signal is delivered once and charged once
- Webhook delivery retries do not incur additional charges

</details>

---

<details>
<summary><strong>Error Response Format</strong></summary>

All error responses follow this format:
```json
{
  "statusCode": 400,
  "message": "Validation failed",
  "errors": ["entityType must be one of: contact, company"]
}
```

| Field | Type | Description |
|-------|------|-------------|
| `statusCode` | number | HTTP status code |
| `message` | string | Error message |
| `errors` | string[] | Detailed error messages (optional) |

</details>
    
---


### Create Subscription

 - [POST /api/subscriptions](https://docs.lusha.com/apis/openapi/webhooks/createsubscription.md): Creates one or more webhook subscriptions for real-time signal notifications.

Delivery & Reliability:
- Webhooks are delivered with automatic retry on failures
- Maximum 3 retry attempts with exponential backoff
- Subscriptions auto-disable after max retries exceeded
- All deliveries are logged in audit logs

> Note: Your webhook endpoint must respond with a proper acknowledgment. 
 See Client Response Format below for details.

> Limit: Maximum 25 subscriptions per request

Endpoint: (POST) https://api.lusha.com/api/subscriptions

---

### Webhook Payload You'll Receive
 When a signal is triggered, this payload is sent to your webhook URL:
json
    {
      "id": "f3b87e05-0402-4f3e-8e26-6a38fd0ad62c",
      "type": "promotion",
      "entityType": "contact",
      "entityId": "4158887495",
      "subscriptionId": "507f1f77bcf86cd799439011",
      "data": {
        "personId": 4158887495,
        "currentCompanyId": 40823133,
        "currentCompanyName": "OMG Hospitality Group LLC",
        "currentDomain": "omghospitalitygroup.com",
        "currentTitle": "Bartender",
        "currentDepartments": [
          { "id": 7, "value": "Other" }
        ],
        "previousCompanyName": "First Watch Restaurants",
        "previousDomain": "firstwatch.com",
        "signalDate": "2025-07-01"
      },
      "timestamp": "2026-01-14T16:16:35.841Z",
      "billing": {
        "creditsCharged": 1
      }
    }
    
            Example — Company News Signal:
    json
            {
              "id": "a7c92f14-1234-4b3e-9d22-8b4fe1d0bc45",
              "type": "commercialActivityNews",
              "entityType": "company",
              "entityId": "33222678",
              "subscriptionId": "507f1f77bcf86cd799439011",
              "data": {
                "companyId": "33222678",
                "companyName": "Lusha",
                "domain": "lusha.com",
                "signalId": "1503910",
                "eventType": "partnership",
                "eventSummary": "Lusha announced a strategic partnership with Salesforce.",
                "articlePublishedDate": "2025-06-15",
                "articleTitle": "Lusha Partners with Salesforce",
                "articleHighlight": "The partnership enables Salesforce users to access Lusha data directly within their CRM.",
                "eventEffectiveDate": "2025-06-10",
                "articleUrl": "https://example.com/lusha-salesforce-partnership"
              },
              "timestamp": "2026-01-14T16:16:35.841Z",
              "billing": {
                "creditsCharged": 1
              }
            }
          

      Headers Included:

      | Header | Description |
      |--------|-------------|
      | X-Lusha-Signature | HMAC-SHA256 signature for verification |
      | X-Lusha-Timestamp | Unix timestamp of the request |
      | Content-Type | application/json |
      | User-Agent | Lusha-Webhooks/1.0 |


---
⚠️ Important: Ensure your account has a webhook secret before creating subscriptions.
Create one via the Regenerate Account Secret endpoint.

---

### Client Response Format (Required)

When your webhook endpoint receives a delivery, it must acknowledge receipt with this response:

  Required Response:
  json
  {
    "received": true,
    "timestamp": "2026-02-05T10:30:45.123Z",
    "webhookId": "f3b87e05-0402-4f3e-8e26-6a38fd0ad62c"
  }
  


Response Requirements

  | Requirement | Value |
  |-------------|-------|
  | HTTP Status | 201 Created (recommended) or any 2xx status |
  | Content-Type | application/json |
  | Response Time | Within 10 seconds |




Field Descriptions & Implementation Guide

  Field Descriptions:
  * received (boolean, required): Confirmation flag - must be true
  * timestamp (string, required): ISO 8601 timestamp of receipt
  * webhookId (string, required): Echo the id from webhook payload

  Implementation Example:
  javascript
  app.post('/webhook', async (req, res) => {
    // 1. Verify signature
    if (!verifyWebhookSignature(req)) {
      return res.status(401).json({ error: 'Invalid signature' });
    }
    
    // 2. Queue for async processing
    await queueWebhook(req.body);
    
    // 3. Acknowledge immediately
    res.status(201).json({
      received: true,
      timestamp: new Date().toISOString(),
      webhookId: req.body.id
    });
    

  Important Notes:
  * Return acknowledgment before heavy processing
  * Non-2xx responses trigger retry mechanism
  * After 3 failed retries, subscription is disabled

  

----

### List Subscriptions

 - [GET /api/subscriptions](https://docs.lusha.com/apis/openapi/webhooks/listsubscriptions.md): Returns all webhook subscriptions for your account with pagination support.

Endpoint: (GET) https://api.lusha.com/api/subscriptions

Pagination:
- Results are sorted by createdAt in descending order (newest first)
- Default limit: 10, max limit: 100
- Use offset for pagination through large result sets

> Note: The webhook secret is never returned in list responses for security.

### Get Subscription by ID

 - [GET /api/subscriptions/{id}](https://docs.lusha.com/apis/openapi/webhooks/getsubscriptionbyid.md): Returns a single webhook subscription by ID.

Endpoint: (GET) https://api.lusha.com/api/subscriptions/{id}

### Update Subscription

 - [PATCH /api/subscriptions/{id}](https://docs.lusha.com/apis/openapi/webhooks/updatesubscription.md): Updates an existing webhook subscription. All fields are optional.

Endpoint: (PATCH) https://api.lusha.com/api/subscriptions/{id}

---
Reactivating Disabled Subscriptions:

When setting isActive: true on a previously disabled subscription, the system automatically:
- Clears the blockReason field
- Clears the blockedAt timestamp
- Resets the retry counter

Regenerating Secrets:

Set regenerateSecret: true to generate a new webhook secret. The new secret:
- Affects all subscriptions for your account
- Is only shown once in the response
- Immediately invalidates the old secret
---

### Test Subscription

 - [POST /api/subscriptions/{id}/test](https://docs.lusha.com/apis/openapi/webhooks/testsubscription.md): Test a webhook subscription by sending a test signal. Supports three test modes.

Endpoint: (POST) https://api.lusha.com/api/subscriptions/{id}/test
---
Test Modes:
- direct - Quick HTTP check only (validates URL responds correctly)
- kafka - Fanout handler only (tests Kafka message processing)
- full - Complete Kafka flow (default - end-to-end test)

Important Notes:
- Test deliveries do NOT consume credits
- Test payloads use mock data
- Useful for verifying webhook configuration before going live

### Delete Subscriptions

 - [POST /api/subscriptions/delete](https://docs.lusha.com/apis/openapi/webhooks/deletesubscriptions.md): Delete one or more webhook subscriptions. Returns detailed results for each deletion with partial success support.

Endpoint: (POST) https://api.lusha.com/api/subscriptions/delete

---

Behavior:
- Each subscription is processed independently
- Returns detailed results for each item including deleted subscription info
- Invalid ID formats are gracefully handled and reported as NOT_FOUND
- Duplicate IDs are automatically deduplicated
- Deletion is permanent and cannot be undone

### Get Audit Logs

 - [GET /api/audit-logs](https://docs.lusha.com/apis/openapi/webhooks/getauditlogs.md): Retrieve webhook delivery logs for your account.

Endpoint: (GET) https://api.lusha.com/api/audit-logs

What's Logged:
- All webhook delivery attempts (success and failures)
- HTTP status codes and response times
- Error messages for failed deliveries
- Delivery timestamps and duration metrics

Filtering:
- Filter by subscription ID to see logs for specific subscriptions
- Filter by status to see only successes, failures, or permanent failures

Rate Limit: 100 requests/minute per account

> Note: Logs are retained for 90 days (successful) and 180 days (failed/DLQ)

### Get Audit Log Statistics

 - [GET /api/audit-logs/stats](https://docs.lusha.com/apis/openapi/webhooks/getauditlogstats.md): Get delivery statistics for your account.

Endpoint: (GET) https://api.lusha.com/api/audit-logs/stats

### Get Account Secret

 - [GET /api/account/secret](https://docs.lusha.com/apis/openapi/webhooks/getaccountsecret.md): Retrieve the current account webhook secret.

Endpoint: (GET) https://api.lusha.com/api/account/secret

### Regenerate Account Secret

 - [POST /api/account/secret/regenerate](https://docs.lusha.com/apis/openapi/webhooks/regenerateaccountsecret.md): Regenerate the account webhook secret. Affects all subscriptions for the account.

Endpoint: (POST) https://api.lusha.com/api/account/secret/regenerate

Behavior:
- If a secret already exists: Replaces with new secret (old secret is invalidated)
- If no secret exists: Creates new secret automatically

Important Notes:
- The secret is only shown once in the response. Store it securely.
- This endpoint always succeeds (upsert operation)
- Regenerating invalidates the old secret for all subscriptions (if one existed)
- An account secret must exist before webhooks can be delivered

### Create Opt-Out Subscription

 - [POST /api/subscriptions/opt-out](https://docs.lusha.com/apis/openapi/webhooks/createoptoutsubscription.md): Subscribe to real-time notifications when a contact opts out of data processing. When a contact requests removal, Lusha sends an OptOutWebhookPayload to your endpoint so you can action the removal in your own systems (CRM, outreach tools, etc.).

Endpoint: (POST) https://api.lusha.com/api/subscriptions/opt-out

---

How it works:
- Create one opt-out subscription per account (scoped to contact entity type)
- Lusha delivers a POST request to your URL whenever a contact opts out
- The payload includes the contact identity, opt-out date, and the specific data points (emails and/or phones) that must be removed

Payload you'll receive:
json
{
  "contactId": "987654321",
  "fullName": "Jane Doe",
  "companyName": "Acme Corp",
  "jobTitle": "Director of Product",
  "linkedinUrl": "https://www.linkedin.com/in/jane-doe",
  "contactOptOutDate": "2026-04-22 14:32:11.412",
  "contactExposureDate": "2025-08-03 09:15:47",
  "datapoints": [
    { "datapointId": "+14155550199", "datapointType": "phone" },
    { "datapointId": "jane.doe@acme.com", "datapointType": "email" }
  ],
  "partnerClientId": "acme-crm-tenant-42"
}


> Important: Signature verification applies the same way as standard webhook deliveries. See Security & Verification for details.

> Note: Ensure your account has a webhook secret before creating this subscription. See Regenerate Account Secret.

## Account

**Account API:** Retrieve account usage, credit balance, rate limits, plan details, and pricing.

Use this endpoint to monitor consumption and understand the credit cost of each action type in the public API flow.

> **Rate limit:** 5 requests per minute.


### Get Account Usage

 - [GET /v3/account/usage](https://docs.lusha.com/apis/openapi/account/getaccountusage.md): Returns a full snapshot of your account status:
- Credits — total, used, and remaining for the current billing cycle
- Rate limits — current usage and reset times for daily, hourly, and per-minute windows
- Plan — your current plan category and renewal dates
- Pricing — credit cost per action type across all public API endpoints

> Rate limit: This endpoint is limited to 5 requests per minute.

