The Mine Works
How to Monitor Competitor Job Postings to Predict Their Strategy
← All posts
use-case November 3, 2025 · 11 min read Updated September 17, 2026

How to Monitor Competitor Job Postings to Predict Their Strategy

Job postings are the most honest signal of a competitor's roadmap. Track their ATS boards automatically and turn hiring data into strategy.

Try the scraper

The actor referenced in this article. Pay only for results delivered.

View the scraper →

A competitor cannot hide their hiring. The moment they open a role on Greenhouse, Lever, Ashby or Workday, the posting is public. If you know where to look, and you automate the looking, you get a 6-to-12-month preview of their product roadmap, new market bets, and technology decisions, all before they announce anything.

TL;DR: Monitor competitor job postings using public ATS job boards (Greenhouse, Lever, Ashby and Workday, no authentication required) to predict strategy: new engineering roles reveal product direction, first sales hire in a region signals market entry, unfamiliar tech stacks mean platform shifts. Automate weekly collection with the ATS Jobs scraper, pipe results to Claude for interpretation, and get a Monday morning briefing on what every competitor is building.

This is not a new insight. CB Insights, investors, and growth teams have used job posting intelligence for years. What has changed is that you can now automate the entire pipeline: collection, interpretation, and alerting, in an afternoon.

Why Job Postings Are the Best Competitive Signal

Most competitive intelligence is lagged. Press releases describe decisions already made. Earnings calls describe results already booked. Blog posts describe features already shipped.

Job postings are leading. A company must hire before they can build. The average time from job posting to new hire to meaningful output is 6 to 12 months. When you see a pattern in their postings, you are looking at their roadmap, not their past.

Specific signals job postings reliably encode:

Product direction: A web-first company posting five iOS engineers is building a native app. A company posting “ML Platform Engineer” (not “ML Research Engineer”) is productionizing AI, not experimenting with it.

Market entry: The first sales hire in a new geography is the most reliable signal of geographic expansion. Companies do not hire salespeople in markets they are not serious about.

Technology decisions: The tech stack in a job description reflects actual infrastructure, not marketing copy. “Experience with ClickHouse and Flink” tells you more about their data architecture than their entire engineering blog.

Organizational structure: Whether they post individual contributor roles or manager roles in a function reveals whether they are scaling a team or building a new one from scratch.

Acquisition interest: A company that posts deep expertise requirements in a niche area they have never mentioned may be building toward an acquisition target, or building to compete with one.

The Data Source: Public ATS APIs

Greenhouse, Lever, and Ashby all expose public-facing job board APIs that require zero authentication. Every company using these ATSs is broadcasting their open roles to anyone who calls the right endpoint. Workday, which a lot of larger companies run, publishes a public board too, though each customer sits on its own tenant URL rather than a guessable slug.

Going to the ATS board directly also beats watching LinkedIn or Indeed. Those sites copy listings after the fact and can trail the company’s own board by a day or more. The ATS board changes the moment a recruiter hits publish, and it carries the full description rather than a trimmed copy.

# Direct API calls, no API key, no auth
# Greenhouse: https://boards-api.greenhouse.io/v1/boards/{slug}/jobs
# Lever: https://api.lever.co/v0/postings/{slug}
# Ashby: https://api.ashbyhq.com/posting-api/job-board/{slug}
# Workday: https://{tenant}.wd{N}.myworkdayjobs.com/{site} (no guessable slug)

The ATS Jobs scraper wraps all four platforms in a single normalized call, handles pagination, and returns clean structured JSON: same schema regardless of which ATS the target company uses.

Setting Up the Monitoring Pipeline

Step 1: Build Your Target Company List

Identify which ATS each competitor uses. The easiest way is to look at their careers page URL:

  • greenhouse.io in the URL → Greenhouse slug is the subdomain
  • lever.co in the URL → Lever slug is the path segment
  • ashbyhq.com in the URL → Ashby slug is the path segment
  • myworkdayjobs.com in the URL → Workday, and you need the whole careers URL, because the tenant and datacentre number (wd1, wd5 and so on) cannot be derived from the company name
COMPETITORS = {
    "greenhouse": [
        "stripe", "linear", "notion", "figma", "vercel",
    ],
    "lever": [
        "planetscale", "turso", "neon",
    ],
    "ashby": [
        "loom", "coda", "retool",
    ],
    "workday": [
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    ],
}

Step 2: Collect and Store Postings

from apify_client import ApifyClient
import json
import hashlib
from pathlib import Path
from datetime import datetime

apify = ApifyClient("YOUR_APIFY_TOKEN")

