Bosco Labs

Tools › Companies

Company Hiring Signals API: open roles, departments, locations

Coming soon to the Store

Is a company hiring, for what, where and since when? Give company names, domains or job board URLs; get one summary per company (open roles by department, location and country, remote share, newest and oldest posting dates, top titles) plus the open jobs, each with a link to the posting. Built for AI agents doing sales prospecting, recruiting or market research, and for people who want hiring data without scraping LinkedIn or Indeed.

Price$0.005 per company found plus $0.001 per job row
DomainCompanies
Call itApify API or MCP

Pricing (pay per event): $0.005 per company summary and $0.001 per job row. Companies without a public board on a supported provider cost nothing.

Coming soon to the Apify StoreAsk for early access

Questions agents ask

  • “Is Notion hiring engineers? How many roles, where, and since when? Link the postings.”

Example

Input

{
  "companies": ["stripe.com", "Notion", "https://jobs.lever.co/spotify"],
  "departments": ["engineering"],
  "postedSince": "30d",
  "maxJobsPerCompany": 20
}

Output

{
  "schema_version": "1",
  "row_type": "company_summary",
  "company": "notion.so",
  "found": true,
  "provider": "ashby",
  "board_token": "notion",
  "board_url": "https://jobs.ashbyhq.com/notion",
  "source_url": "https://api.ashbyhq.com/posting-api/job-board/notion",
  "total_open_roles": 150,
  "matching_roles": 16,
  "filters": { "keywords": ["engineer"], "posted_since": "2026-09-06T00:00:00Z" },
  "by_department": [
    { "name": "Engineering", "count": 8 },
    { "name": "Security", "count": 3 },
    { "name": "Sales", "count": 2 }
  ],
  "by_location": [
    { "name": "San Francisco, California", "count": 11 },
    { "name": "Dublin, Ireland", "count": 2 },
    { "name": "Hyderabad, India", "count": 1 }
  ],
  "by_country": [
    { "name": "United States", "count": 12 },
    { "name": "Ireland", "count": 2 },
    { "name": "India", "count": 1 }
  ],
  "remote_share": 0.0,
  "posted_last_30_days": 6,
  "newest_posted_at": "2026-11-04T23:19:02Z",
  "oldest_posted_at": "2026-09-08T20:54:37Z",
  "top_titles": [
    { "title": "Security Engineer, Detection and Response", "count": 2 },
    { "title": "Forward Deployed Engineer, India", "count": 1 },
    { "title": "Security Engineer, Corporate Security", "count": 1 }
  ],
  "trend": null,
  "jobs_returned": 3,
  "other_boards": [],
  "not_found_reason": null,
  "warnings": [],
  "retrieved_at": "2026-11-05T21:42:10Z"
}

What you get

