Properties
| Name | Type | Description |
|---|---|---|
| public_slug | string | Stable public identifier. The freehire page is https://freehire.me/jobs/{public_slug}. |
| title | string | |
| company | string | |
| company_slug | string | |
| url | string | The employer's own application URL. This is where an applicant goes. Empty when `direct_apply` is true: that vacancy has no page elsewhere. |
| direct_apply | boolean | True for a vacancy its employer published on freehire that takes applications only on its freehire page (`https://freehire.me/jobs/{slug}`). Absent for every other posting. |
| location | string | The posting's own location string, verbatim and unnormalized. Filter on the geography facets instead. |
| source | string | Origin slug — the ATS or board this posting was crawled from. |
| external_id | string | The source's own identifier for the posting. |
| application_deadline | string | Source-stated last application day, inclusive. Absent when the source states no deadline. |
| manually_added | boolean | True for a hand-curated posting rather than an automated crawl. |
| description | string | Stored verbatim HTML by default. `searchJobs` serves a truncated preview; `agentSearchJobs` and `getJob` serve the full body, and `agentSearchJobs` can convert it via `description_format`. |
| regions | array | |
| countries | array | |
| cities | array | |
| metros | array | |
| work_mode | string | Absent when the posting's format could not be resolved. |
| skills | array | |
| collections | array | Curated collection slugs of the posting's company. |
| is_tech | string | Absent when unknown. |
| requires_clearance | boolean | Present and `true` only when the posting states a government security-clearance requirement. Absent otherwise — there is no `false`, because "no requirement was detected" is not the same claim as "thi |
| via_recruiter | boolean | Present and `true` only when the posting states that it is published by an intermediary on a client's behalf. Absent otherwise — a recruiter who never says so is not detected, so absence does not mean |
| equity | string | What the posting states about equity compensation: `salary_and_equity` (offered beside cash pay) or `equity_only` (equity is the whole pay). Absent when the posting states neither — "not stated", not |
| clearance_levels | array | The security-clearance levels the posting states. Present exactly when `requires_clearance` is, absent otherwise. `other` is a non-US scheme or a clearance stated with no level. |
| perks | array | Benefits the description states it offers (see the `perks` filter for the vocabulary). Empty when it names none of them — not a claim that the job offers none. |
| engagement | array | The legal terms the posting states it engages its worker on (see the `engagement` filter for the vocabulary). Empty when it does not say. |
| auto_apply_available | boolean | Present and `true` only when the posting's ATS provider is one freehire's auto-apply feature can currently attempt to fill and submit for. Absent otherwise — a best-effort provider-eligibility signal, |
| apply_questions | integer | How many questions the posting's application form REQUIRES beyond the standard fields every form asks for (name, contact details, CV, cover letter), counted from the form freehire captured from the em |
| posted_at | stringnull | |
| created_at | stringnull | When freehire first saw the posting. |
| updated_at | stringnull | |
| last_seen_at | stringnull | When a re-crawl last confirmed the posting was still live. |
| closed_at | stringnull | Non-null once the posting is no longer open. Only `getJob` ever serves such a row. |
| enrichment | object | |
| enriched_at | stringnull | |
| enrichment_version | integernull | Bumped when the enrichment contract changes — use it to detect re-enriched rows. |
| my_vote | integernull | The calling user's vote. Always null on this unauthenticated schema. |
| reality | object | |
| ghost | object | |
| view_count | integer | |
| applied_count | integer | |
| upvote_count | integer | |
| downvote_count | integer |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/freehire-me/json-schema/freehire-me-job-schema.json",
"title": "Job",
"x-generated": "2026-11-09",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/_original/freehire-me-api-openapi.yml#/components/schemas/Job",
"type": "object",
"additionalProperties": true,
"required": [
"public_slug",
"title",
"company"
],
"properties": {
"public_slug": {
"type": "string",
"description": "Stable public identifier. The freehire page is https://freehire.me/jobs/{public_slug}."
},
"title": {
"type": "string"
},
"company": {
"type": "string"
},
"company_slug": {
"type": "string"
},
"url": {
"type": "string",
"description": "The employer's own application URL. This is where an applicant goes.\nEmpty when `direct_apply` is true: that vacancy has no page elsewhere.\n"
},
"direct_apply": {
"type": "boolean",
"description": "True for a vacancy its employer published on freehire that takes\napplications only on its freehire page (`https://freehire.me/jobs/{slug}`).\nAbsent for every other posting.\n"
},
"location": {
"type": "string",
"description": "The posting's own location string, verbatim and unnormalized. Filter on the geography facets instead."
},
"source": {
"type": "string",
"description": "Origin slug — the ATS or board this posting was crawled from."
},
"external_id": {
"type": "string",
"description": "The source's own identifier for the posting."
},
"application_deadline": {
"type": "string",
"format": "date",
"description": "Source-stated last application day, inclusive. Absent when the source states no deadline."
},
"manually_added": {
"type": "boolean",
"description": "True for a hand-curated posting rather than an automated crawl."
},
"description": {
"type": "string",
"description": "Stored verbatim HTML by default. `searchJobs` serves a truncated\npreview; `agentSearchJobs` and `getJob` serve the full body, and\n`agentSearchJobs` can convert it via `description_format`.\n"
},
"regions": {
"type": "array",
"items": {
"type": "string"
}
},
"countries": {
"type": "array",
"items": {
"type": "string"
}
},
"cities": {
"type": "array",
"items": {
"type": "string"
}
},
"metros": {
"type": "array",
"items": {
"type": "string"
}
},
"work_mode": {
"type": "string",
"enum": [
"remote",
"hybrid",
"onsite"
],
"description": "Absent when the posting's format could not be resolved."
},
"skills": {
"type": "array",
"items": {
"type": "string"
}
},
"collections": {
"type": "array",
"items": {
"type": "string"
},
"description": "Curated collection slugs of the posting's company."
},
"is_tech": {
"type": "string",
"enum": [
"tech",
"non_tech"
],
"description": "Absent when unknown."
},
"requires_clearance": {
"type": "boolean",
"description": "Present and `true` only when the posting states a government\nsecurity-clearance requirement. Absent otherwise — there is no\n`false`, because \"no requirement was detected\" is not the same claim\nas \"this posting needs no clearance\".\n"
},
"via_recruiter": {
"type": "boolean",
"description": "Present and `true` only when the posting states that it is published\nby an intermediary on a client's behalf. Absent otherwise — a\nrecruiter who never says so is not detected, so absence does not\nmean the employer posted it.\n"
},
"equity": {
"type": "string",
"enum": [
"salary_and_equity",
"equity_only"
],
"description": "What the posting states about equity compensation:\n`salary_and_equity` (offered beside cash pay) or `equity_only`\n(equity is the whole pay). Absent when the posting states neither —\n\"not stated\", not \"no equity\".\n"
},
"clearance_levels": {
"type": "array",
"items": {
"type": "string",
"enum": [
"confidential",
"secret",
"top_secret",
"ts_sci",
"public_trust",
"interim",
"other"
]
},
"description": "The security-clearance levels the posting states. Present exactly\nwhen `requires_clearance` is, absent otherwise. `other` is a non-US\nscheme or a clearance stated with no level.\n"
},
"perks": {
"type": "array",
"items": {
"type": "string"
},
"description": "Benefits the description states it offers (see the `perks` filter\nfor the vocabulary). Empty when it names none of them — not a claim\nthat the job offers none.\n"
},
"engagement": {
"type": "array",
"items": {
"type": "string"
},
"description": "The legal terms the posting states it engages its worker on (see\nthe `engagement` filter for the vocabulary). Empty when it does not\nsay.\n"
},
"auto_apply_available": {
"type": "boolean",
"description": "Present and `true` only when the posting's ATS provider is one\nfreehire's auto-apply feature can currently attempt to fill and\nsubmit for. Absent otherwise — a best-effort provider-eligibility\nsignal, never a guarantee of successful submission.\n"
},
"apply_questions": {
"type": "integer",
"minimum": 0,
"description": "How many questions the posting's application form REQUIRES beyond the\nstandard fields every form asks for (name, contact details, CV, cover\nletter), counted from the form freehire captured from the employer's\nATS. Optional questions, the equal-opportunity survey and consent boxes\nare not counted. `0` means no REQUIRED question beyond the basics\n(the form may still offer optional ones). Absent when freehire holds\nno form for the posting (none captured from its ATS, and none written\nfor a vacancy taking applications on freehire) — \"not known\", never\n\"long\".\nServed by search hits and the job detail; a list read straight from\nthe database may omit it.\n"
},
"posted_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"created_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When freehire first saw the posting."
},
"updated_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_seen_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When a re-crawl last confirmed the posting was still live."
},
"closed_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "Non-null once the posting is no longer open. Only `getJob` ever serves such a row."
},
"enrichment": {
"$ref": "#/$defs/Enrichment"
},
"enriched_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"enrichment_version": {
"type": [
"integer",
"null"
],
"description": "Bumped when the enrichment contract changes — use it to detect re-enriched rows."
},
"my_vote": {
"type": [
"integer",
"null"
],
"description": "The calling user's vote. Always null on this unauthenticated schema."
},
"reality": {
"$ref": "#/$defs/Reality"
},
"ghost": {
"$ref": "#/$defs/Ghost"
},
"view_count": {
"type": "integer"
},
"applied_count": {
"type": "integer"
},
"upvote_count": {
"type": "integer"
},
"downvote_count": {
"type": "integer"
}
},
"$defs": {
"Enrichment": {
"type": "object",
"additionalProperties": true,
"description": "Model-extracted attributes, every field omitted when the posting did not\nstate it. `work_mode`, `regions`, `countries`, `cities` and `skills` are\ndeliberately NOT here — those are served top-level from the\ndeterministic dictionaries, and the model's own values for them are not\npublished.\n",
"properties": {
"summary": {
"type": "string",
"description": "The one synthesized field — a 1-2 sentence synopsis, always present on an enriched posting."
},
"employment_type": {
"type": "string"
},
"relocation": {
"type": "string"
},
"visa_sponsorship": {
"type": "boolean"
},
"timezone_note": {
"type": "string"
},
"salary_min": {
"type": "integer"
},
"salary_max": {
"type": "integer"
},
"salary_currency": {
"type": "string"
},
"salary_period": {
"type": "string"
},
"seniority": {
"type": "string"
},
"experience_years_min": {
"type": "integer"
},
"english_level": {
"type": "string"
},
"education_level": {
"type": "string"
},
"category": {
"type": "string"
},
"domains": {
"type": "array",
"items": {
"type": "string"
}
},
"posting_language": {
"type": "string"
},
"company_type": {
"type": "string"
},
"company_size": {
"type": "string"
}
}
},
"Ghost": {
"type": [
"object",
"null"
],
"additionalProperties": true,
"description": "Hedged \"is anyone actually hiring for this\" verdict, raised only when\nevidence fires — most postings carry `null`, so an absent value means\n\"no signal\", never \"verified real\".\n\nAttached by `searchJobs`, `getJob` and the plain jobs list. NOT attached\nby `agentSearchJobs` or `getSimilarJobs`, so its absence on those two is\nnot evidence either way.\n",
"properties": {
"level": {
"type": "string",
"description": "How strongly the evidence reads, e.g. `possible`."
},
"criteria": {
"type": "array",
"items": {
"type": "string"
},
"description": "Which criteria fired, e.g. `evergreen_posting`, `ats_absent`."
},
"criteria_total": {
"type": "integer",
"description": "How many criteria exist, so `criteria` reads as N-of-total."
},
"contributors": {
"type": "integer",
"description": "Number of independent user reports, once past the disclosure gate."
},
"ats_checked_at": {
"type": "string",
"format": "date-time",
"description": "When the posting was last looked for on the employer's own ATS. Present only when the `ats_absent` criterion fired."
}
}
},
"Reality": {
"type": "object",
"additionalProperties": true,
"description": "Signals about whether the posting reflects a real, current opening.",
"properties": {
"class": {
"type": "string",
"enum": [
"fresh",
"stale",
"likely-evergreen"
]
},
"age_days": {
"type": "integer"
},
"repost_count": {
"type": "integer",
"description": "How many times this role has been reposted."
},
"mass_posting_count": {
"type": "integer",
"description": "How many near-identical postings the same role cluster holds."
},
"fake_freshness": {
"type": "boolean",
"description": "True when the stated posting date looks refreshed rather than real."
}
}
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/freehire-me-job"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.