Jobs API: Search 168k Company Jobs, No Board URLs Needed
Pricing
from $0.70 / 1,000 jobs
Jobs API: Search 168k Company Jobs, No Board URLs Needed
Search 168,000 jobs from company career pages by words, location and remote. No board URLs, no company list, no key. 31 fields. $1 per 1,000.
Pricing
from $0.70 / 1,000 jobs
Rating
0.0
(0)
Developer
Dodo Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Search jobs by words, location and remote, with no board URLs and no company list. Type what you are looking for and get clean JSON: 31 fields per job, 0 failures, including a pay range when the employer states one. Measured on Apify on 2026-09-22, a 120-job search took 9 seconds on one run and 57 on another: the endpoint's own latency is what varies, not the paging.
Every other job Actor we publish asks you for career-page URLs. This one does not: it searches the public index of 168,000 open jobs from every company hiring through Workable, one of the applicant-tracking systems those career pages run on.
What you get
{"id": "workable:dd9ebded-b634-4c95-b483-99c2ef13751c","ats": "workable","company": "Terabase Energy","company_name": "Terabase Energy","company_website": "https://www.terabase.energy/","title": "Manager of Project Scheduling, Project Controls","department": null,"team": null,"location": "Woodland, California, United States","locations": ["Woodland, California, United States"],"country": "United States","workplace_type": "remote","remote": true,"employment_type": null,"experience_level": null,"salary_min": 120000,"salary_max": 150000,"salary_currency": "USD","salary_period": "year","salary_text": "mined by role, level, and location. This role offers a base salary of $120,000 – $150,000","salary_source": "description","posted_at": "2026-09-21T21:12:35.639Z","updated_at": "2026-09-21T21:12:35.639Z","requisition_id": "dd9ebded-b634-4c95-b483-99c2ef13751c","description": "What we do At Terabase Energy, we believe that digitalization and automation will drive the next wave of innovation and cost reduction in large scale solar. To fully unlock the potential of this oppor ...","apply_url": "https://jobs.workable.com/view/tngdG3viSCtrbpzqFC9XBj/remote-manager-of-project-scheduling%2C-project-controls-in-woodland-at-terabase-energy","url": "https://jobs.workable.com/view/tngdG3viSCtrbpzqFC9XBj/remote-manager-of-project-scheduling%2C-project-controls-in-woodland-at-terabase-energy","change_status": null,"first_seen_at": null,"last_seen_at": null,"scraped_at": "2026-09-22T07:29:31.495Z"}
What you can search
| Filter | Example | Size today |
|---|---|---|
| words | data engineer | 492 remote in the last 30 days |
| location | London | 3,317 |
| workplace | remote | 48,183 |
| posted within | 7 days | 18,048 |
| remote and last 7 days | 6,035 | |
| everything | 168,324 |
Then narrow further, before a row is saved so you never pay for the rest: Title must contain, Title must not contain (drop "senior", "unpaid"; whole words, so list both "intern" and "internship"), Countries, and Only jobs that state pay.
A daily feed of only the jobs you have not seen
Give the run a Monitor name and schedule it. Every job says whether it is new, updated or already delivered, and carries first_seen_at. With Only changes on, jobs you have already received are left out and not billed, so a daily run returns the day's new matches instead of the same list again.
Measured: two runs of a "remote product manager, last 7 days" search returned 40 jobs, then 40 different ones, because the second run skipped everything it had already delivered and paged deeper.
A search is a window onto a moving index, never a complete listing, so this Actor never claims a job was removed: absence from a search result proves nothing.
Pay, where the employer states it
Workable publishes no salary field. When a job states a range next to a pay word (Salary, Compensation, Base pay, Pay range, Hourly rate), this Actor reads it out into salary_min, salary_max, salary_currency and salary_period, and sets salary_source to description so you always know where a number came from. Measured on 480 real jobs on 24 September: 63 ranges read, every one checked by hand, none wrong. The currency comes from the text when it says (CAD, £, €, AUD), otherwise from the job's country for a bare $, so a Canadian salary is CAD, not USD. A range with no pay word in front of it is not read, on purpose: a wrong salary is worse than none.
Equity grants and on-target earnings are deliberately not matched: an equity table looks exactly like a salary range, and OTE is not base pay.
The same row shape as the rest of the catalogue
The 31 fields here are the ones our Career Page Jobs Scraper produces, so a pipeline that already reads one needs no branch for the other. Use this Actor to find jobs across companies, and that one to watch a specific company's board in full.
What it reads
The public job index at jobs.workable.com, through the same endpoint the site's own search uses. No key, no login, no browser. jobs.workable.com/robots.txt allows it and disallows only the /search HTML pages, which this Actor does not touch. That file also carries a Content-Signal of search=yes, ai-input=yes, ai-train=no, and we respect it: this Actor delivers job data to the person who asked for it and nothing here is used to train a model.
What that means in practice: the index covers companies hiring through Workable. It is a large slice of the market, not all of it. If you need a specific employer who uses Greenhouse, Lever, Ashby or Workday, use the Career Page Jobs Scraper and paste their board.
What we deliberately do not collect
- No e-mail addresses or phone numbers. Contact details written inside a job description are replaced before the row is saved. A first name in a sentence such as "call Maurice" is not detected and stays.
- Public endpoints only, read at a polite rate (5 requests a second at most).
Why not build it yourself
The endpoint is undocumented. Its paging token comes back as nextPageToken but is only accepted as pageToken: send it back under the name it was given and you get page one again, for ever, which is the kind of bug that quietly halves a dataset. limit refuses anything above 20. Locations arrive lowercased with a TELECOMMUTE marker mixed into the list. Descriptions are three separate HTML fragments. $1.00 per 1,000 jobs, and when the source changes we fix it within 48 hours. Every Apify account includes $5 of free usage a month, so your first 5,000 jobs cost nothing.
Founding price: $1.00 per 1,000 jobs for the first 100 users. It then rises to $1.50. Users who joined at the founding price keep it.
How to run it
- Click Run. The prefilled input returns remote jobs posted in the last week.
- Put your own words in Search words, and set Location and Workplace.
- Add Posted within (days) and schedule it for a feed of new jobs.
- Narrow with Title must contain / must not contain, Countries and Only jobs that state pay.
- Set Max rows to cap the run. That is also your spend cap.
- Add a Monitor name with Only changes so each run returns only what is new.
Use it from an AI agent (MCP)
https://mcp.apify.com/?tools=actors,docs,dododata/job-search-api
A search in, typed job rows out, with every field documented in the dataset schema, so an agent can call it without reading this page. The Actor is enabled for Apify's agentic payments (x402, experimental on Apify's side).
Related Actors
- Career Page Jobs Scraper, API & Monitor: every open job from a specific company's board, across twelve applicant-tracking systems
- France Travail Jobs Scraper, API & Monitor: French public-service job offers with salary as numbers
Input reference
| Field | Default | Meaning |
|---|---|---|
query | none | Words to search for |
location | none | City, region or country |
workplace | any | any, remote, hybrid, on_site |
dayRange | none | Only jobs posted in the last N days |
titleKeywords | none | Title must contain one of these |
excludeKeywords | none | Title must not contain any of these |
countries | none | Keep only these countries, by whole name (US, UK, USA understood) |
onlyWithSalary | false | Keep only jobs that state pay |
includeDescription | true | Turn off for lighter rows |
monitorName | none | Turns on change tracking |
onlyChanges | false | With a monitor name: skip and do not bill jobs you already have |
maxItems | 500 | Stop after this many jobs |
maxConcurrency | 5 | Parallel requests |
useProxy | false | Route requests through the Apify proxy. Off by default: the public endpoint answered more than twice as fast without it. Turn it on if a run reports being blocked |
FAQ
Do I need to know which companies to search? No, and that is the point. Every other job Actor we publish needs a board URL. This one takes a search.
Which companies are covered? Every company hiring through Workable that lists on its public index: about 168,000 open jobs as we write this. It is a large slice of the market, not all of it.
How do I get only today's new jobs? Set Posted within (days) to 1, add a Monitor name with Only changes, and schedule it daily. You then pay only for jobs you have not already received.
Why do so few jobs have a salary?
Because the source has no salary field, so a pay range only appears when the employer wrote one into the job text. We read those and mark them salary_source: description, and we never invent the rest.
How fresh is the data? Every run is live. There is no database in between.
Changelog
- 2026-09-22, v0.1: first release. Search by words, location, workplace and recency; title and country filters; pay parsed from the job text; monitoring with
change_statusandfirst_seen_at. Source verified live on 2026-09-22.