Skip to main content
Resources

Product updates

All the latest updates, improvements, and fixes to TheirStack

August 4, 2026

TheirStack is now keyboard and screen-reader accessible

If you use TheirStack with a keyboard, a screen reader, or a browser zoomed well past 100%, parts of the app used to be awkward and a few were simply closed to you. We went through it criterion by criterion against WCAG 2.2 Level A and AA and fixed what we found — and we have published exactly where we stand on each criterion.

You can now navigate the whole app with a keyboard. That was the biggest gap, and it's the change most people will feel first.

The rest of what you're likely to notice:

  • Tab reaches everything. Controls that were clickable divs — and so invisible to Tab and to the Enter key — are real buttons. Every page starts with a "Skip to main content" link, so you no longer tab through the whole sidebar to get to the table.
  • Focus is visible. Every focusable control draws a focus ring, and dialogs and sticky headers no longer sit on top of the control you just moved to.
  • Text is darker. Secondary text, placeholders, error messages, and invoice and request statuses were between 2.2:1 and 3.9:1 against white. They now clear the 4.5:1 that Level AA asks for.
  • Icon-only buttons say what they do. Roughly forty of them announced as "button" and nothing else. They have names now.
  • The page has a shape. Headings form a real outline with no skipped levels, and landmarks are labelled, so jumping by heading or by region actually works.
  • It reflows. Every page fits in a 320px-wide viewport without horizontal scrolling, and survives the line and letter spacing that reader extensions apply.

One find worth calling out: the page title was rendered inside a container hidden below the md breakpoint. On a phone, no page in the app had a heading at all — a screen reader had nothing to announce the page by. That is fixed everywhere at once.

Where we stand

Every page of the app now passes the Level A and AA checks a machine can decide, and passes them again on every change we ship, so this doesn't quietly regress.

What's left is the part no tool decides: whether an alt text describes the right thing, whether the reading order makes sense non-visually, whether a screen reader announces a change in a way you can follow. That's a pass with a real screen reader, and it's the next thing on this list rather than something we're going to claim early.

So instead of a badge, we publish the detail: our Accessibility Statement lists every success criterion we verify automatically, every one we've reviewed by hand, and the ones we haven't assessed yet. If you're working through a procurement questionnaire, that's the page you want — and if it doesn't cover the criterion you need, ask us rather than infer it.

August 3, 2026

LinkedIn company IDs now work in company and job search

LinkedIn identifies a company page two ways: by its vanity slug (linkedin.com/company/deloitte) and by its numeric company ID (linkedin.com/company/1038). Both open the same page, and which one you end up storing depends on where you collected it.

Until now company_linkedin_url_or only ever compared the URL against our stored slug. A URL built on the numeric ID was compared against slugs like deloitte, so it could never match — and it failed quietly: the request succeeded, returned zero results, and consumed no credits. It looked like we simply did not have the company.

That is fixed, in the same filter. All of these now find Deloitte, in both Company Search and Job Search:

{ "company_linkedin_url_or": ["https://www.linkedin.com/company/1038"] }
{ "company_linkedin_url_or": ["https://www.linkedin.com/company/deloitte"] }
{ "company_linkedin_url_or": ["1038"] }
{ "company_linkedin_url_or": ["deloitte"] }

If your calls already send numeric-ID URLs, they start matching on their own — there is nothing to change on your side, and no new filter to migrate to. A value that is entirely digits is matched against both the company's LinkedIn ID and its slug, so you never have to work out which of the two you are holding. Some companies genuinely have a numeric vanity slug, and this way both resolve.

In the app the same filter covers all of it: Linkedin URL, under Company in Company Search and Job Search, accepts a full URL, a bare slug or a numeric ID, one per line.

A note on coverage

The numeric LinkedIn ID is our least complete company identifier: we have one for about 14% of companies, against 26% with a LinkedIn slug and 29% with a domain. This change removes a failure that was total and silent, but it does not make every LinkedIn lookup resolve — an identifier we do not store still returns no results.

If you have the company's domain, company_domain_or remains the identifier that matches most often.

July 20, 2026

Searches are up to 9x faster at higher limits

Searches are up to 9x faster at higher limits

Until now, response times could climb sharply when you raised the result limit and asked for more companies or jobs in each query. We have optimized our backend so that requesting more results has a much smaller impact, and response times now stay much closer to constant as limits grow.

