> ## 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.

# Search Companies By Tech Stack

> Returns companies whose recent job postings mention a given technology.

<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>

Results are ranked by matching post count and paginated 50 per page; walk pages with `?page=1`, `?page=2`, ... using `has_more`. Well-known LinkedIn job aggregators (`jobs-via-*`, `lensa`, `ziprecruiter`, etc.) are excluded by default.

Set `enrich=true` to hydrate each hit with firmographics (employee count, HQ, website, LinkedIn, industries, funding, revenue). The firmographic filters (`hq_country_code`, `min_employee_count`, `max_employee_count`) auto-enable enrichment, so you don't need to set both.

Credits: charged per company returned. The exact amount charged is returned in `credits_consumed` on every response.

Example - US-HQ companies of 1,000+ employees hiring with `Snowflake`:
`GET /api/v2/tech/companies?tech=Snowflake&hq_country_code=USA&min_employee_count=1000`



## OpenAPI

````yaml agent-primitives/openapi.json GET /api/v2/tech/companies
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:
    get:
      tags:
        - Company Search
      summary: Search Companies By Tech Stack
      description: >-
        Returns companies whose recent job postings mention a given technology.


        <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>


        Results are ranked by matching post count and paginated 50 per page;
        walk pages with `?page=1`, `?page=2`, ... using `has_more`. Well-known
        LinkedIn job aggregators (`jobs-via-*`, `lensa`, `ziprecruiter`, etc.)
        are excluded by default.


        Set `enrich=true` to hydrate each hit with firmographics (employee
        count, HQ, website, LinkedIn, industries, funding, revenue). The
        firmographic filters (`hq_country_code`, `min_employee_count`,
        `max_employee_count`) auto-enable enrichment, so you don't need to set
        both.


        Credits: charged per company returned. The exact amount charged is
        returned in `credits_consumed` on every response.


        Example - US-HQ companies of 1,000+ employees hiring with `Snowflake`:

        `GET
        /api/v2/tech/companies?tech=Snowflake&hq_country_code=USA&min_employee_count=1000`
      operationId: tech_companies
      parameters:
        - name: X-API-Key
          in: header
          required: true
          schema:
            type: string
            title: X-Api-Key
        - name: tech
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 128
            title: Tech
          description: >-
            Technology to search for in job descriptions (e.g. 'Snowflake',
            'Kubernetes').
        - name: variations
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
            title: Variations
          description: >-
            Optional alternate phrasings (e.g. 'Snowflake Data Cloud'). Each is
            OR-matched as a phrase.
        - name: lookback_days
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 365
            default: 365
            title: Lookback Days
          description: >-
            Lookback window in days (1–365). Defaults to a full year so coverage
            estimates aren't artificially clipped; narrow this for
            recency-sensitive queries.
        - name: page
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 1000
            default: 1
            title: Page
          description: >-
            1-indexed page number. Page size is fixed at 50. Walk pages with
            `has_more`. Sanity-bounded at 1,000 pages (50,000 results) - the
            long tail is rarely useful for ICP discovery. When firmographic
            filters are set, the addressable pool reflects the filtered set.
        - name: exclude_vendor
          in: query
          required: false
          schema:
            type: boolean
            default: true
            title: Exclude Vendor
          description: >-
            When true (default), excludes job posts from the vendor of the
            technology being searched (e.g. searching `Snowflake` won't return
            Snowflake's own job posts). Set false to include the vendor.
        - name: exclude_aggregators
          in: query
          required: false
          schema:
            type: boolean
            default: true
            title: Exclude Aggregators
          description: >-
            Exclude well-known LinkedIn job aggregators and reposters
            (`jobs-via-*`, `get-it-recruit-*`, `lensa`, `jobot`, `ziprecruiter`,
            `clearancejobs`, `cybercoders`, etc.) which otherwise dominate raw
            counts without representing actual tech adopters. ON by default.
        - name: exclude_company_slugs
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
            title: Exclude Company Slugs
          description: >-
            Additional LinkedIn company slugs to exclude on top of the default
            aggregator block-list. Useful for blocking consultancies
            (`deloitte`, `pwc`, `accenture`), the caller's own company, or known
            competitors.
        - name: include_evidence
          in: query
          required: false
          schema:
            type: boolean
            default: true
            title: Include Evidence
          description: >-
            Include one top-hit job per company with a highlighted snippet
            showing the tech phrase in context. Set false for the leanest
            payload (~6× faster).
        - name: enrich
          in: query
          required: false
          schema:
            type: boolean
            default: false
            title: Enrich
          description: >-
            When true, hydrates each company on this page with firmographics:
            employee count, website, LinkedIn URL, HQ, industries, funding, and
            revenue. Adds ~150–200ms per page. Auto-enabled when any of
            `hq_country_code`, `min_employee_count`, or `max_employee_count` is
            set.
        - name: hq_country_code
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                minLength: 3
                maxLength: 3
              - type: 'null'
            title: Hq Country Code
          description: >-
            Filter by company HQ ISO 3166-1 alpha-3 code (e.g. `USA`, `GBR`,
            `IND`, `DEU`). Top 30 by company volume: USA, GBR, CHN, FRA, IND,
            DEU, BRA, BEL, ESP, CAN, AUS, NLD, ITA, NOR, ZAF, MEX, TUR, CHE,
            ARE, POL, SWE, IDN, ARG, PAK, COL, PRT, JPN, CHL, NGA, AUT. Full
            list of 250 codes via `GET /api/v2/tech/country-options` (under
            Agent Helpers). Auto-enables `enrich`. Companies missing a country
            code are dropped from the page when this filter is active.
        - name: min_employee_count
          in: query
          required: false
          schema:
            anyOf:
              - type: integer
                minimum: 0
              - type: 'null'
            title: Min Employee Count
          description: >-
            Inclusive lower bound on company employee count. Auto-enables
            `enrich`. Companies with no employee count are dropped when this
            filter is active.
        - name: max_employee_count
          in: query
          required: false
          schema:
            anyOf:
              - type: integer
                minimum: 0
              - type: 'null'
            title: Max Employee Count
          description: >-
            Inclusive upper bound on company employee count. Auto-enables
            `enrich`. Companies with no employee count are dropped when this
            filter is active.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompaniesResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    CompaniesResponse:
      type: object
      title: CompaniesResponse
      description: >-
        One page of companies that mention a tech in recent job postings.
        Companies are ranked by `post_count` descending; firmographics are
        populated when `enrich=true` or when any firmographic filter is set.
      required:
        - tech
        - lookback_days
        - page
        - page_size
        - total_results
        - has_more
        - total_companies_matched
        - companies
      properties:
        tech:
          type: string
          title: Tech
          description: The technology phrase searched.
        variations:
          type: array
          items:
            type: string
          default: []
          title: Variations
          description: Alternate phrasings that were OR-matched alongside `tech`.
        lookback_days:
          type: integer
          title: Lookback Days
          description: Lookback window applied to the search, in days.
        page:
          type: integer
          title: Page
          description: 1-indexed page number returned.
        page_size:
          type: integer
          title: Page Size
          description: Items per page. Fixed at 50.
        total_results:
          type: integer
          title: Total Results
          description: >-
            Size of the addressable result set this page slices from. Without
            firmographic filters: bounded by the 50,000-result sanity cap (1,000
            pages × 50). With filters: equals the size of the filtered set after
            firmographic hydration, which is what `has_more` and page indexing
            are computed against.
        has_more:
          type: boolean
          title: Has More
          description: >-
            True when at least one more page is available (`page * page_size <
            total_results`). Loop while this is true to walk the full result
            set.
        total_companies_matched:
          type: integer
          title: Total Companies Matched
          description: >-
            Approximate total distinct companies whose recent job postings match
            the search, BEFORE firmographic filters are applied. Compare with
            `total_results` to see how aggressively your filters narrowed the
            result.
        filters_applied:
          $ref: '#/components/schemas/FiltersApplied'
          description: Echo of the firmographic filters that produced this page.
        companies:
          type: array
          items:
            $ref: '#/components/schemas/CompanyHit'
          title: Companies
          description: The ranked companies on this page.
        credits_consumed:
          type: integer
          default: 0
          title: Credits Consumed
          description: >-
            Credits charged for this response. Computed as `companies_returned ×
            per-company-cost`: 5 credits per company without enrichment, 10
            credits per company with enrichment (or any firmographic filter
            set). The charge is recorded in the background after the response is
            sent, so it never adds to your request latency.
        latency_ms:
          type: integer
          default: 0
          title: Latency Ms
          description: >-
            End-to-end request latency including cache lookup, OS, CH, and
            serialization.
    HTTPValidationError:
      type: object
      properties:
        detail:
          type: array
          items:
            $ref: '#/components/schemas/ValidationError'
    FiltersApplied:
      type: object
      title: FiltersApplied
      description: >-
        Echo of the firmographic filters applied to this page. When any of these
        are set, the page is guaranteed to return up to `page_size`
        filter-matching hits (rather than 50 raw hits trimmed); walk further
        pages with `has_more`.
      properties:
        hq_country_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Hq Country Code
          description: ISO 3166-1 alpha-3 HQ country code applied to this page, if any.
        min_employee_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Min Employee Count
          description: >-
            Inclusive lower bound on employee count applied to this page, if
            any.
        max_employee_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Max Employee Count
          description: >-
            Inclusive upper bound on employee count applied to this page, if
            any.
    CompanyHit:
      type: object
      title: CompanyHit
      description: >-
        One company in a `/api/v2/tech/companies` page. The hiring-signal block
        (slug, post_count, evidence, first/last posted dates) is always
        populated; the firmographics block (website, employee_count, funding,
        HQ, industries) is only populated when `enrich=true`.
      required:
        - company_slug
        - post_count
      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. When `enrich=true` this is the canonical company name;
            otherwise it's the name as it appeared on the most recent matching
            job 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 - useful for
            detecting stale vs active hiring.
        evidence:
          anyOf:
            - $ref: '#/components/schemas/CompanyEvidence'
            - type: 'null'
          description: >-
            Top-hit job evidence for this company. Null when
            `include_evidence=false`.
        enriched:
          type: boolean
          default: false
          title: Enriched
          description: >-
            True iff this hit carries firmographic data. False if `enrich=false`
            was passed, or if no firmographic record was found for this company.
        website:
          anyOf:
            - type: string
            - type: 'null'
          title: Website
          description: Primary company website (domain).
        linkedin_url:
          anyOf:
            - type: string
            - type: 'null'
          title: LinkedIn URL
          description: Canonical LinkedIn company page URL.
        linkedin_org_id:
          anyOf:
            - type: string
            - type: 'null'
          title: LinkedIn Org Id
          description: Internal LinkedIn organization ID for the company.
        linkedin_follower_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: LinkedIn Follower Count
          description: LinkedIn follower count at last refresh.
        employee_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Employee Count
          description: Estimated current employee count.
        industries:
          anyOf:
            - type: array
              items:
                type: string
            - type: 'null'
          title: Industries
          description: Industry tags associated with the company.
        description:
          anyOf:
            - type: string
            - type: 'null'
          title: Description
          description: Short company description, truncated to 500 characters.
        hq_city:
          anyOf:
            - type: string
            - type: 'null'
          title: HQ City
          description: HQ city.
        hq_region:
          anyOf:
            - type: string
            - type: 'null'
          title: HQ Region
          description: HQ state / region.
        hq_country:
          anyOf:
            - type: string
            - type: 'null'
          title: HQ Country
          description: >-
            HQ country English name. Use `hq_country_code` for filtering /
            equality checks.
        hq_country_code:
          anyOf:
            - type: string
            - type: 'null'
          title: HQ Country Code
          description: >-
            ISO 3166-1 alpha-3 (USA, GBR, IND, ...). The reliable, normalized
            country source - use this for filtering rather than `hq_country`.
        funding_stage:
          anyOf:
            - type: string
            - type: 'null'
          title: Funding Stage
          description: >-
            Normalized stage label, e.g. 'Seed', 'Series A', 'Series E',
            'Public', 'Acquired', 'No Funding Yet'.
        total_funding_usd:
          anyOf:
            - type: integer
            - type: 'null'
          title: Total Funding USD
          description: Cumulative funding raised, in USD.
        latest_funding_usd:
          anyOf:
            - type: integer
            - type: 'null'
          title: Latest Funding USD
          description: Size of the most recent funding round, in USD.
        revenue_usd:
          anyOf:
            - type: integer
            - type: 'null'
          title: Revenue USD
          description: Estimated annual revenue, in USD.
    ValidationError:
      type: object
      required:
        - loc
        - msg
        - type
      properties:
        loc:
          type: array
          items:
            anyOf:
              - type: string
              - type: integer
        msg:
          type: string
        type:
          type: string
    CompanyEvidence:
      type: object
      title: CompanyEvidence
      description: >-
        Evidence of the tech mention for a company - the most recent matching
        job posting, with a highlighted description snippet showing the phrase
        in context.
      properties:
        title:
          anyOf:
            - type: string
            - type: 'null'
          title: Title
          description: Job title of the evidence posting.
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: URL
          description: Direct LinkedIn URL of the evidence job posting.
        created:
          anyOf:
            - type: string
            - type: 'null'
          title: Created
          description: ISO timestamp the evidence 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.

````