# Generated by bun scripts/sync-contracts.ts from backend openapi/v1.json.
openapi: 3.0.0
paths:
  /v1/campaigns:
    get:
      operationId: campaigns.list
      summary: List campaigns
      description: Retrieves all campaigns for the workspace with optional status filtering
      parameters:
        - name: status
          required: false
          in: query
          description: Filter by campaign status
          schema:
            default: all
            enum:
              - all
              - active
              - paused
              - draft
              - finished
            type: string
        - name: page
          required: false
          in: query
          description: Page number for pagination (1-indexed)
          schema:
            minimum: 1
            maximum: 100
            default: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Maximum number of items to return
          schema:
            minimum: 1
            maximum: 100
            default: 20
            type: number
      responses:
        '200':
          description: List of campaigns
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CampaignListResponseDto'
        '401':
          description: Invalid or missing API key
        '429':
          description: Rate limit exceeded
      tags:
        - External API - Campaigns
      security:
        - api-key: []
      x-sp-scopes:
        - campaigns:read
  /v1/campaigns/{id}:
    get:
      operationId: campaigns.get
      summary: Get campaign details
      description: Retrieves detailed information about a specific campaign
      parameters:
        - name: id
          required: true
          in: path
          description: Campaign ID
          schema:
            type: string
      responses:
        '200':
          description: Campaign details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CampaignDetailDto'
        '404':
          description: Campaign not found
      tags:
        - External API - Campaigns
      security:
        - api-key: []
      x-sp-scopes:
        - campaigns:read
    patch:
      operationId: campaigns.update
      summary: Update campaign
      description: Pause or resume a campaign
      parameters:
        - name: id
          required: true
          in: path
          description: Campaign ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCampaignDto'
      responses:
        '200':
          description: Campaign updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateCampaignResponseDto'
        '400':
          description: Invalid action or campaign state
        '404':
          description: Campaign not found
      tags:
        - External API - Campaigns
      security:
        - api-key: []
      x-sp-scopes:
        - campaigns:write
  /v1/credits:
    get:
      operationId: credits.get
      summary: Get unified credit balance
      description: >-
        Returns the workspace credit balance. All operations (lead extraction, enrichment, lead
        database) draw from this single pool.
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreditsResponseDto'
        '401':
          description: Invalid or missing API key
        '404':
          description: Workspace not found
        '429':
          description: Rate limit exceeded
        '500':
          description: Internal server error
      tags:
        - External API - Credits
      security:
        - api-key: []
      x-sp-scopes:
        - credits:read
  /v1/inbox/connect:
    post:
      operationId: inbox.sendConnectionRequest
      summary: Send LinkedIn connection request
      description: >-
        Sends a connection request to a LinkedIn profile. Optional connection note only works for
        premium accounts.
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendConnectionRequestDto'
      responses:
        '200':
          description: Connection request sent
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendConnectionRequestResponseDto'
        '400':
          description: Invalid request or sender not found
        '429':
          description: Daily connection limit exceeded
      tags:
        - External API - Inbox
      security:
        - api-key: []
      x-sp-scopes:
        - inbox:send
  /v1/inbox/conversations:
    get:
      operationId: inbox.listConversations
      summary: List conversations
      description: >-
        Returns all conversations for LinkedIn accounts in the workspace. Optionally filter by a
        specific account.
      parameters:
        - name: accountId
          required: false
          in: query
          description: LinkedIn sender ID to filter conversations by a specific account
          schema:
            example: sender_123
            type: string
        - name: limit
          required: false
          in: query
          description: Maximum number of items to return
          schema:
            minimum: 1
            maximum: 100
            default: 20
            type: number
        - name: continuationToken
          required: false
          in: query
          description: Token used for pagination when fetching more messages
          schema:
            type: string
      responses:
        '200':
          description: List of conversations
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListConversationsResponseDto'
        '404':
          description: Account not found
      tags:
        - External API - Inbox
      security:
        - api-key: []
      x-sp-scopes:
        - inbox:read
  /v1/inbox/conversations/{conversationId}/messages:
    get:
      operationId: inbox.listMessages
      summary: Get conversation messages
      description: Returns messages for a specific conversation with pagination.
      parameters:
        - name: conversationId
          required: true
          in: path
          description: Conversation/chat ID
          schema:
            example: 2-OVp-y-UNyFXBYvx0FqmQ
            type: string
        - name: accountId
          required: true
          in: query
          description: LinkedIn sender ID (required to identify which account owns this conversation)
          schema:
            example: sender_123
            type: string
        - name: limit
          required: false
          in: query
          description: Maximum number of items to return
          schema:
            minimum: 1
            maximum: 100
            default: 50
            type: number
        - name: continuationToken
          required: false
          in: query
          description: Token used for pagination when fetching more messages
          schema:
            type: string
      responses:
        '200':
          description: List of messages
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetConversationMessagesResponseDto'
        '400':
          description: Missing accountId parameter
        '404':
          description: Conversation or account not found
      tags:
        - External API - Inbox
      security:
        - api-key: []
      x-sp-scopes:
        - inbox:read
  /v1/inbox/send:
    post:
      operationId: inbox.sendMessage
      summary: Send LinkedIn message
      description: Sends a message via LinkedIn. The recipient must be a 1st degree connection of the sender.
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendMessageDto'
      responses:
        '200':
          description: Message sent or queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendMessageResponseDto'
        '400':
          description: Invalid request or sender not found
        '429':
          description: Daily message limit exceeded
      tags:
        - External API - Inbox
      security:
        - api-key: []
      x-sp-scopes:
        - inbox:send
  /v1/inbox/send/lead/{leadId}:
    post:
      operationId: inbox.sendMessageToLead
      summary: Send message to lead by ID
      description: >-
        Sends a message to a lead using their ID. The lead's LinkedIn URL is looked up
        automatically.
      parameters:
        - name: leadId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendMessageToLeadDto'
      responses:
        '200':
          description: Message sent or queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendMessageResponseDto'
        '400':
          description: Invalid request or sender not found
        '404':
          description: Lead not found
      tags:
        - External API - Inbox
      security:
        - api-key: []
      x-sp-scopes:
        - inbox:send
  /v1/inbox/senders:
    get:
      operationId: inbox.listSenders
      summary: List LinkedIn senders
      description: Returns all LinkedIn accounts connected to the workspace that can send messages
      parameters: []
      responses:
        '200':
          description: List of LinkedIn senders
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListSendersResponseDto'
      tags:
        - External API - Inbox
      security:
        - api-key: []
      x-sp-scopes:
        - senders:read
  /v1/lead-database/filters:
    get:
      operationId: leadDatabase.filters
      summary: Discover supported lead filters and values
      description: >-
        Lists supported filter schemas or searches/paginates the complete bundled value catalog.
        Does not start a search or spend credits.
      parameters:
        - name: filter
          required: false
          in: query
          description: Filter name. Omit to list supported filters.
          schema:
            type: string
        - name: search
          required: false
          in: query
          description: Case-insensitive filter-name or value search.
          schema:
            type: string
        - name: offset
          required: false
          in: query
          schema:
            minimum: 0
            maximum: 1000000
            default: 0
            type: number
        - name: limit
          required: false
          in: query
          schema:
            minimum: 1
            maximum: 100
            default: 50
            type: number
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LeadFilterCatalogResponseDto'
        '400':
          description: Unsupported filter or invalid pagination
        '401':
          description: Invalid or missing API key
        '403':
          description: Key lacks leads:read
      tags:
        - External API - Lead Database
      security:
        - api-key: []
      x-sp-scopes:
        - leads:read
  /v1/lead-database/searches:
    post:
      operationId: leadDatabase.startSearch
      summary: Create a lead database search
      description: Initiates a new lead database search with the specified filters and limit
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateLeadDatabaseSearchDto'
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateLeadDatabaseSearchResponseDto'
        '401':
          description: Invalid or missing API key
        '403':
          description: Insufficient quota
        '429':
          description: Rate limit exceeded
        '500':
          description: Internal server error
      tags:
        - External API - Lead Database
      security:
        - api-key: []
      x-sp-scopes:
        - lead_sourcing:run
      x-sp-costs-credits: true
  /v1/lead-database/searches/{id}/results:
    get:
      operationId: leadDatabase.getSearchResults
      summary: Get found leads
      description: Retrieves the leads found by a completed lead database search with pagination
      parameters:
        - name: id
          required: true
          in: path
          description: Search ID
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Maximum number of items to return
          schema:
            minimum: 1
            maximum: 500
            default: 100
            type: number
        - name: offset
          required: false
          in: query
          description: Offset for pagination (0-indexed)
          schema:
            minimum: 0
            maximum: 10000
            default: 0
            type: number
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetSearchResultsResponseDto'
        '401':
          description: Invalid or missing API key
        '404':
          description: Search not found
        '429':
          description: Rate limit exceeded
      tags:
        - External API - Lead Database
      security:
        - api-key: []
      x-sp-scopes:
        - leads:read
  /v1/lead-database/searches/{id}/status:
    get:
      operationId: leadDatabase.getSearchStatus
      summary: Get search status
      description: Retrieves the current status and progress of a lead database search
      parameters:
        - name: id
          required: true
          in: path
          description: Search ID
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetSearchStatusResponseDto'
        '401':
          description: Invalid or missing API key
        '404':
          description: Search not found
        '429':
          description: Rate limit exceeded
      tags:
        - External API - Lead Database
      security:
        - api-key: []
      x-sp-scopes:
        - leads:read
  /v1/lead-extractor/campaigns:
    post:
      operationId: leadExtractor.startExtraction
      summary: Create a lead extraction campaign
      description: Creates a new lead extraction campaign with the specified search URLs and settings
      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
        '429':
          description: Rate limit exceeded
      tags:
        - External API - Lead Extractor
      security:
        - api-key: []
      x-sp-scopes:
        - lead_sourcing:run
      x-sp-costs-credits: true
  /v1/lead-extractor/campaigns/{id}/results:
    get:
      operationId: leadExtractor.getResults
      summary: Get extracted leads
      description: Retrieves the leads extracted by a campaign with pagination support
      parameters:
        - name: id
          required: true
          in: path
          description: Campaign ID
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Maximum number of items to return
          schema:
            minimum: 1
            maximum: 500
            default: 100
            type: number
        - name: offset
          required: false
          in: query
          description: Offset for pagination (0-indexed)
          schema:
            minimum: 0
            maximum: 10000
            default: 0
            type: number
        - name: enriched_only
          required: false
          in: query
          description: >-
            Return only leads with completed enrichment when true. Omitted or false returns all
            leads. Accepts true, false, 1, or 0.
          schema:
            type: boolean
      responses:
        '200':
          description: Leads retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetResultsResponseDto'
        '401':
          description: Invalid or missing API key
        '404':
          description: Campaign not found
        '429':
          description: Rate limit exceeded
      tags:
        - External API - Lead Extractor
      security:
        - api-key: []
      x-sp-scopes:
        - leads:read
  /v1/lead-extractor/campaigns/{id}/status:
    get:
      operationId: leadExtractor.getStatus
      summary: Get campaign status
      description: Retrieves the current status and progress of a lead extraction campaign
      parameters:
        - name: id
          required: true
          in: path
          description: Campaign ID
          schema:
            type: string
      responses:
        '200':
          description: Campaign status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetCampaignStatusResponseDto'
        '401':
          description: Invalid or missing API key
        '404':
          description: Campaign not found
        '429':
          description: Rate limit exceeded
      tags:
        - External API - Lead Extractor
      security:
        - api-key: []
      x-sp-scopes:
        - leads:read
  /v1/leads:
    get:
      operationId: leads.list
      summary: List leads
      description: List leads with optional filtering by campaign and status
      parameters:
        - name: campaignId
          required: true
          in: query
          description: Campaign ID (required)
          schema:
            example: cmobr5lei0000u1h02ezf5itt
            type: string
        - name: status
          required: false
          in: query
          description: Filter by status
          schema:
            $ref: '#/components/schemas/LeadStatus'
        - name: full
          required: false
          in: query
          description: 'Return full lead data including all dynamic fields (default: false)'
          schema:
            default: false
            example: true
            type: boolean
        - name: page
          required: false
          in: query
          description: Page number for pagination (1-indexed)
          schema:
            minimum: 1
            maximum: 100
            default: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Maximum number of items to return
          schema:
            minimum: 1
            maximum: 100
            default: 50
            type: number
      responses:
        '200':
          description: List of leads
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LeadListResponseDto'
      tags:
        - External API - Leads
      security:
        - api-key: []
      x-sp-scopes:
        - leads:read
    post:
      operationId: leads.add
      summary: Add leads to campaign
      description: Adds multiple leads to an existing campaign. Duplicates are automatically skipped.
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddLeadsToCampaignDto'
      responses:
        '201':
          description: Leads added successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AddLeadsResponseDto'
        '400':
          description: Invalid request data
        '404':
          description: Campaign not found
      tags:
        - External API - Leads
      security:
        - api-key: []
      x-sp-scopes:
        - leads:write
  /v1/leads/{id}:
    get:
      operationId: leads.get
      summary: Get lead details
      description: >-
        Get detailed information about a specific lead. Use ?full=true for all fields including
        dynamic data.
      parameters:
        - name: id
          required: true
          in: path
          description: Lead ID
          schema:
            type: string
        - name: full
          required: false
          in: query
          description: 'true (or 1) for all fields: contact data, profile details and custom fields'
          schema:
            type: boolean
      responses:
        '200':
          description: Lead details (use ?full=true for full data)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LeadFullDto'
        '404':
          description: Lead not found
      tags:
        - External API - Leads
      security:
        - api-key: []
      x-sp-scopes:
        - leads:read
  /v1/leads/{id}/status:
    patch:
      operationId: leads.updateStatus
      summary: Update lead status
      description: >-
        Update the status (OPPORTUNITY, MEETING_BOOKED, DONE, UNSUBSCRIBED, IRRELEVANT) and/or
        custom status of a lead
      parameters:
        - name: id
          required: true
          in: path
          description: Lead ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateLeadStatusDto'
      responses:
        '200':
          description: Lead status updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateLeadResponseDto'
        '400':
          description: At least one of status or customLeadStatus is required
        '404':
          description: Lead not found
      tags:
        - External API - Leads
      security:
        - api-key: []
      x-sp-scopes:
        - leads:write
  /v1/me:
    get:
      operationId: workspace.me
      summary: Get the calling API key and its workspace
      description: >-
        Returns the workspace, whether its subscription is active, and the API key's scopes, expiry
        and rate limits.
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeResponseDto'
        '401':
          description: Invalid or missing API key
        '403':
          description: Key lacks workspace:read
      tags:
        - External API - Workspace
      security:
        - api-key: []
      x-sp-scopes:
        - workspace:read
  /v1/senders/quotas:
    get:
      operationId: senders.quotas
      summary: Get daily LinkedIn quotas per sender
      description: >-
        Every sender in the workspace with today's connection, message and like limits, what is used
        and remaining, and when each resets.
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SenderQuotasResponseDto'
        '401':
          description: Invalid or missing API key
        '403':
          description: Key lacks senders:read
      tags:
        - External API - Senders
      security:
        - api-key: []
      x-sp-scopes:
        - senders:read
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
tags: []
servers:
  - url: https://api.sendpilot.ai
