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

# Start Lead Extraction

> Start an extraction job from LinkedIn or Sales Navigator search URLs.

Requires `lead_sourcing:run` and the creator's `ALLOW_LEAD_EXTRACTION` workspace permission. Supply `name`, HTTPS search `urls`, `url_type`, `mode`, `limit`, and `sender_id`.

* `url_type`: `linkedin_search` or `sales_navigator`.
* `mode`: `extraction_only` or `with_enrichment`.
* `limit`: at least 1; REST is capped by available credits rather than MCP's separate 2,000-lead tool maximum.
* `sender_id`: the LinkedIn account the extraction runs on. Use an `id` from [List Senders](https://docs.sendler.ai/api-reference/endpoint/get-senders.md) or a `senderId` from [Sender Quotas](https://docs.sendler.ai/api-reference/endpoint/get-sender-quotas.md). The account must belong to the workspace and be active. To spread extractions across accounts, pass a different `sender_id` per request.
* `webhook_url`: optional public HTTPS completion destination.

Extraction costs **1 credit per lead**. The response's `id` identifies the extraction job. Despite the URL's `campaigns` segment, this does not create an outreach sequence. [Poll job status](https://docs.sendler.ai/api-reference/endpoint/get-lead-extractor-campaign-status.md), then [read its leads](https://docs.sendler.ai/api-reference/endpoint/get-lead-extractor-campaign-results.md).

Sender errors, returned before any credits are reserved:

| Status | `code` | Meaning |
| - | - | - |
| 400 | — | `sender_id` is missing or empty. |
| 404 | `SENDER_NOT_FOUND` | No sender with that `id` in this workspace. |
| 400 | `SENDER_NOT_ACTIVE` | The sender exists but is paused, disconnected or otherwise not active; the message includes its current status. |
| 400 | `NO_LINKEDIN_ACCOUNT` | The sender has no connected LinkedIn account. |

Use an [Idempotency-Key](https://docs.sendler.ai/api-reference/behavior.md#idempotent-writes) to avoid duplicate paid jobs on retries. An identical request (same URLs, `url_type`, `mode` and `limit`) within about two minutes of another returns `409 DUPLICATE_CAMPAIGN_REQUEST` with the original job's `campaign_id`, even if it names a different `sender_id`.


## OpenAPI

````yaml POST /v1/lead-extractor/campaigns
openapi: 3.0.0
info:
  title: SendPilot External API
  description: >

    # SendPilot External API v1


    Public API for integrating with SendPilot programmatically.


    ## Authentication


    Requests authenticate with a workspace API key in the `X-API-Key` header:


    ```

    X-API-Key: sp_live_your_api_key_here

    ```


    `Authorization: Bearer sp_live_...` (or `sp_test_...`) is also accepted.
    Prefer one header; `X-API-Key` takes precedence. Clerk OAuth tokens for MCP
    connection URLs are not public REST API keys.


    A key only reaches what its scopes and creator's current workspace
    permissions allow. Each operation lists the scopes it needs in
    `x-sp-scopes`. Use `GET /v1/me` to inspect the effective permissions and
    subscription state.


    ## Rate Limits


    - **Per API Key**: 300 requests/minute

    - **Per Workspace**: 50,000 requests/day


    Responses that reach the rate limiter include these headers; early
    authentication failures may not:

    - `X-RateLimit-Limit`: Max requests per minute

    - `X-RateLimit-Remaining`: Remaining requests in current window

    - `X-RateLimit-Reset`: Epoch timestamp when limit resets


    ## LinkedIn Sender Limits


    When using messaging endpoints, these headers show account limits:

    - `X-LinkedIn-Messages-Remaining`: Messages left today

    - `X-LinkedIn-Connections-Remaining`: Connection requests left today

    - `X-LinkedIn-Quota-Reset-At`: When daily limits reset


    ## Retries


    Send an `Idempotency-Key` header on POST and PATCH requests. A retry with
    the same key within 24 hours returns the first result (with
    `Idempotent-Replayed: true`) instead of acting twice. The same key with a
    different request answers 422 `IDEMPOTENCY_KEY_REUSED`; a retry while the
    first request still runs answers 409 `IDEMPOTENCY_IN_PROGRESS`.


    Once execution is attempted, its response (including errors) is retained. If
    a process stops or result storage fails after the attempt, the durable
    record blocks another execution for the replay window and returns 409
    `IDEMPOTENCY_IN_PROGRESS` or `IDEMPOTENCY_REPLAY_UNAVAILABLE`. Check the
    operation's status before using a new key: an uncertain outcome may already
    have acted. Requests refused before execution is claimed, such as
    authentication or rate-limit refusals, can be retried with the same key.


    ## Webhooks


    Configure webhooks in the SendPilot app to receive real-time events:

    - `lead.tag.updated`

    - `lead.updated`

    - `message.sent`

    - `reply.received`

    - `connection_request.sent`

    - `connection_request.accepted`

    - `campaign.started`

    - `campaign.paused`

    - `campaign.resumed`

    - `campaign.finished`


    ## Error Codes


    Errors return a JSON body. Use the machine-readable `code` when supplied;
    validation messages can be arrays, and some legacy errors omit `code`. A
    typical error is:

    ```json

    {
      "statusCode": 400,
      "error": "Bad Request",
      "code": "SPECIFIC_ERROR_CODE",
      "message": "Human-readable description"
    }

    ```
  version: '1.0'
  contact:
    name: SendPilot Support
    url: https://sendpilot.ai
    email: support@sendpilot.ai
servers:
  - url: https://api.sendpilot.ai
security: []
tags: []
paths:
  /v1/lead-extractor/campaigns:
    post:
      tags:
        - External API - Lead Extractor
      summary: Create a lead extraction campaign
      description: >-
        Creates a new lead extraction campaign with the specified search URLs
        and settings
      operationId: leadExtractor.startExtraction
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateLeadExtractorCampaignDto'
      responses:
        '201':
          description: Campaign created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateLeadExtractorCampaignResponseDto'
        '400':
          description: Invalid request parameters
        '401':
          description: Invalid or missing API key
        '403':
          description: Insufficient credits
        '404':
          description: Sender not found in workspace
        '429':
          description: Rate limit exceeded
      security:
        - api-key: []
components:
  schemas:
    CreateLeadExtractorCampaignDto:
      type: object
      properties:
        name:
          type: string
          description: Campaign name
        urls:
          description: Search URLs (LinkedIn or Sales Navigator). Must be HTTPS.
          type: array
          items:
            type: string
        url_type:
          type: string
          enum:
            - linkedin_search
            - sales_navigator
          description: Type of URLs provided
        mode:
          type: string
          enum:
            - extraction_only
            - with_enrichment
          description: Extraction mode
        limit:
          type: number
          description: >-
            Maximum leads to extract (no hard limit - capped by available
            credits)
          minimum: 1
        sender_id:
          type: string
          description: >-
            ID of the LinkedIn account (sender) to run the extraction on. Get it
            from GET /v1/senders/quotas or GET /v1/inbox/senders.
          example: sender_123
        webhook_url:
          type: string
          description: >-
            HTTPS URL to receive a completion notification. Must be a public
            host.
          example: https://my-app.example.com/webhooks/sendpilot
      required:
        - name
        - urls
        - url_type
        - mode
        - limit
        - sender_id
    CreateLeadExtractorCampaignResponseDto:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        status:
          type: string
        created_at:
          type: string
        estimated_credits:
          type: number
          description: Estimated credits to be consumed
      required:
        - id
        - name
        - status
        - created_at
        - estimated_credits
  securitySchemes:
    api-key:
      type: apiKey
      in: header
      name: X-API-Key
      description: 'API key for authentication (prefix: sp_live_ or sp_test_)'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.