# Changelog


All notable changes to the Fantastic.jobs API will be documented here.

---

## 2026-06-05
- Added `x-api-next-billing-date` response header on all successful responses - an ISO-8601 (UTC) timestamp of your next billing date, when the current period's `Jobs` and `API Requests` quotas renew. See [Plans, Limits & Upgrades](/documentation/credit-usage#headers).
- Added `time_frame=1m` to [expired-ats](/api/expired-jobs#expired-ats-jobs) and [expired-jb](/api/expired-jobs#expired-job-board-jobs) for monthly expired-job reconciliation.

---

## 2026-06-03
- Added `linkedin_slug` and `linkedin_name` filters to [ats-organizations-advanced](/api/ats-organizations#advanced-organization-details) for fetching specific companies. Both accept a comma-separated list: `linkedin_slug` filters on `org_linkedin_slug` (unique, stable per company - recommended) and `linkedin_name` filters on `org_linkedin_name` (exact, case-sensitive match).

---

## 2026-06-01
- `exclude_ats_duplicate` (LinkedIn ↔ ATS deduplication) now includes country in both checks, and agency listings are now checked. Matching now uses title + organization name + country and title + LinkedIn company profile + country.

---

## v1 - Migrating from Rapid and api.fantastic.jobs
This is our first major refactor of the Fantastic.jobs API. Below we will describe all major changes. For a focused, field-by-field response-field migration cheat sheet, see [Field changes: old → new API](/documentation/field-changes-old-to-new).

### New Features
- [active-ats-count](/api/new-jobs#ats-jobs-count) and [active-jb-count](/api/new-jobs#job-board-jobs-count) (beta) - Return the total count of ATS / job board listings matching your parameters in the selected time window. No job rows are returned. Intended for selecting a subscription tier that matches your job volume - call with the new 'time_frame=1m' (jobs indexed during the last 31 days, the default) for a monthly estimate. Also accepts '1h', '24h', and '6m'. The endpoints accept the same parameters as [active-ats](/api/new-jobs#ats-jobs) / [active-jb](/api/new-jobs#job-board-jobs) except those that shape the response or paginate.  `description` / `description_advanced` are not available on 'time_frame=6m'. Each call consumes 1 API Request and 0 Jobs credits.
- Expanded `include_basic_organization_details=true` (replacement of include_li) on [active-ats](/api/new-jobs#ats-jobs) and [modified-ats](/api/modified-jobs#modified-ats-jobs) with four additional company fields: `org_linkedin_name`, `org_crunchbase_categories`, `org_crunchbase_total_investment`, and `org_logo_permalink`. These four fields are populated for newly indexed jobs only; backfilling them across the 'time_frame=6m' window is in progress.
- Added [ats-organizations](/api/ats-organizations#organization-list) - a slim catalog of every organization currently tracked across ATS sources (org name, derived domain, LinkedIn slug, name, industry, headcount, HQ). Intended for browsing the catalog and discovering valid `organization`, `organization_domain`, and `organization_slug` filter values - not an enrichment endpoint.
- Added [ats-organizations-advanced](/api/ats-organizations#advanced-organization-details) (beta) - returns advanced organization data including LinkedIn profile, Crunchbase funding & investment, Glassdoor ratings & reviews, headcount/follower/revenue timeseries, and news articles. Fixed at 100 results per page. Heavy nested fields are excluded by default and must be opted into via `include_crunchbase_funding_and_investment`, `include_linkedin_headcount_timeseries`, `include_linkedin_followers_timeseries`, `include_linkedin_estimated_revenue_timeseries`, `include_news_articles`, and `include_glassdoor_reviews`.
- Added `has_no_location` parameter to [active-ats](/api/new-jobs#ats-jobs), [active-jb](/api/new-jobs#job-board-jobs), [modified-ats](/api/modified-jobs#modified-ats-jobs), [active-ats-count](/api/new-jobs#ats-jobs-count), and [active-jb-count](/api/new-jobs#job-board-jobs-count). Set to 'true' to return only listings with no normalized location set (i.e. `locations_derived` is null) - useful for surfacing jobs whose source feed didn't include structured location data and would otherwise be missed by location-based searches. Omit (or pass 'false') to include all listings. 

### Breaking Changes
- Response field `id` is now returned as a numeric 'bigint' instead of a string.
- [active-ats](/api/new-jobs#ats-jobs) - Unified ATS endpoint replacing the separate 'active-ats-1h', 'active-ats-24h', 'active-ats-7d', and 'active-ats-6m' endpoints. Use the `time_frame` parameter to select the time window ('1h', '24h', '7d', '6m').
- [active-jb](/api/new-jobs#job-board-jobs) - Unified job board endpoint replacing the separate 'active-jb-hourly', 'active-jb-24h', 'active-jb-7d', and 'active-jb-6m' endpoints. Use the `time_frame` parameter to select the time window ('1h', '24h', '7d', '6m').
- **Expired feeds** - Unified expired endpoints replacing the separate 'ats-expired-1h', 'ats-expired-6m', 'jb-expired-1h', and 'jb-expired-6m' endpoints. Use [expired-ats](/api/expired-jobs#expired-ats-jobs) or [expired-jb](/api/expired-jobs#expired-job-board-jobs) with `time_frame` set to '1h' (rolling), '1d' (daily snapshot, refreshed at 01:00 UTC), or '6m'.
- Default `limit` is now 100, max increased to 1000 on [active-ats](/api/new-jobs#ats-jobs), [active-jb](/api/new-jobs#job-board-jobs), and [modified-ats](/api/modified-jobs#modified-ats-jobs). [ats-organizations-advanced](/api/ats-organizations#advanced-organization-details) is fixed at 100 per page.
- Removed `date_filter` parameter. Use `date_posted_gte` and `date_posted_lt` instead.
- Removed `remote` parameter and `remote_derived` response field. Use `ai_work_arrangement` instead, which provides a more comprehensive analysis ('Remote Solely', 'Remote OK', 'Hybrid', 'On-site') than the previous keyword-matching heuristic.
- Removed `organization_description` parameter.
- Removed `organization_specialties` parameter.
- Removed `include_ai` parameter. AI-enriched fields are now included by default.
- Renamed `include_li` to `include_basic_organization_details`
- Renamed query parameters for consistency:
  - `title_filter` -> `title`
  - `description_filter` -> `description`
  - `location_filter` -> `location`
  - `advanced_title_filter` -> `title_advanced`
  - `advanced_description_filter` -> `description_advanced`
  - `advanced_location_filter` -> `location_advanced`
  - `advanced_organization_filter` -> `organization_advanced`
  - `organization_filter` -> `organization`
  - `organization_exclusion_filter` -> `exclude_organization`
  - `domain_filter` -> `domain`
  - `domain_exclusion_filter` -> `exclude_domain`

  - `li_industry_filter` -> `organization_industry`
  - `li_organization_slug_filter` -> `organization_slug`
  - `li_organization_slug_exclusion_filter` -> `exclude_organization_slug`
  - `li_organization_employees_gte` -> `organization_headcount_gte`
  - `li_organization_employees_lte` -> `organization_headcount_lt` (note: bound is now exclusive - see below)
  - `ai_experience_level_filter` -> `ai_experience_level`
  - `ai_work_arrangement_filter` -> `ai_work_arrangement`
  - `ai_employment_type_filter` -> `ai_employment_type`
  - `ai_education_requirements_filter` -> `ai_education`
  - `ai_taxonomies_a_filter` -> `ai_taxonomies_a`
  - `ai_taxonomies_a_exclusion_filter` -> `exclude_ai_taxonomies_a`
  - `ai_taxonomies_a_primary_filter` -> `ai_taxonomies_a_primary`
  - `ai_visa_sponsorship_filter` -> `ai_visa_sponsorship`
  - `ai_has_salary` -> `has_salary`
  - `agency` -> `organization_agency`
  - `description_type` -> `description_format`
- Exclusion parameters now use the 'exclude_' prefix instead of the '_exclusion' suffix (e.g. `organization_exclusion` -> `exclude_organization`).
- New Tri-state parameters `organization_agency`, `direct_apply` (active-jb only), and `ai_visa_sponsorship` no longer accept 'true'/'false'. They now take an enum of 'only' or 'exclude'; omit the parameter to include both. (e.g. '?organization_agency=only' returns only agency listings, '?organization_agency=exclude' returns only non-agency listings, omitting it returns both.)
- Renamed `directapply` to `direct_apply` for snake_case consistency. This applies to both the query parameter on [active-jb](/api/new-jobs#job-board-jobs) and the response field on 'ActiveJbJob'. The wire format is otherwise unchanged.
- Renamed response field `org_linkedin_url` to `org_linkedin_website` on [active-ats](/api/new-jobs#ats-jobs), [active-jb](/api/new-jobs#job-board-jobs), and [modified-ats](/api/modified-jobs#modified-ats-jobs). The value is the company's website (e.g. 'https://example.com'), not the LinkedIn profile URL - the new name reflects the actual data and matches the field name on [ats-organizations-advanced](/api/ats-organizations#advanced-organization-details). On [ats-organizations-advanced](/api/ats-organizations#advanced-organization-details), `org_linkedin_url` (the LinkedIn profile URL) and `org_linkedin_website` (the company website) remain as two distinct fields.
- Deprecated response field `organization_logo` on [active-ats](/api/new-jobs#ats-jobs) and [modified-ats](/api/modified-jobs#modified-ats-jobs). The ATS-supplied URL can break or expire over time. Use `org_logo_permalink` instead. `organization_logo` continues to be returned without a flag in the meantime. [active-jb](/api/new-jobs#job-board-jobs) keeps `organization_logo` as the primary logo field.
- Dropped the '_raw' suffix from source-supplied response fields. `locations_raw` -> `locations`, `locations_alt_raw` -> `locations_alt` (active-ats and modified-ats only; not present on active-jb), `location_requirements_raw` -> `location_requirements`, `salary_raw` -> `salary`. The '_raw' suffix was redundant given the existing convention ('_derived' for normalized values, 'ai_' for AI-extracted, 'org_' for organization context, bare name for source-of-truth). Applies to [active-ats](/api/new-jobs#ats-jobs), [active-jb](/api/new-jobs#job-board-jobs), and [modified-ats](/api/modified-jobs#modified-ats-jobs).
- Renamed response fields to proper snake_case:
  - `date_validthrough` → `date_valid_through`
  - `ai_salary_minvalue` → `ai_salary_min_value`
  - `ai_salary_maxvalue` → `ai_salary_max_value`
  - `ai_salary_unittext` → `ai_salary_unit_text`
  - `ai_education_requirements` → `ai_education`
  - `linkedin_org_foundeddate` → `org_linkedin_founded_date`
- Renamed all 'linkedin_org_' response field prefixes to 'org_linkedin_' to group organization fields by entity. This applies to all LinkedIn organization fields (e.g., `linkedin_org_slug` → `org_linkedin_slug`, `linkedin_org_employees` → `org_linkedin_headcount`, etc.).
- Renamed `org_linkedin_employees` response field and `organization_employees_gte` / `organization_employees_lte` filter parameters to `org_linkedin_headcount`, `organization_headcount_gte`, and `organization_headcount_lt`.
- All range parameters now follow a consistent '_gte' (inclusive lower) + '_lt' (exclusive upper) convention. The previous `organization_headcount_lte` (inclusive upper) has been replaced by `organization_headcount_lt` (exclusive upper); to keep the same result set, increment the value by 1 (e.g. 'organization_headcount_lte=100' → 'organization_headcount_lt=101').
- Added `exclude_organization_industry` parameter to [active-ats](/api/new-jobs#ats-jobs), [active-jb](/api/new-jobs#job-board-jobs), and [modified-ats](/api/modified-jobs#modified-ats-jobs) for parity with `organization_industry` (matches the existing `organization`/`exclude_organization`, `domain`/`exclude_domain`, `source`/`exclude_source`, `organization_slug`/`exclude_organization_slug` pattern).
- Removed `advanced_organization_description_filter` parameters.
- [active-jb](/api/new-jobs#job-board-jobs) - additional parameter and field changes:
  - `source` parameter now supports multiple values (comma-separated) instead of single value.
  - Removed `has_external_apply` query parameter and `external_apply_url` response field. The LinkedIn job `url` remains the canonical apply entry point. Note that `direct_apply` is a separate signal from LinkedIn (whether the job offers in-platform "Easy Apply") and is not an inverse of having an external apply URL - it remains available as both a filter and a response field.
  - Renamed `recruiter` toggle to `exclude_recruiter_fields` (polarity flipped: default is still to include the three recruiter fields; pass 'exclude_recruiter_fields=true' to drop them).
  - Renamed `type_filter` to `employment_type`.
  - Renamed `seniority_filter` to `seniority`.
  - Added `exclude_organization`, `exclude_source`, `ai_education`, `ai_employment_type` parameters.
  - Same parameter naming conventions as ATS (dropped '_filter' suffixes, 'organization_' prefix for LinkedIn params, '_advanced' suffix for FTS).
  - Same limit/offset, snake_case renames, and 'org_linkedin_' prefix changes as ATS.
- [active-jb](/api/new-jobs#job-board-jobs) - `employment_type` filter is deprecated and will be removed in a future version. Use `ai_employment_type` instead, which provides normalized, market-independent values now that every job is AI-analysed.

### Minor Changes
- For [active-ats](/api/new-jobs#ats-jobs), `date_modified` and `modified_fields` are only available when 'time_frame=6m'.
- Description search (`description`, `description_advanced`) is not available with 'time_frame=6m' on [active-jb](/api/new-jobs#job-board-jobs), [active-ats-count](/api/new-jobs#ats-jobs-count), and [active-jb-count](/api/new-jobs#job-board-jobs-count) (returns 400). It remains allowed on [active-ats](/api/new-jobs#ats-jobs).
- `org_linkedin_slug` is now always included so jobs can be matched to advanced company details, even when `include_basic_organization_details` is not set.
