Lusha Webhooks API

Subscription management for real-time signal callbacks — bulk create and delete up to 25 items per request, account-level HMAC-SHA256 secret with rotation, delivery test, contact opt-out notifications, and a delivery audit log with statistics.

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/lusha-webhooks-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

lusha-webhooks-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Lusha API Documentation Webhooks API
  version: ''
  x-logo:
    url: https://www.lusha.com/logo.png
  license:
    name: Proprietary
    url: https://lusha.com/legal/terms
  description: "<blockquote class=\"callout\">\n\n **This is the Lusha API V3 documentation.** \n \n 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/`.\n\n  For more information on V3, refer to the [Migration Guide](/tutorials/v3-migration-guide).\n\n</blockquote>\n\n  --- \n\nLusha 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.\n\nUse the Lusha API to **search for new prospects**, **enrich existing records**, **react to real-world changes**, and **expand coverage** with AI-powered lookalike recommendations.\n\n> All API requests must be made over **HTTPS**. All responses are returned in **JSON** format.\n\n--- \n## Available Endpoints\n\n| Category | Description |\n|---|---|\n| [**Search**](#tag/Search) | Find contacts or companies using known identifiers |\n| [**Enrich**](#tag/Enrich) | Retrieve full profile data for contacts or companies by ID |\n| [**Search & Enrich**](#tag/Search-and-Enrich) | Find and retrieve full contact or company data in a single call |\n| [**Prospecting**](#tag/Prospecting) | Filter-based search across contacts and companies |\n| [**Lookalikes**](#tag/Lookalikes) | AI-powered recommendations for similar contacts and companies |\n| [**Buying Group**](#tag/Buying-Group) | Identify decision makers, champions, and end users within target accounts |\n| [**Contacts Tables**](#tag/Contacts-Tables) | Persist, organize, and enrich contacts in reusable tables |\n| [**Companies Tables**](#tag/Companies-Tables) | Persist, organize, and enrich companies in reusable tables |\n| [**Signals**](#tag/Signals) | Real-world activity data for contacts and companies |\n| [**Website Visitors**](#tag/Website-Visits) | Companies ranked by website-visit signals for your tracked domains |\n| [**Filters**](#tag/Filters) | Discover valid filter values for prospecting |\n| [**Webhooks**](#tag/Webhooks) | Real-time signal notifications via HTTP callbacks |\n| [**Account**](#tag/Account) | Usage, credits, rate limits, and pricing |\n\n<blockquote class=\"callout\">\n\n **Waterfall Reveal for Contact Enrichment.**\n\n  Enrich Contacts now supports `waterfallEnabled`. Fall through to your enabled third-party providers when Lusha's own data has no match, for extra reach on hard-to-match contacts. On by default once your account has it turned on - pass `waterfallEnabled: false` to opt a specific call out. [See Enrich Contacts](#operation/enrichContacts).\n\n</blockquote>\n\n---\n\n## Data Source and Privacy\n\n**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.\n\nFor more details on how we collect and handle data, see our [Privacy Policy](https://lusha.com/legal/privacy-notice/).\n\n---\n\n## Authentication\n\nAll 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.\n\n> Generate and manage your API key in the [Lusha dashboard](https://dashboard.lusha.com/enrich/api).\n\nStore your API key securely and use it only in **server-side environments**.\n\n---\n\n## Rate Limiting\n\nLusha 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.\n\nRate limits for the **Credit Usage API** differ from standard endpoint limits.\n\n> **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.\n\n**Rate Limit Response Headers**\n\n| Header | Description |\n|--------|-------------|\n| `x-rate-limit-daily` | Total requests allowed per day |\n| `x-daily-requests-left` | Requests remaining in your daily quota |\n| `x-daily-usage` | Requests made in the current daily period |\n| `x-rate-limit-hourly` | Total requests allowed per hour |\n| `x-hourly-requests-left` | Requests remaining in your hourly quota |\n| `x-hourly-usage` | Requests made in the current hourly period |\n| `x-rate-limit-minute` | Total requests allowed per minute |\n| `x-minute-requests-left` | Requests remaining in the current minute window |\n| `x-minute-usage` | Requests made in the current minute window |\n\n---\n## Error Codes\n\nLusha uses standard HTTP status codes to indicate the result of each request.\n\n| Code | Name | Description |\n|------|------|-------------|\n| `200` | OK | Request was successful |\n| `400` | Bad Request | Request is malformed or missing required fields |\n| `401` | Unauthorized | API key is missing or invalid |\n| `402` | Payment Required | Insufficient credits or payment needed |\n| `403` | Forbidden | Account is inactive. Contact support@lusha.com |\n| `404` | Not Found | Endpoint or resource does not exist |\n| `429` | Too Many Requests | Rate limit or daily quota exceeded |\n| `451` | Unavailable For Legal Reasons | Request blocked due to GDPR regulations |\n| `499` | Client Closed Request | Request timed out before completing |\n| `5XX` | Server Error | Issue on Lusha's end. Retry with exponential backoff |\n\n**Error Response Format**\n\n```json\n{\n  \"statusCode\": 400,\n  \"message\": \"Invalid request parameters\"\n}\n```\n\n**Tables-specific error codes**\n\n| Code | Status | Meaning |\n|---|---|---|\n| `TABLE_NOT_FOUND` | 404 | The `table_id` does not exist or is not accessible to this account |\n| `COLUMN_NOT_FOUND` | 404 | The `column_id` does not exist on the given table |\n| `TABLE_NAME_CONFLICT` | 409 | A table with this name already exists |\n\nTables error bodies use the shape `{ \"message\": \"...\", \"code\": <status>, ... }` rather than the `statusCode`/`errors` shape used elsewhere in this doc.\n\n**Limits:** up to 500 entity IDs per add/remove call · max 50,000 entities per table · max 500 tables per account · `page` 0–100 · `size` default 100.\n\n**Tips for Handling Errors**\n\n- Verify your API key is correct and active\n- Read the `message` field for specific troubleshooting details\n- For `429` errors, wait before retrying\n- For `5XX` errors, use exponential backoff before retrying\n"
  contact:
    name: Lusha Support
    url: https://api.lusha.com
    email: support@lusha.com
  termsOfService: https://lusha.com/legal/terms
  x-privacy-policy:
    name: Privacy Policy
    url: https://lusha.com/legal/privacy-notice/
