New jobs
Active jobs we first collected in a time window, as a JSON array. This is the feed to poll when you keep your own copy of the catalogue: call it on a fixed schedule and every new job reaches you once.
GET/v1/active-ats
Time frames
| Value | Use | Window |
|---|---|---|
| 1h | Hourly polling | The last full UTC hour. Called at 09:15 it returns jobs collected 08:00–09:00. Each hour becomes available two minutes after it ends. |
| 24h | Daily polling (default) | The 24 hours up to the last full UTC hour. Call it in the same hour every day. |
| 7d | Short backfill | Rolling 7 days up to now. |
| 6m | Full backfill | Every active job collected in the last 183 days, which is essentially the whole catalogue. Page it with cursor. |
Why windows end on the hour
A window that ends at a fixed hour boundary returns the same jobs whenever in the next hour you call it, so hourly or daily polling never skips or repeats a job. For the freshest data, poll1h a few minutes after each hour, or use the changes feed, which is seconds behind collection.Parameters
Pagination and response
| Parameter | Type | Description |
|---|---|---|
| time_frame | string | 1h, 24h, 7d or 6m. Default 24h. |
| limit | integer | Jobs per page, 1–1000. Default 100. |
| offset | integer | Jobs to skip. Pages are ordered by date_posted, newest first (jobs without a posted date use date_created). |
| cursor | integer | Pass the last id of the previous page. Orders by id ascending and overrides offset. Use it for 6m backfills. |
| description_format | string | text or html. Omit to leave descriptions out, which keeps pages small. |
| include_source_fields | boolean | true adds source_fields: department, pay tiers, qualifications and other facts exactly as the employer published them, with where each was found. |
| include_basic_organization_details, include_beta | boolean | Accepted for compatibility; they add no fields. |
Search
| Parameter | Type | Description |
|---|---|---|
| title | string | Search the title. nurse manager needs both words, "nurse manager" is a phrase, nurse OR manager either, -assistant excludes, engineer* is a prefix. |
| description | string | Same syntax, over the title, employer name and description together. |
| location | string | Full place names, City, Region, Country, combined with OR. See Location search. |
| title_advanced, description_advanced, location_advanced, organization_advanced | string | Boolean expressions with &, |, !, <->, parentheses and :*. They take precedence over the plain parameter. See Advanced search. |
Dates
| Parameter | Type | Description |
|---|---|---|
| date_posted_gte, date_posted_lt | ISO 8601 | When the employer says the job was posted. A time without a zone is UTC. |
| date_created_gte, date_created_lt | ISO 8601 | When we first collected the job. Use these to replay a missed window exactly. See Time fields. |
Filters
| Parameter | Type | Description |
|---|---|---|
| country | list | CA, US or both (the default). |
| organization, exclude_organization | list | Exact, case-sensitive employer names, comma-separated. Quote a name that contains a comma: "Acme, Inc.". The organization list has every name. |
| source, exclude_source | list | Source systems, e.g. workday,icims. See Sources. |
| has_salary | boolean | true: the employer published pay. false: it did not. |
| remote | boolean | true: marked remote by the employer. false: not remote. |
| has_no_location | boolean | true: jobs without a resolved location. |
| id | list | Only these job ids. |
Unknown parameters are rejected with a suggestion (timeframe → time_frame) instead of being ignored, so a typo never silently widens your results.
Example
curl --get "https://api.thejobsapi.com/v1/active-ats" \
-H "Authorization: Bearer $THEJOBSAPI_KEY" \
--data-urlencode 'time_frame=1h' \
--data-urlencode 'title="registered nurse" OR rn' \
--data-urlencode 'location="Ontario, Canada" OR "New York, United States"' \
--data-urlencode 'description_format=text'Pagination
For 1h, 24h and 7d, page with offset: request limit=1000&offset=0, then offset=1000, and so on until a page has fewer than limit jobs.
For 6m, use cursor: start with cursor=0 and pass the last id of each page. Cursor pages are ordered by id and stay fast however deep you go.
let cursor = 0;
for (;;) {
const url = `https://api.thejobsapi.com/v1/active-ats?time_frame=6m&limit=1000&cursor=${cursor}&description_format=html`;
const response = await fetch(url, { headers: { Authorization: `Bearer ${process.env.THEJOBSAPI_KEY}` } });
if (!response.ok) throw new Error((await response.json()).detail);
const jobs = await response.json();
await saveJobs(jobs);
if (jobs.length < 1000) break;
cursor = jobs[jobs.length - 1].id;
}Response
An array of jobs. Fields we don't collect are null; see Job fields for every field and where it comes from.
[
{
"id": 4183022,
"title": "Registered Nurse, Emergency",
"organization": "Example Health",
"organization_url": null,
"organization_logo": null,
"date_posted": "2026-10-12T00:00:00Z",
"date_created": "2026-10-12T14:31:07Z",
"date_valid_through": "2026-11-01T00:00:00Z",
"locations": [{
"@type": "Place",
"address": { "@type": "PostalAddress", "addressLocality": "Toronto", "addressRegion": "ON", "addressCountry": "CA" },
"latitude": 43.70011, "longitude": -79.4163
}],
"locations_alt": ["Toronto, ON"],
"locations_derived": ["Toronto, Ontario, Canada"],
"location_type": null,
"location_requirements": null,
"salary": {
"@type": "MonetaryAmount", "currency": "CAD",
"value": { "@type": "QuantitativeValue", "minValue": 42.5, "maxValue": 51.0, "unitText": "HOUR" }
},
"employment_type": ["FULL_TIME"],
"url": "https://example.wd3.myworkdayjobs.com/careers/job/Toronto/Registered-Nurse_R12345",
"source": "workday",
"source_type": "ats",
"source_domain": "example.wd3.myworkdayjobs.com",
"source_slug": "example.wd3.myworkdayjobs.com/careers",
"domain_derived": null,
"cities_derived": ["Toronto"],
"counties_derived": null,
"regions_derived": ["Ontario"],
"countries_derived": ["Canada"],
"timezones_derived": null,
"lats_derived": [43.70011],
"lngs_derived": [-79.4163],
"country": "CA",
"apply_url": null,
"work_arrangement": "onsite"
}
]Usage
Each job returned counts once toward your plan's job allowance; each call counts as one request. See Errors, limits & usage.