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

# Initiate Sourcing Preview Run

> Starts an asynchronous candidate sourcing preview run. Returns immediately with a requestId and status 'processing'. Results are delivered via webhook (SOURCING_COMPLETED / SOURCING_FAILED) or by polling GET /sourcing/preview/{id}/results.

Starts an asynchronous candidate sourcing preview pipeline. Returns immediately with a `requestId` and `status: "processing"`.

## Overview

The preview endpoint allows you to rapidly run candidate searches and obtain preview results. Under the hood, it queries the underlying provider's search preview API.

### Key Differences from Standard Sourcing

* **No Deep Enrichment**: Preview results do not include deep profile enrichment (like contact details, emails, work history, fit points, or red flags).
* **Fast Execution**: Responses are prepared quickly (usually in a few milliseconds to seconds).
* **Stripped-down Candidate DTO**: Candidates in the results only contain 9 basic fields (listed below).
* **Credit Cost**: Candidate previews charge 1 credit (or 0.4 minutes) per preview page successfully queried (where each page contains up to 20 candidates).

### Candidate Limits and Internal Pagination

The preview API automatically handles pagination internally based on the number of candidates you request:

* Use the optional `limit` parameter to specify the desired candidate count (between `1` and `100`, default: `20`).
* The system automatically polls the underlying provider's preview pages sequentially (up to 5 pages of 20 results each) to satisfy your requested limit.
* Previews are charged per page queried (1 credit / 0.4 minutes per page). For example, requesting a limit of 40 candidates queries up to 2 pages, costing up to 2 credits.

Results are delivered via [webhooks](/guides/webhooks) (recommended) or by polling [GET /sourcing/preview/{id}/results](/api-reference/sourcing/get-sourcing-preview-results).

## Billing and Pre-Flight

Candidate previews charge 1 credit (or 0.4 minutes) per preview page successfully queried.

At initialization, a pre-flight balance check is performed for the maximum possible cost based on the requested `limit` (computed as `Math.ceil(limit / 20) * 1 credit`). If the company does not have sufficient credits or minutes, the request is rejected with a `402 Payment Required` status.

During execution, if the provider returns fewer pages than requested (e.g. because results are exhausted), only the pages successfully queried are charged, and any unused credits from the initial hold are automatically released.

## Webhook Delivery

To receive results without polling, pass a `webhookId` referencing a pre-registered `WebhookConfig` that subscribes to at least one of `SOURCING_COMPLETED` or `SOURCING_FAILED`. The webhook config must belong to the same company as the authenticating API key.

When the preview run completes, a `SOURCING_COMPLETED` webhook event is dispatched. The candidates array in the webhook payload will contain preview-formatted candidates containing only the 9 basic fields.

<Info>
  See [Setting Up Webhooks](/guides/webhooks) for instructions on registering a
  webhook config and storing the signing secret securely.
</Info>

## Examples

### Minimal Request

```json theme={null}
{
  "title": "Senior Backend Engineer",
  "jobDescription": "We are looking for a Senior Backend Engineer with 5+ years of Node.js and TypeScript experience, strong PostgreSQL skills, and familiarity with AWS."
}
```

### Full Request with Candidate Limit

```json theme={null}
{
  "title": "Senior Staff ML Engineer",
  "jobDescription": "We are seeking a Staff Machine Learning Engineer to design and scale our agentic coding infrastructure. Experience with prompt engineering pipelines, LLM fine-tuning, vector search, and latency optimization is highly required.",
  "location": "Remote, USA",
  "query": "Prioritize candidates with active contributions to major LLM libraries or frameworks like LangChain, LlamaIndex, or vLLM.",
  "webhookId": "3f9a12c7-44b8-4d32-b71f-e29a7d1e0f5c",
  "limit": 50
}
```

### Response (202 Accepted)

```json theme={null}
{
  "success": true,
  "requestId": "req_prev_9f3b827e-8c31-4bda-a7a2-b2d99d14f4e2",
  "status": "processing",
  "message": "Sourcing preview run accepted and queued for processing.",
  "webhookId": "3f9a12c7-44b8-4d32-b71f-e29a7d1e0f5c",
  "createdAt": "2026-06-11T19:50:45.000Z"
}
```

## Preview Candidate Fields

The `candidates` array returned for preview requests (both from the polling endpoint and webhook) is stripped down to exactly the following 9 fields:

* `profileId` (Opaque identifier, MD5 hash of LinkedIn profile URL)
* `fullName`
* `profileUrl`
* `title`
* `headline`
* `location`
* `country`
* `companyName`
* `companyUrl`