SEEN_FILE = Path("seen_postings.json")

def load_seen() -> set:
    if SEEN_FILE.exists():
        return set(json.loads(SEEN_FILE.read_text()))
    return set()

def save_seen(seen: set):
    SEEN_FILE.write_text(json.dumps(list(seen)))

def job_id(job: dict) -> str:
    key = f"{job.get('_company')}-{job.get('title')}-{job.get('location', '')}"
    return hashlib.md5(key.encode()).hexdigest()

def collect_new_postings(competitors: dict) -> list[dict]:
    seen = load_seen()
    new_jobs = []

    for platform, slugs in competitors.items():
        for slug in slugs:
            run = apify.actor("themineworks/ats-jobs").call(run_input={
                "boards": [{"ats": platform, "slug": slug}],
                "maxJobsPerCompany": 100,
                "includeDescription": True,
            })
            for job in apify.dataset(run["defaultDatasetId"]).iterate_items():
                job["_company"] = slug
                job["_platform"] = platform
                jid = job_id(job)
                if jid not in seen:
                    job["_first_seen"] = datetime.utcnow().isoformat()
                    new_jobs.append(job)
                    seen.add(jid)

    save_seen(seen)
    return new_jobs

For Workday entries, _company will be the careers URL, so map it to a readable name before the brief goes out. Workday rows also come back without a department, because Workday’s public board does not publish one; for those companies the titles and descriptions carry the signal.

Step 3: Interpret With Claude

Raw job postings are useful. Interpreted job postings are intelligence. Claude can read a batch of new postings and surface what they signal, not just list them.

import anthropic
import os

claude = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def interpret_new_postings(new_jobs: list[dict]) -> str:
    if not new_jobs:
        return "No new postings this week."

    # Build company summaries
    by_company = {}
    for job in new_jobs:
        company = job["_company"]
        if company not in by_company:
            by_company[company] = []
        by_company[company].append({
            "title": job.get("title"),
            "department": job.get("department"),
            "location": job.get("location"),
            "description_excerpt": (job.get("description") or "")[:400],
        })

    response = claude.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=2000,
        messages=[{
            "role": "user",
            "content": f"""You are a competitive intelligence analyst. Analyze these new job postings from the past week.

NEW POSTINGS BY COMPANY:
{json.dumps(by_company, indent=2)}

Write a Monday morning competitive intelligence brief covering:

1. MOST SIGNIFICANT SIGNALS: What are the 3 most important things these postings tell us about competitor direction? Be specific: "Company X is building Y because they posted Z roles."

2. COMPANY-BY-COMPANY SUMMARY: For each company with new postings, one paragraph: what are they hiring for, what does it suggest about their roadmap?

3. PATTERNS ACROSS COMPANIES: Are multiple competitors hiring in the same area? That signals an industry-wide shift worth noting.

4. WHAT TO WATCH: Which companies or role types should we track most closely next week?

Be specific and analytical. "They're hiring engineers" is not useful. "They posted 4 ML Platform roles and 2 data infrastructure roles but zero ML Research roles, which suggests they are productionizing an existing capability rather than building a new one" is useful."""
        }]
    )

    return response.content[0].text

Step 4: Schedule and Alert

import schedule
import time

def weekly_competitive_brief():
    print("Collecting new job postings...")
    new_jobs = collect_new_postings(COMPETITORS)
    print(f"Found {len(new_jobs)} new postings")

    brief = interpret_new_postings(new_jobs)

    # Save locally
    filename = f"competitive_brief_{datetime.now().strftime('%Y_%m_%d')}.md"
    with open(filename, "w") as f:
        f.write(f"# Competitive Intelligence Brief, {datetime.now().strftime('%B %d, %Y')}\n\n")
        f.write(f"**New postings analyzed:** {len(new_jobs)}\n\n")
        f.write(brief)

    print(f"Brief saved to {filename}")
    print("\n" + "="*60 + "\n")
    print(brief)

# Run every Monday at 8am
schedule.every().monday.at("08:00").do(weekly_competitive_brief)

while True:
    schedule.run_pending()
    time.sleep(60)

The Signals That Matter Most

Not all job postings carry equal intelligence value. These are the patterns worth watching closely:

First hire in a function: The first data engineer, the first compliance officer, the first sales hire in a new city. First hires signal new bets. Tenth hires in a function signal scale, which is less interesting for strategy.

Role titles that don’t exist yet: If a competitor posts “Agentic Infrastructure Engineer” or “AI Reliability Engineer,” they are naming a discipline that does not have standard terminology. They are inventing their organizational model in real time.

