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

# Preview an AI Finder search

> **What it does.** Takes either a natural-language query (e.g. *"VP of Finance at Series B SaaS companies in California"*) or a saved filter ID and returns a `previewId`. Text queries run through AI Finder to generate provider-specific filters; saved filters are loaded directly into the preview cache without regenerating them. Use this as the first step when a user asks you to build a new prospecting list, find new companies, or find new contacts; do not answer those requests by only browsing existing CRM contacts or existing lists. No data is imported yet.

**When to use.** Call this first when you want to start an AI-driven list-building flow. After you see what the AI produced, you can:
- Refine the filters by calling the iterate endpoint with more instructions.
- Commit the preview to a list by calling the import endpoint.

**Provider selection.** Omit `provider` (or pass `AUTO`) to let the system pick the best provider for the query. Pass an explicit value to force one. Valid providers:
- `LINKEDIN` — LinkedIn Sales Nav. AI infers contacts-vs-companies from the query.
- `CRM_CONTACTS` / `CRM_COMPANIES` — the client's configured CRM (HubSpot, Salesforce, Dynamics, Zoho, TribeCRM, or Attio). The specific CRM is auto-detected from the client's integrations. Returns 422 if no CRM is configured.
- `STORELEADS` — StoreLeads (ecommerce / DTC / Shopify brands).
- `CRUNCHBASE_COMPANIES` / `CRUNCHBASE_CONTACTS` — Crunchbase organizations or people.
- `CRUNCHBASE_INVESTORS` — Crunchbase investor search (VCs, angels, funds).
- `THEIRSTACK_TECHNOLOGY` — companies using a given tech stack.
- `THEIRSTACK_JOBS` — companies hiring for certain roles (based on job postings).
- `GOOGLE_MAPS` — local businesses / places.

**Saved filters.** Instead of `text`, you can send `savedFilterId` to create a preview from an existing saved filter. Saved-filter previews require a concrete provider; omit `provider` to default to `LINKEDIN`.

**Scope to a LinkedIn identity.** Only pass `identityId` when the user explicitly asks for an identity-specific LinkedIn search, such as importing 2nd-degree connections for identity 123. For normal sourcing requests like "software engineers in Girona", do NOT infer or pass an identity — omit `identityId` so AI Finder can auto-pick an available Sales Navigator identity. `identityId` is only valid with `provider: LINKEDIN`, and the identity must have `linkedinSearchEnabled: true` (Sales Navigator + valid credentials). List eligible identities with `GET /v1/identities?linkedinSearchEnabled=true`. The chosen `identityId` carries through iterate and into import.

**What you get back.** A `previewId` (valid for 24 hours) plus the `result` object with the AI-generated filters, a human-readable `title` and `reasoning`, the `resolvedProvider` (useful when you passed `AUTO`), and `identityId` echoed back when you scoped the search to one.

**What to do next.** Pass the `previewId` to `POST /v1/ai-finder/previews/{previewId}/iterate` to refine, or to `POST /v1/ai-finder/previews/{previewId}/import` to commit.

    > **Required scope:** `ACTIONS_WRITE`
    >
    > **Rate limit:** 10 requests per minute



## OpenAPI

````yaml https://openapi.enginy.ai/definitions.json post /v1/ai-finder/previews
openapi: 3.1.0
info:
  title: Enginy API
  version: 1.0.0
  description: Public API for Enginy platform
servers:
  - url: https://openapi.enginy.ai
    description: Configured server
security: []
tags:
  - name: AI Variables
    description: >-
      Manage AI variables and discover the entity fields you can reference in
      prompts and entity requests.
  - name: Inbox
    description: >-
      Inbox endpoints for listing contact threads, reading thread messages,
      managing tags, and sending manual replies.
  - name: Workflows
    description: >-
      Build, validate, publish, run, and inspect advanced (graph) workflows,
      plus the block/condition catalog needed to author a workflow plan.
