Where job postings actually come from: the ATS behind every careers page

Careers pages are just a window on an applicant tracking system. Learn how Greenhouse, Lever and Workday feeds work, why aggregator copies lag a day, and how to read hiring at the source.

Click "Careers" on almost any company website and you are not really looking at that website. You are looking at a window. Behind the window sits an applicant tracking system, usually called an ATS. The ATS is where recruiters create the job, edit it, and close it. Everything else, including the careers page itself, is a copy of that record.

This matters if you treat hiring as a signal. The copy you read on a job board is downstream. The record in the ATS is the source. If you want to know what a company is doing today, you read the source. If you are fine knowing what it was doing yesterday, the aggregators will tell you.

This article explains the plumbing. Where the posting is born, how it travels, and why each hop adds delay.

The careers page is a widget

Open the careers page of a typical venture-backed company and view the page source. In many cases the job list is not in the HTML at all. The page loads a small script. The script calls the company's ATS and renders whatever comes back.

Greenhouse is the clearest example. A company on Greenhouse gets a hosted job board. The board has a token, usually a slug of the company name. Greenhouse publishes a documented, public JSON endpoint for that board. Anyone can request it with curl. No key, no login, no cost. The response lists every open role, its location, its department, and when it was last updated.

Lever works the same way. Public postings endpoint, company slug in the URL, JSON out. Ashby, Workable, SmartRecruiters and Recruitee all offer some flavor of a public feed for published jobs. Workday careers sites also load their listings from a JSON service behind the page, though Workday does not document it as a public API in the way Greenhouse does.

The point is not the vendor list. The point is the architecture. The careers page is a rendering layer. The truth lives one HTTP request deeper, and for a large share of companies that request is open to anyone.

How a posting travels

Follow one job from creation to your screen.

First, a recruiter opens the role in the ATS. At this moment the job exists in exactly one place. If the company publishes it, the ATS feed updates within moments. The careers page, which reads that feed live, shows it on the next page load.

Second, the aggregators find it. LinkedIn, Indeed and the rest ingest jobs in a few ways. Some companies pay to post directly. Some ATS vendors push jobs to partner boards through integrations. And a large amount arrives through crawling, where the aggregator's bots revisit careers pages and structured data feeds on a schedule.

Google's job search works this way too. It reads JobPosting structured data, the schema.org markup that sites embed in their pages, and it picks the posting up when its crawler next visits. A crawl schedule is the key phrase. Crawls happen on the crawler's clock, not the company's.

Third, the copies of copies appear. Smaller job boards syndicate from bigger ones. Newsletter roundups summarize the boards. By the time a role shows up in a weekly "who's hiring" thread, it may have been public at the source for days, and it may already be closed.

Each hop is a cache. Each cache has an expiry measured in hours or days. That is the whole reason the aggregator copy is stale. Nobody is doing anything wrong. Crawling is batch work, and batch work runs on a schedule.

Removal is the better signal, and it lags worse

New postings get most of the attention, but removals are often more informative. A company that quietly closes half its open engineering roles is telling you something before any press release does. A frozen job board, where nothing new appears for weeks at a company that used to post constantly, is telling you something too.

Here the lag problem is worse. Aggregators are reasonably quick to add jobs, because companies want jobs added and often push them. Nobody pushes a removal. The aggregator only learns a job is gone when its crawler revisits and gets an error or an empty slot. Stale postings for closed roles linger on job boards all the time. If you count a company's open roles by counting aggregator listings, you will overcount, and the overcount grows exactly when things change fast.

Reading the ATS feed directly fixes this. The feed reflects the current state of the board. A role that was in yesterday's response and missing from today's response was closed or unpublished in between. Diffing the feed day over day gives you additions and removals with no crawler in the loop.

Why this belongs on a disclosures site

We spend most of our time on official filings, and hiring data is a useful complement because it moves faster than any filing can.

Public companies do describe their workforce in filings. Since the SEC modernized Regulation S-K in 2020, annual reports must include human capital disclosure where material, and you can read the rule change on sec.gov. But a 10-K is an annual document. It describes headcount as it stood at a point in the past, in prose the company chose. Job feeds update daily and describe intent, not history.

For private companies the pairing is even more direct. A startup that raises money will usually file a Form D with the SEC, and you can find those filings through EDGAR full-text search. We cover how to interpret one in how to read a Form D filing, so we will not repeat it here. The short version is that a Form D tells you money arrived. It does not tell you what the company does with it. The job feed does. A raise followed by a burst of new postings in a specific function is a readable story: money in, hiring for X. A raise followed by silence is a different story.

The same logic drives everything we publish. Filed data is honest but slow, and the delay is defined by rules. Congressional trade reports run on a filing clock we covered in the 45-day rule and why it matters. Institutional holdings run on the quarterly cycle covered in 13F deadlines and the 45-day lag. Job feeds have no filing clock at all. Their only delay is the one you add by reading a copy instead of the source.

Doing it yourself, for free

You do not need us or any paid tool to read hiring at the source. The recipe is short.

Find the ATS. Open the careers page, open your browser's network tab, reload, and look at where the job data comes from. The hostname usually names the vendor.

Fetch the feed. For documented APIs like Greenhouse and Lever, the vendor's developer docs give you the exact URL pattern. A single curl command returns the JSON.

Store and diff. Save each day's response. Compare today against yesterday. New IDs are new roles. Missing IDs are removals. A shell script and a cron job cover it. Respect the vendor's terms and keep your request rate polite, since one request per company per day is all this takes.

That is the entire mechanism. What we add on top is scale, history and scoring across many companies at once, plus the joins against filing data. But the underlying read is open to anyone with a terminal, and it should be.

One honest caveat. A job posting is intent, not outcome. Companies post roles they never fill, keep evergreen postings open for pipeline, and sometimes hire without posting at all. Treat feed data as one input, weigh it against filings, and remember that nothing here is investment advice.

If you want to see hiring signals joined with the filings that explain them, start where the money enters the building. Our Startup Capital Raises Form D report tracks new Form D filings and scores them, so you can watch which newly funded companies start hiring at the source, days before the aggregator copy catches up.


Want the signal instead of the raw filings? Get a free report preview. Prefer the tool to the write-up? Browse all data feeds or connect the free MCP server.