SOURCE_ID: find_companies_hiring NAME: Find Companies Hiring CATEGORY: List Building Build a static list of companies that are actively hiring, filtered by the roles they post, the technologies in their job ads, firmographics, and location. Imported records become available to your Floqer workflows for enrichment, scoring, outreach, and the like. INDEX: 1. Endpoints 2. Body shape (preview + create) 3. Filter fields catalogue 4. Dynamic options 5. How to configure end-to-end 6. Key notes 7. When to use ================================================================================ 1. ENDPOINTS ================================================================================ Source identifier (used in every endpoint path): `find_companies_hiring`. POST /api/v1/sources/find_companies_hiring/preview Scope: sources:read Returns a sample of companies (up to 25) that WOULD be imported for the given filters, without creating anything. Use this to validate filter combinations and inspect row shape before committing. `metadata.total_results` reports the full match count. POST /api/v1/sources/find_companies_hiring Scope: sources:write Creates the source and starts a one-time import of matching companies (up to `max_count`). Returns `source_instance_id` (the new source's UUID). The import runs asynchronously. GET /api/v1/sources//data Scope: sources:read Paginated rows imported into the created source. `` is the UUID returned by Create. Query: `page_no` (default 1), `page_size` (default 20, max 200). Source-agnostic; see concepts.txt §10. POST /api/v1/sources//sync Scope: sources:write Connects the created source to a workflow and (by default) backfills it with the source's current rows. `` here is the UUID returned by Create. Body: { workflow_id, field_mapping, push_existing?, run? } — `field_mapping` keys are `input.` references on the target workflow, values are the source fields to pull. This step is source-agnostic; see concepts.txt §10 for the full shape. No connection is required. There is no dynamic-options endpoint for this source today (see §4). ================================================================================ 2. BODY SHAPE (PREVIEW + CREATE) ================================================================================ Find Companies Hiring is always a one-time static import — there is no `pull_mode`, `schedule`, or recurring re-pull. `max_count` caps the import size. Preview accepts (all snake_case; unknown filter keys rejected with 400): filters required: object with at least one filter key (see §3) max_count optional: integer | string; ignored on preview Create accepts all the preview fields plus: name required: display name for the new source max_count optional: cap on rows imported; default 25, max 60000 The `filters` object is a flat bag of filter keys. Each filter key is a field base (see §3) combined with an operator suffix or range prefix — the full key documents one field + operator pair. The schema validates the field BASE of every key: an unrecognized base (a typo, or a field not in the catalogue) is rejected up front with a 400, so check §3 carefully. Example create body: { "name": "US SaaS companies hiring backend engineers", "max_count": 1000, "filters": { "company_country_code_or": ["US"], "job_filters.job_title_or": ["Backend Engineer", "Software Engineer"], "job_filters.posted_at_max_age_days": 30, "min_employee_count": 50 } } Preview response envelope: { "status": 200, "data": { "data": [ { "name": "Acme Corporation", "domain": "acme.com", ... } ], "metadata": { "total_results": 1234 } } } Rows are plain key/value objects describing each matching company (name, domain, country, industry, headcount, LinkedIn URL, and the matching job/technology signals when present). Preview returns up to 25 rows; `metadata.total_results` is the full match count. Create response envelope: { "status": 201, "data": { "source_instance_id": "", "name": "US SaaS companies hiring backend engineers", "created_at": "2026-06-02T12:00:00.000Z" } } ================================================================================ 3. FILTER FIELDS CATALOGUE ================================================================================ All filter keys live inside the `filters` object. Keys combine a FIELD BASE (below) with an OPERATOR SUFFIX or RANGE PREFIX. The validator rejects any key whose base is not listed here. OPERATOR SUFFIXES (append to a text/array field base): _or match ANY of the given values (default OR) _not exclude rows matching ANY of the values _and match ALL of the given values _case_insensitive_or case-insensitive ANY match _partial_match_or partial (substring) ANY match _partial_match_not exclude on partial match _pattern_or regex ANY match _pattern_and regex ALL match _pattern_not regex exclude _exists presence check (boolean value) RANGE PREFIXES / SUFFIXES (for numeric and date field bases): min_ lower bound max_ upper bound min__or_null lower bound, also include rows with no value max__or_null upper bound, also include rows with no value _max_age_days "within the last N days" (date fields) _gte / _lte explicit date range bounds (ISO YYYY-MM-DD) Nested groups use a dotted prefix on the key: technology filters go under `tech_filters.`, job-posting filters under `job_filters.`. ──────────────────────────────────────────────────────────────────── GROUP: company (flat keys, no prefix) ──────────────────────────────────────────────────────────────────── company_country_code Company HQ country, ISO-3166 alpha-2. Example: company_country_code_or: ["US","GB"] company_technology_slug Technologies the company uses (technology slugs — see §4). Example: company_technology_slug_or: ["salesforce","snowflake"] company_name Company name keyword. Operators: _or, _not, _case_insensitive_or, _partial_match_or, _partial_match_not. company_description Company description regex. Operators: _pattern_or, _pattern_not. company_location Company city regex. Operators: _pattern_or. company_domain Company domain match. Operators: _or, _not. industry_id Numeric industry id (see §4). Operators: _or, _not. revenue_usd Annual revenue (USD) range. Use min_revenue_usd / max_revenue_usd. funding_usd Total funding (USD) range. Use min_funding_usd / max_funding_usd. funding_stage Funding stage label, e.g. "Seed", "Series A". Operator: _or. company_type "recruiting_agency" | "direct_employer" | "all". Plain value (no suffix). company_linkedin_url Company LinkedIn URL. Operators: _or, _exists. employee_count Headcount range. Use min_employee_count / max_employee_count, or the _or_null variants to also include companies with unknown headcount. ──────────────────────────────────────────────────────────────────── GROUP: technology (prefix every key with `tech_filters.`) ──────────────────────────────────────────────────────────────────── tech_filters.technology_category_slug Technology category slug. Operators: _or, _not. tech_filters.confidence Detection confidence level for the technology. tech_filters.first_date_found When the technology was first detected (date range / max_age_days). tech_filters.last_date_found When the technology was last detected (date range / max_age_days). tech_filters.jobs Restrict the technology match to technologies seen in the job ads. ──────────────────────────────────────────────────────────────────── GROUP: job posting (prefix every key with `job_filters.`) ──────────────────────────────────────────────────────────────────── job_filters.posted_at When the job was posted. Use job_filters.posted_at_max_age_days: N (last N days) or job_filters.posted_at_gte / _lte (ISO dates). job_filters.job_title Title of the open role. Operators: _or, _not, _pattern_or, _pattern_and, _pattern_not. Example: job_filters.job_title_or: ["VP Sales"] job_filters.job_description Job-ad text regex. Operators: _pattern_or, _pattern_not. job_filters.job_country_code Job location country, ISO-3166 alpha-2. Operators: _or, _not. job_filters.job_location Job city/state regex. Operators: _pattern_or, _pattern_not. job_filters.remote Boolean — only remote roles. Example: job_filters.remote: true job_filters.salary_usd Annual salary (USD) range. Use min_/max_ on job_filters.salary_usd. job_filters.job_technology_slug Technologies mentioned in the job ad (technology slugs — see §4). Operators: _or, _and, _not. job_filters.scraper_name_pattern Job board / source regex (e.g. "Indeed", "LinkedIn"). Operator: _or. Examples: US companies hiring backend engineers in the last 30 days: { "filters": { "company_country_code_or": ["US"], "job_filters.job_title_or": ["Backend Engineer"], "job_filters.posted_at_max_age_days": 30 } } Mid-market companies posting roles that mention Snowflake: { "filters": { "min_employee_count": 200, "max_employee_count": 5000, "job_filters.job_technology_slug_or": ["snowflake"] } } Companies using Salesforce that are hiring (any role) remotely: { "filters": { "company_technology_slug_or": ["salesforce"], "job_filters.remote": true, "job_filters.posted_at_max_age_days": 90 } } ================================================================================ 4. DYNAMIC OPTIONS ================================================================================ No dynamic-options endpoint is registered for this source. Technology slugs and industry ids referenced by `company_technology_slug`, `tech_filters.technology_category_slug`, `job_filters.job_technology_slug`, and `industry_id` share the same catalogues exposed for `find_job_postings` (see that source's dynamic options: `company_technology_slug`, `job_technology_slug`, `industry_id`). Resolve the slugs/ids there, then reuse them here. Country codes are ISO-3166 alpha-2; size, revenue, and funding are open numeric ranges. ================================================================================ 5. HOW TO CONFIGURE END-TO-END ================================================================================ Step 1 — Preview before committing POST /api/v1/sources/find_companies_hiring/preview Body: { "filters": { "company_country_code_or": ["US"], "job_filters.job_title_or": ["Backend Engineer"], "job_filters.posted_at_max_age_days": 30 } } Check the returned `data[]` and `metadata.total_results`. Iterate the filters until you're happy — preview never creates anything. Step 2 — Create the source POST /api/v1/sources/find_companies_hiring Body: { "name": "US companies hiring backend engineers", "max_count": 1000, "filters": { ...same filters as preview... } } Set `max_count` ≤ the Preview `metadata.total_results`. Response: { "status": 201, "data": { "source_instance_id": "", "name", "created_at" }} Step 2b — (Optional) Poll imported rows while the backfill runs GET /api/v1/sources//data?page_no=1&page_size=20 ( = UUID from Step 2) Step 3 — Sync the source into a workflow POST /api/v1/sources//sync ( = the UUID from Step 2 ) First build `field_mapping`: a. GET /api/v1/workflows → pick the destination workflow_id. b. GET /api/v1/workflows//sheets//inputs → each input has a `reference` like `{{input.website}}`. c. Map each workflow input (reference WITHOUT braces) to a source field. Body: { "workflow_id": "", "field_mapping": { "input.company_name": "name", "input.website": "domain" }, "push_existing": true, "run": "all" } See concepts.txt §10 for the full sync semantics (source-agnostic). The initial import runs asynchronously — the create call returns as soon as the source is created and the import has started, not when records have finished arriving. Expect records over seconds to minutes depending on `max_count`. ================================================================================ 6. KEY NOTES ================================================================================ - No connection required. This endpoint does NOT return 424 for a missing integration. - Unknown filter keys are rejected. The schema validates the field base of every key in `filters`; a key whose base is not in §3 returns 400 with the offending key named. Operator suffixes and min_/max_ prefixes are understood, so `company_country_code_or` and `min_revenue_usd` are valid; `company_country_codes` (typo) is not. - One-time static import. There is no `pull_mode` or `schedule`; re-run Create for a fresh pull. `max_count` defaults to 25 when omitted. - Preview does not import anything and does not consume credits. Create starts the real import. - A posted-date policy is applied server-side once any job filter is active: if you don't pass a `job_filters.posted_at_*` window, a default recency cap is applied so you don't pull stale postings. - Total counts are best-effort. `metadata.total_results` may lag slightly. - Credits are consumed when the source is created. Insufficient balance surfaces as 402. ================================================================================ 7. WHEN TO USE ================================================================================ - Hiring-intent prospecting: "Companies hiring sales reps in the US": filters: company_country_code_or + job_filters.job_title_or + posted_at window. - Technographic + hiring signal: "Companies on Salesforce hiring RevOps": filters: company_technology_slug_or + job_filters.job_title_or. - Growth signal by headcount: "Companies 200-5000 employees posting engineering roles": min_/max_employee_count + job_filters.job_title_or. - Combine with Sync to push the companies into an enrichment + outreach workflow. When you instead want the individual job postings themselves (one row per open role, with title/salary/URL), use `find_job_postings`. When you want to enrich a single known company, use a workflow action template such as `enrich_company_linkedin_profile` — see the action catalog in llms-full.txt. ================================================================================ Last updated: 2026-06-02. Reference: https://floqer.com/docs/reference