servers:
- url: https://api.lusha.com
  description: Production server
security:
- ApiKeyAuth: []
tags:
- name: Webhooks
  description: "Subscribe to real-time notifications when contacts change jobs or companies experience key business events.\n\nWebhooks deliver HTTP POST requests to your endpoints when signals occur - from promotions and job changes to company growth.\n\n> For a full list of available signals, refer to [**Signal Options**](https://docs.lusha.com/apis/openapi/signals/getsignaloptions).\n---\n**Key Features:**\n- Real-time contact & company signal notifications\n- Bulk subscription management (up to 25 items per request)\n- Secure delivery with HMAC-SHA256 signatures\n- Delivery monitoring with audit logs\n\n **Available Endpoints:**\n\n| Method | Endpoint | Purpose |\n|--------|----------|---------|\n| POST | `/api/subscriptions` | Create subscriptions (bulk supported) |\n| GET | `/api/subscriptions` | List all subscriptions |\n| GET | `/api/subscriptions/{id}` | Get subscription by ID |\n| PATCH | `/api/subscriptions/{id}` | Update subscription |\n| POST | `/api/subscriptions/delete` | Delete subscriptions (bulk supported) |\n| POST | `/api/subscriptions/{id}/test` | Test subscription delivery |\n| GET | `/api/audit-logs` | Get webhook delivery logs |\n| GET | `/api/audit-logs/stats` | Get delivery statistics |\n| GET | `/api/account/secret` | Get account webhook secret |\n| POST | `/api/account/secret/regenerate` | Regenerate account secret |\n| POST | `/api/subscriptions/opt-out` | Subscribe to contact opt-out notifications |\n\n> **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.\n      ---\n\n<details>\n<summary><strong>Rate Limits</strong></summary>\n\n| Operation | Limit |\n|-----------|-------|\n| API Requests | 100 requests/minute per account |\n| Create Subscriptions | 25 items per request |\n| Delete Subscriptions | 25 items per request |\n\n</details>\n\n---\n\n<details>\n<summary><strong>Security & Verification</strong></summary>\n\n**HTTPS Requirement:**\n- Production webhook URLs **must** use HTTPS\n- HTTP URLs are not accepted\n\n**Signature Verification:**\n\nAll webhook deliveries include an `X-Lusha-Signature` header containing an HMAC-SHA256 signature. Verify this signature to ensure the request is from Lusha:\n\n1. Extract the `X-Lusha-Signature` and `X-Lusha-Timestamp` headers\n2. Concatenate: `timestamp + \".\" + JSON.stringify(payload)`\n3. Compute HMAC-SHA256 using your webhook secret\n4. Compare the computed signature with the received signature\n\n**Example (Node.js):**\n```javascript\nconst crypto = require('crypto');\n\nfunction verifySignature(payload, signature, timestamp, secret) {\n  const signedPayload = `${timestamp}.${JSON.stringify(payload)}`;\n  const expectedSignature = crypto\n    .createHmac('sha256', secret)\n    .update(signedPayload)\n    .digest('hex');\n  \n  return crypto.timingSafeEqual(\n    Buffer.from(signature),\n    Buffer.from(expectedSignature)\n  );\n}\n```\n\n> **Security Best Practice:** Always verify webhook signatures to prevent spoofed requests.\n\n</details>\n\n---\n\n<details>\n<summary><strong>Credits & Billing</strong></summary>\n\n**Credit Charges:**\n- Credits are charged when signals are detected and delivered to your webhook\n- The `creditsCharged` field in the webhook payload indicates how many credits were used\n- Credits are deducted from your account balance per signal type\n\n**No Duplicate Charges:**\n- Each signal is delivered once and charged once\n- Webhook delivery retries do not incur additional charges\n\n</details>\n\n---\n\n<details>\n<summary><strong>Error Response Format</strong></summary>\n\nAll error responses follow this format:\n```json\n{\n  \"statusCode\": 400,\n  \"message\": \"Validation failed\",\n  \"errors\": [\"entityType must be one of: contact, company\"]\n}\n```\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `statusCode` | number | HTTP status code |\n| `message` | string | Error message |\n| `errors` | string[] | Detailed error messages (optional) |\n\n</details>\n    \n---\n"
  x-tag-expanded: true
