Lensmor Contacts API

Search contacts and run asynchronous email or phone unlock workflows.

Operations 5

GET /external/contacts/search Search contacts #
POST /external/contacts/unlock Unlock contact emails #
GET /external/contacts/unlock-tasks/{taskId} Get contact unlock task #
POST /external/contacts/unlock-phone Unlock contact phone numbers #
GET /external/contacts/unlock-phone-tasks/{taskId} Get phone unlock task #

Work with this as data

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

MCP server

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

https://apis.io/mcp

Tools for apis

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

Call it yourself

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

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

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

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

OpenAPI Specification

lensmor-contacts-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Lensmor Contacts API
  version: 0.27.0
  description: Lensmor Event Intelligence API for event discovery, exhibitor research, personnel lookup, credits, and profile matching.
  license:
    name: Lensmor Terms of Service
    url: https://www.lensmor.com/terms
servers:
- url: https://platform.lensmor.com
security:
- bearerAuth: []
tags:
- name: Contacts
  description: Search contacts and run asynchronous email or phone unlock workflows.
paths:
  /external/contacts/search:
    get:
      tags:
      - Contacts
      summary: Search contacts
      description: 'Search Lensmor contacts within a required company scope. Start with `company_name`, then add `role`, `person_name`, or both to narrow the results.


        Use this endpoint to find people at a target account, confirm coverage before an unlock workflow, and collect personnel IDs for profile, email, phone, or outreach actions.


        This is a read-only, company-scoped discovery endpoint; it does not unlock contact data. Use only the documented filters. No matches return `200 OK` with an empty `items` array. `sourceType` contains non-exclusive labels aggregated across associated events, while `linkedinActivity` and `linkedinActivityStatus` remain `null` here.'
      operationId: searchContacts
      parameters:
      - name: company_name
        in: query
        required: true
        description: 'Required company-name search term that scopes the contact search. Length: 1–200 characters.'
        example: Acme
        schema:
          type: string
          minLength: 1
          maxLength: 200
      - name: role
        in: query
        description: Optional job-role or title term used to narrow people within the company. Blank values are ignored.
        example: VP Marketing
        schema:
          type: string
          maxLength: 200
      - name: person_name
        in: query
        description: Optional person-name term used to narrow people within the company. Blank values are ignored.
        example: Jane
        schema:
          type: string
          maxLength: 200
      - $ref: '#/components/parameters/Page'
      - $ref: '#/components/parameters/PageSize'
      responses:
        '200':
          description: Paginated matching contacts. A valid search with no matches returns the same envelope with an empty `items` array and zero totals.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactPage'
              example:
                items:
                - id: '101'
                  fullName: Jane Doe
                  title: VP Marketing
                  department: marketing
                  seniorityLevel: vp
                  linkedinUrl: https://linkedin.com/in/jane
                  companyName: Acme
                  sourceType:
                  - social
                  - visitors
                  email: null
                  phone: null
                  contactUnlockStatus: locked
                  phoneUnlockStatus: null
                  linkedinActivity: null
                  linkedinActivityStatus: null
                  eventCount: 3
                total: 1
                page: 1
                pageSize: 20
                totalPages: 1
                hasMore: false
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
  /external/contacts/unlock:
    post:
      tags:
      - Contacts
      summary: Unlock contact emails
      description: 'Submit personnel records for email enrichment, optionally in an event context.


        Use this endpoint after contact or personnel discovery when the integration needs email addresses. Newly chargeable work consumes `15` credits per contact and returns `status: accepted` with a task identifier. `event_id` is optional; omitting it skips event membership validation. If every record is already unlocked or skipped, the endpoint can return `status: success` without a task.


        Only poll the email task endpoint when `status` is `accepted` and `task_id` is present. A `201` response means the submission was processed, not that every email was found. Inspect skipped details and item-level results, and avoid duplicate work while an earlier task is active.'
      operationId: unlockContactEmails
      parameters:
      - $ref: '#/components/parameters/CallSource'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - personnel_ids
              properties:
                personnel_ids:
                  type: array
                  minItems: 1
                  maxItems: 2000
                  items:
                    type: string
                  description: Lensmor personnel identifiers selected for this batch operation.
                  example:
                  - '789'
                event_id:
                  type: string
                  minLength: 1
                  maxLength: 100
                  description: Optional Lensmor event identifier returned as `id` or `eventId`. When omitted, event membership validation is skipped.
                  example: '26855'
            example:
              personnel_ids:
              - '789'
              - '790'
              event_id: '139574'
      responses:
        '201':
          description: Unlock submission accepted, or completed with no chargeable work
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactUnlockSubmission'
              example:
                status: accepted
                task_id: '321'
                job_id: '321'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
  /external/contacts/unlock-tasks/{taskId}:
    get:
      tags:
      - Contacts
      summary: Get contact unlock task
      description: 'Poll an email-unlock task created by the contact email submission endpoint.


        Store the returned `task_id` and use it here to make the workflow resumable across background jobs, frontend refreshes, or retries. Continue polling while `taskStatus` is `pending` or `processing`, then stop when it reaches `completed` or `failed`. Use a controlled polling interval and treat each read as a status check, not a new unlock request.


        Task completion does not guarantee an email for every submitted person. Process item-level status, email, and error information independently, persist successful results, and do not retry the same task after it reaches a terminal state.'
      operationId: getContactUnlockTask
      parameters:
      - name: taskId
        in: path
        required: true
        schema:
          type: string
          pattern: ^[0-9]+$
        description: Email-unlock task identifier returned as `task_id` by the submission endpoint.
        example: '321'
      responses:
        '200':
          description: Unlock task status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactUnlockTask'
              example:
                taskId: '321'
                taskStatus: processing
                items:
                - personnelId: '789'
                  status: unlocked
                  email: jane@acme.example
                - personnelId: '790'
                  status: processing
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
  /external/contacts/unlock-phone:
    post:
      tags:
      - Contacts
      summary: Unlock contact phone numbers
      description: 'Submit personnel records for phone-number enrichment, optionally in an event context.


        Use this endpoint after contact or personnel discovery when the integration needs phone numbers. Newly chargeable work consumes `150` credits per contact and returns `status: accepted` with a task identifier. `event_id` is optional; omitting it skips event membership validation. When there is no chargeable work, the endpoint can return `status: success` without a task.


        Only poll the phone task endpoint when `status` is `accepted` and `task_id` is present. A `201` response does not guarantee that every phone number will be found. Inspect skipped details and item-level failures, and avoid duplicate submissions while a task is pending or processing.'
      operationId: unlockContactPhones
      parameters:
      - $ref: '#/components/parameters/CallSource'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PhoneUnlockRequest'
            example:
              personnel_ids:
              - '789'
              event_id: '139574'
      responses:
        '201':
          description: Phone unlock submission accepted, or completed with no chargeable work
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactUnlockSubmission'
              example:
                status: accepted
                task_id: '321'
                job_id: '321'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
  /external/contacts/unlock-phone-tasks/{taskId}:
    get:
      tags:
      - Contacts
      summary: Get phone unlock task
      description: 'Poll a phone-unlock task created by the contact phone submission endpoint.


        Store the returned `task_id` so the workflow can resume across background jobs, frontend refreshes, or retries. Poll while `taskStatus` is `pending` or `processing`, then stop when it reaches `completed` or `failed`. Use a controlled interval and treat each read as a status check, not a new unlock request.


        Task-level completion does not guarantee a phone number for every person. Handle item-level status, phone, and `errorCode` independently, persist successful results, surface per-record failures, and do not retry a terminal task.'
      operationId: getPhoneUnlockTask
      parameters:
      - name: taskId
        in: path
        required: true
        schema:
          type: string
          pattern: ^[0-9]+$
        description: Phone-unlock task identifier returned as `task_id` by the submission endpoint.
        example: '321'
      responses:
        '200':
          description: Phone unlock task status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhoneUnlockTask'
              example:
                taskId: '321'
                taskStatus: completed
                items:
                - personnelId: '789'
                  status: unlocked
                  phone: +1 415 555 0100
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    Page:
      name: page
      in: query
      description: One-based page number. Use `1` for the first page and increment it while `hasMore` is `true`.
      example: 1
      schema:
        type: integer
        minimum: 1
        default: 1
    CallSource:
      name: x-call-source
      in: header
      required: false
      schema:
        type: string
        enum:
        - api
        - agent
      description: Identify the caller as `api` or `agent` for usage attribution. Defaults to `api` when omitted.
      example: api
    PageSize:
      name: pageSize
      in: query
      description: Maximum number of records requested per page. The shared default is `20` and the shared upper limit is `100`; individual endpoints can document a lower maximum.
      example: 20
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 20
  schemas:
    ContactItem:
      type: object
      description: Public personnel/contact record with identity, access state, and optional unlocked values.
      required:
      - id
      - fullName
      - contactUnlockStatus
      properties:
        id:
          type: string
          description: Personnel identifier to pass to profile, event, email-unlock, phone-unlock, and outreach workflows.
          example: '101'
        fullName:
          type:
          - string
          - 'null'
          description: Person's display name when available.
          example: Jane Doe
        title:
          type:
          - string
          - 'null'
          description: Current job title when available.
          example: VP Marketing
        department:
          type:
          - string
          - 'null'
          description: Normalized department label when available.
          example: marketing
        seniorityLevel:
          type:
          - string
          - 'null'
          description: Normalized seniority label when available.
          example: vp
        linkedinUrl:
          type:
          - string
          - 'null'
          description: LinkedIn profile URL when available.
          example: https://linkedin.com/in/jane
        companyName:
          type:
          - string
          - 'null'
          description: Company associated with the person when available.
          example: Acme
        sourceType:
          type: array
          description: 'Lensmor source/business labels for this person. Source labels are not mutually exclusive. Product mapping: Exhibitor is exhibitor, Social Signals is social, and Visitor is visitors. Visitor represents registered attendees obtained through organizer or data-provider partnerships; Social Signals is not proof of official registration. Event personnel lists return event-scoped labels, while personnel profile and contact search can aggregate labels across associated events.'
          items:
            type: string
            enum:
            - exhibitor
            - social
            - visitors
        email:
          type:
          - string
          - 'null'
          description: Email address when already accessible to the caller; otherwise `null`. Search endpoints do not unlock it.
          example: null
        phone:
          type:
          - string
          - 'null'
          description: Phone number when already accessible to the caller; otherwise `null`. Search endpoints do not unlock it.
          example: null
        contactUnlockStatus:
          type: string
          description: Current email/contact access state for the authenticated API key owner.
          example: locked
        phoneUnlockStatus:
          type:
          - string
          - 'null'
          enum:
          - ready
          - processing
          - failed
          - null
          description: 'Phone unlock state: `ready`, `processing`, `failed`, or `null` when no phone-unlock state is available.'
          example: null
        linkedinActivity:
          type:
          - object
          - 'null'
          description: LinkedIn activity summary when populated by the endpoint; otherwise `null`.
          properties:
            activityLevel:
              type: string
              description: Normalized LinkedIn activity level.
            isActive:
              type: boolean
              description: Whether recent LinkedIn activity indicates that the person is active.
            latestPostAt:
              type:
              - string
              - 'null'
              description: Timestamp of the latest known LinkedIn post when available.
        linkedinActivityStatus:
          type:
          - string
          - 'null'
          description: LinkedIn activity analysis state when populated by the endpoint; otherwise `null`.
          example: null
        eventCount:
          type:
          - integer
          - 'null'
          description: Number of Lensmor events associated with the person when available.
          example: 3
        outreachMessageStatus:
          type:
          - string
          - 'null'
          description: Current outreach generation state when this endpoint includes outreach metadata.
        outreachMessageChannels:
          type: array
          items:
            type: string
          description: Generated or requested outreach channels when outreach metadata is present.
    ContactUnlockTask:
      type: object
      required:
      - taskId
      - taskStatus
      - items
      properties:
        taskId:
          type: string
          description: Asynchronous task identifier.
          pattern: ^[0-9]+$
          example: '321'
        taskStatus:
          type: string
          enum:
          - pending
          - processing
          - completed
          - failed
          description: Current task lifecycle state.
        items:
          type: array
          items:
            type: object
            required:
            - personnelId
            - status
            properties:
              personnelId:
                type: string
                description: Personnel Id returned as part of this contact unlock task object.
              status:
                type: string
                enum:
                - pending
                - processing
                - unlocked
                - failed
                description: Current normalized status for the submission, task, or generated content.
              email:
                type:
                - string
                - 'null'
                description: Email address when already accessible; otherwise `null`.
              errorCode:
                type: string
                description: Error Code returned as part of this contact unlock task object.
          description: Records returned on the current page or in the current batch.
      description: Asynchronous email unlock task and its item-level results.
    ContactUnlockSubmission:
      type: object
      required:
      - status
      properties:
        status:
          type: string
          enum:
          - accepted
          - success
          description: accepted when an asynchronous task was created; success when there was no chargeable work to enqueue.
        task_id:
          type: string
          description: TaskCenter identifier. Present when status is accepted.
          pattern: ^[0-9]+$
          example: '321'
        job_id:
          type: string
          description: Alias of task_id. Present when status is accepted.
          pattern: ^[0-9]+$
          example: '321'
        skipped_personnel_ids:
          type: array
          items:
            type: string
          description: Submitted personnel identifiers that did not create chargeable work.
        skipped_detail:
          type: object
          properties:
            invalid_personnel_ids:
              type: array
              items:
                type: string
              description: Invalid personnel ids returned as part of this contact unlock submission object.
            missing_personnel_ids:
              type: array
              items:
                type: string
              description: Missing personnel ids returned as part of this contact unlock submission object.
            unlinked_personnel_ids:
              type: array
              items:
                type: string
              description: Unlinked personnel ids returned as part of this contact unlock submission object.
            already_unlocked_personnel_ids:
              type: array
              items:
                type: string
              description: Already unlocked personnel ids returned as part of this contact unlock submission object.
            unlocking_personnel_ids:
              type: array
              items:
                type: string
              description: Unlocking personnel ids returned as part of this contact unlock submission object.
          description: Reasons submitted personnel records were skipped, grouped by condition.
      oneOf:
      - properties:
          status:
            const: accepted
            description: Current normalized status for the submission, task, or generated content.
        required:
        - task_id
        - job_id
      - properties:
          status:
            const: success
            description: Current normalized status for the submission, task, or generated content.
      description: Email or phone unlock submission outcome, including accepted work and skipped records.
    ContactPage:
      type: object
      description: Standard paginated collection of contact records.
      required:
      - items
      - total
      - page
      - pageSize
      - totalPages
      - hasMore
      properties:
        items:
          type: array
          description: Contact records returned on the current page.
          items:
            $ref: '#/components/schemas/ContactItem'
        total:
          type: integer
          description: Total matching contacts across all pages.
          example: 1
        page:
          type: integer
          description: One-based page number returned.
          example: 1
        pageSize:
          type: integer
          description: Requested maximum number of contacts per page.
          example: 20
        totalPages:
          type: integer
          description: Total number of pages for the current search.
          example: 1
        hasMore:
          type: boolean
          description: Whether another page is available after the current page.
          example: false
    PhoneUnlockRequest:
      type: object
      required:
      - personnel_ids
      properties:
        personnel_ids:
          type: array
          minItems: 1
          maxItems: 2000
          items:
            type: string
          description: Lensmor personnel identifiers selected for this batch operation.
          example:
          - '789'
        event_id:
          type: string
          minLength: 1
          maxLength: 100
          description: Optional Lensmor event identifier returned as `id` or `eventId`. When omitted, event membership validation is skipped.
          example: '26855'
      description: Batch phone enrichment request with optional event context.
    PhoneUnlockTask:
      type: object
      required:
      - taskId
      - taskStatus
      - items
      properties:
        taskId:
          type: string
          description: Asynchronous task identifier.
          pattern: ^[0-9]+$
          example: '321'
        taskStatus:
          type: string
          enum:
          - pending
          - processing
          - completed
          - failed
          description: Current task lifecycle state.
        items:
          type: array
          items:
            type: object
            required:
            - personnelId
            - status
            properties:
              personnelId:
                type: string
                description: Personnel Id returned as part of this phone unlock task object.
              status:
                type: string
                enum:
                - pending
                - processing
                - unlocked
                - failed
                description: Current normalized status for the submission, task, or generated content.
              phone:
                type:
                - string
                - 'null'
                description: Phone number when already accessible; otherwise `null`.
              errorCode:
                type: string
                description: Error Code returned as part of this phone unlock task object.
          description: Records returned on the current page or in the current batch.
      description: Asynchronous phone unlock task and its item-level results.
    ApiError:
      type: object
      required:
      - code
      - message
      - errorKey
      - traceId
      properties:
        code:
          type: integer
          description: Numeric or symbolic code that identifies the response or business condition.
        message:
          type: string
          description: Human-readable explanation suitable for logs or user-facing error handling.
        errorKey:
          type: string
          description: Stable machine-readable error key for branching and analytics.
        traceId:
          type: string
          description: Request trace identifier to include in support or incident reports.
        details:
          description: Optional structured business or validation context. Omitted when the error has no additional details.
      description: Shared error envelope returned by public Lensmor API endpoints.
  responses:
    Conflict:
      description: Business conflict
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            code: 409
            message: Request conflicts with the current resource state
            errorKey: STATE_CONFLICT
            traceId: 2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            code: 404
            message: Resource not found
            errorKey: NOT_FOUND
            traceId: 2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10
    UnprocessableEntity:
      description: Selected personnel batch exceeds the runtime limit
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            code: 422
            message: 'Selected leads limit exceeded: requested 2001, limit 2000'
            errorKey: LEAD_SELECTION_LIMIT_EXCEEDED
            details:
              requestedCount: 2001
              limit: 2000
              selectionMode: selected
            traceId: 2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10
    RateLimited:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            code: 429
            message: Rate limit exceeded
            errorKey: RATE_LIMIT_EXCEEDED
            traceId: 2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10
    PaymentRequired:
      description: Insufficient credits
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            code: 402
            message: Insufficient credits
            errorKey: INSUFFICIENT_CREDITS
            traceId: 2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10
    BadRequest:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            code: 400
            message: Invalid request
            errorKey: INVALID_REQUEST
            traceId: 2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            code: 401
            message: Invalid API key
            errorKey: INVALID_API_KEY
            traceId: 2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Business sk API key
      description: 'Send the full Business API key from Settings -> API Keys, for example `Authorization: Bearer sk_your_api_key`.'