## OpenAPI

````yaml POST /sourcing/preview
openapi: 3.0.0
info:
  title: InstaView API
  description: |-
    InstaView API Documentation

    ## Authentication

    All endpoints require API key authentication using Bearer token:
    ```
    Authorization: Bearer sk_your_api_key_here
    ```

    ## API Key Management

    The API Key module provides comprehensive key management for:
    - **Direct Client Keys**: Company-scoped keys for your applications
    - **ATS Partner Keys**: Resource-scoped keys for ATS integrations

    ### Key Features
    - HMAC-SHA256 hashing for API key storage
    - Configurable rate limiting
    - Comprehensive audit logging
    - Company-level isolation
    - Resource scoping for ATS partners
  version: 1.0.0
  contact: {}
servers:
  - url: https://api.instaview.sk
    description: Production API Gateway
security: []
tags: []
paths:
  /sourcing/preview:
    post:
      tags:
        - Public Sourcing
      summary: Initiate sourcing preview run
      description: >-
        Starts an asynchronous candidate sourcing preview run. Returns
        immediately with a requestId and status 'processing'. Results are
        delivered via webhook (SOURCING_COMPLETED / SOURCING_FAILED) or by
        polling GET /sourcing/preview/{id}/results.
      operationId: PublicSourcingController_initiateSourcingPreview_v1
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicInitiateSourcingPreviewDto'
      responses:
        '202':
          description: Sourcing preview run accepted and queued for processing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicSourcingInitiatedResponseDto'
        '400':
          description: Bad Request - Missing required fields or invalid payload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment Required - Insufficient prepaid credit balance
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - Insufficient scope or webhook company mismatch
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found - Webhook config not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Unprocessable Entity - Webhook not subscribed to sourcing events
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too Many Requests - Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - bearer: []
components:
  schemas:
    PublicInitiateSourcingPreviewDto:
      type: object
      properties:
        title:
          type: string
          description: Human-readable title for this sourcing run.
          example: Senior Backend Engineers – FinTech
          maxLength: 200
        jobDescription:
          type: string
          description: Full job description used to build the candidate-search query.
          example: >-
            We are looking for a Senior Backend Engineer with 5+ years of
            Node.js experience…
          maxLength: 10000
        location:
          type: string
          description: >-
            Target location for the search (e.g. 'San Francisco, CA' or
            'Remote').
          example: San Francisco, CA
          maxLength: 200
        query:
          type: string
          description: >-
            Override for the free-text search query sent to the sourcing agent.
            When omitted the agent derives it from jobDescription.
          example: Senior Node.js engineer fintech
          maxLength: 500
        limit:
          type: integer
          description: 'Maximum number of candidates to return (default: 20, max: 100).'
          example: 20
          minimum: 1
          maximum: 100
          default: 20
        webhookId:
          type: string
          format: uuid
          description: >-
            UUID of a WebhookConfig to notify when the run completes or fails.
            The webhook must belong to the same company and subscribe to at
            least one sourcing event.
          example: 123e4567-e89b-12d3-a456-426614174000
      required:
        - title
        - jobDescription
    PublicSourcingInitiatedResponseDto:
      type: object
      properties:
        success:
          type: boolean
          description: Whether the request was accepted for processing.
          example: true
        requestId:
          type: string
          description: Unique external identifier for this sourcing run.
          example: req_550e8400-e29b-41d4-a716-446655440000
        status:
          type: string
          description: Current status of the run.
          enum:
            - processing
            - completed
            - failed
          example: processing
        message:
          type: string
          description: Human-readable message.
          example: Sourcing run accepted and queued for processing.
        webhookId:
          type: string
          description: >-
            UUID of the webhook configuration that will receive completion
            events.
          example: 123e4567-e89b-12d3-a456-426614174000
        createdAt:
          type: string
          description: ISO 8601 timestamp when the run was created (POST only).
          example: '2025-01-01T00:00:00.000Z'
        updatedAt:
          type: string
          description: ISO 8601 timestamp when the run was last updated (PATCH only).
          example: '2025-01-01T00:01:00.000Z'
      required:
        - success
        - requestId
        - status
        - message
    ErrorResponse:
      type: object
      properties:
        statusCode:
          type: integer
          example: 400
        message:
          type: string
          example: Validation failed
        error:
          type: string
          example: Bad Request
      required:
        - statusCode
        - message
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      description: API key for authentication using Bearer scheme

````