Skip to content
API v1 preview — endpoints and fields may change before general availability.

Field dictionary

What does every field mean, how is it derived, and what do providers call it?

View .md

Every field BetterJobs returns, in one table. Field names are dotted paths as they appear in the API response: salary.min is min inside salary, and sources[].url is url inside each item of sources. The OpenAPI spec is the source of truth; this page is built from the same field list.

Filter by name, for example salary or seen. Each row has a stable anchor you can link to, such as #field-job-last_verified_at or #field-company-is_hiring-value.

FieldTypeDescriptionnull / [] meansDerivationExample
idstringCanonical job id (job_...). Stable across sources and requests.Never nullnormalized"job_01JC8X4M2Q7RV3T9KD5W6YH0AB"
titlestringJob title as posted.Never nullraw"Head of Revenue Operations"
company.idstringCanonical company id (cmp_...).Never nullnormalized"cmp_4Rk7TzP1aQ"
company.namestringCompany name.Never nullnormalized"Acme Robotics"
company.domainstring | nullPrimary web domain of the company.Unknown. No source reported it.normalized"acme-robotics.example"
location.citystring | nullCity.Unknown. No source reported it.normalized"Berlin"
location.regionstring | nullState, province or region.Unknown. No source reported it.normalized"Berlin"
location.country_codestring | nullISO 3166-1 alpha-2 country code.Unknown. No source reported it.normalized"DE"
location.remoteboolean | nulltrue remote, false on-site or hybrid.Unknown. Not the same as false.normalizedfalse
employment_typefull_time | part_time | contract | internship | temporary | nullEmployment type.Unknown. No source reported it.normalized"full_time"
seniorityintern | junior | mid | senior | lead | director | vp | c_level | nullSeniority level.Unknown. No source reported it.inferred"lead"
job_familystring | nullJob family, e.g. engineering, sales, operations.Unknown. No source reported it.inferred"operations"
salarySalary | nullPay range. See the salary.* fields.Unknown. No source reported pay.normalized{"min":110000,"max":135000,"currency":"EUR","period":"year","origin":"declared"}
salary.minnumber | nullLower bound in salary.currency per salary.period.Unknown lower bound.normalized110000
salary.maxnumber | nullUpper bound in salary.currency per salary.period.Unknown upper bound.normalized135000
salary.currencystringISO 4217 currency code.Never nullnormalized"EUR"
salary.periodyear | month | hourPay period.Never nullnormalized"year"
salary.origindeclared | inferreddeclared = stated in the posting. inferred = estimated by a source.Never nullnormalized"declared"
descriptionstring | nullPlain-text job description.Unknown. No source reported it.raw"Acme Robotics is hiring a Head of Revenue Operations..."
apply_urlstring | nullWhere a candidate applies.Unknown. No source reported it.raw"https://jobs.acme-robotics.example/revops-lead/apply"
posted_atdate-time | nullDate the employer posted the job.Unknown. Use first_seen_at instead.raw"2026-10-08T00:00:00Z"
first_seen_atdate-timeEarliest time any source saw the job.Never nullnormalized"2026-10-08T06:40:00Z"
last_seen_atdate-timeLatest time any source saw the job.Never nullnormalized"2026-10-11T06:10:00Z"
last_verified_atdate-time | nullLatest time the job was confirmed live at its origin.Never verified at origin.normalized"2026-10-11T06:10:00Z"
statusopen | closedLifecycle status.Never nullnormalized"open"
closed_reasonfilled | expired | removed | unknown | nullWhy the job closed.The job is open.normalizednull
repost_countintegerTimes the same job was re-listed.Never nullnormalized0
p_realnumber (0-1)Probability the job is a real open req, from cross-source corroboration.Never nullinferred0.94
sourcesSource[]Every provider that saw this job, with what it contributed.Never nullraw[{"provider":"theirstack",...}]
sources[].providerProviderSlugProvider slug.Never nullraw"theirstack"
sources[].provider_job_idstringThe provider's own id for this posting.Never nullraw"ts_88213377"
sources[].urlstring | nullPosting URL as this provider saw it.The provider did not report a URL.raw"https://jobs.acme-robotics.example/revops-lead"
sources[].first_seen_atdate-timeWhen this provider first saw the job.Never nullraw"2026-10-08T07:12:00Z"
sources[].last_seen_atdate-timeWhen this provider last saw the job.Never nullraw"2026-10-11T04:02:00Z"
sources[].fieldsstring[]Job fields this source contributed to the canonical record.[] = the source corroborated the job but contributed no field.raw["salary","seniority"]
license.displaybooleanYou may show this job to your end users.Never nullnormalizedtrue
license.resalebooleanYou may resell or redistribute this job as data.Never nullnormalizedfalse
companyCompanyCompany reference: id, name, domain.Never nullnormalized{"id":"cmp_4Rk7TzP1aQ","name":"Acme Robotics","domain":"acme-robotics.example"}
open_jobs_countintegerOpen canonical jobs right now.Never nullnormalized42
is_hiring.valueboolean | nullWhether the company is hiring.Unknown. Never treat null as false.inferredtrue
is_hiring.confidencenumber (0-1)Confidence in is_hiring.value.Never nullinferred0.96
is_hiring.basisstringPlain-English reason for the value.Never nullinferred"42 open jobs corroborated by 4 sources in the last 30 days"
hiring_pulse.directionup | flat | downDirection of open jobs over the last 30 days.Never nullinferred"up"
hiring_pulse.open_jobs_30d_changeintegerChange in open jobs over the last 30 days.Never nullnormalized9
top_job_families{job_family, open_jobs}[]Job families with the most open jobs.[] = no open jobs found.inferred[{"job_family":"engineering","open_jobs":18}]
sources{provider, open_jobs, last_seen_at}[]Open jobs per provider for this company.[] = no source sees this company.raw[{"provider":"theirstack","open_jobs":31,"last_seen_at":"2026-10-11T04:02:00Z"}]

