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

# Add profiles to project

> Add sourcing profiles to a project's pipeline with automatic deduplication.

**Important:** Pass the full profile objects from search results (including `experiences`, `educations`, `skills`, `summary`, `picture_url`, and `location`). The more fields you include, the richer the created contact record will be. Fields like `already_in_project` and `existing_contact_id` are response-only and will be ignored if passed.

The endpoint performs cascade deduplication: if a profile matches an existing contact (by LinkedIn URL, then by name + company), the existing contact is updated with any missing fields instead of creating a duplicate.




## OpenAPI

````yaml /openapi.yaml post /sourcing/add-to-project
openapi: 3.0.3
info:
  title: Leonar API
  description: >
    REST API for accessing and managing workspace data in Leonar CRM.


    ## Authentication


    All API requests require a Bearer token in the Authorization header:


    ```

    Authorization: Bearer leo_xxxxx

    ```


    API keys can be created and managed in Settings > API.


    ## Rate limiting


    - **2000 requests per hour by default**, configurable per workspace and
    shared by all API keys owned by the same user

    - Rate limit headers are included in all responses


    ## Pagination


    List endpoints support pagination via `limit` and `offset` query parameters.
  version: 1.0.0
  contact:
    name: Leonar Support
    url: https://leonar.ai
    email: support@leonar.ai
servers:
  - url: https://app.leonar.app/api/v1
    description: Production
security:
  - BearerAuth: []
tags:
  - name: Contacts
    description: Manage contacts in your workspace
  - name: Companies
    description: Manage companies and their relationships
  - name: Deals
    description: Track and manage sales deals
  - name: Deal Pipelines
    description: View deal pipeline configurations
  - name: Projects
    description: Organize recruiting projects
  - name: Pipeline Entries
    description: Manage candidates in project pipelines
  - name: Tasks
    description: Track to-dos and follow-ups
  - name: Tags
    description: Organize resources with tags
  - name: Notes
    description: Manage notes on contacts, companies, deals, and projects
  - name: Sequences
    description: Automate outreach campaigns
  - name: Conversations
    description: View conversations across channels
  - name: Messages
    description: Send messages via email, LinkedIn, or WhatsApp
  - name: Enrichment
    description: Find emails and phone numbers for contacts
  - name: Sourcing
    description: Search and import candidates
  - name: Connected Accounts
    description: View linked LinkedIn accounts
