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

# Tech Intent Search Results

> Poll a tech intent-search job and page through its results. Submit a job first via **`POST /api/v2/tech/companies/intent-search`** ("Search Companies by Tech Stack with Intent", under Company Search), which returns a `job_id`.

<Info>**No API key yet?** [Sign up via Agent Auth](/agent-auth/agent-auth/agent-sign-up) to get your `X-API-Key` - the only required header for this endpoint.</Info>

This single endpoint returns both the job `status` (`pending` → `running` → `completed` / `failed`), a `manifest` summary once complete, **and** one page of result `rows`. Walk pages by passing the returned `next_cursor` as `?cursor=`.

**Check `status` for completion - not `next_cursor`.** A still-running job can return a null `next_cursor` simply because later pages haven't been written yet; only `status: "completed"` means the full result set is available.

Each row is a company hit (same shape as Search Companies By Tech Stack, with firmographics when enrichment ran) plus an `intent` block: the verified `activity`, an LLM `reason` quoting the exact posting phrases that support the verdict, and the `qualified_job` itself. The manifest also reports `companies_scanned` vs `companies_qualified` so you can see how selective your activity was.

No credits are charged for polling - the job's credits are billed once, when it completes.



## OpenAPI

````yaml agent-primitives/openapi.json GET /api/v2/tech/companies/intent-search/{job_id}
openapi: 3.1.0
info:
  title: OpenFunnel Agent Primitives
  version: 1.0.0
servers:
  - url: https://api.openfunnel.dev