components:
  securitySchemes:
    api-key:
      type: apiKey
      in: header
      name: X-API-Key
      description: 'API key for authentication (prefix: sp_live_ or sp_test_)'
  schemas:
    AddLeadsResponseDto:
      type: object
      properties:
        success:
          type: boolean
          description: Success status
          example: true
        leadsAdded:
          type: number
          description: Number of leads added
          example: 10
        duplicatesSkipped:
          type: number
          description: Number of duplicates skipped
          example: 2
        invalidEntries:
          type: number
          description: Number of invalid entries
          example: 0
        errors:
          description: Details of any errors
          type: array
          items:
            type: object
      required:
        - success
        - leadsAdded
        - duplicatesSkipped
        - invalidEntries
    AddLeadsToCampaignDto:
      type: object
      properties:
        campaignId:
          type: string
          description: Campaign ID to add leads to
          example: cmobr5lei0000u1h02ezf5itt
        leads:
          type: array
          description: >-
            Array of leads (1 to 1000 per request) - only linkedinUrl required, all other fields are
            dynamic
          minItems: 1
          maxItems: 1000
          items:
            type: object
            properties:
              linkedinUrl:
                type: string
                example: https://www.linkedin.com/in/johndoe/
              firstName:
                type: string
                example: John
              lastName:
                type: string
                example: Doe
              company:
                type: string
                example: Acme Corp
              title:
                type: string
                example: VP of Engineering
              email:
                type: string
                example: john@example.com
            additionalProperties: true
            required:
              - linkedinUrl
          example:
            - linkedinUrl: https://www.linkedin.com/in/johndoe/
              firstName: John
              lastName: Doe
              company: Acme Corp
              title: VP of Engineering
              industry: SaaS
              region: EMEA
      required:
        - campaignId
        - leads
    CampaignDetailDto:
      type: object
      properties:
        id:
          type: string
          description: Campaign ID
          example: clxyz123...
        name:
          type: string
          description: Campaign name
          example: Q1 Outreach
        status:
          type: string
          description: Campaign status
          example: started
          enum:
            - not_started
            - started
            - paused
            - failed
            - finished
            - scheduling
            - draft
            - unknown
        totalLeads:
          type: number
          description: Total leads in campaign
          example: 500
        leadsContacted:
          type: number
          description: Leads contacted
          example: 250
        connectionsSent:
          type: number
          description: Connections sent
          example: 200
        messagesSent:
          type: number
          description: Messages sent
          example: 150
        repliesReceived:
          type: number
          description: Replies received
          example: 25
        createdAt:
          format: date-time
          type: string
          description: When the campaign was created
        updatedAt:
          format: date-time
          type: string
          description: When the campaign was last updated
        type:
          type: string
          description: Campaign type
          example: regular
        linkedInSenderIds:
          description: Linked LinkedIn account IDs
          example:
            - sender_123
          type: array
          items:
            type: string
      required:
        - id
        - name
        - status
        - totalLeads
        - createdAt
        - type
        - linkedInSenderIds
    CampaignListResponseDto:
      type: object
      properties:
        campaigns:
          description: List of campaigns
          type: array
          items:
            $ref: '#/components/schemas/CampaignSummaryDto'
        pagination:
          description: Pagination info
          allOf:
            - $ref: '#/components/schemas/PaginationDto'
      required:
        - campaigns
        - pagination
    CampaignProgressDto:
      type: object
      properties:
        total_expected:
          type: number
        extracted:
          type: number
        enriched:
          type: number
        percent_complete:
          type: number
      required:
        - total_expected
        - extracted
        - enriched
        - percent_complete
    CampaignSummaryDto:
      type: object
      properties:
        id:
          type: string
          description: Campaign ID
          example: clxyz123...
        name:
          type: string
          description: Campaign name
          example: Q1 Outreach
        status:
          type: string
          description: Campaign status
          example: started
          enum:
            - not_started
            - started
            - paused
            - failed
            - finished
            - scheduling
            - draft
            - unknown
        totalLeads:
          type: number
          description: Total leads in campaign
          example: 500
        leadsContacted:
          type: number
          description: Leads contacted
          example: 250
        connectionsSent:
          type: number
          description: Connections sent
          example: 200
        messagesSent:
          type: number
          description: Messages sent
          example: 150
        repliesReceived:
          type: number
          description: Replies received
          example: 25
        createdAt:
          format: date-time
          type: string
          description: When the campaign was created
        updatedAt:
          format: date-time
          type: string
          description: When the campaign was last updated
      required:
        - id
        - name
        - status
        - totalLeads
        - createdAt
    ConversationMessageDto:
      type: object
      properties:
        id:
          type: string
          description: Message ID
          example: msg_123456789
        content:
          type: string
          description: Message content
          example: Hi John, I wanted to follow up on our conversation...
        sender:
          description: Message sender information
          allOf:
            - $ref: '#/components/schemas/MessageSenderDto'
        recipient:
          description: Message recipient information
          allOf:
            - $ref: '#/components/schemas/MessageSenderDto'
        direction:
          type: string
          description: Message direction
          enum:
            - sent
            - received
          example: sent
        sentAt:
          type: string
          description: When the message was sent (ISO 8601)
          example: '2026-04-23T10:30:00.000Z'
        readStatus:
          type: string
          description: Message read status
          enum:
            - read
            - unread
            - unknown
          example: read
        contentType:
          type: string
          description: Message content type
          example: TEXT
        attachments:
          description: Message attachments
          type: array
          items:
            $ref: '#/components/schemas/MessageAttachmentDto'
      required:
        - id
        - content
        - sender
        - recipient
        - direction
        - sentAt
        - readStatus
        - contentType
    ConversationPaginationDto:
      type: object
      properties:
        continuationToken:
          type: string
          description: Token used for pagination when fetching more conversations
        limit:
          type: number
          description: Items per page
          example: 20
        hasMore:
          type: boolean
          description: Whether there are more pages
          example: true
      required:
        - continuationToken
        - limit
        - hasMore
    ConversationParticipantDto:
      type: object
      properties:
        id:
          type: string
          description: LinkedIn provider ID
          example: ACoAAA123456
        name:
          type: string
          description: Participant name
          example: John Doe
        profileUrl:
          type: string
          description: LinkedIn profile URL
          example: https://www.linkedin.com/in/johndoe/
        profilePicture:
          type: string
          description: Profile picture URL
          example: https://media.licdn.com/...
      required:
        - id
        - name
    ConversationSummaryDto:
      type: object
      properties:
        id:
          type: string
          description: Conversation/chat ID
          example: 2-OVp-y-UNyFXBYvx0FqmQ
        accountId:
          type: string
          description: >-
            LinkedIn sender account ID (Prisma ID); null if the underlying provider account is not
            registered in this workspace
          example: sender_123
          nullable: true
        participants:
          description: Conversation participants
          type: array
          items:
            $ref: '#/components/schemas/ConversationParticipantDto'
        lastMessage:
          description: Last message preview
          allOf:
            - $ref: '#/components/schemas/LastMessagePreviewDto'
        lastActivityAt:
          type: string
          description: Last activity timestamp (ISO 8601)
          example: '2026-04-23T10:30:00.000Z'
        unreadCount:
          type: number
          description: Number of unread messages
          example: 2
        createdAt:
          type: string
          description: Conversation creation time (ISO 8601)
          example: '2026-04-20T08:00:00.000Z'
        updatedAt:
          type: string
          description: Conversation last update time (ISO 8601)
          example: '2026-04-23T10:30:00.000Z'
      required:
        - id
        - participants
        - lastActivityAt
        - unreadCount
    CreateLeadDatabaseSearchDto:
      type: object
      properties:
        name:
          type: string
          description: Search name
        filters:
          type: object
          additionalProperties: false
          minProperties: 1
          properties:
            member_full_name:
              description: Person name search.
              type: string
              minLength: 1
              maxLength: 2000
            job_titles:
              description: Current job titles. Use the filter catalog for suggested values.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_job_titles:
              description: Job titles to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            job_title_match_mode:
              description: 'Job-title matching: exact, contains (provider default), or smart.'
              type: string
              minLength: 1
              maxLength: 2000
              enum:
                - exact
                - contains
                - smart
            job_title_smart_mode:
              description: Sensitivity when job_title_match_mode is smart.
              type: string
              minLength: 1
              maxLength: 2000
              enum:
                - loose
                - normal
                - strict
            member_skills:
              description: Profile skills.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_member_skills:
              description: Profile skills to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            member_linkedin_username:
              description: LinkedIn usernames or profile URLs.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_member_linkedin_username:
              description: LinkedIn usernames or profile URLs to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            locations:
              description: Person country, region or city.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_locations:
              description: Person locations to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            member_description:
              description: Keywords in profile summaries.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_member_description:
              description: Profile-summary keywords to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            seniority_levels:
              description: Seniority level; use exact catalog values, e.g. C-Level or President/Vice President.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Specialist
                  - Manager
                  - Owner
                  - Founder
                  - President/Vice President
                  - Director
                  - Senior
                  - Head
                  - C-Level
                  - Partner
                  - Intern
            excluded_seniority_levels:
              description: Seniority levels to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Specialist
                  - Manager
                  - Owner
                  - Founder
                  - President/Vice President
                  - Director
                  - Senior
                  - Head
                  - C-Level
                  - Partner
                  - Intern
            member_department:
              description: Departments; mapped to the supported provider department filter.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_member_department:
              description: Departments to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            member_certifications:
              description: Professional certifications.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_member_certifications:
              description: Certifications to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            min_total_experience_duration_months:
              description: Minimum total experience in months.
              type: integer
              minimum: 0
            max_total_experience_duration_months:
              description: Maximum total experience in months.
              type: integer
              minimum: 0
            min_job_duration_months:
              description: Minimum time in the current job, in months.
              type: integer
              minimum: 0
            max_job_duration_months:
              description: Maximum time in the current job, in months.
              type: integer
              minimum: 0
            companies:
              description: Company names.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_companies:
              description: Company names to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            bulk_domains:
              description: Company domains separated by commas or newlines.
              type: string
              minLength: 1
              maxLength: 2000
            excluded_bulk_domains:
              description: Company domains to exclude, separated by commas or newlines.
              type: string
              minLength: 1
              maxLength: 2000
            company_linkedin_username:
              description: Company LinkedIn usernames or URLs.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_company_linkedin_username:
              description: Company LinkedIn usernames or URLs to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            company_type:
              description: Company types.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Privately Held
                  - Public Company
                  - Self-Owned
                  - Partnership
                  - Self-Employed
                  - Nonprofit
                  - Educational
                  - Government Agency
            excluded_company_type:
              description: Company types to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Privately Held
                  - Public Company
                  - Self-Owned
                  - Partnership
                  - Self-Employed
                  - Nonprofit
                  - Educational
                  - Government Agency
            industries:
              description: >-
                Company industries. Uses the supported experimental_industries provider field; query
                the catalog for values.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_industries:
              description: Industries to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            is_mapped_industries_strict:
              description: >-
                True requires exact industry matching; false lets the provider match related
                industries.
              type: boolean
            company_sizes:
              description: Employee-size ranges.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - '1'
                  - 2-10
                  - 11-50
                  - 51-200
                  - 201-500
                  - 501-1000
                  - 1001-5000
                  - 5001-10000
                  - 10001+
            excluded_company_sizes:
              description: Employee-size codes to exclude, from 1 (one employee) to 9 (10001+).
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: integer
                enum:
                  - 1
                  - 2
                  - 3
                  - 4
                  - 5
                  - 6
                  - 7
                  - 8
                  - 9
            hq_location:
              description: Company headquarters locations.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_hq_location:
              description: Headquarters locations to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            sic_codes:
              description: SIC code objects from the catalog. Only each value is sent to the provider.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 2000
                  value:
                    type: string
                    minLength: 1
                    maxLength: 2000
                required:
                  - label
                  - value
                additionalProperties: false
            excluded_sic_codes:
              description: SIC code strings to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            naics_codes:
              description: NAICS code objects from the catalog. Only each value is sent to the provider.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 2000
                  value:
                    type: string
                    minLength: 1
                    maxLength: 2000
                required:
                  - label
                  - value
                additionalProperties: false
            excluded_naics_codes:
              description: NAICS code strings to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            keywords:
              description: Keywords in company descriptions or specialties.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_keywords:
              description: Company keywords to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            last_funding_round_name:
              description: Latest funding-round types.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Seed Round
                  - Pre Seed Round
                  - Venture Round
                  - Series A
                  - Grant
                  - Non Equity Assistance
                  - Private Equity Round
                  - Series B
                  - Angel Round
                  - Debt Financing
                  - Post-IPO Equity
                  - Series C
                  - Corporate Round
                  - Equity Crowdfunding
                  - Funding Round
                  - Convertible Note
                  - Post-IPO Debt
                  - Series D
                  - Secondary Market
                  - Post-IPO Secondary
                  - Initial Coin Offering
                  - Product Crowdfunding
                  - Series E
                  - Series F
                  - Series G
                  - Series H
            ownership_status:
              description: Company ownership status.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Private
                  - Public
                  - Investment Company
                  - NGO/NPO/NFP/Organization/Association
                  - Government
                  - Product/Brand/Service
                  - SPAC
            min_last_funding_round_amount_raised:
              description: Minimum latest funding amount.
              type: integer
              minimum: 0
            max_last_funding_round_amount_raised:
              description: Maximum latest funding amount.
              type: integer
              minimum: 0
            ipo_start_date:
              description: IPO date range start, dd/mm/yyyy.
              type: string
              minLength: 1
              maxLength: 2000
            ipo_end_date:
              description: IPO date range end, dd/mm/yyyy.
              type: string
              minLength: 1
              maxLength: 2000
            acquired_start_date:
              description: Acquisition date range start, dd/mm/yyyy.
              type: string
              minLength: 1
              maxLength: 2000
            acquired_end_date:
              description: Acquisition date range end, dd/mm/yyyy.
              type: string
              minLength: 1
              maxLength: 2000
            min_revenue_annual:
              description: Minimum annual revenue.
              type: integer
              minimum: 0
            max_revenue_annual:
              description: Maximum annual revenue.
              type: integer
              minimum: 0
            min_total_website_visits_monthly:
              description: Minimum monthly website visits.
              type: integer
              minimum: 0
            max_total_website_visits_monthly:
              description: Maximum monthly website visits.
              type: integer
              minimum: 0
            min_rank_global:
              description: Minimum global website rank.
              type: integer
              minimum: 0
            max_rank_global:
              description: Maximum global website rank.
              type: integer
              minimum: 0
            min_rank_country:
              description: Minimum website rank within its country.
              type: integer
              minimum: 0
            max_rank_country:
              description: Maximum website rank within its country.
              type: integer
              minimum: 0
            min_rank_category:
              description: Minimum website rank within its category.
              type: integer
              minimum: 0
            max_rank_category:
              description: Maximum website rank within its category.
              type: integer
              minimum: 0
            min_bounce_rate:
              description: Minimum bounce-rate percentage.
              type: integer
              minimum: 0
              maximum: 100
            max_bounce_rate:
              description: Maximum bounce-rate percentage.
              type: integer
              minimum: 0
              maximum: 100
            min_pages_per_visit:
              description: Minimum average pages per visit.
              type: integer
              minimum: 0
            max_pages_per_visit:
              description: Maximum average pages per visit.
              type: integer
              minimum: 0
            min_average_visit_duration_seconds:
              description: Minimum visit duration in seconds.
              type: integer
              minimum: 0
            max_average_visit_duration_seconds:
              description: Maximum visit duration in seconds.
              type: integer
              minimum: 0
            top_topics:
              description: Topics covered by the company website.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_top_topics:
              description: Website topics to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            technologies_used:
              description: Technologies used by the company.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_technologies_used:
              description: Company technologies to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            pricing_available:
              description: Company publishes pricing.
              type: boolean
            demo_available:
              description: Company offers a demo.
              type: boolean
            documentation_exist:
              description: Company provides documentation.
              type: boolean
            free_trial_available:
              description: Company offers a free trial.
              type: boolean
            is_downloadable:
              description: Company offers downloadable software/resources.
              type: boolean
            mobile_apps_exist:
              description: Company has mobile apps.
              type: boolean
            online_reviews_exist:
              description: Company has online reviews.
              type: boolean
            min_company_employee_reviews_aggregate_score:
              description: Minimum employee-review score.
              type: integer
              minimum: 0
            max_company_employee_reviews_aggregate_score:
              description: Maximum employee-review score.
              type: integer
              minimum: 0
            job_posting_title:
              description: Job titles the company is recruiting.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_job_posting_title:
              description: Recruiting titles to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            job_posting_location:
              description: Job posting locations.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_job_posting_location:
              description: Job posting locations to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            excluded_job_posting_functions:
              description: Job functions to exclude.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
            job_posting_start_date:
              description: Job posting date range start, dd/mm/yyyy.
              type: string
              minLength: 1
              maxLength: 2000
            job_posting_end_date:
              description: Job posting date range end, dd/mm/yyyy.
              type: string
              minLength: 1
              maxLength: 2000
            job_posting_type:
              description: Employment types.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Full-time
                  - Part-time
                  - Contract
                  - Internship
                  - Volunteer
                  - Temporary
                  - Other
            job_posting_seniority:
              description: Recruiting seniority levels.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
                enum:
                  - Entry level
                  - Internship
                  - Associate
                  - Mid-Senior level
                  - Director
                  - Executive
                  - Not Applicable
            experimental_industries:
              description: Compatibility alias for industries; do not supply both with different values.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
              deprecated: true
            excluded_experimental_industries:
              description: >-
                Compatibility alias for excluded_industries; do not supply both with different
                values.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
              deprecated: true
            experimental_member_department:
              description: Compatibility alias for member_department; do not supply both with different values.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
              deprecated: true
            excluded_experimental_department:
              description: >-
                Compatibility alias for excluded_member_department; do not supply both with
                different values.
              type: array
              minItems: 1
              maxItems: 100
              items:
                type: string
                minLength: 1
                maxLength: 2000
              deprecated: true
        limit:
          type: number
          description: Maximum leads to find (no hard limit - capped by available credits)
          minimum: 1
        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
        - filters
        - limit
    CreateLeadDatabaseSearchResponseDto:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        status:
          type: string
        created_at:
          type: string
        estimated_quota:
          type: number
          description: Quota to be consumed
      required:
        - id
        - name
        - status
        - created_at
        - estimated_quota
    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
        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
    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
    CreditsResponseDto:
      type: object
      properties:
        available:
          type: number
          example: 12500
          description: Total credits available now (sum of subscription + purchased buckets).
        subscription:
          type: number
          example: 7500
          description: Plan allocation remaining. Reset to the plan total at the start of each billing cycle.
        purchased:
          type: number
          example: 5000
          description: Purchased credits remaining. These never expire and roll over across billing cycles.
        used:
          type: number
          example: 2500
          description: Credits consumed in the current billing cycle.
        nextResetDate:
          type: string
          example: '2026-06-01T00:00:00.000Z'
          description: >-
            ISO 8601 timestamp at which the subscription bucket will next reset to the plan total.
            `null` for workspaces with no active subscription/license.
          nullable: true
      required:
        - available
        - subscription
        - purchased
        - used
    ExtractedLeadDto:
      type: object
      properties:
        id:
          type: string
        linkedin_identifier:
          type: string
        linkedin_num_id:
          type: string
        linkedin_url:
          type: string
        public_profile_url:
          type: string
        input_url:
          type: string
        first_name:
          type: string
        last_name:
          type: string
        full_name:
          type: string
        headline:
          type: string
        summary:
          type: string
        about:
          type: string
        location:
          type: string
        city:
          type: string
        country:
          type: string
        country_code:
          type: string
        profile_picture_url:
          type: string
        profile_picture_url_large:
          type: string
        avatar:
          type: string
        background_picture_url:
          type: string
        banner_image:
          type: string
        default_avatar:
          type: boolean
        company:
          type: string
        current_company:
          type: string
        current_company_id:
          type: string
        current_company_link:
          type: string
        job_position:
          type: string
        email:
          type: string
        emails:
          type: array
          items:
            type: string
        phone:
          type: string
        phones:
          type: array
          items:
            type: string
        websites:
          type: object
          additionalProperties: true
        contact_info:
          type: object
          additionalProperties: true
        connections:
          type: number
        connections_count:
          type: number
        followers:
          type: number
        follower_count:
          type: number
        shared_connections_count:
          type: number
        network_distance:
          type: string
        is_creator:
          type: boolean
        is_hiring:
          type: boolean
        is_influencer:
          type: boolean
        is_open_profile:
          type: boolean
        is_open_to_work:
          type: boolean
        is_premium:
          type: boolean
        can_send_inmail:
          type: boolean
        experience:
          type: object
          additionalProperties: true
        work_experience:
          type: object
          additionalProperties: true
        education:
          type: object
          additionalProperties: true
        educations_details:
          type: string
        certifications:
          type: object
          additionalProperties: true
        courses:
          type: object
          additionalProperties: true
        projects:
          type: object
          additionalProperties: true
        publications:
          type: object
          additionalProperties: true
        honors_and_awards:
          type: object
          additionalProperties: true
        volunteering_experience:
          type: object
          additionalProperties: true
        languages:
          type: object
          additionalProperties: true
        skills:
          type: object
          additionalProperties: true
        activity:
          type: object
          additionalProperties: true
        posts:
          type: object
          additionalProperties: true
        people_also_viewed:
          type: object
          additionalProperties: true
        similar_profiles:
          type: object
          additionalProperties: true
        recommendations:
          type: object
          additionalProperties: true
        recommendations_count:
          type: number
        hashtags:
          type: object
          additionalProperties: true
        bio_links:
          type: object
          additionalProperties: true
        invitation:
          type: object
          additionalProperties: true
        birthdate:
          type: object
          additionalProperties: true
        primary_locale:
          type: object
          additionalProperties: true
        is_enriched:
          type: boolean
        extracted_at:
          type: string
        memorialized_account:
          type: boolean
      required:
        - id
        - linkedin_url
        - is_enriched
        - extracted_at
    FoundLeadDto:
      type: object
      properties:
        id:
          type: string
        first_name:
          type: string
        last_name:
          type: string
        full_name:
          type: string
        email:
          type: string
        phone:
          type: string
        linkedin_url:
          type: string
        job_title:
          type: string
        company:
          type: string
        location:
          type: string
        person_address:
          type: string
        country:
          type: string
        industry:
          type: string
        seniority:
          type: string
        departments:
          type: string
        profile_summary:
          type: string
        company_linkedin_url:
          type: string
        company_summary:
          type: string
        company_keywords:
          type: object
          additionalProperties: true
        website:
          type: string
        employees:
          type: string
        company_address:
          type: string
        company_city:
          type: string
        company_state:
          type: string
        company_country:
          type: string
        company_phone:
          type: object
          additionalProperties: true
        company_email:
          type: object
          additionalProperties: true
        technologies:
          type: object
          additionalProperties: true
        latest_funding:
          type: string
        latest_funding_amount:
          type: string
        last_raised_at:
          type: string
        facebook:
          type: string
        twitter:
          type: string
        youtube:
          type: string
        instagram:
          type: string
        annual_revenue:
          type: string
      required:
        - id
    GetCampaignStatusResponseDto:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        status:
          type: string
          enum:
            - pending
            - running
            - completed
            - failed
            - cancelled
        progress:
          $ref: '#/components/schemas/CampaignProgressDto'
        created_at:
          type: string
        completed_at:
          type: string
        error_message:
          type: string
      required:
        - id
        - name
        - status
        - progress
        - created_at
    GetConversationMessagesResponseDto:
      type: object
      properties:
        conversationId:
          type: string
          description: Conversation ID
          example: 2-OVp-y-UNyFXBYvx0FqmQ
        messages:
          description: List of messages
          type: array
          items:
            $ref: '#/components/schemas/ConversationMessageDto'
        pagination:
          description: Pagination information
          allOf:
            - $ref: '#/components/schemas/MessagesPaginationDto'
      required:
        - conversationId
        - messages
        - pagination
    GetResultsResponseDto:
      type: object
      properties:
        campaign_id:
          type: string
        leads:
          type: array
          items:
            $ref: '#/components/schemas/ExtractedLeadDto'
        total:
          type: number
        offset:
          type: number
        limit:
          type: number
        has_more:
          type: boolean
      required:
        - campaign_id
        - leads
        - total
        - offset
        - limit
        - has_more
    GetSearchResultsResponseDto:
      type: object
      properties:
        search_id:
          type: string
        leads:
          type: array
          items:
            $ref: '#/components/schemas/FoundLeadDto'
        total:
          type: number
        offset:
          type: number
        limit:
          type: number
        has_more:
          type: boolean
      required:
        - search_id
        - leads
        - total
        - offset
        - limit
        - has_more
    GetSearchStatusResponseDto:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        status:
          type: string
          enum:
            - pending
            - processing
            - completed
            - failed
        progress:
          $ref: '#/components/schemas/SearchProgressDto'
        created_at:
          type: string
        completed_at:
          type: string
        error_message:
          type: string
      required:
        - id
        - name
        - status
        - progress
        - created_at
    LastMessagePreviewDto:
      type: object
      properties:
        content:
          type: string
          description: Message content preview (truncated to 100 chars)
          example: Hi John, I wanted to follow up on...
        sentAt:
          type: string
          description: When the message was sent (ISO 8601)
          example: '2026-04-23T10:30:00.000Z'
        direction:
          type: string
          description: Message direction
          enum:
            - sent
            - received
          example: sent
      required:
        - content
        - sentAt
        - direction
    LeadFilterCatalogResponseDto:
      type: object
      properties:
        filters:
          type: array
          items:
            type: object
            additionalProperties: true
          description: Filter names, descriptions, input_schema, value_mode and compatibility aliases.
        filter:
          type: string
          nullable: true
        values:
          type: array
          items:
            type: object
            additionalProperties: true
          description: Exact input values and readable labels. Empty for free-form filters.
        total:
          type: number
        offset:
          type: number
        limit:
          type: number
        has_more:
          type: boolean
      required:
        - filters
        - filter
        - values
        - total
        - offset
        - limit
        - has_more
    LeadFullDto:
      type: object
      properties:
        id:
          type: string
          description: Lead ID
        linkedinUrl:
          type: string
          description: LinkedIn URL
        firstName:
          type: string
          description: First name
        lastName:
          type: string
          description: Last name
        company:
          type: string
          description: Company
        title:
          type: string
          description: Title
        status:
          $ref: '#/components/schemas/LeadStatus'
        customLeadStatus:
          type: string
          description: Custom lead status
        campaignId:
          type: string
          description: Campaign ID the lead belongs to
        senderId:
          type: string
          description: >-
            LinkedIn sender assigned to this lead (use as senderId for /v1/inbox/send); null until
            the campaign assigns one
          nullable: true
        createdAt:
          format: date-time
          type: string
          description: When the lead was added
        email:
          type: string
          description: Email address
        location:
          type: string
          description: Location
        industry:
          type: string
          description: Industry
        about:
          type: string
          description: About/bio
        website:
          type: string
          description: Website
        profilePictureUrl:
          type: string
          description: Profile picture URL
        isPremium:
          type: boolean
          description: Is premium LinkedIn account
        isOpenProfile:
          type: boolean
          description: Is open profile
        connectionCount:
          type: number
          description: Connection count
        followerCount:
          type: number
          description: Follower count
        data:
          type: object
          description: All dynamic lead data including custom fields
          additionalProperties: true
        updatedAt:
          format: date-time
          type: string
          description: When the lead was last updated
      required:
        - id
        - linkedinUrl
        - status
        - customLeadStatus
        - campaignId
        - createdAt
        - updatedAt
    LeadListResponseDto:
      type: object
      properties:
        leads:
          description: List of leads
          type: array
          items:
            $ref: '#/components/schemas/LeadSummaryDto'
        pagination:
          description: Pagination info
          allOf:
            - $ref: '#/components/schemas/PaginationDto'
      required:
        - leads
        - pagination
    LeadStatus:
      type: string
      description: Lead status
      enum:
        - PENDING
        - PROCESSING
        - MESSAGE_SENT
        - CONNECTION_SENT
        - CONNECTION_ACCEPTED
        - CONNECTION_ALREADY_SENT
        - REPLY_RECEIVED
        - FOLLOWUP_SENT
        - BLOCKED
        - PROFILE_UNREACHABLE
        - RATE_LIMITED
        - FAILED
        - SUCCESS
        - UNSUBSCRIBED
        - IRRELEVANT
        - SKIPPED
        - DONE
        - MEETING_BOOKED
        - OPPORTUNITY
        - LIKED_POST
        - MESSAGE_SCHEDULED
        - CONNECTION_SCHEDULED
        - LIKE_POST_SCHEDULED
        - VIEW_PROFILE_SCHEDULED
        - CONNECTED
        - CONNECTION_WITHDRAWN
        - WITHDRAWAL_SCHEDULED
        - WITHDRAWAL_NOT_POSSIBLE
        - NOT_CONNECTED
        - ICP_MATCH
        - ICP_NOT_MATCH
        - PROFILE_VIEWED
        - STARTED
        - STOPPED
        - WAITING
    LeadSummaryDto:
      type: object
      properties:
        id:
          type: string
          description: Lead ID
        linkedinUrl:
          type: string
          description: LinkedIn URL
        firstName:
          type: string
          description: First name
        lastName:
          type: string
          description: Last name
        company:
          type: string
          description: Company
        title:
          type: string
          description: Title
        status:
          $ref: '#/components/schemas/LeadStatus'
        customLeadStatus:
          type: string
          description: Custom lead status
        campaignId:
          type: string
          description: Campaign ID the lead belongs to
        senderId:
          type: string
          description: >-
            LinkedIn sender assigned to this lead (use as senderId for /v1/inbox/send); null until
            the campaign assigns one
          nullable: true
        createdAt:
          format: date-time
          type: string
          description: When the lead was added
      required:
        - id
        - linkedinUrl
        - status
        - customLeadStatus
        - campaignId
        - createdAt
    LinkedInSenderDto:
      type: object
      properties:
        id:
          type: string
          description: Sender ID
          example: sender_123
        name:
          type: string
          description: LinkedIn profile name
          example: John Doe
        linkedinUrl:
          type: string
          description: LinkedIn profile URL
          example: https://www.linkedin.com/in/johndoe/
        status:
          type: string
          description: Account status
          enum:
            - active
            - disconnected
            - rate_limited
            - suspended
        dailyMessageLimit:
          type: number
          description: Daily message limit
          example: 100
        messagesSentToday:
          type: number
          description: Messages sent today
          example: 45
        remainingMessages:
          type: number
          description: Remaining messages today
          example: 55
      required:
        - id
        - name
        - linkedinUrl
        - status
        - dailyMessageLimit
        - messagesSentToday
        - remainingMessages
    ListConversationsResponseDto:
      type: object
      properties:
        conversations:
          description: List of conversations
          type: array
          items:
            $ref: '#/components/schemas/ConversationSummaryDto'
        pagination:
          description: Pagination information
          allOf:
            - $ref: '#/components/schemas/ConversationPaginationDto'
      required:
        - conversations
        - pagination
    ListSendersResponseDto:
      type: object
      properties:
        senders:
          description: Available LinkedIn senders
          type: array
          items:
            $ref: '#/components/schemas/LinkedInSenderDto'
        total:
          type: number
          description: Total number of senders
          example: 3
      required:
        - senders
        - total
    MeApiKeyDto:
      type: object
      properties:
        id:
          type: string
          example: key_123
        name:
          type: string
          example: Claude agent (read-only)
        scopes:
          type: array
          description: What the key may do, including implied scopes
          items:
            type: string
            enum:
              - workspace:read
              - campaigns:read
              - campaigns:write
              - leads:read
              - leads:write
              - inbox:read
              - inbox:send
              - senders:read
              - senders:manage
              - lead_sourcing:run
              - credits:read
              - webhooks:read
              - webhooks:manage
              - content:read
              - content:write
        fullAccess:
          type: boolean
          description: True for keys created without scopes
        expiresAt:
          format: date-time
          type: string
          description: When the key stops working
        rateLimits:
          $ref: '#/components/schemas/MeRateLimitsDto'
      required:
        - id
        - name
        - scopes
        - fullAccess
        - rateLimits
    MeRateLimitsDto:
      type: object
      properties:
        perMinute:
          type: number
          example: 300
        perDay:
          type: number
          example: 50000
      required:
        - perMinute
        - perDay
    MeResponseDto:
      type: object
      properties:
        workspace:
          $ref: '#/components/schemas/MeWorkspaceDto'
        subscription:
          $ref: '#/components/schemas/MeSubscriptionDto'
        apiKey:
          $ref: '#/components/schemas/MeApiKeyDto'
        missingScopes:
          type: array
          description: Scopes the key would need for full access
          items:
            type: string
            enum:
              - workspace:read
              - campaigns:read
              - campaigns:write
              - leads:read
              - leads:write
              - inbox:read
              - inbox:send
              - senders:read
              - senders:manage
              - lead_sourcing:run
              - credits:read
              - webhooks:read
              - webhooks:manage
              - content:read
              - content:write
      required:
        - workspace
        - subscription
        - apiKey
        - missingScopes
    MeSubscriptionDto:
      type: object
      properties:
        active:
          type: boolean
          description: >-
            False when the subscription has lapsed: reads still work, changes return 402
            SUBSCRIPTION_INACTIVE
      required:
        - active
    MeWorkspaceDto:
      type: object
      properties:
        id:
          type: string
          example: ws_123
        name:
          type: string
          example: Acme Outbound
        active:
          type: boolean
          description: False once the workspace is deactivated
      required:
        - id
        - name
        - active
    MessageAttachmentDto:
      type: object
      properties:
        type:
          type: string
          description: Attachment type
          example: IMAGE
        url:
          type: string
          description: Attachment URL
          example: https://media.licdn.com/...
        name:
          type: string
          description: Attachment filename
          example: document.pdf
        size:
          type: number
          description: Attachment size in bytes
          example: 1024
      required:
        - type
        - url
    MessageSenderDto:
      type: object
      properties:
        id:
          type: string
          description: Sender ID
          example: ACoAAA123456
        name:
          type: string
          description: Sender name
          example: John Doe
        profileUrl:
          type: string
          description: LinkedIn profile URL
          example: https://www.linkedin.com/in/johndoe/
      required:
        - id
        - name
    MessagesPaginationDto:
      type: object
      properties:
        continuationToken:
          type: string
          description: Token used for pagination when fetching more messages
        limit:
          type: number
          description: Items per page
          example: 50
        hasMore:
          type: boolean
          description: Whether there are more messages
          example: true
      required:
        - continuationToken
        - limit
        - hasMore
    PaginationDto:
      type: object
      properties:
        page:
          type: number
          description: Current page number
          example: 1
        limit:
          type: number
          description: Items per page
          example: 20
        total:
          type: number
          description: Total number of items
          example: 150
        totalPages:
          type: number
          description: Total number of pages
          example: 8
      required:
        - page
        - limit
        - total
        - totalPages
    SearchProgressDto:
      type: object
      properties:
        requested:
          type: number
        found:
          type: number
        percent_complete:
          type: number
      required:
        - requested
        - found
        - percent_complete
    SendConnectionRequestDto:
      type: object
      properties:
        senderId:
          type: string
          description: LinkedIn sender ID to use (must be connected to workspace)
          example: sender_123
        recipientLinkedinUrl:
          type: string
          description: LinkedIn URL of the recipient to connect with
          example: https://www.linkedin.com/in/johndoe/
        message:
          type: string
          description: Optional connection note (only works for premium LinkedIn accounts)
          example: Hi John, I would love to connect with you!
          maxLength: 300
      required:
        - senderId
        - recipientLinkedinUrl
    SendConnectionRequestResponseDto:
      type: object
      properties:
        success:
          type: boolean
          description: Success status
          example: true
        requestId:
          type: string
          description: Request ID
          example: conn_123
        recipientLinkedinUrl:
          type: string
          description: Recipient LinkedIn URL
        status:
          type: string
          description: Connection status
          example: sent
          enum:
            - sent
            - already_connected
            - failed
        error:
          type: string
          description: Error message if failed
        timestamp:
          format: date-time
          type: string
          description: Timestamp when request was sent
      required:
        - success
        - requestId
        - recipientLinkedinUrl
        - status
        - timestamp
    SendMessageDto:
      type: object
      properties:
        senderId:
          type: string
          description: LinkedIn sender ID to use (must be connected to workspace)
          example: sender_123
        recipientLinkedinUrl:
          type: string
          description: LinkedIn URL of the recipient (must be a 1st degree connection)
          example: https://www.linkedin.com/in/johndoe/
        message:
          type: string
          description: Message content to send
          example: Hi John, I wanted to follow up on our conversation...
          minLength: 1
          maxLength: 8000
        campaignId:
          type: string
          description: Optional campaign ID to associate this message with
          example: campaign_123
        leadId:
          type: string
          description: Optional lead ID to associate this message with
          example: lead_123
      required:
        - senderId
        - recipientLinkedinUrl
        - message
    SendMessageResponseDto:
      type: object
      properties:
        success:
          type: boolean
          description: Success status
          example: true
        messageId:
          type: string
          description: Message ID
          example: msg_123
        recipientLinkedinUrl:
          type: string
          description: Recipient LinkedIn URL
        leadId:
          type: string
          description: Lead ID if message was sent to a lead
        conversationId:
          type: string
          description: >-
            LinkedIn conversation ID, when the provider returns one (use with GET
            /v1/inbox/conversations/:conversationId/messages)
        status:
          type: string
          description: Message status
          example: sent
          enum:
            - queued
            - sent
            - failed
        error:
          type: string
          description: Error message if failed
        timestamp:
          format: date-time
          type: string
          description: Timestamp when message was sent/queued
      required:
        - success
        - messageId
        - recipientLinkedinUrl
        - status
        - timestamp
    SendMessageToLeadDto:
      type: object
      properties:
        senderId:
          type: string
          description: LinkedIn sender ID to use
          example: sender_123
        message:
          type: string
          description: Message content to send
          example: Hi {{firstName}}, I wanted to follow up on our conversation...
          minLength: 1
          maxLength: 8000
        campaignId:
          type: string
          description: Optional campaign ID to associate this message with
      required:
        - senderId
        - message
    SenderQuotaDto:
      type: object
      properties:
        limit:
          type: number
          example: 25
        used:
          type: number
          example: 7
        remaining:
          type: number
          example: 18
        resetAt:
          type: string
          description: 'Next reset: midnight in the sender''s reset timezone'
          example: '2026-09-26T00:00:00.000Z'
      required:
        - limit
        - used
        - remaining
        - resetAt
    SenderQuotasDto:
      type: object
      properties:
        senderId:
          type: string
          example: sender_123
        name:
          type: string
          example: Jane Doe
        linkedinUrl:
          type: string
          example: https://www.linkedin.com/in/janedoe/
        status:
          type: string
          description: Sender status
          example: active
        isPremium:
          type: boolean
        timezone:
          type: string
          example: UTC
        connections:
          $ref: '#/components/schemas/SenderQuotaDto'
        messages:
          $ref: '#/components/schemas/SenderQuotaDto'
        likes:
          $ref: '#/components/schemas/SenderQuotaDto'
      required:
        - senderId
        - name
        - linkedinUrl
        - status
        - isPremium
        - timezone
        - connections
        - messages
        - likes
    SenderQuotasResponseDto:
      type: object
      properties:
        senders:
          type: array
          items:
            $ref: '#/components/schemas/SenderQuotasDto'
        total:
          type: number
          example: 2
      required:
        - senders
        - total
    UpdateCampaignDto:
      type: object
      properties:
        action:
          type: string
          description: Action to perform on the campaign
          enum:
            - pause
            - resume
          example: pause
      required:
        - action
    UpdateCampaignResponseDto:
      type: object
      properties:
        success:
          type: boolean
          description: Success status
          example: true
        campaignId:
          type: string
          description: Campaign ID
          example: clxyz123...
        action:
          type: string
          description: Action performed
          example: pause
        newStatus:
          type: string
          description: New campaign status
          example: paused
        message:
          type: string
          description: Message
          example: Campaign paused successfully
      required:
        - success
        - campaignId
        - action
        - newStatus
        - message
    UpdateLeadResponseDto:
      type: object
      properties:
        success:
          type: boolean
          description: Success status
          example: true
        leadId:
          type: string
          description: Lead ID
          example: lead_123
        status:
          type: string
          description: New status
          example: MEETING_BOOKED
        message:
          type: string
          description: Message
      required:
        - success
        - leadId
        - status
        - message
    UpdateLeadStatusDto:
      type: object
      properties:
        status:
          type: string
          description: >-
            New status for the lead. Only outcome statuses can be set; statuses managed by the
            sequence engine are rejected.
          example: MEETING_BOOKED
          enum:
            - OPPORTUNITY
            - MEETING_BOOKED
            - DONE
            - UNSUBSCRIBED
            - IRRELEVANT
        customLeadStatus:
          type: string
          description: New custom lead status for CRM categorization
          example: INTERESTED
          enum:
            - LEAD
            - INTERESTED
            - MEETING_BOOKED
            - MEETING_COMPLETE_NOT_CLOSED
            - CLOSED
            - WRONG_PERSON
            - NOT_INTERESTED
            - NO_RESPONSE
        note:
          type: string
          description: Optional note/reason for status change
          example: Customer showed interest in demo
          maxLength: 1000