paths:
  /api/subscriptions:
    post:
      tags:
      - Webhooks
      summary: Create Subscription
      description: "Creates one or more webhook subscriptions for real-time signal notifications.\n\n**Delivery & Reliability:**\n- Webhooks are delivered with automatic retry on failures\n- Maximum 3 retry attempts with exponential backoff\n- Subscriptions auto-disable after max retries exceeded\n- All deliveries are logged in audit logs\n\n> **Note:** Your webhook endpoint must respond with a proper acknowledgment. \n See Client Response Format below for details.\n\n> **Limit:** Maximum 25 subscriptions per request\n\n*Endpoint*: **(POST) https://api.lusha.com/api/subscriptions**\n\n---\n\n### Webhook Payload You'll Receive\n When a signal is triggered, this payload is sent to your webhook URL:\n```json\n    {\n      \"id\": \"f3b87e05-0402-4f3e-8e26-6a38fd0ad62c\",\n      \"type\": \"promotion\",\n      \"entityType\": \"contact\",\n      \"entityId\": \"4158887495\",\n      \"subscriptionId\": \"507f1f77bcf86cd799439011\",\n      \"data\": {\n        \"personId\": 4158887495,\n        \"currentCompanyId\": 40823133,\n        \"currentCompanyName\": \"OMG Hospitality Group LLC\",\n        \"currentDomain\": \"omghospitalitygroup.com\",\n        \"currentTitle\": \"Bartender\",\n        \"currentDepartments\": [\n          { \"id\": 7, \"value\": \"Other\" }\n        ],\n        \"previousCompanyName\": \"First Watch Restaurants\",\n        \"previousDomain\": \"firstwatch.com\",\n        \"signalDate\": \"2025-07-01\"\n      },\n      \"timestamp\": \"2026-01-14T16:16:35.841Z\",\n      \"billing\": {\n        \"creditsCharged\": 1\n      }\n    }\n    ```\n            **Example — Company News Signal:**\n    ```json\n            {\n              \"id\": \"a7c92f14-1234-4b3e-9d22-8b4fe1d0bc45\",\n              \"type\": \"commercialActivityNews\",\n              \"entityType\": \"company\",\n              \"entityId\": \"33222678\",\n              \"subscriptionId\": \"507f1f77bcf86cd799439011\",\n              \"data\": {\n                \"companyId\": \"33222678\",\n                \"companyName\": \"Lusha\",\n                \"domain\": \"lusha.com\",\n                \"signalId\": \"1503910\",\n                \"eventType\": \"partnership\",\n                \"eventSummary\": \"Lusha announced a strategic partnership with Salesforce.\",\n                \"articlePublishedDate\": \"2025-06-15\",\n                \"articleTitle\": \"Lusha Partners with Salesforce\",\n                \"articleHighlight\": \"The partnership enables Salesforce users to access Lusha data directly within their CRM.\",\n                \"eventEffectiveDate\": \"2025-06-10\",\n                \"articleUrl\": \"https://example.com/lusha-salesforce-partnership\"\n              },\n              \"timestamp\": \"2026-01-14T16:16:35.841Z\",\n              \"billing\": {\n                \"creditsCharged\": 1\n              }\n            }\n          ```\n\n      **Headers Included:**\n\n      | Header | Description |\n      |--------|-------------|\n      | `X-Lusha-Signature` | HMAC-SHA256 signature for verification |\n      | `X-Lusha-Timestamp` | Unix timestamp of the request |\n      | `Content-Type` | application/json |\n      | `User-Agent` | Lusha-Webhooks/1.0 |\n\n\n---\n⚠️ **Important:** Ensure your account has a webhook secret before creating subscriptions.\nCreate one via the [Regenerate Account Secret](#operation/regenerateAccountSecret) endpoint.\n\n---\n\n### Client Response Format (Required)\n\nWhen your webhook endpoint receives a delivery, it **must** acknowledge receipt with this response:\n\n  **Required Response:**\n  ````json\n  {\n    \"received\": true,\n    \"timestamp\": \"2026-02-05T10:30:45.123Z\",\n    \"webhookId\": \"f3b87e05-0402-4f3e-8e26-6a38fd0ad62c\"\n  }\n  ````\n\n<details>\n<summary><strong>Response Requirements</strong></summary>\n\n  | Requirement | Value |\n  |-------------|-------|\n  | **HTTP Status** | `201 Created` (recommended) or any `2xx` status |\n  | **Content-Type** | `application/json` |\n  | **Response Time** | Within 10 seconds |\n</details>\n\n\n<details>\n<summary><strong>Field Descriptions & Implementation Guide</strong></summary>\n\n  **Field Descriptions:**\n  * `received` (boolean, required): Confirmation flag - must be `true`\n  * `timestamp` (string, required): ISO 8601 timestamp of receipt\n  * `webhookId` (string, required): Echo the `id` from webhook payload\n\n  **Implementation Example:**\n  ```javascript\n  app.post('/webhook', async (req, res) => {\n    // 1. Verify signature\n    if (!verifyWebhookSignature(req)) {\n      return res.status(401).json({ error: 'Invalid signature' });\n    }\n    \n    // 2. Queue for async processing\n    await queueWebhook(req.body);\n    \n    // 3. Acknowledge immediately\n    res.status(201).json({\n      received: true,\n      timestamp: new Date().toISOString(),\n      webhookId: req.body.id\n    });\n    ```\n\n  **Important Notes:**\n  * Return acknowledgment **before** heavy processing\n  * Non-2xx responses trigger retry mechanism\n  * After 3 failed retries, subscription is disabled\n\n  </details>\n\n----\n"
      operationId: createSubscription
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubscriptionRequest'
            examples:
              singleSubscription:
                summary: Create a single subscription
                value:
                  defaults:
                    entityType: contact
                    signalTypes:
                    - promotion
                    - companyChange
                    url: https://example.com/webhooks/lusha
                  subscriptions:
                  - entityId: '123456'
                    name: My Test Webhook
              multipleSubscriptions:
                summary: Create multiple subscriptions with shared URL
                value:
                  defaults:
                    entityType: contact
                    signalTypes:
                    - promotion
                    - companyChange
                    url: https://example.com/webhooks/lusha
                  subscriptions:
                  - entityId: '123'
                    name: Contact 123
                  - entityId: '456'
                    name: Contact 456
                  - entityId: '789'
                    name: Contact 789
              mixedEntityTypes:
                summary: Mixed entity types with shared URL
                value:
                  defaults:
                    signalTypes:
                    - promotion
                    - itSpendIncrease
                    url: https://example.com/webhooks/lusha
                  subscriptions:
                  - entityType: contact
                    entityId: '123'
                  - entityType: company
                    entityId: '456'
      responses:
        '201':
          description: Subscriptions created (full or partial success)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateSubscriptionResponse'
              examples:
                allSuccessful:
                  summary: All subscriptions created successfully
                  value:
                    total: 3
                    successful: 3
                    failed: 0
                    results:
                    - index: 0
                      success: true
                      subscription:
                        id: 507f1f77bcf86cd799439011
                        entityType: contact
                        entityId: '123'
                        signalTypes:
                        - promotion
                        - companyChange
                        url: https://example.com/webhooks/lusha
                        name: Contact 123
                        isActive: true
                        createdAt: '2026-02-02T10:00:00.000Z'
                        updatedAt: '2026-02-02T10:00:00.000Z'
                partialSuccess:
                  summary: Some subscriptions failed (partial success)
                  value:
                    total: 3
                    successful: 2
                    failed: 1
                    results:
                    - index: 0
                      success: true
                      subscription:
                        id: 507f1f77bcf86cd799439011
                        entityType: contact
                        entityId: '123'
                        signalTypes:
                        - promotion
                        - companyChange
                        url: https://example.com/webhooks/lusha
                        name: Contact 123
                        isActive: true
                        createdAt: '2026-02-02T10:00:00.000Z'
                        updatedAt: '2026-02-02T10:00:00.000Z'
                    - index: 1
                      success: false
                      error:
                        code: DUPLICATE_SUBSCRIPTION
                        message: Subscription already exists for entity type 'contact' with entity ID '456'
        '400':
          description: Bad request - URL validation failed or invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                statusCode: 400
                message: Validation failed
                errors:
                - 'entityType must be one of: contact, company'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Forbidden - feature not available or limit reached
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                statusCode: 403
                message: Maximum subscriptions limit reached for your account
        '500':
          $ref: '#/components/responses/InternalServerError'
    get:
      tags:
      - Webhooks
      summary: List Subscriptions
      description: '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.

        '
      operationId: listSubscriptions
      parameters:
      - name: limit
        in: query
        required: false
        description: Maximum number of results (1-100)
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 10
        example: 10
      - name: offset
        in: query
        required: false
        description: Number of results to skip
        schema:
          type: integer
          minimum: 0
          default: 0
        example: 0
      responses:
        '200':
          description: List of subscriptions retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionListResponse'
              example:
                data:
                - id: 507f1f77bcf86cd799439011
                  entityType: contact
                  entityId: '123456'
                  signalTypes:
                  - promotion
                  - companyChange
                  url: https://example.com/webhook
                  name: My Contact Webhook
                  isActive: true
                  createdAt: '2024-01-01T00:00:00.000Z'
                  updatedAt: '2024-01-01T00:00:00.000Z'
                pagination:
                  total: 25
                  limit: 10
                  offset: 0
                  hasMore: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/subscriptions/{id}:
    get:
      tags:
      - Webhooks
      summary: Get Subscription by ID
      description: 'Returns a single webhook subscription by ID.


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

        '
      operationId: getSubscriptionById
      parameters:
      - name: id
        in: path
        required: true
        description: Subscription ID
        schema:
          type: string
        example: 507f1f77bcf86cd799439011
      responses:
        '200':
          description: Subscription retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionWithoutSecret'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      tags:
      - Webhooks
      summary: Update Subscription
      description: '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

        ---

        '
      operationId: updateSubscription
      parameters:
      - name: id
        in: path
        required: true
        description: Subscription ID
        schema:
          type: string
        example: 507f1f77bcf86cd799439011
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSubscriptionRequest'
            examples:
              disableSubscription:
                summary: Disable a subscription
                value:
                  isActive: false
              updateSignals:
                summary: Change subscribed signals
                value:
                  signalTypes:
                  - promotion
                  - companyChange
              regenerateSecret:
                summary: Regenerate webhook secret
                value:
                  regenerateSecret: true
              updateUrl:
                summary: Update webhook URL
                value:
                  url: https://new-domain.com/webhooks/lusha
      responses:
        '200':
          description: Subscription updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/subscriptions/{id}/test:
    post:
      tags:
      - Webhooks
      summary: Test Subscription
      description: '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

        '
      operationId: testSubscription
      parameters:
      - name: id
        in: path
        required: true
        description: Subscription ID
        schema:
          type: string
        example: 507f1f77bcf86cd799439011
      - name: mode
        in: query
        required: false
        description: Test mode
        schema:
          type: string
          enum:
          - direct
          - kafka
          - full
          default: full
        example: full
      responses:
        '200':
          description: Test executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TestSubscriptionResponse'
              example:
                subscriptionId: 507f1f77bcf86cd799439011
                subscriptionName: My Test Webhook
                url: https://example.com/webhook
                mode: full
                flowCheck:
                  success: true
                  statusCode: 200
                  durationMs: 150
                testPayload:
                  entityType: contact
                  signalType: promotion
                  data: {}
                isSuccess: true
                timestamp: '2024-01-01T00:00:00.000Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Subscription does not belong to your account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                statusCode: 403
                message: Subscription does not belong to your account
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/subscriptions/delete:
    post:
      tags:
      - Webhooks
      summary: Delete Subscriptions
      description: '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

        '
      operationId: deleteSubscriptions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - ids
              properties:
                ids:
                  type: array
                  minItems: 1
                  maxItems: 25
                  items:
                    type: string
                  description: Array of subscription IDs to delete
                  example:
                  - 507f1f77bcf86cd799439011
                  - 507f1f77bcf86cd799439012
            examples:
              singleDelete:
                summary: Delete a single subscription
                value:
                  ids:
                  - sub-123
              multipleDelete:
                summary: Delete multiple subscriptions
                value:
                  ids:
                  - sub-123
                  - sub-456
                  - sub-789
      responses:
        '200':
          description: Delete operation completed (full or partial success)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteSubscriptionResponse'
              examples:
                allSuccessful:
                  summary: All subscriptions deleted successfully
                  value:
                    total: 3
                    successful: 3
                    failed: 0
                    results:
                    - index: 0
                      success: true
                      subscription:
                        id: sub-123
                        entityType: contact
                        entityId: '123'
                        name: Contact Webhook
                partialSuccess:
                  summary: Some deletions failed
                  value:
                    total: 3
                    successful: 2
                    failed: 1
                    results:
                    - index: 0
                      success: true
                      subscription:
                        id: sub-123
                        entityType: contact
                        entityId: '123'
                        name: Contact Webhook
                    - index: 1
                      success: false
                      error:
                        code: NOT_FOUND
                        message: Subscription with id 'sub-456' not found
        '400':
         

# --- truncated at 32 KB (57 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/lusha/refs/heads/main/openapi/lusha-webhooks-api-openapi.yml