Search the starter list by place and role (free, not every employer)
jobs_search_by_location
Indexed Jobs search is COMING SOON: faster and more comprehensive than this free 135-board live scan. Indexed search covers 8,700+ boards. Get 8,700+ boards free with Apify's $5 starter credit: create an Apify account and an API token at https://console.apify.com/settings/integrations. Use the free tools until indexed search ships. jobs_search_companies is temporarily offline and does not run the old paid Actor.
WHAT: Free search of the bundled starter list (135 public Greenhouse, Lever and Ashby boards). Not every employer and not every company. No company name. Live jobs from each board's official public API. Same normalized "job" rows as jobs_get_board. One call may cover only part of the list.
WHEN: The user asks for jobs by place and/or role and does not name a company. Call THIS tool immediately. Do not ask the user for a company. Do not call jobs_get_board or jobs_find_board first. Examples: "avionics jobs in Baltimore MD", "avionics jobs in Costa Mesa", "remote RN jobs in PA", "nursing jobs in Maryland". Put the place in locations (Baltimore, Baltimore MD, MD, Maryland, BWI, PA, Costa Mesa) or countries, or set remote to "only". Put a skill or role that may not be the job title in descriptionIncludes (avionics, nurse), not in titleIncludes.
WHEN NOT: The user already named one company or board (jobs_find_board, then jobs_get_board). They want history, closed jobs, reposts, or employers outside this starter list: indexed search (faster, 8,700+ boards) is COMING SOON. jobs_search_companies is temporarily offline and does not run the old paid Actor. This tool does not search all companies. The free limits stay 135 starter boards.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. Each starter-list board slug is sent to its public ATS host. Requires a place signal or it returns INVALID_INPUT and does not fetch: a non-empty locations list, a non-empty countries list, or remote "only". Reads starter boards with the same client, kill switch and rate limits as the other free tools (at most 2 requests in flight per host, Lever spaced 1 s apart, up to 4 boards at a time). A board GET that fails before any job is read (network error, timeout, or HTTP 5xx) is retried once after about 300 ms and that retry is named in meta.notes. HTTP 403 and 429 are not retried. A second failure is skipped and named in meta.notes. The retry is skipped when the CPU budget, the wall clock, or the request cap is already spent. Greenhouse matches title and department on the lite list before any body request. A body is a second request to that same host only when a description keyword is still missing from the title and department, or includeDescription needs the text, and the lite list already has a job in the place. A Greenhouse board with more than 1000 jobs does not get a body request (the Anduril body is about 44 MB and does not fit the 128 MB isolate). Those boards are listed in meta.title_only_boards and return title and department matches only. Lever and Ashby descriptions are in the one list response. Each board is read in small slices, one job at a time. Description fields are not copied unless descriptionIncludes or includeDescription needs them. A text field longer than 20,000 characters is cut before matching and named in meta.notes. A board that is still too large is cut off and the scan continues. A missing board (BOARD_NOT_FOUND) is skipped. A board error is skipped and named in meta.notes. HOST_BLOCKED stops that host for the session; other hosts continue. The scan stops early on a 25 second wall clock, on the CPU work budget (12,000 ms estimated, a hard ceiling, 8,000 JSON characters per millisecond plus 0.08 ms per row built, because the hosted Worker clock does not advance during synchronous parsing; Paid Workers default to about 30 seconds of CPU and this soft-stop returns JSON before that; one call does not run unbounded), on a cap of 200 matched rows, or after 300 ATS requests (a hard ceiling: 135 starter boards take one lite request each, plus a Greenhouse body only when a description is still needed and the board has at most 1000 jobs, at most about 223 requests; Paid Workers allow 10,000 subrequests). It returns the jobs already matched (meta.partial true, meta.stop_reason "time_budget", "cpu_budget", "row_cap" or "subrequest_budget", meta.cost_usd 0). A scan error still returns that JSON (meta.stop_reason "error"); it does not throw a Server error and it does not invent jobs. Nothing is stored. offset pages rows inside this response. It does not continue the board walk. Pass boardCursor from meta.next_board_cursor, with the same place and keywords, to read boards this call did not start. next_board_cursor is null only when every board from the current board_cursor through the end was started, or no boards remain. Do not call again when it is null. A cpu_budget, subrequest_budget, time_budget, or row_cap stop before the end of the list sets it to the next unstarted index. A board error is skipped and named in meta.notes; it does not rewind the cursor behind boards this call already started.
COST: No APIFY_TOKEN, no billing. meta.cost_usd is 0.
RETURNS: Paged "job" rows. meta.notice (also meta.notes[0]) is the coming-soon indexed search note: faster than this 135-board scan, indexed search covers 8,700+ boards, and Apify's $5 starter credit at https://console.apify.com/settings/integrations. When meta.partial is true or the board walk is incomplete, meta.notice starts with how many of meta.boards_total boards this call finished. Also meta.boards_total, meta.boards_reached (boards this call started), meta.boards_scanned (boards that finished), meta.boards_ok, meta.boards_failed, meta.boards_skipped, meta.jobs_matched, meta.partial, meta.complete, meta.cut, meta.board_cursor, meta.next_board_cursor, meta.notes and meta.cost_usd. meta.stop_reason is set when partial is true. meta.title_only_boards lists Greenhouse boards whose body was skipped. meta.complete is true when this call started every board from board_cursor through the end and did not hit a budget. meta.next_board_cursor is the first starter index this call did not start, or null when nothing is left to resume. meta.cut is true when coverage is narrower than a full read. When jobs_matched is 0 after at least one board answered, meta.suggestions lists the title and description tokens tried, place aliases that had open roles, a sample of open titles in the requested place with the keyword removed, and a note that this list is not every employer and which ATS are covered. Suggestions are not job listings. Relay meta.notice to the user.
PARAMETERS: At least one of locations, countries or remote "only" is required. There is no company parameter. titleIncludes and titleExcludes are whole words on the title only. descriptionIncludes is whole-word on the title, the department, or the scrubbed description, so "avionics" matches an Avionics department or Electrical Technician when the body says avionics. Do not put the same word in both titleIncludes and descriptionIncludes. "RN" matches RN, not "Registered Nurse". titleRegex is optional. postedWithinDays drops rows with no ATS date. includeDescription adds scrubbed plain text to the rows; descriptionIncludes still matches when it is false and does not add that text. Location terms expand US state names and codes both ways (MD and Maryland, PA and Pennsylvania) and metro aliases (NYC, SF, LA, DC, Tampa Bay, Baltimore / Baltimore MD / BWI). Two-letter codes match as whole tokens. countries stays ISO-2. boardCursor is an index into the starter list, not a row offset.
EXAMPLE: {"locations":["Costa Mesa"],"descriptionIncludes":["avionics"]} -> starter-list jobs in Costa Mesa whose title, department or description says avionics. If meta.complete is false and meta.next_board_cursor is a number, call again with the same filters and
Schema valid · SHA-256 60d9d1ce2bfe…
View input schema
{
"type": "object",
"properties": {
"titleIncludes": {
"description": "Optional, 0-50 strings, any-of. Keep titles containing any of these whole words/phrases, case-insensitive. Title only. For a skill that may appear only in the posting, use descriptionIncludes instead. Example: [\"engineer\"]",
"maxItems": 50,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 100
}
},
"titleExcludes": {
"description": "Optional, 0-50 strings, any-of. Drop titles containing any of these. Example: [\"intern\"]",
"maxItems": 50,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 100
}
},
"descriptionIncludes": {
"description": "Optional, 0-50 strings, any-of. Whole words matched against the title, the department, or the scrubbed description, case-insensitive, any-of. Use this for a role or skill that may not be the job title (\"avionics\" matches an Avionics department, or Electrical Technician when the body says avionics). Do not also put the same word in titleIncludes. \"RN\" does not match \"Registered Nurse\". Greenhouse checks title and department on the lite list first. The row includes description_text only when includeDescription is true. Example: [\"avionics\"]",
"maxItems": 50,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 100
}
},
"titleRegex": {
"description": "Optional case-insensitive regular expression the title must match (max 200 characters, no nested quantifiers). Example: \"^senior\\\\b\"",
"type": "string",
"minLength": 1,
"maxLength": 200
},
"locations": {
"description": "Optional, 0-50 strings, any-of. Place names, any-of. US state names and codes match both ways (Baltimore MD, MD, Maryland, FL, Florida). Metro aliases include NYC, SF, LA, DC, Tampa Bay, and Baltimore / BWI. \"remote\" also matches ATS remote flags. At least one of locations, countries or remote \"only\" is required. This tool has no company parameter. Example: [\"Tampa\"]",
"maxItems": 50,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 100
}
},
"countries": {
"description": "Optional ISO-3166 alpha-2 codes, any-of, case-insensitive. Counts as a place signal. Example: [\"US\"]",
"maxItems": 50,
"type": "array",
"items": {
"type": "string",
"pattern": "^[A-Za-z]{2}$"
}
},
"remote": {
"description": "Optional, \"any\" | \"only\" | \"exclude\", default \"any\". \"only\" is a place signal and keeps remote jobs. \"exclude\" alone does not start a scan.",
"type": "string",
"enum": [
"any",
"only",
"exclude"
]
},
"postedWithinDays": {
"description": "Optional integer 1-3650: keep jobs whose ATS publish date is at most this many days old. Example: 14",
"type": "integer",
"minimum": 1,
"maximum": 3650
},
"longOpenDays": {
"description": "Optional integer, default 60: rows older than this get long_open = true (a heuristic, not proof of a ghost job)",
"type": "integer",
"minimum": 1,
"maximum": 3650
},
"includeDescription": {
"description": "Optional boolean, default false. true adds description_text (plain text, <= 20,000 chars, e-mails/phones removed)",
"type": "boolean"
},
"limit": {
"description": "Optional page size, integer 1-500, default 50",
"type": "integer",
"minimum": 1,
"maximum": 500
},
"offset": {
"description": "Optional items to skip, integer >= 0, default 0; pass nextOffset from the previous response",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"boardCursor": {
"description": "Optional index into the starter list, integer >= 0, default 0. Pass meta.next_board_cursor from the previous response, with the same place and keywords, to continue boards that call did not start. This is not the row offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}