paths:
  /v1/ai-finder/previews:
    post:
      tags:
        - AI Finder
      summary: Preview an AI Finder search
      description: >-
        **What it does.** Takes either a natural-language query (e.g. *"VP of
        Finance at Series B SaaS companies in California"*) or a saved filter ID
        and returns a `previewId`. Text queries run through AI Finder to
        generate provider-specific filters; saved filters are loaded directly
        into the preview cache without regenerating them. Use this as the first
        step when a user asks you to build a new prospecting list, find new
        companies, or find new contacts; do not answer those requests by only
        browsing existing CRM contacts or existing lists. No data is imported
        yet.


        **When to use.** Call this first when you want to start an AI-driven
        list-building flow. After you see what the AI produced, you can:

        - Refine the filters by calling the iterate endpoint with more
        instructions.

        - Commit the preview to a list by calling the import endpoint.


        **Provider selection.** Omit `provider` (or pass `AUTO`) to let the
        system pick the best provider for the query. Pass an explicit value to
        force one. Valid providers:

        - `LINKEDIN` — LinkedIn Sales Nav. AI infers contacts-vs-companies from
        the query.

        - `CRM_CONTACTS` / `CRM_COMPANIES` — the client's configured CRM
        (HubSpot, Salesforce, Dynamics, Zoho, TribeCRM, or Attio). The specific
        CRM is auto-detected from the client's integrations. Returns 422 if no
        CRM is configured.

        - `STORELEADS` — StoreLeads (ecommerce / DTC / Shopify brands).

        - `CRUNCHBASE_COMPANIES` / `CRUNCHBASE_CONTACTS` — Crunchbase
        organizations or people.

        - `CRUNCHBASE_INVESTORS` — Crunchbase investor search (VCs, angels,
        funds).

        - `THEIRSTACK_TECHNOLOGY` — companies using a given tech stack.

        - `THEIRSTACK_JOBS` — companies hiring for certain roles (based on job
        postings).

        - `GOOGLE_MAPS` — local businesses / places.


        **Saved filters.** Instead of `text`, you can send `savedFilterId` to
        create a preview from an existing saved filter. Saved-filter previews
        require a concrete provider; omit `provider` to default to `LINKEDIN`.


        **Scope to a LinkedIn identity.** Only pass `identityId` when the user
        explicitly asks for an identity-specific LinkedIn search, such as
        importing 2nd-degree connections for identity 123. For normal sourcing
        requests like "software engineers in Girona", do NOT infer or pass an
        identity — omit `identityId` so AI Finder can auto-pick an available
        Sales Navigator identity. `identityId` is only valid with `provider:
        LINKEDIN`, and the identity must have `linkedinSearchEnabled: true`
        (Sales Navigator + valid credentials). List eligible identities with
        `GET /v1/identities?linkedinSearchEnabled=true`. The chosen `identityId`
        carries through iterate and into import.


        **What you get back.** A `previewId` (valid for 24 hours) plus the
        `result` object with the AI-generated filters, a human-readable `title`
        and `reasoning`, the `resolvedProvider` (useful when you passed `AUTO`),
        and `identityId` echoed back when you scoped the search to one.


        **What to do next.** Pass the `previewId` to `POST
        /v1/ai-finder/previews/{previewId}/iterate` to refine, or to `POST
        /v1/ai-finder/previews/{previewId}/import` to commit.

            > **Required scope:** `ACTIONS_WRITE`
            >
            > **Rate limit:** 10 requests per minute
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - type: object
                  properties:
                    text:
                      type: string
                      minLength: 1
                      maxLength: 2000
                      description: >-
                        Natural-language description of the contacts or
                        companies to find. Be specific — include titles,
                        seniority, geography, industries, company size, tech
                        stack, funding, or any other qualifier the AI should
                        use. Example: "VP of Finance at Series B SaaS companies
                        in California with 50-500 employees". 1–2000 characters.
                        This is the natural-language search shape — it has no
                        `savedFilterId`.
                    provider:
                      type: string
                      enum:
                        - AUTO
                        - LINKEDIN
                        - CRM_CONTACTS
                        - CRM_COMPANIES
                        - STORELEADS
                        - CRUNCHBASE_COMPANIES
                        - CRUNCHBASE_CONTACTS
                        - CRUNCHBASE_INVESTORS
                        - THEIRSTACK_TECHNOLOGY
                        - THEIRSTACK_JOBS
                        - GOOGLE_MAPS
                      description: >-
                        Which AI Finder provider to use. Omit (or pass `AUTO`)
                        to let the system route to the best provider for a text
                        query. Pass an explicit value to force one.


                        Each value encodes the entity type — do NOT pass a
                        separate `entity` field.


                        | Value | Target | Entity |

                        |---|---|---|

                        | `AUTO` | System picks based on the text query |
                        inferred |

                        | `LINKEDIN` | LinkedIn Sales Nav | inferred from query
                        |

                        | `CRM_CONTACTS` | Client's configured CRM (HubSpot,
                        Salesforce, Dynamics, Zoho, TribeCRM, or Attio) |
                        CONTACT |

                        | `CRM_COMPANIES` | Client's configured CRM | COMPANY |

                        | `STORELEADS` | StoreLeads (ecommerce, DTC, Shopify,
                        brands) | COMPANY |

                        | `CRUNCHBASE_COMPANIES` | Crunchbase organizations,
                        startups, funds | COMPANY |

                        | `CRUNCHBASE_CONTACTS` | Crunchbase people (founders,
                        execs, board members) | CONTACT |

                        | `CRUNCHBASE_INVESTORS` | Crunchbase investors (VCs,
                        angels, funds) | CONTACT |

                        | `THEIRSTACK_TECHNOLOGY` | Companies using a given tech
                        stack | COMPANY |

                        | `THEIRSTACK_JOBS` | Companies hiring for certain roles
                        | COMPANY |

                        | `GOOGLE_MAPS` | Local businesses, restaurants,
                        clinics, stores | COMPANY |


                        For `CRM_CONTACTS` / `CRM_COMPANIES` the specific CRM is
                        auto-detected from the client's configured integrations
                        (preference order: HubSpot → Salesforce → Dynamics →
                        Zoho → Attio → TribeCRM). If the client has no CRM
                        configured, the request returns 422.
                  required:
                    - text
                  additionalProperties: false
                - type: object
                  properties:
                    text:
                      type: string
                      minLength: 1
                      maxLength: 2000
                      description: >-
                        Natural-language description of the identity-specific
                        LinkedIn contacts to find, such as "2nd-degree
                        connections who are VPs of Sales". Use this shape only
                        when the user explicitly named the identity/account
                        scope.
                    provider:
                      type: string
                      enum:
                        - LINKEDIN
                      description: Required for identity-scoped AI Finder searches.
                    identityId:
                      type: integer
                      exclusiveMinimum: 0
                      description: >-
                        Scope a LinkedIn AI Finder search to a specific identity
                        (LinkedIn account) so the resulting list is built using
                        that account. Only valid when `provider` is `LINKEDIN`,
                        and only for identity-specific requests such as
                        importing 2nd-degree connections for a named identity.
                        Do not infer or pass `identityId` for generic sourcing
                        queries; omit it to let the system auto-pick an
                        available Sales-Nav identity. Must be an identity with
                        `linkedinSearchEnabled: true` (Sales Navigator + valid
                        credentials) — list eligible identities via GET
                        /v1/identities?linkedinSearchEnabled=true.
                  required:
                    - text
                    - provider
                    - identityId
                  additionalProperties: false
                - type: object
                  properties:
                    savedFilterId:
                      type: integer
                      exclusiveMinimum: 0
                      description: >-
                        Replay a specific saved AI Finder filter by its id. Use
                        this shape ONLY when the user explicitly asks to reuse a
                        named saved AI Finder filter — never derive an id from
                        page context or the active table view. Pass the
                        `provider` that owns the filter.
                    provider:
                      type: string
                      enum:
                        - AUTO
                        - LINKEDIN
                        - CRM_CONTACTS
                        - CRM_COMPANIES
                        - STORELEADS
                        - CRUNCHBASE_COMPANIES
                        - CRUNCHBASE_CONTACTS
                        - CRUNCHBASE_INVESTORS
                        - THEIRSTACK_TECHNOLOGY
                        - THEIRSTACK_JOBS
                        - GOOGLE_MAPS
                      description: >-
                        Which AI Finder provider to use. Omit (or pass `AUTO`)
                        to let the system route to the best provider for a text
                        query. Pass an explicit value to force one.


                        Each value encodes the entity type — do NOT pass a
                        separate `entity` field.


                        | Value | Target | Entity |

                        |---|---|---|

                        | `AUTO` | System picks based on the text query |
                        inferred |

                        | `LINKEDIN` | LinkedIn Sales Nav | inferred from query
                        |

                        | `CRM_CONTACTS` | Client's configured CRM (HubSpot,
                        Salesforce, Dynamics, Zoho, TribeCRM, or Attio) |
                        CONTACT |

                        | `CRM_COMPANIES` | Client's configured CRM | COMPANY |

                        | `STORELEADS` | StoreLeads (ecommerce, DTC, Shopify,
                        brands) | COMPANY |

                        | `CRUNCHBASE_COMPANIES` | Crunchbase organizations,
                        startups, funds | COMPANY |

                        | `CRUNCHBASE_CONTACTS` | Crunchbase people (founders,
                        execs, board members) | CONTACT |

                        | `CRUNCHBASE_INVESTORS` | Crunchbase investors (VCs,
                        angels, funds) | CONTACT |

                        | `THEIRSTACK_TECHNOLOGY` | Companies using a given tech
                        stack | COMPANY |

                        | `THEIRSTACK_JOBS` | Companies hiring for certain roles
                        | COMPANY |

                        | `GOOGLE_MAPS` | Local businesses, restaurants,
                        clinics, stores | COMPANY |


                        For `CRM_CONTACTS` / `CRM_COMPANIES` the specific CRM is
                        auto-detected from the client's configured integrations
                        (preference order: HubSpot → Salesforce → Dynamics →
                        Zoho → Attio → TribeCRM). If the client has no CRM
                        configured, the request returns 422.
                  required:
                    - savedFilterId
                  additionalProperties: false
                - type: object
                  properties:
                    savedFilterId:
                      type: integer
                      exclusiveMinimum: 0
                      description: >-
                        Replay a specific saved AI Finder LinkedIn filter by its
                        id under a specific identity. Use this shape ONLY when
                        the user explicitly asks to replay a saved filter for a
                        named identity.
                    provider:
                      type: string
                      enum:
                        - LINKEDIN
                      description: Required for identity-scoped saved-filter previews.
                    identityId:
                      type: integer
                      exclusiveMinimum: 0
                      description: >-
                        Scope a LinkedIn AI Finder search to a specific identity
                        (LinkedIn account) so the resulting list is built using
                        that account. Only valid when `provider` is `LINKEDIN`,
                        and only for identity-specific requests such as
                        importing 2nd-degree connections for a named identity.
                        Do not infer or pass `identityId` for generic sourcing
                        queries; omit it to let the system auto-pick an
                        available Sales-Nav identity. Must be an identity with
                        `linkedinSearchEnabled: true` (Sales Navigator + valid
                        credentials) — list eligible identities via GET
                        /v1/identities?linkedinSearchEnabled=true.
                  required:
                    - savedFilterId
                    - provider
                    - identityId
                  additionalProperties: false
              description: >-
                Provide EITHER a `{ text }` natural-language search (the usual
                case) OR a `{ savedFilterId }` saved-filter replay. These are
                two distinct shapes — never combine `text` and `savedFilterId`.
                For generic sourcing, the body has no `identityId` property.
                `identityId` is only legal in the separate identity-scoped
                LinkedIn shape, where `provider` must be exactly `LINKEDIN`.
            examples:
              autoRouted:
                summary: Auto-routed search (typical)
                value:
                  text: VP Finance at Series B SaaS companies in California
              linkedinScopedToIdentity:
                summary: Identity-specific LinkedIn search
                value:
                  text: >-
                    2nd-degree connections who are Heads of Engineering at
                    Series B SaaS companies in Europe
                  provider: LINKEDIN
                  identityId: 12345
              savedFilter:
                summary: Preview a saved filter directly
                value:
                  savedFilterId: 42
                  provider: STORELEADS
              crunchbaseCompanies:
                summary: Force a Crunchbase companies search
                value:
                  text: Fintech companies that raised a Series A in 2025
                  provider: CRUNCHBASE_COMPANIES
              googleMaps:
                summary: Google Maps local businesses
                value:
                  text: Yoga studios in Brooklyn
                  provider: GOOGLE_MAPS
              crmContacts:
                summary: Search the client's configured CRM for contacts
                value:
                  text: Existing accounts with a VP of Marketing title
                  provider: CRM_CONTACTS
              theirstackJobs:
                summary: 'TheirStack: companies hiring for a role'
                value:
                  text: Companies hiring senior Rust engineers right now
                  provider: THEIRSTACK_JOBS
      responses:
        '201':
          description: Preview generated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      previewId:
                        type: string
                        format: uuid
                        description: >-
                          UUID that identifies this cached preview. Pass it as
                          the `{previewId}` path parameter on the iterate or
                          import endpoints. Valid for 24 hours after creation.
                      createdAt:
                        type: string
                        format: date-time
                        description: When this preview was generated (ISO-8601).
                      expiresAt:
                        type: string
                        format: date-time
                        description: >-
                          When this preview will be evicted from the cache (24h
                          after creation).
                      userInput:
                        type: string
                        description: >-
                          The exact preview input. For text-based previews this
                          is the natural-language query; for saved-filter
                          previews this identifies the saved filter that seeded
                          the preview. For iterated previews this includes the
                          original input plus all refinement feedback applied so
                          far.
                      requestedProvider:
                        type: string
                        enum:
                          - AUTO
                          - LINKEDIN
                          - CRM_CONTACTS
                          - CRM_COMPANIES
                          - STORELEADS
                          - CRUNCHBASE_COMPANIES
                          - CRUNCHBASE_CONTACTS
                          - CRUNCHBASE_INVESTORS
                          - THEIRSTACK_TECHNOLOGY
                          - THEIRSTACK_JOBS
                          - GOOGLE_MAPS
                        description: >-
                          The `provider` value you sent in the request (`AUTO`
                          if omitted). Useful for logging and debugging.
                      resolvedProvider:
                        type: string
                        enum:
                          - LINKEDIN
                          - CRM_CONTACTS
                          - CRM_COMPANIES
                          - STORELEADS
                          - CRUNCHBASE_COMPANIES
                          - CRUNCHBASE_CONTACTS
                          - CRUNCHBASE_INVESTORS
                          - THEIRSTACK_TECHNOLOGY
                          - THEIRSTACK_JOBS
                          - GOOGLE_MAPS
                        description: >-
                          The provider that actually ran. Always a concrete
                          value — never `AUTO`. If you passed `AUTO`, this tells
                          you which provider the router picked.
                      crmProvider:
                        type: string
                        enum:
                          - HUBSPOT
                          - SALESFORCE
                          - ZOHO
                          - DYNAMICS
                          - TRIBECRM
                          - ATTIO
                        description: >-
                          Only set when `resolvedProvider` is `CRM_CONTACTS` or
                          `CRM_COMPANIES`. The specific CRM used for the search
                          (HUBSPOT, SALESFORCE, DYNAMICS, ZOHO, TRIBECRM,
                          ATTIO), auto-detected from the client's configured
                          integrations.
                      entity:
                        type: string
                        enum:
                          - COMPANY
                          - CONTACT
                        description: >-
                          The entity (`COMPANY` or `CONTACT`) this preview
                          produced. Use this to decide which type of list to
                          pass to the import endpoint.
                      theirstackImportType:
                        type: string
                        enum:
                          - TECHNOLOGY
                          - JOBS
                        description: >-
                          Only set when `resolvedProvider` is
                          `THEIRSTACK_TECHNOLOGY` or `THEIRSTACK_JOBS`.
                          `TECHNOLOGY` = companies using a tech stack; `JOBS` =
                          companies hiring.
                      result:
                        type: object
                        additionalProperties: {}
                        description: >-
                          The generated search result. Always includes a
                          human-readable `title` and `reasoning`. The filter
                          shape depends on the provider: LinkedIn uses
                          `filtersByType` keyed by LinkedIn Sales Nav filter
                          IDs; CRM uses `filters` (an array of CRM property
                          filters); Crunchbase / StoreLeads / TheirStack /
                          Google Maps each use their own `filters` object.
                          Inspect this to understand what will be imported
                          before committing.
                      droppedFilters:
                        type: array
                        items:
                          type: string
                        description: >-
                          Qualifiers from your query that the AI explicitly said
                          it could NOT map onto the resolved provider (e.g.
                          "healthtech" when targeting Crunchbase CONTACTS, which
                          has no industry field) — extracted heuristically from
                          phrases like "omitted"/"cannot filter" in the AI
                          reasoning, and cross-checked against the values in
                          `result` so a term that WAS applied as a structured
                          filter is never listed here. If present, the returned
                          filters are less specific than your query asked for —
                          consider switching provider or tightening with the
                          iterate endpoint. Absence of this field does not
                          guarantee every qualifier was applied; it only reports
                          terms the AI reasoning called out as dropped.
                      previousPreviewId:
                        type: string
                        format: uuid
                        description: >-
                          Only set when this preview was produced via the
                          iterate endpoint. Points at the preview this one
                          refines. Builds an implicit chain you can walk back.
                      identityId:
                        type: number
                        description: >-
                          Only set for LinkedIn previews scoped to a specific
                          identity. Echoes the `identityId` you sent — the
                          import will run the LinkedIn search under this
                          identity (LinkedIn account).
                    required:
                      - previewId
                      - createdAt
                      - expiresAt
                      - userInput
                      - requestedProvider
                      - resolvedProvider
                      - result
                required:
                  - status
                  - message
                  - data
        '400':
          description: Validation error
        '422':
          description: >-
            AI could not build a valid search, or the requested provider is
            unavailable (e.g. CRM_CONTACTS/CRM_COMPANIES with no CRM
            configured).
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key

````