Senior versus junior mix: A company posting all Staff and Principal engineers and no mid-level engineers is either burning out, scaling fast, or building a new team from scratch. Any of these is worth understanding.

Location and remote signals: A company that was fully remote suddenly posting office-required roles in a specific city may be making a strategic partnership or acquisition that requires physical presence.

Volume spikes: A company that normally posts 5 roles per month suddenly posting 20 is in an expansion phase. A company that drops from 20 to 0 has either hit a hiring freeze or a structural problem.

Who Else Reads Hiring Data

Competitive intelligence is the most common use of this feed, but other teams pull the same data for different reasons.

Investors watch open roles at portfolio companies and at private comparables, where there is no filing to read. A steady rise in engineering openings points to growth, and a sudden drop in open roles usually means a freeze, often months before anyone says so.

Talent teams pull descriptions for the same role from competitor boards before writing their own. It shows which skills and experience ranges the market asks for, and in places where pay transparency laws apply, the salary bands competitors disclose.

Staffing recruiters use it to build target lists. A recruiter who places mid-market sales roles can pull every open Account Executive and Sales Manager posting across a couple of hundred company boards in one run.

Researchers use the structured output to study which skills employers ask for and how requirements shift over time, and niche job boards (fintech engineering, climate tech, biotech research) are built by aggregating boards from a curated company list. The ATS aggregation guide covers that build.

What Job Postings Will Not Show You

ATS boards only list the roles a company chose to advertise. Internal transfers, retained executive searches and roles filled through referrals before they were ever posted do not appear, so a quiet board does not always mean a quiet hiring team. Some companies also keep their Workday board behind an employee login, and those cannot be read from outside. Treat it as a signal of intent. It will not give you a full headcount plan.

Real Example: What Competitor Job Postings Revealed

A growth team at a Series B developer tools company tracked their top three competitors weekly. Signals they caught before public announcements:

  • One competitor posted 6 “Enterprise Sales Engineer” roles across New York, London, and Singapore in a single month, despite being primarily self-serve. This preceded their enterprise tier launch by 8 months.

  • Another competitor’s engineering job descriptions shifted from mentioning PostgreSQL to mentioning ClickHouse and Apache Iceberg across multiple roles over a 6-week period. This signaled a data infrastructure rewrite before any engineering blog post.

  • A third competitor posted “Head of Partnerships: Systems Integrators” with a description explicitly mentioning “SAP, Salesforce, and ServiceNow ecosystem.” Their integration marketplace launched 9 months later.

None of these signals required inside information. They were in public job postings, visible to anyone who was reading.

Frequently Asked Questions

Is it legal to scrape public ATS job boards?

Yes. Greenhouse, Lever, and Ashby job boards are explicitly public-facing APIs with no authentication requirement. The data is intended to be publicly accessible for job seekers. The hiQ v. LinkedIn ruling (9th Circuit) confirmed that scraping publicly accessible data does not violate the Computer Fraud and Abuse Act. Avoid storing personal employee data, and use the data for research and analysis rather than automated mass outreach.

How often should I run the collection to catch new postings quickly?

Daily collection is sufficient for most competitive intelligence purposes. Most strategic signals emerge from patterns over weeks, not hours. If you are in a fast-moving competitive situation, twice-daily collection is reasonable. Avoid running more frequently than necessary: it creates noise and wastes compute.

How many companies can I effectively monitor at once?

The practical limit is determined by signal-to-noise ratio, not technical constraints. Monitoring 50 companies produces so many postings that patterns get lost. Most effective competitive intelligence programs track 10 to 20 carefully selected companies, the ones where hiring signals are most relevant to your own strategy.

What if a competitor uses Workday or another enterprise ATS?

The ATS Jobs scraper covers Greenhouse, Lever, Ashby and Workday. Workday needs the company’s full careers URL (for example https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite) passed in boards, because there is no slug to guess, and its rows carry no department field. Companies on iCIMS, SuccessFactors or a custom careers page are outside these four systems and need a different scraping approach. A practical fallback is to watch their LinkedIn company page job postings, which pull from every ATS.

How do I separate signal from routine backfill hiring?

Establish a baseline. After 4 to 6 weeks of collection, you will know each company’s typical posting volume by department and role type. Deviations from baseline, more than 2x volume in any category, new role types that haven’t appeared before, sudden geographic expansion, are the signals worth investigating. Claude’s pattern analysis does this automatically when you provide historical context alongside new postings.

Related Actor

Explore the scraper referenced in this article: inputs, outputs, and pricing, then run it on Apify.