Job Schema
Every field returned for a job, plus the response metadata.
POST /v1/jobs/search returns { metadata, data }, where data is an array of job objects. Every job has the same shape whatever its source. Most fields are null when the source does not supply them.
Metadata
| Field | Type | Description |
|---|---|---|
total_results | number | null | Total matches. null unless include_total_results was set. |
truncated_results | number | Number of jobs returned in this data array. |
total_companies | number | null | Total distinct companies across matches, when computed. |
truncated_companies | number | Distinct companies in this page. |
next_cursor | string | null | Cursor for the next page, or null if there are no more results. |
credits_charged, jobs_already_paid, credits_remaining, credits_allowance | number | What the call cost and what is left. See jobs search. |
Identity & links
| Field | Type | Description |
|---|---|---|
id | string | number | Stable ID of the posting on its source. Store it to look the job up later. |
job_title | string | The posting's job title. |
normalized_title | string | null | Title normalized to a canonical form. |
url | string | null | Canonical posting URL. |
final_url | string | null | Always null. See reserved fields. |
source_url | string | null | URL on the source the job was first seen on. |
sources | object[] | Every source the job has been seen on. |
company | string | null | Hiring company name. |
company_domain | string | null | Company website domain, for CRM and account matching. |
company_object | object | null | Structured company details, or null when nothing beyond the name is known. |
id is the posting's ID on its source, so its format varies (a number, a UUID, a hex string). Treat it as an opaque string.
A role listed on two boards is returned as one record, attributed to one source. Look it up by that source's ID; the other board's ID returns nothing.
company_object
| Field | Type | Description |
|---|---|---|
name | string | null | Company name. |
domain | string | null | Bare website host, e.g. stripe.com. |
url | string | null | Company website. |
logo | string | null | Logo image URL. |
employee_count | number | null | Headcount. May be an estimate. |
employee_count_min | number | null | Lower bound when only a size band is known (10000 for "10,000+"). |
linkedin_url | string | null | Company LinkedIn page. |
description | string | null | Company description. |
location | object | null | Headquarters: street, city, region, postal_code, country. |
founded | string | null | Year the company was founded, where known. |
intelligence | object | null | Revenue, legal identity and entity type of the employer. See below. |
Every field can be null on its own, so a job may carry a domain and a logo but no employee_count. The object is null when nothing beyond the name is known, so if (job.company_object) is a safe test.
company_object.intelligence
The employer as a business: revenue, type of organisation and legal identity. It is resolved in the posting's country, so the same name in two countries can carry two different records.
| Field | Type | Description |
|---|---|---|
revenue_usd | number | null | Most recent known annual revenue, converted to US dollars. |
revenue_year | number | null | Fiscal year the revenue figure refers to. |
revenue_source | string | null | Short identifier of the revenue figure's origin. |
revenue_confidence | string | null | How the figure was obtained. One of the values below. |
entity_kind | string | null | company, branch, public_sector or staffing_agency. |
founded_year | number | null | Year the legal entity was founded or registered. |
headcount | number | null | Employee count recorded for the legal entity. Can differ from employee_count. |
industry | string | null | Industry of the legal entity. |
hq_region | string | null | Region or state of the headquarters, e.g. California. |
hq_city | string | null | City of the headquarters. |
revenue_low_usd | number | null | Lower bound of the revenue range in US dollars, when a range is known. |
revenue_high_usd | number | null | Upper bound of the revenue range in US dollars, when a range is known. |
headcount_low | number | null | Lower bound of the headcount range, when a range is known. |
headcount_high | number | null | Upper bound of the headcount range, when a range is known. |
lei | string | null | The company's Legal Entity Identifier (ISO 17442), 20 characters. |
legal_name | string | null | The registered legal name of the entity lei identifies. |
group_lei | string | null | The LEI of the corporate group the company belongs to: its ultimate parent, or its direct parent when no ultimate parent is recorded. |
group_name | string | null | The registered legal name of the entity group_lei identifies. |
revenue_confidence tells you how far to trust revenue_usd, strongest first:
| Value | Meaning |
|---|---|
filed | Taken from the company's statutory accounts. |
reported | Stated by the company itself. |
band | Only an estimated range is known; revenue_usd is a representative figure within it. |
derived | Estimated from funding or valuation. |
extracted | Read from public text about the company. |
"intelligence": {
"revenue_usd": 12500000,
"revenue_year": 2025,
"revenue_source": null,
"revenue_confidence": "filed",
"entity_kind": "company",
"founded_year": 1998,
"headcount": 140,
"industry": "Software publishing",
"hq_region": "California",
"hq_city": "South San Francisco",
"revenue_low_usd": null,
"revenue_high_usd": null,
"headcount_low": null,
"headcount_high": null,
"lei": "5493001KJTIIGC8Y1R12",
"legal_name": "EXAMPLE SOFTWARE INC.",
"group_lei": "213800ABCDEFGHIJKL12",
"group_name": "EXAMPLE HOLDINGS PLC"
}intelligence is null when there is no record for the company in that country. Inside it, every field is null when unknown: a company with no disclosed revenue still carries its entity_kind and lei, and a company known only by its legal entity still has an intelligence object.
The legal-entity fields are null when:
leiandlegal_name: we have not identified the company's legal entity in the posting's country.group_leiandgroup_name: the company has no recorded parent, orleiisnull. A company that heads its own group can carry its own LEI asgroup_lei.
To search by LEI, including every company of a group, use lei_or.
sources
| Field | Type | Description |
|---|---|---|
provider | string | Source name, e.g. linkedin, greenhouse. |
url | string | null | The posting's URL on that source. |
seen_at | string | null | When the job was seen on that source. |
sources is present on every job and normally holds one entry. Read it as an array, but do not expect it to list every board a role appears on. source_url matches sources[0].url.
Dates & lifecycle
| Field | Type | Description |
|---|---|---|
date_posted | string | null | When the job was posted, in the source's own format. |
discovered_at | string | null | When JobsPipe first ingested the posting. |
last_seen_at | string | null | When we last saw the posting live, on a collection run or a recheck (YYYY-MM-DD HH:MM:SS, UTC). Usually null once the posting is closed. |
verified_at | string | null | When we last updated the posting's status: a collection run, a recheck or a close (YYYY-MM-DD HH:MM:SS, UTC). |
status | string | active or closed. Only active postings are returned unless the status filter says otherwise. |
closed_at | string | null | When the posting was detected closed. |
closed_reason | string | null | Why it closed: closed, gone or stale. |
reposted | boolean | Whether the role was reposted. |
date_reposted | string | null | Always null. See reserved fields. |
has_blurred_data | boolean | Deprecated. Always false: preview mode has been removed. |
To tell whether a posting is still open, read status and closed_at. Don't compare verified_at with last_seen_at: on an open posting they describe the same check and can differ by minutes to hours, and a check that fails to reach the source is not recorded at all.
Timestamp formats differ. last_seen_at, verified_at and closed_at are UTC YYYY-MM-DD HH:MM:SS. discovered_at and sources[].seen_at are ISO-8601 with an offset. date_posted is as the source publishes it, usually ISO-8601 but sometimes a bare YYYY-MM-DD, so accept both.
Location
| Field | Type | Description |
|---|---|---|
location | string | null | Display location string. |
short_location | string | null | Condensed location. |
long_location | string | null | Full location string. |
country | string | null | Primary country name. |
country_code | string | null | Primary ISO country code. |
countries | string[] | All associated country names. |
country_codes | string[] | All associated ISO country codes. |
cities | string[] | Every city the posting names, primary first (a multi-location posting lists them all). |
continents | string[] | Associated continents. |
state_code | string | null | State or region, exactly as the source wrote it, so one response can carry CA for one posting and California for another. See normalized_region for the resolved code. |
postal_code | string | null | Postal code. |
latitude | number | null | Latitude of the job's location: the source's coordinates for the posting, or else the centre of its city. null when there are none. |
longitude | number | null | Longitude, under the same rules as latitude. |
coordinates_source | string | null | "source" (published with the posting) or "city_centroid" (the centre of the posting's city, not the workplace address). null when there are no coordinates. |
remote | boolean | null | Remote flag. |
hybrid | boolean | null | Hybrid flag. |
work_arrangement | string | null | "remote", "hybrid" or "onsite"; null when the posting doesn't say. |
work_arrangement_source | string | null | How work_arrangement was decided: "source" (declared by the job board) or "text" (parsed from the description). |
metro_code | string | null | US CBSA metro code resolved from the job's location. null outside covered metros. |
metro_label | string | null | Metro display name for metro_code, e.g. New York-Newark-Jersey City, NY-NJ. |
normalized_city | string | null | The city the posting's location names, in one canonical spelling: Munich for a posting stored as München, London for London Area or Mayfair. null when the location could not be placed (a region or placeholder in the city field). city_or matches on it. |
normalized_region | string | null | state_code resolved to an ISO 3166-2 code, e.g. US-CA whether the source wrote CA or California. null when it could not be resolved. Use it to group or filter in your own code. |
remote reads false for hybrid and onsite alike; work_arrangement separates them, and hybrid always agrees with it. Filter with work_arrangement_or. See field coverage.
Compensation
Pay is present only when the posting discloses it (roughly a quarter of postings). min_annual_salary and max_annual_salary are annualized (hourly, daily, weekly and monthly rates are scaled to a year); salary_string keeps the original text. The _usd fields convert other currencies at a fixed snapshot of European Central Bank rates, so treat them as approximate. They are null when the currency has no rate.
| Field | Type | Description |
|---|---|---|
salary_string | string | null | Pay as written in the posting, e.g. $120K - $150K a year. |
salary_currency | string | null | ISO 4217 currency code, e.g. USD, GBP, EUR. |
min_annual_salary | number | null | Minimum pay annualized, in the original currency. |
max_annual_salary | number | null | Maximum pay annualized, in the original currency. |
min_annual_salary_usd | number | null | min_annual_salary in USD, converted at the pinned ECB rate for non-USD pay; null when the currency has no rate. |
max_annual_salary_usd | number | null | max_annual_salary in USD, converted the same way. |
avg_annual_salary_usd | number | null | Midpoint of the USD min and max, or the single known bound when only one is present. |
salary_source | string | null | Where the salary came from: "source" (structured data from the board) or "description" (parsed from the posting text). |
salary_type | string | null | "observed" when the posting itself carries pay, "estimated" when only the corpus benchmark does, null when neither. |
estimated_min_annual_salary_usd | number | null | 25th-percentile annual USD benchmark for this occupation and location. |
estimated_avg_annual_salary_usd | number | null | Median benchmark. |
estimated_max_annual_salary_usd | number | null | 75th-percentile benchmark. |
The estimated_* fields are a benchmark, not the employer's pay: percentiles of annual USD pay for the job's occupation and location, from public salary statistics or from pay posted for the same occupation in that country. They never replace observed pay; salary_type says which a job carries. The min_salary_usd filter uses observed pay only.
Classification & content
| Field | Type | Description |
|---|---|---|
seniority | string | null | One of entry_level, mid_level, senior, director, executive. |
seniority_source | string | null | How seniority was decided: "source", "title" or "onet_prior" (inferred from the occupation). |
is_manager | boolean | null | Whether the role manages people. |
job_function | string | null | Broad function of the role, e.g. Engineering. |
language | string | null | Language the posting text is written in, as a lowercase ISO 639-1 code, e.g. en. null until labelled. |
employer_type | string | Who posted the job: employer, agency or broker. |
employment_statuses | string[] | Employment types, e.g. ["full_time"]. |
easy_apply | boolean | null | Always null. See reserved fields. |
technologies | object[] | Technologies the posting names, graded. Returned only when the request sets include_technologies: true, and then on every job; empty until the posting has been extracted. Each job that names at least one costs 1 extra credit, once per calendar month. Sorted required, preferred, mentioned, then confidence high to low, then name. See technologies. |
technology_slugs | string[] | Ungraded list of named technologies (languages, frameworks, products, tools, platforms, standards, certifications), e.g. python, snowflake, soc2. Broader skills such as ci/cd appear only in keyword_slugs. Prefer technologies. |
keyword_slugs | string[] | Skill slugs extracted from title + description against a curated lexicon. |
esco_skills | object[] | ESCO skill concepts for the extracted skills, as stable { id, label } pairs. Filter on them with esco_skill_id_or. |
occupation_code | string | null | ISCO-08 unit group of the role (4-digit), e.g. 2512. |
occupation_label | string | null | Human-readable ISCO-08 label, e.g. Software Developers. |
isic_division | string | null | ISIC Rev.4 industry division of the employer (2-digit), e.g. 62. |
isic_division_label | string | null | Human-readable ISIC division label. |
hiring_team | array | Always empty. See reserved fields. |
description | string | null | Full job description. |
matching_phrases | string[] | Always empty. |
matching_words | string[] | Always empty. |
employer_type is classified per company. A company not yet classified is returned as "employer". See employer type.
seniority: "director" also covers lead, staff and principal individual contributors. Use is_manager to tell them apart: a principal engineer with no reports is false, an actual director is true, and null means unknown.
language is the language the posting is written in, not the language of its country. Filter with language_or / language_not.
technologies
Opt-in: send include_technologies: true on POST /v1/jobs/search and every job carries this list; without it the field is absent. Each returned job that names at least one technology costs 1 extra credit, once per job per calendar month. See billing for technologies.
| Field | Type | Description |
|---|---|---|
slug | string | Taxonomy slug, e.g. snowflake, .net. |
name | string | Display name, e.g. Snowflake. |
kind | string | product, language, framework, methodology, certification or standard. |
category | string | e.g. Databases; empty string when unknown. |
parent_category | string | e.g. Software and tools; empty string when unknown. |
logo | string | null | Absolute URL of the technology's logo; null when there is none. |
strength | string | required (asked for), preferred (nice to have) or mentioned (named, not asked for). |
confidence | string | high when independent checks agree the posting names it; medium when it is required or in the title; low otherwise. |
sections | string[] | Posting sections it appears in, e.g. ["requirements"]. |
in_title | boolean | Whether the job title names it. |
terms | string[] | Case-insensitive text forms that find the mention in description. |
terms_cs | string[] | Case-sensitive text forms, e.g. Go, R. |
Hiring signals
| Field | Type | Description |
|---|---|---|
visa_sponsorship | string | null | Visa stance parsed from the posting: "offers", "no" or "citizenship_required". null where the posting says nothing. |
benefits | string[] | Benefit slugs (health_insurance, 401k, ...) from a source's structured benefit fields. Empty where the source publishes none. |
applicant_count | number | null | Number of applicants, where the source publishes it. |
recruiter_emails | string[] | Recruiter contact emails parsed from the posting text. |
listing_type | string | null | How the posting was listed where the source exposes it. |
expires_at | string | null | Application deadline where the source publishes one (YYYY-MM-DD HH:MM:SS, UTC). |
ghost_score | number | null | 0-100 likelihood the posting is stale or evergreen rather than a live vacancy. null until scored. |
ghost_score is built from repost cadence, how long the posting has been up, and its content: 0 reads as a live vacancy, 100 as almost certainly not one. The max_ghost_score filter lets unscored jobs pass.
Field coverage
For a live figure on the fields a search filters on, read metadata.field_coverage in the response (see unknown values & coverage).
The table below is a sample of 500 recent postings (September 2026) from a broad query. Coverage varies by source, so a query narrowed to one source can differ a lot.
| Field | Populated |
|---|---|
sources, description | ~100% |
country, countries, country_code, continents | 97% |
remote | 91% |
state_code | 82% |
latitude, longitude | 78% |
keyword_slugs | 76% |
cities | 74% |
employment_statuses, last_seen_at, verified_at | 67% |
esco_skills | 52% |
min_annual_salary_usd | 47% |
postal_code | 42% |
company_object, company_domain | 38-40% |
occupation_code, isic_division | 38% |
technology_slugs | 36% |
metro_code, metro_label | 24% |
salary_string | 20% |
normalized_title, job_function | 18% |
work_arrangement, hybrid | 17% |
ghost_score | 14% |
seniority | 10% |
is_manager, recruiter_emails | 4% |
visa_sponsorship | 2% |
applicant_count, benefits, expires_at, listing_type | ~0% |
latitude and longitude come either from the source (coordinates_source: "source") or from the centre of the posting's city ("city_centroid"), which may be many kilometres from the workplace. No centroid is set for a country, a state, a metro area or Remote, or for the city-states (Singapore, Hong Kong, Macau).
Reserved for compatibility
These fields are always present and always empty:
| Field | Value | Use instead |
|---|---|---|
final_url | null | url, or source_url for the link on the source. |
easy_apply | null | - |
hiring_team | [] | - |
date_reposted | null | reposted, which is populated. |
matching_phrases | [] | - |
matching_words | [] | - |
Do not branch on them.
New fields are added over time. Ignore fields you don't recognise and read only the ones you need.
Data attributions
Some derived fields use public datasets:
esco_skillsuses the ESCO classification (© European Union, CC BY 4.0).seniority_source: "onet_prior"levels derive from the O*NET database by the U.S. Department of Labor, Employment and Training Administration (CC BY 4.0).estimated_*_annual_salary_usdbenchmarks derive from U.S. Bureau of Labor Statistics OEWS data andmetro_codefrom U.S. Census Bureau CBSA delineations (both public domain).- City-centre coordinates (
coordinates_source: "city_centroid") use the GeoNames geographical database (CC BY 4.0).