The improvement applies to searches in the app and through the API, and is especially visible at higher limits. Searches were about 3x faster overall, and the slowest company searches are now up to 9x faster.

Average response times by requested result limit:

  • Limit 25: 4.08s before -> 1.99s after, about 2.0x faster.
  • Limit 100: 7.76s before -> 2.62s after, about 3.0x faster.
  • Limit 200: 12.27s before -> 3.25s after, about 3.8x faster.
  • Limit 500: 34.68s before -> 5.25s after, about 6.6x faster across the company-search queries measured at this limit.

How we measured it

The figures shown summarize 160 end-to-end requests: 64 company-search requests and 96 job-search requests. We tested four company-search types across limits 25, 100, 200, and 500, plus eight job-search types across limits 25, 100, and 200.

For every search type and limit, we sent four requests: two to our production deployment and two to a preview deployment running the optimized code. The order alternated between preview -> production -> production -> preview and production -> preview -> preview -> production, so both deployments appeared at the beginning and end of a run. This reduces the influence of hot-versus-cold queries and other order effects. Each before value is the average of the two production requests, and each after value is the average of the two preview requests.

Both deployments connected to the same production database, so they used the same underlying data and normal live workload rather than isolated copies.

Each measurement covers the complete HTTP request and response, not only the database query. Exact response times can still be higher or lower at different moments as database load changes, so the figures are benchmark averages rather than latency guarantees.

Why higher limits benefit more

Finding the matching rows in our database is only part of the request. The API still has to fetch, join, and build the response object for every company or job it returns.

The optimized search path reduces the work needed to fetch and prepare each response. That matters most when the response contains hundreds of rows: the fixed request overhead stays similar, but the per-row savings compound.

Company searches

For company searches, the after run was faster or equal in all 16/16 measured rows. The largest gains appear at the higher limits, where the before numbers scaled up sharply and the after numbers stayed much flatter.

The benchmark covers common company search shapes: country filters, technology filters, job filters, and combined technology + job filters, measured at limits 25, 100, 200, and 500.

QueryLimit 25Limit 100Limit 200Limit 500
US companies✅ 4.7s -> 1.97s (2.39x)✅ 5.8s -> 1.84s (3.15x)✅ 7.6s -> 1.94s (3.92x)✅ 25.6s -> 2.62s (9.77x)
US companies using Python✅ 4.9s -> 2.45s (2.00x)✅ 8.8s -> 2.98s (2.95x)✅ 14.7s -> 4.00s (3.67x)✅ 44.1s -> 6.57s (6.71x)
US companies hiring software engineers, 30d✅ 5.3s -> 2.13s (2.49x)✅ 9.2s -> 3.66s (2.51x)✅ 14.2s -> 3.87s (3.67x)✅ 34.6s -> 6.18s (5.60x)
US companies using Python and hiring software engineers✅ 6.4s -> 2.56s (2.50x)✅ 10.6s -> 3.35s (3.16x)✅ 17.9s -> 3.92s (4.57x)✅ 34.4s -> 5.61s (6.13x)

Each cell shows before -> after and the speedup for that limit. means the after run was faster or equal. Open a query to try the same measured filter shape in the app.

Company search benchmark grouped by limit

Job searches

Job searches were faster or equal in all 24/24 measured rows across limits 25, 100, and 200.

We measured title filters, keyword filters, description filters, recent-posting filters, and the same query shapes with 30-day posting windows.

QueryLimit 25Limit 100Limit 200
Title: software engineer, 365d✅ 2.8s -> 1.80s (1.56x)✅ 5.7s -> 2.02s (2.82x)✅ 8.5s -> 2.81s (3.02x)
Keyword slug: Python, 365d✅ 3.9s -> 2.20s (1.77x)✅ 6.7s -> 3.09s (2.17x)✅ 10.5s -> 4.14s (2.54x)
Description: Python, 365d✅ 4.7s -> 2.40s (1.96x)✅ 7.8s -> 3.50s (2.23x)✅ 17.4s -> 3.94s (4.42x)
Posted in last 30d✅ 3.6s -> 1.61s (2.24x)✅ 7.1s -> 1.78s (3.99x)✅ 10.0s -> 2.31s (4.33x)
Posted in last 365d✅ 2.9s -> 1.52s (1.91x)✅ 5.6s -> 1.93s (2.90x)✅ 7.9s -> 2.14s (3.69x)
Title: software engineer, 30d✅ 2.8s -> 1.57s (1.78x)✅ 5.5s -> 1.96s (2.81x)✅ 9.8s -> 2.49s (3.94x)
Keyword slug: Python, 30d✅ 3.3s -> 1.72s (1.92x)✅ 8.8s -> 2.55s (3.45x)✅ 11.4s -> 3.81s (2.99x)
Description: Python, 30d✅ 3.6s -> 2.00s (1.80x)✅ 11.5s -> 2.80s (4.11x)✅ 17.3s -> 3.64s (4.75x)