For the same fields grouped with a record sample and coverage notes, see Jobs and Companies. Enum values are listed in Taxonomies.

The Derivation column tells you how much BetterJobs changed the value before returning it.

Derivation Meaning Trust it as
raw Passed through from a source as posted. What the posting says.
normalized Mapped to one format: ISO codes, BetterJobs enums, merged timestamps, canonical ids. The posting’s data in a consistent shape.
inferred Estimated from other data, for example seniority from the title or p_real from cross-source corroboration. A best estimate. Check it before you rely on it for hard filtering.

salary.origin adds a second layer for pay. declared means the posting stated it. inferred means a source estimated it.

The rule is the same for every field:

You see It means
null Unknown. No source reported it.
[] Verified none. For example top_job_families: [] means no open jobs found.
Field missing Not part of this payload, for example the lifecycle-only job in a job.closed event.

Fields marked Never null in the table always carry a value.

How often a field is non-null in your results is reported live in metadata.field_coverage. See Coverage.

Each partner provider names the same data differently. This table maps BetterJobs fields to the names each provider uses in its own documentation. Only fields with at least one confident equivalent are shown.

— = no confident one-to-one equivalent in that provider's published field names.
BetterJobsReqbeatSignalsAPITheirStackJobsPipeCoresignalTechmap
title——job_titlejob_title——
company.domain——company_domain———
location.remote——remote———
employment_type—————contractType
seniority——seniorityseniority——
salary——salary_stringsalary_usd——
salary.min——min_annual_salary_usd———
posted_at——date_posteddate_posted——
first_seen_at——discovered_atdiscovered_at——
last_seen_at———last_seen_at——
last_verified_at———verified_at——
closed_reason———closed_reason——
sources[].url——urlurl——
sources[].first_seen_at——discovered_atdiscovered_at——
sources[].last_seen_at—observed_at—last_seen_at——

Notes on the mapping:

  • One field, different units. TheirStack min_annual_salary_usd and JobsPipe salary_usd are in US dollars. BetterJobs keeps the posting’s currency in salary.currency and its period in salary.period.
  • Inverse scores. JobsPipe publishes a ghost_score, a measure of how likely a posting is a ghost job. BetterJobs p_real runs the opposite way: higher = more likely a real open req. Do not copy thresholds across.
  • Per-source vs canonical timestamps. A provider’s discovered_at maps to sources[].first_seen_at for that provider. The top-level first_seen_at is the earliest across all sources.
  • No equivalent (—) means we found no confident one-to-one match in the provider’s published names. It does not mean the provider lacks the data.

Moving from one provider? The migration guides translate queries as well as fields: TheirStack, JobsPipe, Coresignal, Techmap.