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

# Search LinkedIn profiles by name

> Searches public LinkedIn profiles for a person by first and last name, optionally narrowed by employer. Returns candidate profiles with their headline, parsed employer and title, location, and profile URL — feed a chosen `linkedinUrl` into `POST /api/v1/find` (linkedin mode) to get a verified email for it. At most one candidate comes back; a completed not-found carries no `reason`. Send an `Idempotency-Key` to make a retry safe: the same key replays the first answer, uncharged. Rate limited per workspace.

#### Billing

- charged per completed search — matches or none — never on provider errors.

The current cost is shown in the app under Settings → Billing and in the live `GET /api/v1/openapi.json`. Calls that end in a system or provider error (HTTP 500) or are rate limited (HTTP 429) are not billed. The `charged` and `pointsCharged` fields of the response state what this call actually consumed.



## OpenAPI

````yaml /openapi.json post /api/v1/linkedin-search
openapi: 3.1.0
info:
  title: Loice API
  version: v1
  description: >-
    The Loice API finds and verifies professional contact data. Every capability
    is exposed here, key-authenticated and rate-limited; the web app is a client
    of the same platform.


    **Authentication** — pass your workspace API key on every request (except
    the API description) as `Authorization: Bearer loice_sk_…`. Keys are created
    under Settings → API Keys.


    **Billing** — operations are billed in points against your workspace
    balance. Each operation below states when the charge applies. The current
    cost of every operation is shown in the app under [Settings →
    Billing](https://app.loice.ai/settings/account?tab=billing) and in the live
    API description, `GET /api/v1/openapi.json`. Calls that fail because of a
    system or provider error (timeouts, upstream failures, our defects) are not
    billed, and rate-limited calls are rejected before any billable work. Check
    headroom with `GET /api/v1/points`. Where an operation documents an
    `Idempotency-Key` header, send one to retry safely: a repeated request
    returns the original outcome and is not charged again.


    **Errors** — every non-200 response has the shape `{ "error": { "message":
    "…" } }`. Operations whose error responses document an `error.code` also
    return that machine-readable code beside the message; branch on the code,
    not the text.
servers:
  - url: https://app.loice.ai
security: []
paths:
  /api/v1/linkedin-search:
    post:
      summary: Search LinkedIn profiles by name
      description: >-
        Searches public LinkedIn profiles for a person by first and last name,
        optionally narrowed by employer. Returns candidate profiles with their
        headline, parsed employer and title, location, and profile URL — feed a
        chosen `linkedinUrl` into `POST /api/v1/find` (linkedin mode) to get a
        verified email for it. At most one candidate comes back; a completed
        not-found carries no `reason`. Send an `Idempotency-Key` to make a retry
        safe: the same key replays the first answer, uncharged. Rate limited per
        workspace.


        #### Billing


        - charged per completed search — matches or none — never on provider
        errors.


        The current cost is shown in the app under Settings → Billing and in the
        live `GET /api/v1/openapi.json`. Calls that end in a system or provider
        error (HTTP 500) or are rate limited (HTTP 429) are not billed. The
        `charged` and `pointsCharged` fields of the response state what this
        call actually consumed.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                firstName:
                  type: string
                  description: First name of the person to search for.
                lastName:
                  type: string
                  description: Last name of the person to search for.
                company:
                  type: string
                  description: >-
                    Employer name used to disambiguate between matching
                    profiles.
              required:
                - firstName
                - lastName
              additionalProperties: false
            example:
              firstName: Satya
              lastName: Nadella
              company: Microsoft
      responses:
        '200':
          description: >-
            Search completed (including zero-match outcomes — inspect `matches`,
            `reason`, and `charged`).
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      matches:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                              description: >-
                                Deprecated — use person.fullName. Display name
                                as LinkedIn shows it.
                            headline:
                              type:
                                - string
                                - 'null'
                              description: >-
                                Deprecated — use person.title. Profile headline,
                                when present.
                            companyName:
                              type:
                                - string
                                - 'null'
                              description: >-
                                Deprecated — use person.companyName. Employer
                                parsed from the headline, when it states one.
                            title:
                              type:
                                - string
                                - 'null'
                              description: >-
                                Deprecated — use person.title. Title parsed from
                                the headline, when it states one.
                            location:
                              type:
                                - string
                                - 'null'
                              description: Deprecated — use person.location.
                            linkedinUrl:
                              type: string
                              description: Canonical URL of the matched profile.
                            person:
                              allOf:
                                - $ref: '#/components/schemas/Person'
                                - type: object
                                  description: THE canonical Person for this match.
                          required:
                            - name
                            - headline
                            - companyName
                            - title
                            - location
                            - linkedinUrl
                            - person
                        description: >-
                          At most one candidate: the first profile result,
                          accepted only when it states the name and company
                          asked for. Empty on a completed not-found and on every
                          refusal.
                      charged:
                        type: boolean
                        description: Whether this call consumed points.
                      pointsCharged:
                        type: integer
                        description: Points consumed by this call.
                      balance:
                        type:
                          - object
                          - 'null'
                        properties:
                          available:
                            type: integer
                          reserved:
                            type: integer
                          granted:
                            type: integer
                        required:
                          - available
                          - reserved
                          - granted
                        description: >-
                          The workspace balance after the call; null when it
                          could not be read.
                      reason:
                        type:
                          - string
                          - 'null'
                        enum:
                          - invalid-input
                          - suppressed
                          - insufficient-credits
                          - search-unavailable
                          - rate-limited
                        description: >-
                          null when answered (a profile found, or a charged
                          not-found). A refusal is uncharged: `invalid-input`,
                          `suppressed` (the person is on a do-not-contact list),
                          `insufficient-credits` (HTTP 402),
                          `search-unavailable` (provider not configured or did
                          not answer), `rate-limited` (the provider asked us to
                          slow down).
                      cached:
                        type: boolean
                        description: >-
                          Whether the answer was served from owned data. Same
                          price.
                      replay:
                        type: boolean
                        description: >-
                          True when this is the stored outcome of an earlier
                          call with the same `Idempotency-Key` (never charged
                          again).
                      creditsCharged:
                        type: integer
                        description: >-
                          = `pointsCharged` (legacy field name, kept for
                          compatibility).
                    required:
                      - matches
                      - charged
                      - pointsCharged
                      - balance
                      - reason
                      - cached
                      - replay
                      - creditsCharged
                required:
                  - data
              example:
                data:
                  matches:
                    - name: Satya Nadella
                      headline: Chairman and CEO at Microsoft
                      companyName: Microsoft
                      title: Chairman and CEO
                      location: Redmond, Washington, United States
                      linkedinUrl: https://www.linkedin.com/in/satyanadella/
                  charged: true
                  pointsCharged: 1
                  balance:
                    available: 99
                    reserved: 0
                    granted: 100
                  reason: null
                  cached: false
                  replay: false
                  creditsCharged: 1
        '400':
          description: >-
            `validation_error`. Missing or blank name (`firstName and lastName
            are required`), an unknown field, a wrong type, or a malformed
            `Idempotency-Key`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - unauthenticated
                          - not_found
                          - forbidden
                          - method_not_allowed
                          - idempotency_conflict
                          - idempotency_in_progress
                          - rate_limited
                          - internal_error
                          - run_already_active
                          - search_unavailable
                          - invalid_continuation
                        description: >-
                          Machine-readable error code. Branch on this, not on
                          `message`.
                      message:
                        type: string
                        description: Human-readable explanation.
                      retryAfterSeconds:
                        type: integer
                        description: >-
                          Present on a 429 only: seconds until the workspace may
                          call again (same value as the `Retry-After` header).
                    required:
                      - code
                      - message
                required:
                  - error
        '401':
          description: '`unauthenticated`. API key missing, invalid or expired.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - unauthenticated
                          - not_found
                          - forbidden
                          - method_not_allowed
                          - idempotency_conflict
                          - idempotency_in_progress
                          - rate_limited
                          - internal_error
                          - run_already_active
                          - search_unavailable
                          - invalid_continuation
                        description: >-
                          Machine-readable error code. Branch on this, not on
                          `message`.
                      message:
                        type: string
                        description: Human-readable explanation.
                      retryAfterSeconds:
                        type: integer
                        description: >-
                          Present on a 429 only: seconds until the workspace may
                          call again (same value as the `Retry-After` header).
                    required:
                      - code
                      - message
                required:
                  - error
        '402':
          description: >-
            `insufficient-credits`: the body is the usual `data` object with
            `reason` set. Nothing was charged.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - unauthenticated
                          - not_found
                          - forbidden
                          - method_not_allowed
                          - idempotency_conflict
                          - idempotency_in_progress
                          - rate_limited
                          - internal_error
                          - run_already_active
                          - search_unavailable
                          - invalid_continuation
                        description: >-
                          Machine-readable error code. Branch on this, not on
                          `message`.
                      message:
                        type: string
                        description: Human-readable explanation.
                      retryAfterSeconds:
                        type: integer
                        description: >-
                          Present on a 429 only: seconds until the workspace may
                          call again (same value as the `Retry-After` header).
                    required:
                      - code
                      - message
                required:
                  - error
        '405':
          description: >-
            `method_not_allowed` (`Method not allowed`) — see the `Allow`
            response header.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - unauthenticated
                          - not_found
                          - forbidden
                          - method_not_allowed
                          - idempotency_conflict
                          - idempotency_in_progress
                          - rate_limited
                          - internal_error
                          - run_already_active
                          - search_unavailable
                          - invalid_continuation
                        description: >-
                          Machine-readable error code. Branch on this, not on
                          `message`.
                      message:
                        type: string
                        description: Human-readable explanation.
                      retryAfterSeconds:
                        type: integer
                        description: >-
                          Present on a 429 only: seconds until the workspace may
                          call again (same value as the `Retry-After` header).
                    required:
                      - code
                      - message
                required:
                  - error
        '409':
          description: >-
            The `Idempotency-Key` cannot be used for this request.
            `idempotency_conflict`: the key was already used with a different
            request. `idempotency_in_progress`: the first request with this key
            is still running. Never billed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - unauthenticated
                          - not_found
                          - forbidden
                          - method_not_allowed
                          - idempotency_conflict
                          - idempotency_in_progress
                          - rate_limited
                          - internal_error
                          - run_already_active
                          - search_unavailable
                          - invalid_continuation
                        description: >-
                          Machine-readable error code. Branch on this, not on
                          `message`.
                      message:
                        type: string
                        description: Human-readable explanation.
                      retryAfterSeconds:
                        type: integer
                        description: >-
                          Present on a 429 only: seconds until the workspace may
                          call again (same value as the `Retry-After` header).
                    required:
                      - code
                      - message
                required:
                  - error
        '429':
          description: >-
            `rate_limited` (`Rate limit exceeded`): this workspace’s request
            budget is spent. Retry after the `Retry-After` header. Never billed.
          headers:
            Retry-After:
              schema:
                type: string
                description: Seconds to wait before calling again.
              required: true
              description: Seconds to wait before calling again.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - unauthenticated
                          - not_found
                          - forbidden
                          - method_not_allowed
                          - idempotency_conflict
                          - idempotency_in_progress
                          - rate_limited
                          - internal_error
                          - run_already_active
                          - search_unavailable
                          - invalid_continuation
                        description: >-
                          Machine-readable error code. Branch on this, not on
                          `message`.
                      message:
                        type: string
                        description: Human-readable explanation.
                      retryAfterSeconds:
                        type: integer
                        description: >-
                          Present on a 429 only: seconds until the workspace may
                          call again (same value as the `Retry-After` header).
                    required:
                      - code
                      - message
                required:
                  - error
        '500':
          description: >-
            `internal_error` (`Internal error`): an unexpected failure on our
            side. Never billed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - unauthenticated
                          - not_found
                          - forbidden
                          - method_not_allowed
                          - idempotency_conflict
                          - idempotency_in_progress
                          - rate_limited
                          - internal_error
                          - run_already_active
                          - search_unavailable
                          - invalid_continuation
                        description: >-
                          Machine-readable error code. Branch on this, not on
                          `message`.
                      message:
                        type: string
                        description: Human-readable explanation.
                      retryAfterSeconds:
                        type: integer
                        description: >-
                          Present on a 429 only: seconds until the workspace may
                          call again (same value as the `Retry-After` header).
                    required:
                      - code
                      - message
                required:
                  - error
      security:
        - workspaceApiKey: []
components:
  schemas:
    Person:
      type:
        - object
        - 'null'
      properties:
        avatarUrl:
          type:
            - string
            - 'null'
          description: >-
            Owned image address (`/api/images/<id>`, authenticated). Null ⇒
            render initials.
        fullName:
          type:
            - string
            - 'null'
          description: The source's own statement of the name.
        linkedinUrl:
          type: string
          description: Canonical profile URL — the identity. Never null.
        title:
          type:
            - string
            - 'null'
          description: Title of the primary current position.
        about:
          type:
            - string
            - 'null'
        company:
          $ref: '#/components/schemas/Company'
        companyName:
          type:
            - string
            - 'null'
          description: Alias of `company.name`.
        companyLinkedinUrl:
          type:
            - string
            - 'null'
          description: Alias of `company.linkedinUrl`.
        companyLogoUrl:
          type:
            - string
            - 'null'
          description: Alias of `company.logoImageUrl` (owned).
        domain:
          type:
            - string
            - 'null'
          description: >-
            The company's website domain, else the domain the profile resolver
            stated.
        industry:
          type:
            - string
            - 'null'
          description: Alias of `company.industry`.
        location:
          type:
            - string
            - 'null'
          description: The person's own location (never company HQ).
        department:
          type:
            - string
            - 'null'
          enum:
            - Accounting
            - Administrative
            - Arts and Design
            - Business Development
            - Community & Social Services
            - Consulting
            - Customer Success and Support
            - Education
            - Engineering
            - Entrepreneurship
            - Finance
            - Healthcare Services
            - Human Resources
            - Information Technology
            - Legal
            - Marketing
            - Media and Communication
            - Military and Protective Services
            - Operations
            - Product Management
            - Program and Project Management
            - Purchasing
            - Quality Assurance
            - Real Estate
            - Research
            - Sales
          description: Source-stated only; never classified from the title.
        seniority:
          type:
            - string
            - 'null'
          enum:
            - In Training
            - Entry Level
            - Senior
            - Strategic
            - Entry Level Manager
            - Experienced Manager
            - Director
            - Vice President
            - CXO
            - Owner / Partner
          description: Source-stated only; never classified from the title.
        yearsOfExperience:
          type:
            - string
            - 'null'
          enum:
            - Less than 1 year
            - 1-2 years
            - 3-5 years
            - 6-10 years
            - 11-15 years
            - 16-20 years
            - 20+ years
          description: >-
            Overlap-free union of stated positions; null when any start is
            missing or the stated precision leaves it between two buckets.
        employment:
          type: array
          items:
            $ref: '#/components/schemas/EmploymentEntry'
          description: Source order; [] when not available.
        education:
          type: array
          items:
            $ref: '#/components/schemas/EducationEntry'
          description: Source order; [] when not available.
        historyStatus:
          type: object
          properties:
            employment:
              type: string
              enum:
                - available
                - not-yet-available
              description: >-
                `not-yet-available`: no source has supplied this history yet
                (the list is []). `available` with [] means the source supplied
                an empty history.
            education:
              type: string
              enum:
                - available
                - not-yet-available
              description: >-
                `not-yet-available`: no source has supplied this history yet
                (the list is []). `available` with [] means the source supplied
                an empty history.
          required:
            - employment
            - education
      required:
        - avatarUrl
        - fullName
        - linkedinUrl
        - title
        - about
        - company
        - companyName
        - companyLinkedinUrl
        - companyLogoUrl
        - domain
        - industry
        - location
        - department
        - seniority
        - yearsOfExperience
        - employment
        - education
        - historyStatus
      description: >-
        linkedin mode only: THE canonical Person, present whenever resolution
        found someone; otherwise null.
    Company:
      type: object
      properties:
        name:
          type:
            - string
            - 'null'
        linkedinUrl:
          type:
            - string
            - 'null'
        tagline:
          type:
            - string
            - 'null'
        description:
          type:
            - string
            - 'null'
        industry:
          type:
            - string
            - 'null'
        employeeBand:
          type:
            - string
            - 'null'
          description: Size band as the source displays it.
        employeeCount:
          type:
            - integer
            - 'null'
          description: Exact headcount, when stated.
        followerCount:
          type:
            - integer
            - 'null'
        websiteUrl:
          type:
            - string
            - 'null'
        websiteDomain:
          type:
            - string
            - 'null'
        headquarters:
          type:
            - string
            - 'null'
        hqLocality:
          type:
            - string
            - 'null'
        hqRegion:
          type:
            - string
            - 'null'
        hqCountry:
          type:
            - string
            - 'null'
        foundedYear:
          type:
            - integer
            - 'null'
        companyType:
          type:
            - string
            - 'null'
        specialties:
          type: array
          items:
            type: string
        logoUrl:
          type: 'null'
          description: >-
            Always null. Reserved so the shape stays stable: a provider image
            address is never returned (it is signed, expires, and discloses the
            viewer). Render `logoImageUrl`.
        logoImageUrl:
          type:
            - string
            - 'null'
          description: >-
            Our own copy of the logo (`/api/images/<id>`, same authentication as
            this API). Null when the source states no logo or no copy is held.
        phone:
          type:
            - string
            - 'null'
          description: >-
            The company phone. Always null until phone verification is
            available; reserved so the shape does not change when it is.
        email:
          type:
            - string
            - 'null'
          description: >-
            The company's general contact email: only a generic role address
            (info@, sales@, …) on the company's own domain, stated by the
            company, that passed email verification. Null when none is stated or
            it did not verify. Never a personal address.
        xUrl:
          type:
            - string
            - 'null'
          description: >-
            X (Twitter) profile the company states as its own, as
            `https://x.com/<handle>`. Null when not stated; never constructed
            from the name.
        facebookUrl:
          type:
            - string
            - 'null'
          description: >-
            Facebook page the company states as its own, as
            `https://www.facebook.com/<page>`. Null when not stated.
        instagramUrl:
          type:
            - string
            - 'null'
          description: >-
            Instagram profile the company states as its own, as
            `https://www.instagram.com/<user>`. Null when not stated.
        youtubeUrl:
          type:
            - string
            - 'null'
          description: >-
            YouTube channel the company states as its own, as
            `https://www.youtube.com/` followed by `@handle`, `channel/…`, `c/…`
            or `user/…`. Null when not stated.
        confirmedAt:
          type:
            - string
            - 'null'
          description: >-
            When this record was last confirmed against the source. Null when
            the Company is built only from what a lead or list row observed (no
            company record).
      required:
        - name
        - linkedinUrl
        - tagline
        - description
        - industry
        - employeeBand
        - employeeCount
        - followerCount
        - websiteUrl
        - websiteDomain
        - headquarters
        - hqLocality
        - hqRegion
        - hqCountry
        - foundedYear
        - companyType
        - specialties
        - logoUrl
        - logoImageUrl
        - phone
        - email
        - xUrl
        - facebookUrl
        - instagramUrl
        - youtubeUrl
        - confirmedAt
      description: >-
        The canonical Company for the current employer (same schema as `POST
        /api/v1/company`).
    EmploymentEntry:
      type: object
      properties:
        companyName:
          type:
            - string
            - 'null'
        companyLinkedinUrl:
          type:
            - string
            - 'null'
        title:
          type:
            - string
            - 'null'
        start:
          $ref: '#/components/schemas/StatedDate'
        end:
          $ref: '#/components/schemas/StatedDate'
        current:
          type: boolean
        location:
          type:
            - string
            - 'null'
          description: Where the position was held, as the source stated it.
        description:
          type:
            - string
            - 'null'
          description: The person's own description of the position, as stated.
      required:
        - companyName
        - companyLinkedinUrl
        - title
        - start
        - end
        - current
        - location
        - description
    EducationEntry:
      type: object
      properties:
        school:
          type:
            - string
            - 'null'
        schoolLinkedinUrl:
          type:
            - string
            - 'null'
        degree:
          type:
            - string
            - 'null'
        field:
          type:
            - string
            - 'null'
        start:
          $ref: '#/components/schemas/StatedDate'
        end:
          $ref: '#/components/schemas/StatedDate'
      required:
        - school
        - schoolLinkedinUrl
        - degree
        - field
        - start
        - end
    StatedDate:
      type:
        - object
        - 'null'
      properties:
        year:
          type: integer
        month:
          type:
            - integer
            - 'null'
          description: 1–12, or null when the source stated the year only (never padded).
      required:
        - year
        - month
  securitySchemes:
    workspaceApiKey:
      type: http
      scheme: bearer
      description: >-
        Workspace API key (`loice_sk_` + 48 hex characters), created under
        Settings → API Keys. Sent as `Authorization: Bearer loice_sk_…`.
        Invalid, missing, or expired keys are rejected with 401 before any
        billable work happens.

````

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