FieldTypeMeaning
schema_versionstringOutput schema version.
row_typestringcompany_summary (one per input company, found or not) or job (one per open role).
companystringThe company as given in the input.
foundboolean | nullSummary rows: true if a public job board was found. Not-found rows are free of charge.
providerstring | nullJob board provider: greenhouse, lever, lever-eu (Lever's EU instance) or ashby.
board_tokenstring | nullThe company's board name at the provider, e.g. stripe. Pass it as provider:token for an exact lookup.
board_urlstring | nullSummary rows: the company's public job board page.
source_urlstring | nullSummary rows: the public API URL all counts were computed from. Job rows: the job's public posting page.
total_open_rolesinteger | nullSummary rows: all open roles on the board, before filters.
matching_rolesinteger | nullSummary rows: open roles matching departments, locations, keywords and postedSince. All counts below are over these.
filtersobject | nullSummary rows: the filters applied (lower-cased), null if none.
by_departmentarraySummary rows: top 15 departments as {name, count}, largest first. Roles without a department are not listed.
by_locationarraySummary rows: top 15 primary locations as written by the company, as {name, count}.
by_countryarraySummary rows: top 15 countries as {name, count}: ISO codes for Lever, country names for Ashby, empty for Greenhouse (no country field).
remote_sharenumber | nullSummary rows: share of matching roles marked remote, 0-1. Greenhouse: roles whose location text says remote. null when no roles match.
posted_last_30_daysinteger | nullSummary rows: matching roles posted in the 30 days before retrieved_at.
newest_posted_atstring | nullSummary rows: newest posting date among matching roles (ISO 8601 UTC).
oldest_posted_atstring | nullSummary rows: oldest posting date among matching roles: how long the company has been hiring for its open roles.
top_titlesarraySummary rows: the 10 most common job titles as {title, count}.
trendobject | nullSummary rows with compareWithPrevious: {previous_retrieved_at, previous_total_open_roles, change, new_jobs, closed_jobs} versus the last such run. null on the first run or when off.
jobs_returnedinteger | nullSummary rows: job rows returned for this company (at most maxJobsPerCompany, newest first).
other_boardsarraySummary rows: other boards found for the same name (usually old, smaller ones). The board with most open roles is used.
not_found_reasonstring | nullSummary rows: why no board was found, and how to fix it. null when found.
warningsarraySummary rows: caveats in plain words, e.g. a provider that could not be read or several providers with a board under the same name.
job_idstring | nullJob rows: the provider's job posting ID.
titlestring | nullJob rows: job title as published.
departmentstring | nullJob rows: department (Greenhouse: top-level department).
teamstring | nullJob rows: team or sub-department, null if none or the same as department.
locationstring | nullJob rows: primary location as written by the company.
other_locationsarrayJob rows: further locations of the same posting (Lever, Ashby).
countrystring | nullJob rows: country: ISO 3166 alpha-2 for Lever, country name for Ashby, null for Greenhouse.
workplace_typestring | nullJob rows: remote, hybrid or on-site (Lever, Ashby); null when not stated or on Greenhouse.
remoteboolean | nullJob rows: true if remote; false if hybrid or on-site; null when unknown. Greenhouse: true when the location text says remote, else null.
employment_typestring | nullJob rows: as the provider gives it, e.g. FullTime, Intern (Ashby) or Permanent (Lever commitment). null on Greenhouse.
posted_atstring | nullJob rows: ISO 8601 UTC. Greenhouse: first published; Lever: created; Ashby: last published.
updated_atstring | nullJob rows: last update (Greenhouse only), ISO 8601 UTC.
retrieved_atstringWhen the board was read (ISO 8601 UTC).

Use with AI agents (MCP)

Add this URL to your MCP client (Claude, Cursor, VS Code, ...) to load the Actor as a tool through the Apify hosted MCP server. It signs you in with OAuth or accepts Authorization: Bearer <APIFY_TOKEN>. It works once the Actor is live on the Apify Store.

https://mcp.apify.com?tools=bosco_labs/company-hiring-signals

For “Is Notion hiring engineers? How many roles, where, and since when? Link the postings.” the agent passes:

{ "companies": ["notion.so"], "keywords": ["engineer"], "maxJobsPerCompany": 10 }

stable snake_case fields, ISO 8601 UTC dates, counts as numbers, null for unknown, a source URL per row. One summary is about 2-4 KB; a 5-company summary-only run is under 20 KB. Typical time: 5-15 seconds for 5 companies (Lever asks for one request per second, so many Lever lookups take a little longer).

Or call the Apify API: POST https://api.apify.com/v2/acts/bosco_labs~company-hiring-signals/run-sync-get-dataset-items with the input as JSON body. Cost: $0.005 per company found plus $0.001 per job row.

Input fields

FieldTypeMeaning
companiesarray (required)Companies to check, 1-50: a name ("Notion"), a website domain ("stripe.com"), a job board URL ("https://jobs.lever.co/spotify", "https://job-boards.greenhouse.io/airbnb", "https://jobs.ashbyhq.com/ramp") or provider:token ("greenhouse:stripe", "lever:spotify", "lever-eu:<token>", "ashby:notion"). Names and domains are matched to likely board names on Greenhouse, Lever and Ashby; a board URL is exact. Required.
departmentsarrayOnly count and return roles whose department or team has a word starting with one of these, case-insensitive, e.g. ["engineering", "data"]. Department names are each company's own (Stripe uses "Tech" and team codes), so keywords on the title is often more reliable. Empty = all departments.
locationsarrayOnly roles whose location text, other locations or country contains one of these as whole words, case-insensitive ("US" does not match "Australia"), e.g. ["London", "Germany", "remote"]. Lever gives ISO country codes ("GB"), Ashby country names; Greenhouse has the location text only. Empty = all locations.
keywordsarrayOnly roles whose job title has a word starting with one of these, case-insensitive ("engineer" matches "Engineering", "ai" not "Retail"), e.g. ["engineer", "data scientist"]. Empty = all titles.
postedSincestringOnly roles first published on or after this date: an ISO date ("2026-10-01") or a number of days back ("30d"). Greenhouse: first published; Lever: created; Ashby: last published. Empty = any date.
maxJobsPerCompanyintegerMost job rows to return per company, newest first, e.g. 20. Default 50, maximum 1000; 0 = summary only. The summary always counts all matching roles, whatever this limit. Each job row is charged.
summaryOnlybooleantrue = one summary row per company and no job rows (cheapest; answers "is X hiring and where?"). Default false.
compareWithPreviousbooleantrue = add a trend (change in open roles, new and closed jobs) versus the last run that also had this on, and save this run's job IDs for next time in the key-value store "company-hiring-signals-history" in your account. The first run has no trend. Default false.

Sources, licence and limits

Which companies are covered? Companies whose public job board runs on Greenhouse, Lever or Ashby: many tech and venture-backed companies (Stripe, Airbnb, Figma, Spotify, Palantir, Notion, Ramp, ...). Companies on Workday, SmartRecruiters, Workable, iCIMS, SuccessFactors or their own careers site are not covered and come back as found: false at no charge.

A name gave no board or the wrong one. Board names don't always match the company name. Open the company's careers page, follow a job link, and pass that URL (e.g. https://job-boards.greenhouse.io/airbnb) or greenhouse:airbnb.

Why is by_country empty, or remote null? Greenhouse has no country or workplace field: remote is true only when the location text says "remote", and country counts are empty. Lever gives ISO country codes (GB), Ashby country names (United Kingdom).

What do departments look like? Each company names its own. Some use broad names ("Engineering"), some internal codes (Stripe: "Tech" with teams like "8217 Risk Engineering"). For Greenhouse, department is the top-level department and team the one the job sits in. Filtering on title keywords is often more reliable across companies.

What does posted_at mean? Greenhouse: first published; Lever: when the posting was created; Ashby: when it was last published. Postings are as the company publishes them; the Actor doesn't check whether a role is really still open.

Are job descriptions or salaries included? No. Rows hold titles, departments, locations, dates and links; descriptions stay on the linked posting page.

Personal data? Company-level data only. No recruiter or hiring-manager names or emails are collected or output.

How fresh is it? Live: every run reads the job boards directly.

Coming soon to the Apify StoreAsk for early access