security: []
paths:
  /api/v2/tech/companies/intent-search/{job_id}:
    get:
      tags:
        - Tech Intent Search Results
      summary: Tech Intent Search Results
      description: >-
        Poll a tech intent-search job and page through its results. Submit a job
        first via **`POST /api/v2/tech/companies/intent-search`** ("Search
        Companies by Tech Stack with Intent", under Company Search), which
        returns a `job_id`.


        <Info>**No API key yet?** [Sign up via Agent
        Auth](/agent-auth/agent-auth/agent-sign-up) to get your `X-API-Key` -
        the only required header for this endpoint.</Info>


        This single endpoint returns both the job `status` (`pending` →
        `running` → `completed` / `failed`), a `manifest` summary once complete,
        **and** one page of result `rows`. Walk pages by passing the returned
        `next_cursor` as `?cursor=`.


        **Check `status` for completion - not `next_cursor`.** A still-running
        job can return a null `next_cursor` simply because later pages haven't
        been written yet; only `status: "completed"` means the full result set
        is available.


        Each row is a company hit (same shape as Search Companies By Tech Stack,
        with firmographics when enrichment ran) plus an `intent` block: the
        verified `activity`, an LLM `reason` quoting the exact posting phrases
        that support the verdict, and the `qualified_job` itself. The manifest
        also reports `companies_scanned` vs `companies_qualified` so you can see
        how selective your activity was.


        No credits are charged for polling - the job's credits are billed once,
        when it completes.
      operationId: >-
        tech_intent_search_status_api_v2_tech_companies_intent_search__job_id__get
      parameters:
        - name: job_id
          in: path
          required: true
          schema:
            type: string
            title: Job Id
          description: The `job_id` returned by the intent-search submit endpoint.
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Cursor
          description: >-
            Page to read, e.g. `page_0001` (use the `next_cursor` from the
            previous response). Omit for the first page.
        - name: X-API-Key
          in: header
          required: true
          schema:
            type: string
            title: X-Api-Key
      responses:
        '200':
          description: Job status, manifest, and one page of results.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TechIntentJobResponse'
              example:
                job_id: 8bda2224-3772-4430-94d3-69a526872227
                status: completed
                manifest:
                  pages: 1
                  page_size: 100
                  count: 50
                  partial: false
                  tech: Snowflake
                  activity: migrating off Redshift to Snowflake
                  companies_scanned: 230
                  companies_skipped_no_evidence: 4
                  companies_qualified: 50
                  total_companies_matched: 8412
                  credits_consumed: 500
                error_message: null
                rows:
                  - company_slug: acme-analytics
                    company_name: Acme Analytics
                    post_count: 7
                    first_posted_at: '2026-02-11T09:30:00Z'
                    last_posted_at: '2026-05-28T17:05:00Z'
                    enriched: true
                    website: acme-analytics.com
                    linkedin_url: https://www.linkedin.com/company/acme-analytics
                    employee_count: 850
                    hq_country_code: USA
                    funding_stage: Series C
                    intent:
                      activity: migrating off Redshift to Snowflake
                      reason: >-
                        The posting describes "leading our migration from
                        Redshift to Snowflake" as a core responsibility of the
                        role.
                      qualified_job:
                        title: Senior Data Engineer
                        url: https://www.linkedin.com/jobs/view/4012345678
                        created: '2026-05-28T17:05:00Z'
                        snippet: >-
                          …experience leading our migration from Redshift to
                          <em>Snowflake</em>…
                page: page_0000
                next_cursor: null
                count: 50
        '400':
          description: Unknown `cursor` for this job.
        '404':
          description: Job not found for this API key.
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      x-codeSamples:
        - lang: bash
          label: Poll results
          source: >-
            # first page (also shows status)

            curl -sS
            "https://api.openfunnel.dev/api/v2/tech/companies/intent-search/JOB_ID"
            \
              -H "X-API-Key: YOUR_API_KEY"

            # next page

            curl -sS
            "https://api.openfunnel.dev/api/v2/tech/companies/intent-search/JOB_ID?cursor=page_0001"
            \
              -H "X-API-Key: YOUR_API_KEY"
components:
  schemas:
    TechIntentJobResponse:
      type: object
      title: TechIntentJobResponse
      description: >-
        Combined job status + one page of results. Check `status` for completion
        (not `next_cursor`), and walk pages with `next_cursor`.
      required:
        - job_id
        - status
      properties:
        job_id:
          type: string
          title: Job Id
        status:
          type: string
          title: Status
          description: '`pending`, `running`, `completed`, or `failed`.'
        manifest:
          anyOf:
            - $ref: '#/components/schemas/TechIntentManifest'
            - type: 'null'
          description: Job summary; populated once the job completes.
        error_message:
          anyOf:
            - type: string
            - type: 'null'
          title: Error Message
          description: Failure reason when `status` is `failed`.
        rows:
          type: array
          items:
            $ref: '#/components/schemas/TechIntentCompanyRow'
          title: Rows
          description: Qualified companies in the requested page.
        page:
          anyOf:
            - type: string
            - type: 'null'
          title: Page
          description: Name of the page returned, e.g. `page_0000`.
        next_cursor:
          anyOf:
            - type: string
            - type: 'null'
          title: Next Cursor
          description: >-
            Pass as `?cursor=` to fetch the next page; null on the last
            available page.
        count:
          type: integer
          default: 0
          title: Count
          description: Number of rows in this page.
    HTTPValidationError:
      type: object
      properties:
        detail:
          type: array
          items:
            $ref: '#/components/schemas/ValidationError'
    TechIntentManifest:
      type: object
      title: TechIntentManifest
      description: >-
        Summary of a completed (or partial) tech intent-search job, returned on
        the poll endpoint once the job finishes.
      properties:
        pages:
          type: integer
          title: Pages
          description: Number of result pages available to walk via the poll endpoint.
        page_size:
          type: integer
          title: Page Size
          description: Rows per page.
        count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Count
          description: Qualified companies written. Null on a partial/failed job.
        partial:
          type: boolean
          default: false
          title: Partial
          description: >-
            True if the job failed after writing some pages; the pages that
            landed are still readable.
        tech:
          anyOf:
            - type: string
            - type: 'null'
          title: Tech
          description: Echo of the technology searched.
        activity:
          anyOf:
            - type: string
            - type: 'null'
          title: Activity
          description: Echo of the activity intent that was verified.
        companies_scanned:
          anyOf:
            - type: integer
            - type: 'null'
          title: Companies Scanned
          description: >-
            Companies whose evidence posting was LLM-verified before the scan
            stopped. Compare with `companies_qualified` to see how selective the
            activity was.
        companies_skipped_no_evidence:
          anyOf:
            - type: integer
            - type: 'null'
          title: Companies Skipped No Evidence
          description: >-
            Companies skipped because no usable posting text was available to
            verify.
        companies_qualified:
          anyOf:
            - type: integer
            - type: 'null'
          title: Companies Qualified
          description: Companies that passed intent verification (equals `count`).
        total_companies_matched:
          anyOf:
            - type: integer
            - type: 'null'
          title: Total Companies Matched
          description: >-
            Approximate distinct companies matching the tech search, BEFORE
            intent verification.
        credits_consumed:
          anyOf:
            - type: integer
            - type: 'null'
          title: Credits Consumed
          description: >-
            Credits charged for the job (20 credits per qualified company
            returned).
    TechIntentCompanyRow:
      type: object
      title: TechIntentCompanyRow
      description: >-
        One qualified company. Carries the same hiring-signal and firmographic
        fields as a Search Companies By Tech Stack hit (firmographics populated
        when enrichment ran), plus the `intent` verification block.
      additionalProperties: true
      required:
        - company_slug
        - post_count
        - intent
      properties:
        company_slug:
          type: string
          title: Company Slug
          description: LinkedIn company slug (lowercased), e.g. 'stripe', 'snowflake-inc'.
        company_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Name
          description: >-
            Display name. Canonical company name when enriched; otherwise as it
            appeared on the posting.
        post_count:
          type: integer
          title: Post Count
          description: Number of matching job postings within the lookback window.
        first_posted_at:
          anyOf:
            - type: string
            - type: 'null'
          title: First Posted At
          description: ISO timestamp of the earliest matching posting.
        last_posted_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Posted At
          description: ISO timestamp of the most recent matching posting.
        enriched:
          type: boolean
          default: false
          title: Enriched
          description: >-
            True iff this row carries firmographic data (website,
            employee_count, HQ fields, funding, revenue - same fields as Search
            Companies By Tech Stack).
        intent:
          $ref: '#/components/schemas/TechIntentVerdict'
          description: The intent verification block for this company.
    ValidationError:
      type: object
      required:
        - loc
        - msg
        - type
      properties:
        loc:
          type: array
          items:
            anyOf:
              - type: string
              - type: integer
        msg:
          type: string
        type:
          type: string
    TechIntentVerdict:
      type: object
      title: TechIntentVerdict
      description: Why this company qualified for the activity intent.
      required:
        - activity
        - reason
        - qualified_job
      properties:
        activity:
          type: string
          title: Activity
          description: Echo of the activity intent that was verified.
        reason:
          type: string
          title: Reason
          description: >-
            LLM explanation of the verdict, with the exact supporting phrases
            from the posting wrapped in double quotes.
        qualified_job:
          type: object
          title: Qualified Job
          description: The job posting that passed intent verification.
          properties:
            title:
              anyOf:
                - type: string
                - type: 'null'
              title: Title
              description: Job title of the qualifying posting.
            url:
              anyOf:
                - type: string
                - type: 'null'
              title: URL
              description: Direct LinkedIn URL of the qualifying posting.
            created:
              anyOf:
                - type: string
                - type: 'null'
              title: Created
              description: ISO timestamp the posting was created.
            snippet:
              anyOf:
                - type: string
                - type: 'null'
              title: Snippet
              description: >-
                Highlighted text fragment showing the tech phrase in context
                inside the job description.

````