paths:
  /sourcing/add-to-project:
    post:
      tags:
        - Sourcing
      summary: Add profiles to project
      description: >
        Add sourcing profiles to a project's pipeline with automatic
        deduplication.


        **Important:** Pass the full profile objects from search results
        (including `experiences`, `educations`, `skills`, `summary`,
        `picture_url`, and `location`). The more fields you include, the richer
        the created contact record will be. Fields like `already_in_project` and
        `existing_contact_id` are response-only and will be ignored if passed.


        The endpoint performs cascade deduplication: if a profile matches an
        existing contact (by LinkedIn URL, then by name + company), the existing
        contact is updated with any missing fields instead of creating a
        duplicate.
      operationId: add-to-project
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - project_id
                - profiles
              properties:
                project_id:
                  type: string
                  format: uuid
                  description: >-
                    Target project ID. Profiles are added to the first stage of
                    this project's pipeline.
                account_id:
                  type: string
                  format: uuid
                  description: >-
                    Connected LinkedIn account ID. Required when `resolve_names`
                    is true. Get it from `GET /connected-accounts`.
                resolve_names:
                  type: boolean
                  default: false
                  description: >-
                    When true, automatically resolves missing
                    `first_name`/`last_name` via LinkedIn profile lookup for
                    profiles that have a `linkedin_url`. Requires `account_id`.
                    Recommended when using LinkedIn Classic search results which
                    often return null names.
                profiles:
                  type: array
                  items:
                    $ref: '#/components/schemas/SourcingProfile'
                  minItems: 1
                  maxItems: 100
                  description: >
                    Profile objects from search results. Pass them directly from
                    the search response for maximum data capture.

                    Key fields that enrich the contact record:

                    - `experiences` → stored as work history (positions)

                    - `educations` → stored as education history (schools)

                    - `skills` → stored as skills list

                    - `summary` → stored as professional bio

                    - `picture_url` → stored as contact avatar

                    - `location` → stored as contact location

                    - `current_job` → sets the contact's job title and company
      responses:
        '201':
          description: Profiles added
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      added:
                        type: integer
                      skipped:
                        type: integer
                      contact_ids:
                        type: array
                        items:
                          type: string
                          format: uuid
                      skipped_profiles:
                        type: array
                        items:
                          type: object
                          properties:
                            profile_id:
                              type: string
                            reason:
                              type: string
                      stage:
                        type: object
                        properties:
                          id:
                            type: string
                            format: uuid
                          name:
                            type: string
                          category:
                            type: string
              example:
                data:
                  added: 5
                  skipped: 2
                  contact_ids:
                    - a1b2c3d4-5678-90ab-cdef-1234567890ab
                    - b2c3d4e5-6789-01ab-cdef-234567890abc
                    - c3d4e5f6-7890-12ab-cdef-345678901bcd
                    - d4e5f6a7-8901-23bc-defa-456789012cde
                    - e5f6a7b8-9012-34cd-efab-567890123def
                  skipped_profiles:
                    - profile_id: urn:li:member:123456
                      reason: already_in_project
                    - profile_id: urn:li:member:789012
                      reason: already_in_project
                  stage:
                    id: f6a7b8c9-0123-45de-fabc-678901234ef0
                    name: Sourced
                    category: sourced
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    SourcingProfile:
      type: object
      description: >-
        A candidate profile returned by sourcing search endpoints. Pass these
        objects directly to the add-to-project endpoint to create contacts with
        full data.
      properties:
        profile_id:
          type: string
          description: Unique identifier from the source (LinkedIn URN or Neuron360 ID)
        first_name:
          type: string
          nullable: true
          description: >-
            May be null for LinkedIn Classic search results. Use `resolve_names:
            true` in add-to-project to auto-resolve.
        last_name:
          type: string
          nullable: true
          description: >-
            May be null for LinkedIn Classic search results. Use `resolve_names:
            true` in add-to-project to auto-resolve.
        headline:
          type: string
          nullable: true
        picture_url:
          type: string
          format: uri
          nullable: true
          description: Profile photo URL. Stored as the contact's avatar.
        location:
          type: string
          nullable: true
          description: Geographic location string. Stored on the contact record.
        linkedin_url:
          type: string
          format: uri
          nullable: true
          description: >-
            LinkedIn profile URL. Used for deduplication and stored on the
            contact.
        summary:
          type: string
          nullable: true
          description: Professional summary or bio. Stored on the contact record.
        current_job:
          type: object
          nullable: true
          description: >-
            Current position. Used to set the contact's title and
            current_company fields.
          properties:
            title:
              type: string
              nullable: true
            company_name:
              type: string
              nullable: true
        experiences:
          type: array
          description: >-
            Work history. Stored as the contact's positions. The first current
            experience sets the contact's title and current_company if
            current_job is not provided.
          items:
            $ref: '#/components/schemas/SourcingExperience'
        educations:
          type: array
          description: Education history. Stored as the contact's schools.
          items:
            $ref: '#/components/schemas/SourcingEducation'
        skills:
          type: array
          description: Professional skills. Stored on the contact record.
          items:
            type: string
        total_years_experience:
          type: number
          nullable: true
          description: Calculated total years of experience.
        already_in_project:
          type: boolean
          readOnly: true
          description: >-
            Whether this profile is already in the target project. Response-only
            field.
        existing_contact_id:
          type: string
          format: uuid
          nullable: true
          readOnly: true
          description: >-
            If the profile matches an existing CRM contact, its ID.
            Response-only field.
        api_provider:
          type: string
          readOnly: true
          description: >-
            Source of the profile (e.g. "linkedin", "neuron360"). Response-only
            field.
      example:
        profile_id: ACwAABrjaVMBOLcCrV5aEw1zCAjE_zec6PbnU1A
        first_name: Sophie
        last_name: Martin
        headline: Senior Software Engineer at Doctolib
        picture_url: https://media.licdn.com/dms/image/example.jpg
        location: Paris, Île-de-France, France
        linkedin_url: https://www.linkedin.com/in/sophie-martin
        summary: Experienced engineer with 8 years in full-stack development...
        current_job:
          title: Senior Software Engineer
          company_name: Doctolib
        experiences:
          - title: Senior Software Engineer
            company_name: Doctolib
            start_date: '2021-03-01'
            end_date: null
            description: Leading backend team, Python/Django stack...
            is_current: true
          - title: Software Engineer
            company_name: Criteo
            start_date: '2018-01-01'
            end_date: '2021-02-28'
            description: Built real-time bidding systems in Python...
            is_current: false
        educations:
          - educational_establishment: École Polytechnique
            diploma: Master of Engineering
            specialization: Computer Science
            start_date: '2014-09-01'
            end_date: '2018-06-30'
        skills:
          - Python
          - Django
          - TypeScript
          - PostgreSQL
        total_years_experience: 8.2
        already_in_project: false
        existing_contact_id: null
    SourcingExperience:
      type: object
      description: A work experience entry from a sourcing profile.
      properties:
        title:
          type: string
          nullable: true
          description: Job title (e.g. "Senior Software Engineer")
        company_name:
          type: string
          nullable: true
          description: Company name (e.g. "Doctolib")
        company_domain:
          type: string
          nullable: true
          description: Company website domain (e.g. "doctolib.com")
        start_date:
          type: string
          nullable: true
          description: Start date in ISO format (YYYY-MM-DD)
        end_date:
          type: string
          nullable: true
          description: End date in ISO format, or null if current position
        description:
          type: string
          nullable: true
          description: Role description or responsibilities
        is_current:
          type: boolean
          description: Whether this is a current position
    SourcingEducation:
      type: object
      description: An education entry from a sourcing profile.
      properties:
        educational_establishment:
          type: string
          nullable: true
          description: School or university name (e.g. "École Polytechnique")
        diploma:
          type: string
          nullable: true
          description: Degree or diploma (e.g. "Master of Engineering")
        specialization:
          type: string
          nullable: true
          description: Field of study (e.g. "Computer Science")
        start_date:
          type: string
          nullable: true
          description: Start date in ISO format (YYYY-MM-DD)
        end_date:
          type: string
          nullable: true
          description: End date in ISO format (YYYY-MM-DD)
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - invalid_api_key
                - insufficient_scope
                - rate_limit_exceeded
                - validation_error
                - not_found
                - internal_error
                - billing_required
                - plan_upgrade_required
              description: >
                Error codes:

                - `invalid_api_key` — API key is missing, malformed, or revoked

                - `insufficient_scope` — API key lacks the required scope for
                this endpoint

                - `rate_limit_exceeded` — Too many requests (2000/hour)

                - `validation_error` — Request body or parameters failed
                validation

                - `not_found` — The requested resource does not exist

                - `internal_error` — Unexpected server error

                - `billing_required` — Workspace has no active subscription

                - `plan_upgrade_required` — Current plan does not include this
                feature
            message:
              type: string
              description: Human-readable error description
  responses:
    ValidationError:
      description: Invalid request data
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: validation_error
              message: Invalid input
    Unauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: invalid_api_key
              message: Invalid API key
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key starting with `leo_`

````