Each cell shows before -> after and the speedup for that limit. means the after run was faster or equal. Open a query to try the same filter shape in the app.

Job search benchmark grouped by limit

What you need to do

Nothing. The improvements apply automatically in the app and through the API, with no workflow or integration changes required.

July 9, 2026

Internship seniority is clearer and more accurate

We made two seniority improvements:

  1. Internship and co-op roles are classified more accurately as junior, especially when the title also contains senior-sounding words.
  2. Job detail pages now show seniority as its own chip, separate from employment status chips such as Internship.

Previously, titles like Senior Marketing Intern, Product Management Intern, Member of Technical Staff Intern, or Intern - Office of the CEO could be classified as senior, staff, or C-level because those signals were checked before the internship signal. Those now correctly resolve to junior.

We also expanded matching for common internship variants such as internship, externship, co-op, co op, and titles with separators like Intern_Engineering or Co-op_Fall 2026.

Here are a few examples from the labeled set we used to validate the change:

This table refers to the seniority value shown in the new seniority chip, used by filters, exports, the API, webhooks, and the MCP server.

JobSeniority beforeSeniority now
Machine Learning Intern✅ junior✅ junior
Human Resources Intern✅ junior✅ junior
Intern, Student Co-Op (RT)✅ junior✅ junior
Product Management Intern - Tools & Processes❌ senior✅ junior
Intern - Office of the CEO❌ c_level✅ junior
Member of Technical Staff Intern❌ staff✅ junior
Mechanical Engineering Co-op_Fall 2026❌ mid_level✅ junior
Intern_Engineering❌ mid_level✅ junior

The classification improvement applies anywhere job seniority is used: job detail pages, Job Search, exports, the API, webhooks, and the MCP server.

June 25, 2026

New: Agent Skills for the TheirStack MCP

We just shipped the first set of Agent Skills for the TheirStack MCP. A skill is a ready-made playbook you drop into Claude Code (or any MCP client): you give it a product website or a handful of customers, and it does the GTM research for you — grounded in real TheirStack data, not guesses. Every result comes back as a live company count that links straight into a pre-filtered search.

Three skills are available today:

  • Find the sales signals for any product or service — Give it a product or service URL. It reads what the offering does and the problems it solves, then maps them to the TheirStack signals a GTM team should run for outbound (technographics, hiring, buying intent), grouped by the offering each one pitches.
  • Find look-alike companies from your won customers — Give it 4–5 closed-won customers. It profiles each one on TheirStack — what they run, hire for, and mention — extracts the customer fingerprint they share, and finds new companies that look just like them, saved as ready-to-use searches.
  • Keyword research for job-description search — Give it a product or service URL. It derives the pains a buyer would describe in a job post, then iterates against real job postings — reading actual descriptions to learn the exact words companies use — and hands back keyword groups, each tied to a feature with a live job count.

All three run on the TheirStack MCP. Sizing every search is free; you only spend credits if you pull the actual companies. Copy any of them into your own setup and point it at a product URL.

June 12, 2026

Company search is now faster

Company search is now faster

Company Search now returns results noticeably faster. Across the searches we measured in production, queries run roughly 2-3x faster than before — so finding the companies you care about feels quicker, whether you're filtering by the technologies a company uses or by the jobs they're hiring for.

This applies everywhere Company Search runs: in the app, in your saved searches, in exports, and through the API. You don't need to change anything to benefit from it.

We also made the default ordering smarter. Results now come back sorted by relevance automatically, so the most relevant companies show up first:

  • Filtering by technology → companies we're most confident use it come first.
  • Filtering by jobs → companies hiring the most for what you searched come first.
  • Both → most confident technology match first, then by hiring volume.
  • Neither → larger companies first.

