SOURCE_ID: track_job_postings NAME: Track Job Postings CATEGORY: Signals Monitor newly published job postings that match a structured filter set — job titles, technologies, locations, company size, and more. Creates an ongoing source that re-checks for new matching postings on a schedule until a stop date. Imported job rows become available to your Floqer workflows for hiring-intent prospecting, account scoring, and competitive intelligence. INDEX: 1. Endpoints 2. Search model 3. Lifecycle (ongoing only) 4. Body shape (preview + create) 5. Field catalogue 6. Dynamic options 7. How to configure end-to-end 8. Key notes 9. When to use ================================================================================ 1. ENDPOINTS ================================================================================ Source identifier (used in every endpoint path): `track_job_postings`. POST /api/v1/sources/track_job_postings/preview Scope: sources:read Returns a sample page of matching job postings for the given filters, without creating anything. Use this to validate the filter set and inspect row shape before committing. Does not consume Floqer credits. POST /api/v1/sources/track_job_postings Scope: sources:write Creates an ongoing source, runs an immediate first fetch, and schedules recurring checks. Returns `source_instance_id` (the new source's UUID). Each fetch consumes Floqer credits. 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? }. Source-agnostic; see concepts.txt §10 for the full shape. PATCH /api/v1/sources//status Scope: sources:write Pause or resume an ongoing source. Body: {"status": "active"|"paused"}. A paused source stops scheduling new checks until resumed. No connection is required. There is no dynamic-options endpoint for this source today (see §6). ================================================================================ 2. SEARCH MODEL ================================================================================ Every preview/create call searches recently published job postings using a single structured `filters` object. Core behaviour: - `filters` is required and must contain at least one filter key. It is a free-form object of search criteria — you compose the ICP you care about (titles, technologies, locations, company headcount, salary, etc.). - Posted-date window: results are scoped to a posted-date lookback. When you do not supply a posted-date filter, a default lookback is applied, and any posted-date lookback you do supply is capped at 180 days. This keeps each run focused on recent postings. - Sorting: you may include an `order_by` array inside `filters` to sort results. Valid sort fields are: `date_posted`, `discovered_at`, `salary`, `job_title`, `company`, `num_jobs`. Other sort fields are dropped silently. Each entry is `{ "field": "", "desc": true }`. - Empty filter values (empty arrays, empty strings, null) are ignored, so you can pass a partially populated filter object safely. There is no import-mode switch — you always pass `filters` plus the lifecycle fields in §5. ================================================================================ 3. LIFECYCLE (ONGOING ONLY) ================================================================================ Track Job Postings is always an ongoing source — there is no one-time / static mode. expiration_date (create only) Required on create. Date string (YYYY-MM-DD or any ISO-like value). The source stops scheduling new checks after this date. Accepted but ignored on preview. start_date (optional) Optional date string. Sets the earliest posted date the monitor begins tracking from. Accepted but ignored on preview if you do not need it. On create the source runs an immediate first fetch and then re-checks on a schedule until `expiration_date`. Each scheduled run imports only postings newer than the last run, so the same posting is never imported twice. Discovered postings are appended to the source and pushed to any connected workflows automatically. ================================================================================ 4. BODY SHAPE (PREVIEW + CREATE) ================================================================================ Field names are snake_case. Unknown top-level keys are rejected with 400 — the body is strict. Preview accepts: filters required: object with at least one filter key start_date optional: valid date string expiration_date optional on preview: valid date string (create-only meaning) max_count optional: positive number (import cap; see §5) Create accepts: filters required: object with at least one filter key expiration_date required: valid date string start_date optional: valid date string max_count optional: positive number name required: display name for the new source Example preview body: { "filters": { "job_title_or": ["Head of Data", "VP Engineering"], "job_technology_slug_or": ["snowflake"], "job_country_code_or": ["US"], "posted_at_max_age_days": 30, "order_by": [{ "field": "date_posted", "desc": true }] } } Example create body: { "name": "Snowflake hiring — US data leaders", "filters": { "job_title_or": ["Head of Data", "VP Engineering"], "job_technology_slug_or": ["snowflake"], "job_country_code_or": ["US"] }, "expiration_date": "2026-09-01", "max_count": 2000 } Preview response envelope: { "status": 200, "data": { "data": [ { ...job posting row... } ], "metadata": { "total_results": 412 } } } Rows are plain key/value objects (see §5 for fields). `total_results` is the best-effort total match count for the search window; it can exceed the number of rows returned (preview returns one page). Create response envelope: { "status": 201, "data": { "source_instance_id": "", "name": "Snowflake hiring — US data leaders", "created_at": "2026-05-27T12:00:00.000Z" } } The initial fetch runs asynchronously — Create returns as soon as the source is created and the first fetch is started, not when postings have finished arriving. ================================================================================ 5. FIELD CATALOGUE ================================================================================ filters (object) — required Structured search criteria. Must contain at least one filter key. The filter vocabulary is rich; common keys include: job_title_or array of title strings to match (any of) job_title_not array of title strings to exclude job_description_pattern_or array of phrase patterns in the description job_technology_slug_or array of technology slugs (e.g. "snowflake") job_country_code_or array of ISO country codes (e.g. "US") job_seniority_or array of seniority levels remote true to require remote postings hybrid true to require hybrid postings posted_at_max_age_days posted-date lookback in days (capped at 180) company_name_or array of company names to include company_name_not array of company names to exclude min_employee_count / max_employee_count company headcount bounds order_by array of { field, desc } sort directives Empty arrays / empty strings / null values are ignored. Pass only the criteria you care about. order_by (inside filters) — optional Array of sort directives. Each entry: { "field": "", "desc": bool }. Allowed fields: date_posted, discovered_at, salary, job_title, company, num_jobs. Entries with any other field are dropped. `desc` defaults to true when omitted. start_date (string) — optional Earliest posted date the monitor tracks from. YYYY-MM-DD or ISO-like. Accepted but ignored on preview. expiration_date (string) — required on create only Stop monitoring after this date. YYYY-MM-DD or any ISO-like date string. Accepted but ignored on preview. Example: "2026-09-01" max_count (number) — optional Caps the number of postings imported per run. Must be a positive number. Omit to use the platform default. name (string) — required on create only Human-readable display name for the source. Example: "Snowflake hiring — US data leaders" Imported row fields (read-only — returned by preview and stored on create). Each job posting row carries job, location, salary, and company attributes, including: Job id Unique posting identifier job_title Posting title normalized_title Normalised job title url Posting URL final_url Canonical / employer apply URL source_url Original source URL date_posted Date the job was posted discovered_at When the posting was first discovered description Full job description text reposted Whether the posting is a repost date_reposted Repost date, if any easy_apply Whether one-click apply is available manager_roles Manager-role flag(s) matching_phrases Phrases that matched your filters matching_words Words that matched your filters job_technology_slugs Technologies detected on the posting keyword_slugs Keyword slugs detected seniority Seniority level employment_statuses Employment type(s) remote / hybrid Work-arrangement flags Location location, short_location, long_location, city, state_code, postal_code, country, country_code, countries, country_codes, cities, continents, latitude, longitude Salary salary_string, salary_currency, min_annual_salary, max_annual_salary, min_annual_salary_usd, max_annual_salary_usd, avg_annual_salary_usd Company company, company_domain, hiring_team, name, domain, industry, industry_id, company_country, company_country_code, employee_count, employee_count_range, logo, linkedin_url, linkedin_id, url_source, is_recruiting_agency, yc_batch, num_jobs, num_jobs_last_30_days, num_technologies, founded_year, annual_revenue_usd, annual_revenue_usd_readable, total_funding_usd, last_funding_round_date, last_funding_round_amount_readable, funding_stage, investors, publicly_traded_symbol, publicly_traded_exchange, company_keywords, company_tags, technology_slugs ================================================================================ 6. DYNAMIC OPTIONS ================================================================================ None. The `filters` object is free-form — there are no predefined option lists to resolve via `POST /api/v1/sources/track_job_postings/options/`. ================================================================================ 7. HOW TO CONFIGURE END-TO-END ================================================================================ Step 1 — Preview before committing POST /api/v1/sources/track_job_postings/preview Body: { "filters": { ...your ICP criteria... } } Check the returned `data[]` rows and `metadata.total_results`. Iterate the filter set until you are happy — preview never creates anything and does not consume credits. Step 2 — Create the source POST /api/v1/sources/track_job_postings Body: + `"name"`, `"expiration_date"`, and optionally `"start_date"` / `"max_count"`. Response: { "status": 201, "data": { "source_instance_id": "", ... } } Step 2b — (Optional) Poll imported postings after create GET /api/v1/sources//data?page_no=1&page_size=20 ( = UUID from Step 2) Row keys match preview. The count grows as the first fetch and later scheduled runs import new postings. Step 3 — Sync the source into a workflow POST /api/v1/sources//sync ( = UUID from Step 2 ) Build `field_mapping` from your workflow inputs to source row fields (common: `input.job_title`, `input.company`, `input.company_domain`, `input.url`, `input.location`). See concepts.txt §10 for the full source-agnostic sync semantics. The source keeps checking on a schedule until `expiration_date`. New postings discovered on each run are appended and pushed to connected workflows automatically. ================================================================================ 8. KEY NOTES ================================================================================ - No connection is required. There is no "connect first" gate. - Preview does not create anything and does not consume credits — credits are consumed per fetch only after create. - `filters` must contain at least one filter key, or create/preview return 400. - A posted-date lookback is always applied: defaulted when absent, capped at 180 days when supplied. - Scheduled runs import only postings newer than the previous run, so the same posting is never imported twice. - `order_by` entries with sort fields outside the allowed set are dropped silently rather than rejected. - If credit consumption fails during a scheduled run, the source may be paused. Top up credits and resume the source to continue. ================================================================================ 9. WHEN TO USE ================================================================================ - Hiring-intent prospecting: alert when target accounts post roles matching your ICP (titles + technologies + geography). - Account scoring: feed posting volume and seniority into a workflow that scores accounts by active hiring. - Competitive intelligence: track which companies are hiring for a specific technology or function over time. - Territory monitoring: scope `job_country_code_or` to your region and run an ongoing monitor to a 90-day `expiration_date`. When you instead want a one-time snapshot of current job postings rather than an ongoing monitor, use the `find_job_postings` source. ================================================================================ Last updated: 2026-06-02. Reference: https://floqer.com/docs/reference