This new default applies automatically to existing API clients and saved searches too — no changes needed on your side. If you set your own sort order, that still takes priority.

Location search now handles typos and punctuation

Location search now handles typos and punctuation

When you look up a location, you no longer have to type it exactly the way our catalog stores it. Common variations — missing punctuation, dropped apostrophes, and plain typos — now resolve to the right city instead of coming back empty.

Before, small differences would return 0 results even when the city clearly existed. Now they just work:

  • St Petersburg (no period) → resolves to St. Petersburg
  • St. Petersburg, FL → ranks St. Petersburg, Florida first, ahead of the more populous Saint Petersburg in Russia
  • coeur dalene (missing apostrophe) → resolves to the right city in Idaho
  • los angelos, manchster, san fransico (typos) → resolve to Los Angeles, Manchester, and San Francisco

Adding a state also helps us pick the right match: when two cities share a name, the qualifier you type guides which one comes first.

This applies everywhere location lookup happens — autocomplete in the app, the /v0/catalog/locations API endpoint, and the MCP server. Exact and partial inputs are unchanged; we only step in to catch the variants that used to fall through.

June 9, 2026

Company Search: filter by companies with a hiring team

Company Search can already filter companies by their job postings (title, location, posted date, technologies…). You can now also require that those jobs have specific fields set — most notably a hiring team.

This mirrors the property_exists filters we have in Jobs Search, but nested inside job_filters so it applies to the jobs a company is hiring for.

API

Pass property_exists_or (any of) or property_exists_and (all of) inside job_filters. Supported values: hiring_team, final_url, employment_statuses.

{
    "job_filters": {
        "job_title_pattern_or": ["Software Developer"],
        "posted_at_max_age_days": 15,
        "property_exists_or": ["hiring_team"]
    }
}

This returns only companies that have at least one matching job with a hiring team — perfect for finding accounts where you already know who to reach out to.

App

In Company Search add the Job property not empty filter (under Job Posting) and select Hiring Team.

June 8, 2026

New filter: Job Closed

New filter: Job Closed

You can now filter job searches by whether a posting is still open or has been closed.

When TheirStack detects a job is no longer live at its source, it records the date it went offline. The Job Closed filter lets you act on that date — show only closed roles, only open ones, or narrow to jobs closed in a specific window.

In the app

Open Job Search, click + Add Filter, and select Job Closed. Toggle between open and closed, or switch to a date range to find roles that went offline between two specific dates. The same filter is available in Company Search.

Try it: closed jobs in the last 15 days

In the API

Use is_closed, closed_at_gte, and closed_at_lte in the Jobs API:

curl -X POST https://api.theirstack.com/v1/jobs/search \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "is_closed": true,
    "closed_at_gte": "2026-05-01",
    "closed_at_lte": "2026-05-31",
    "posted_at_max_age_days": 30,
    "limit": 10
  }'

Available now in Job Search, Company Search, and the Jobs API.

Jobs Closed dataset

Jobs Closed dataset

There's a new dataset for closed job postings. Each record includes the job's standard fields plus closed_at — the date TheirStack detected the posting was no longer live at its source.

Files follow the same Parquet format and API as the existing jobs datasets, partitioned by the day the job closed. Request a specific date, a date range, or pull an incremental feed of jobs that closed today.

  • closed_at — the day TheirStack first detected the posting was offline.
  • Full job record — same schema as the daily jobs dataset: title, company, location, description, and more.
  • Daily and hourly partitions — scope the download to exactly the window you need.

Learn more about how datasets work or how to access them.

Webhooks now fire when a matching job closes

Webhooks now fire when a matching job closes

You already get a webhook ping when a job matching your search is posted. Now you can get one when it closes.

Add job.closed to any job-search webhook alongside job.new. When a previously matched job goes offline, TheirStack sends a notification with the job ID and the date it closed — use the ID to pull the full job and company details whenever you need them.

More on how webhooks work in the webhooks documentation or see the job.closed reference.

May 22, 2026

MCP now accepts API key auth — no more daily re-logins

Most MCP clients today don't refresh OAuth tokens transparently, so you end up re-logging in every day. Annoying when you're in the middle of a conversation with Claude or Cursor.

Our MCP server now accepts a TheirStack API key as a Bearer token on the same endpoint. Create one at app.theirstack.com → API Keys. Keys don't expire until you revoke them, so the connection stays stable.

The MCP docs now show both options side-by-side inside every client tab — Claude Code, Claude.ai, Cursor, VS Code, ChatGPT, Windsurf, Cline, Codex, Gemini CLI. Pick OAuth or API key per agent; your choice is remembered across tabs.

Cursor / VS Code / Cline / Windsurf
{
    "mcpServers": {
        "theirstack": {
            "url": "https://api.theirstack.com/mcp",
            "headers": { "Authorization": "Bearer <YOUR_API_KEY>" }
        }
    }
}

OAuth still works — it's just no longer your only option.

May 14, 2026

Better Company Type filtering

The Company Type filter now does a better job of keeping staffing, recruiting, and other hiring intermediaries out of your Company Search results when you select Direct Employer.

That matters because many searches are meant to find final customers, not companies selling staffing or recruiting services. If you are looking for companies hiring data engineers, you usually want the employer building the data team, not an agency posting jobs for someone else. If you are looking for companies using Kubernetes, Salesforce, or Snowflake, a technology mentioned by an intermediary in a job post does not necessarily mean the intermediary uses that technology.

With this update, selecting Company Type → Direct Employer removes more of that intermediary noise from company searches, hiring-intent searches, technographic searches, exports, and API results.

Some recruiting firms were previously listed under broader industries like IT Services and IT Consulting, Business Consulting and Services, Software Development, or Hospitals and Health Care. They could still appear in Direct Employer searches even when their descriptions clearly said they offered staffing, recruitment, executive search, or talent placement services.

We now classify more of those companies as recruiting agencies, including companies that describe those services in English, Spanish, Portuguese, French, German, Dutch, Polish, Swedish, Danish, Norwegian, Finnish, Romanian, Hungarian, Czech, Slovak, Turkish, Korean, Arabic, Afrikaans, Japanese, and Hebrew.

Examples of companies this catches:

CompanyPrevious industryMatched phrase
1000 FarmersIT Services and IT ConsultingStaff Augmentation
5 Star HRNot setEmpresa de reclutamiento
2G Gente & GestãoProfessional Training and Coachingrecrutamento e seleção
111 CONSEILSNot setcabinet de recrutement
1a-ÄrztevermittlungNot setPersonalvermittlung
24/7 DriveTransportation, Logistics, Supply Chain and Storageuitzendbureau
ARTTIME - agencja pracyTemporary Help Servicesagencja pracy
FörsäkringsTalangerInsurancerekryteringsföretag
Altid VikarTemporary Help Servicesvikarbureau
Drift SørOil and GasBemanningsbyrå
Econia OyNot setHenkilöstövuokraus
에이치알그룹Not set헤드헌팅
El Maaly Group For RecruitmentNot setشركة توظيف
Cape Human CapitalNot setwerwingsagentskap
MWH HR Products株式会社Not set人材紹介
אורפלי ייעוץNot setחברת השמה
ActalentBusiness Consulting and Servicestalent solutions

In production impact checks, this found 30,846 companies that were previously not marked as recruiting agencies.

Note: we are not changing the company's source industry. If a company is listed as IT Services and IT Consulting on LinkedIn or another source, we keep that industry as-is. This means you can still inspect the original industry, and to exclude third-party staffing and recruiting firms, use our Company Type → Direct Employer filter.

Use it in Company Search by selecting Company Type → Direct Employer.

You can now filter jobs by region, county, or metro area

55 million jobs that you couldn't find before — now you can.

When you searched for jobs in Greater London, Los Angeles County, Tokyo or any other county / borough / region / metro area, you'd get back a tiny fraction of the actual jobs in that area. The region a city belongs to wasn't being recorded correctly on most jobs, so when you filtered by that region, almost nothing came back.

We fixed the ingestion so every new job gets the right region tagged, and we backfilled every historical job in the database. 55.2 million jobs are now discoverable through region / county / metro filters that were previously missing them.

Examples

Jobs that match each filter over a 90-day window — click any row to run the search live:

What you need to do

Nothing. If you're already filtering by region IDs via job_location_or / job_location_not (the admin2_id-typed entries in the location catalog) or via the Job Location filter in the UI, your existing queries will start returning the correct, much higher counts. Historical results refresh automatically.