Ashby Job Board Postings - Company Jobs, Pay, Remote avatar

Ashby Job Board Postings - Company Jobs, Pay, Remote

Pricing

from $0.70 / 1,000 job row writtens

Go to Apify Store
Ashby Job Board Postings - Company Jobs, Pay, Remote

Ashby Job Board Postings - Company Jobs, Pay, Remote

Open roles from any Ashby-hosted job board, read through Ashby's documented public posting API - keyless, no browser. One row per posting: title, department, team, location plus every secondary location, remote flag, workplace type, employment type, pay range, published date and apply link.

Pricing

from $0.70 / 1,000 job row writtens

Rating

0.0

(0)

Developer

Samat Makatov

Samat Makatov

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Open roles from any Ashby-hosted job board, read through Ashby's documented public posting API - keyless, no browser. One row per posting: title, department, team, location plus every secondary location, remote flag, workplace type, employment type, pay range, published date and apply link.

Give it the companies you follow — Ramp, Linear, Vanta, elevenlabs — and every open posting of their boards comes back as a flat row: job title, department and team, the location the employer typed, all secondary locations of a role that is open in several countries, the remote flag and workplace type, employment type, the published pay range parsed into numbers, the publication time in UTC and the links to the posting and to its application form. No API key, no proxy and no browser: one plain HTTPS request per board, filtered and sorted here.

Need it tailored to your workflow? Missing a field, a filter, another source or a different output format? Open an issue and describe what you need — we read every request and adapt the actor.

Use cases

  • Watch the hiring of companies you care about: run a list of boards on a schedule with sinceHours and onlyNew and the dataset holds only the roles that went live since the last run — the hiring signal behind account research.
  • Build a niche job board: take a shortlist of employers, keep the roles that match titleKeywords and locationContains, and publish the rows with their apply links.
  • Benchmark published pay: withCompensationOnly plus the parsed salaryMin / salaryMax / salaryCurrency / salaryInterval turn pay-transparency ranges into a table you can average.
  • Find remote roles across a shortlist: remoteOnly uses the employer's own flag, and workplaceTypes the field the company set on the posting — no guessing from location text.
  • Feed postings to a model: includeDescription adds the full description as plain text and as HTML, ready for screening, skill extraction or matching.
  • Fill a CRM or lead pipeline: postedWithinDays answers "which of my target accounts started hiring" with the department, country and job link in the same row.

Input

Only boardNames is required. Filters are combined with AND, the values inside one filter with OR.

FieldTypeDefaultAllowed values / notes
boardNamesstring[]requiredAshby boards, e.g. ["Ramp", "Linear"]. The name is the segment in jobs.ashbyhq.com/<board>; the whole address (with or without a posting id) works too. Case does not matter. One request per board
titleKeywordsstring[]allKeep a posting when its title contains one of these words, case-insensitive
excludeTitleKeywordsstring[]noneDrop a posting whose title contains one of these words. Applied after titleKeywords
departmentsstring[]allKeep postings whose department or team contains one of these. Labels are each company's own — see Departments and teams
locationContainsstring[]allKeep postings whose location wording contains one of these. Searched over the primary location, every secondary location and the city, region and country of the address — the locationsText column of a row is exactly that text
workplaceTypesstring[]allRemote, Hybrid, OnSite — see Workplace types
employmentTypesstring[]allFullTime, PartTime, Intern, Contract, Temporary — see Employment types
remoteOnlybooleanfalseKeep only postings the employer marked remote (isRemote)
withCompensationOnlybooleanfalseKeep only postings with a published pay range. Needs includeCompensation on
postedWithinDaysintegerno limitPublished in the last N days, 1–365, counted in UTC
sinceHoursintegerno limitPublished in the last N hours, 1–8760, counted in UTC
onlyNewbooleanfalseWrite only postings that were not delivered by an earlier run — one memory per saved task, see Scheduling
includeDescriptionbooleanfalseAdd descriptionText and descriptionHtml to every row
includeCompensationbooleantrueAsk the API for pay and fill the salary columns
includeUnlistedbooleanfalseAlso write postings whose isListed is false (kept off the company's board page)
sortBystringpublishedDescpublishedDesc, publishedAsc, titleAsc, boardOrder — see Sort orders
maxItemsinteger25Hard ceiling on the rows of a run, marker rows included, 1–5000. With several boards these are the first rows of one sort across all of them
maxItemsPerBoardintegerno capRows taken from each board before the global ceiling, 1–2000
fieldsstring[]allKeep only these output fields, in this order. boardName and found are always kept. A near miss (titel) or another letter case is corrected and a name that is no column is left out — both are named in the status message; when no name is a column the run stops before any request. Naming a description column switches includeDescription on

Reference

Board names

A company's Ashby board lives at jobs.ashbyhq.com/<board> — Ramp, Vanta, Linear, elevenlabs, Sierra, Modal. Copy that last segment, or paste the whole address of the board or of a single posting; the name is taken out of it. Upper and lower case lead to the same board; Ashby echoes the case you asked with, so the company column and the posting links keep your spelling (RAMP stays RAMP) — compare board names case-insensitively. A name Ashby does not serve comes back as one row with found: false and the run still ends as succeeded — even when that was the only name asked for, so a typo in a scheduled run never turns the schedule red. A company that hires elsewhere simply has no Ashby board. A run fails only if the API itself stays unreachable for every board it tried, because then nothing is known about any of the names — and such a run writes no row, so it costs only the start event. After three boards in a row without an answer the remaining boards are not tried; the status message and SUMMARY.boardsNotRead name them.

Workplace types

TokenWhat the employer means
RemoteThe role is not tied to an office
HybridOffice and home, usually with a home base
OnSiteOn location

The field is optional on Ashby: many postings leave it empty, and those are never swept into a workplaceTypes filter. remoteOnly is a separate flag on the posting — a hybrid role can carry it too, so use workplaceTypes when you want strictly remote-first roles.

Employment types

FullTime, PartTime, Intern, Contract, Temporary — the form offers them as Full time, Part time, Internship, Contract and Temporary. Through the API send exactly these values: the platform checks the list before the run starts and refuses any other spelling ("full time", "full-time") with the list of allowed values.

Departments and teams

Ashby carries two levels and every company invents its own labels: Vanta files roles under the department Revenue with teams Sales Development and Account Executives, Linear uses GTM and Product, elevenlabs Engineering & Product. departments searches both levels, so ["Sales Development"] finds the team inside Revenue. To see what a board uses, run it once without filters and read the department and team columns. A value that no label of the board contains is corrected to the closest label of that board when it is obviously a typo ("Enginering" → "Engineering", or "Software Engineering" on a board that only has that); when nothing is close the value is kept as typed. Both cases are named in the run's status message (

departments: "Enginering" read as "Engineering" on Ramp
, no department or team contains "Revenue" on Linear) and in SUMMARY.filterCorrections / SUMMARY.filtersWithoutMatch, so a filter never quietly returns more than you asked for.

Sort orders

ValueOrder
publishedDescNewest publication first (default)
publishedAscOldest publication first
titleAscJob title A–Z
boardOrderThe order the board returns

With several boards the rows are ordered across all of them, after maxItemsPerBoard was applied.

Scheduling with onlyNew

onlyNew remembers board, posting id and publication time of every row written, in a named key-value store of your account, and writes only what was not delivered before. The first run returns everything it finds; a posting taken down and published again counts as new, because its publication time moved. Combine it with sinceHours on a schedule to keep runs small.

  • One memory per saved task. Run the actor from a saved task (that is what a schedule usually starts) and the task keeps its own memory (store ashby-job-postings-state-<task id>), so two schedules on the same board with different filters no longer hide postings from each other. A task's first run starts from what earlier runs of the actor delivered, so nothing comes twice after an upgrade. Runs started without a task (Console, API) share one memory (store ashby-job-postings-state).
  • Only what was really written is remembered. Rows cut by maxItems, by your max cost per run or by the run timeout are not remembered and come with the next run.
  • Marker rows come once. With onlyNew, the row of a board name the API does not serve and the row of a board without postings are written once, not on every run; a board the API did not answer for is reported by every run in which that happens.
  • Two runs of the same task that start at the same moment read the same memory — schedule them one after another.

Examples

Engineering roles at one employer

{ "boardNames": ["Ramp"], "titleKeywords": ["engineer"], "sortBy": "publishedDesc", "maxItems": 20 }

Remote roles across a shortlist of companies

{ "boardNames": ["Linear", "elevenlabs", "Modal"], "remoteOnly": true, "maxItemsPerBoard": 8, "maxItems": 24 }

Published pay ranges for a salary benchmark

{ "boardNames": ["Ramp", "Vanta"], "withCompensationOnly": true, "maxItems": 20 }

Revenue-side roles, department and team

{ "boardNames": ["Vanta", "elevenlabs"], "departments": ["Revenue"], "maxItems": 20 }

What appeared in the last 90 days (hiring signal)

{ "boardNames": ["Linear", "elevenlabs", "Vanta"], "postedWithinDays": 90, "maxItems": 20 }

Full posting text for a model

{ "boardNames": ["Sierra"], "includeDescription": true, "maxItems": 5 }

UK roles, secondary locations included

{ "boardNames": ["elevenlabs", "Linear"], "locationContains": ["United Kingdom"], "maxItems": 20 }

Output

One row per posting. A real row from the cloud run nG6mfs3wiP9SLeZa4 (2026-09-25) with {"boardNames": ["Ramp", "Vanta"], "includeCompensation": true, "withCompensationOnly": true, "sortBy": "publishedDesc", "maxItems": 20} (the errorCode column was added on 2026-10-02; it is null on every posting row):

{
"boardName": "Ramp",
"company": "Ramp",
"jobId": "72c3ef8f-e390-4ee1-9c0d-83b7b616ee17",
"title": "Principal Brand Designer",
"department": "Design",
"team": "Design",
"employmentType": "FullTime",
"location": "New York, NY (HQ)",
"secondaryLocations": [],
"locationsText": "New York, NY (HQ) | New York City | NY | USA",
"city": "New York City",
"region": "NY",
"country": "USA",
"isRemote": true,
"workplaceType": "Hybrid",
"isListed": true,
"publishedAt": "2026-09-25T21:05:27.698Z",
"hasSalary": true,
"salaryMin": 200000,
"salaryMax": 275000,
"salaryCurrency": "USD",
"salaryInterval": "year",
"compensationSummary": "$200K - $275K",
"compensationDetails": "$200K – $275K • Offers Equity",
"offersEquity": true,
"offersCommission": false,
"url": "https://jobs.ashbyhq.com/Ramp/72c3ef8f-e390-4ee1-9c0d-83b7b616ee17",
"applyUrl": "https://jobs.ashbyhq.com/Ramp/72c3ef8f-e390-4ee1-9c0d-83b7b616ee17/application",
"postingsOnBoard": 157,
"found": true,
"error": null,
"errorCode": null,
"sourceUrl": "https://api.ashbyhq.com/posting-api/job-board/Ramp?includeCompensation=true",
"fetchedAt": "2026-09-25T22:54:36.041Z"
}

A board name Ashby serves nothing for produces one marker row instead, and the run stays successful — cloud run b0tkqRVVnf0ebWCX3 with {"boardNames": ["Rmap"], "maxItems": 5} ended as succeeded with the status line 0 posting(s) from 0 of 1 board(s) · no board served for Rmap and one row. It carries the same columns as a posting row with the posting fields left null; the columns that say what happened are (errorCode added on 2026-10-02):

{
"boardName": "Rmap",
"company": null,
"title": null,
"postingsOnBoard": 0,
"found": false,
"error": "no Ashby job board is served for \"Rmap\" (the API answered 404). Open the company's job page and copy the name from jobs.ashbyhq.com/<board> — a company that does not hire through Ashby has no board at all.",
"errorCode": "board-not-found",
"sourceUrl": "https://api.ashbyhq.com/posting-api/job-board/Rmap?includeCompensation=true",
"fetchedAt": "2026-09-25T22:54:53.604Z"
}
FieldTypeAlways filledMeaning
boardNamestringyesThe board as you asked for it. Always kept, whatever fields lists
companystringfor found: trueThe board name, taken from the posting link — in the case you requested it (Ashby echoes it)
jobIdstringfor postingsAshby posting id (the last segment of the job link)
titlestringfor postingsJob title as published
departmentstringusuallyThe department the company filed the role under
teamstringusuallyThe narrower team inside the department
employmentTypestringusuallyFullTime, PartTime, Intern, Contract, Temporary
locationstringfor postingsThe primary location text the employer typed
secondaryLocationsstring[]when the role is open in several placesEvery further location of the posting
locationsTextstringfor postingsAll location wordings of the posting joined with | — the text locationContains searches
citystringwhen the address has oneaddressLocality of the posting address
regionstringwhen the address has oneState or region of the posting address
countrystringusuallyCountry of the posting address, as the employer wrote it ("USA", "United States")
isRemotebooleanwhen the employer set itThe remote flag of the posting, null when it was left empty
workplaceTypestringwhen the employer set itRemote, Hybrid or OnSite
isListedbooleanfor postingsWhether the posting is shown on the company's board page
publishedAtstringfor postingsFirst publication, ISO 8601 UTC
hasSalarybooleanyesWhether a pay range was published for this posting
salaryMinnumberwhen publishedLower end of the range, whole currency units
salaryMaxnumberwhen publishedUpper end of the range
salaryCurrencystringwhen publishedISO currency code, e.g. USD, GBP, SEK
salaryIntervalstringwhen publishedyear, month, hour — never assumed, always the employer's
compensationSummarystringwhen publishedThe range as the board shows it, e.g. $224K - $263K
compensationDetailsstringwhen publishedThe full pay line incl. equity, bonus and benefit notes
offersEquitybooleanyesEquity is part of the package
offersCommissionbooleanyesCommission is part of the package
descriptionTextstringwith includeDescriptionThe posting text, tags stripped
descriptionHtmlstringwith includeDescriptionThe description as published
urlstringfor postingsThe posting page on jobs.ashbyhq.com
applyUrlstringfor postingsThe application form of the posting
postingsOnBoardnumberyesHow many postings the board serves in total (before filters)
foundbooleanyesfalse only on the marker row of a board the API does not serve or did not answer for. Always kept, whatever fields lists
errorstringon marker rowsWhy a board produced no postings
errorCodestringon marker rowsboard-not-found (the API answered 404), board-empty (the board publishes nothing right now; found stays true) or board-unreachable (no usable answer: timeout, 5xx, throttling, a block)
sourceUrlstringyesThe API address the row came from
fetchedAtstringyesWhen the board was read, ISO 8601 UTC

Marker rows. A run never ends silently empty. A board name the API does not serve gives one row with found: false, the reason in error and errorCode: "board-not-found"; a real board without open roles gives one row with found: true, postingsOnBoard: 0, its own error text and errorCode: "board-empty"; a board the API did not answer for while others did gives found: false and errorCode: "board-unreachable". All keep the columns of a posting row, so the dataset stays one table; they come after the postings and count against maxItems. Marker rows do not fail the run: check found / errorCode in your code instead of the run status. With onlyNew the first two kinds are written once, not on every run.

SUMMARY. The key-value store of a run holds a SUMMARY record (linked from the run's output as summary): boards requested, served, without postings, not served, unreadable, emptied by the filters (boardsEmptiedByFilters: no posting passed the filters), cut by the row limit (boardsCutByLimit: postings passed but none fitted into maxItems or your max cost per run), already delivered (boardsAlreadyDelivered, onlyNew) and not read (boardsNotRead with the reason); the per-board counts (postingsOnBoard, matched, fresh, written), the filters as they were applied, every correction (corrections, filterCorrections), filtersWithoutMatch, sort order, limits, the onlyNew store, delivered, stoppedBy (limit, timeout or aborted when the run was cut short), the number of requests and the run's status line.

Dataset views: Open postings (the overview columns), Published pay (range, currency, interval, equity) and Recently published (what is new, with country, employment type and apply link).

Use it from code / agents

curl -X POST "https://api.apify.com/v2/acts/yadroo~ashby-job-postings/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"boardNames":["Ramp"],"titleKeywords":["engineer"],"maxItems":20}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/ashby-job-postings').call({
boardNames: ['Ramp', 'Vanta'],
withCompensationOnly: true,
fields: ['company', 'title', 'salaryMin', 'salaryMax', 'salaryCurrency', 'url'],
maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/ashby-job-postings").call(run_input={
"boardNames": ["Linear", "elevenlabs"],
"sinceHours": 24,
"onlyNew": True,
"maxItems": 50,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items

MCP: add https://mcp.apify.com to Claude / Cursor / any MCP client and call the yadroo/ashby-job-postings tool with the same JSON input. For an agent, keep includeDescription off until you really need the text — rows are about twenty times larger with it — and cut the row down with fields to the columns your prompt reads.

Pricing

Pay per event: $0.001 per run start + $0.001 per dataset row. A row is one posting — or the marker row of a board that returned nothing. The start event is charged once per GB of run memory, at least once — once at the default 256 MB. Nothing else is charged, and maxItems is the hard ceiling on what a run can cost. Your maximum cost per run is respected too: the run writes only the rows it pays for and ends with the status

Stopped at your spending limit: N rows delivered
; a run that fails because the API answered for no board writes no row.

RunCost
25 rows (the default)$0.026
50 rows$0.051
500 rows$0.501

Apify's paid plans discount every tier: Bronze −10 %, Silver −20 %, Gold and above −30 % on the per-row price; the start event stays flat. A 50-row run on Gold therefore costs $0.001 + 50 × $0.0007 = $0.036.

Limits & FAQ

  • Coverage is per company. Ashby has no cross-company search, so this actor reads the boards you name. Companies that use another applicant-tracking system have no Ashby board at all — the run says so in a found: false row.
  • No "changed since". Ashby publishes the first publication time only, so every time window here (postedWithinDays, sinceHours) is about when a posting appeared, never about when it was last edited.
  • Locations and departments are free text. Countries come out as the employer typed them ("United States", "USA", "US", "European Union"), and department labels differ per company. Match on the words a company would write, and read a board's own labels once before filtering.
  • Pay is published by the employer. Many boards publish no ranges at all; withCompensationOnly then returns nothing, which is an honest empty result and not an error. Ranges can be hourly or monthly — always read salaryInterval before averaging.
  • Large boards are slow. Descriptions are always part of the API response, so a board with a few hundred roles answers with several megabytes even when descriptions are not written out. maxItems does not make the download smaller, because the whole list comes in one response. The largest board measured while building this actor served 829 postings in 14.5 MB and was read inside 256 MB of memory in four seconds, so big boards cost time, not failures. With includeDescription, the rows that wait for the cross-board sort keep their descriptions compressed in a temporary file rather than in memory: 30 boards with 2,779 postings and descriptions ran in the default 256 MB (cloud run RELo8R4ZkNKjzTNE2, 134 s — writing rows with descriptions takes most of that, roughly 20 rows a second).
  • Run timeout. Boards are read one after another and the rows are written once every board is read (the order is one sort across all of them). Near the run timeout the actor stops starting new boards, writes what it has read and ends as succeeded with Stopped before the run timeout: N rows saved; the boards it did not read are named in the status and in SUMMARY.boardsNotRead. A request is never allowed to run past that point. With the default 15-minute timeout this matters only for long board lists — split those, or raise the timeout.
  • Unreachable source. After three boards in a row without an answer the remaining boards are not tried; the run keeps what it read and names the rest. If no board answered at all, the run fails and writes nothing.
  • Unlisted roles are only written with includeUnlisted; by default the output matches what a visitor of the board sees.
  • Rate limits. Ashby documents none for this endpoint. The actor sends one request per board, retries politely on 429 and 5xx and honours Retry-After. If the source ever puts the posting API behind a key, this actor is paused rather than worked around.
  • Which boards exist? Ashby has no directory. Open a company's careers page: if its job links point to jobs.ashbyhq.com, the segment after the host is the board name.

Made by Yadroo. Sibling actors: greenhouse-jobs · hh-kz-vacancies · github-repo-intel · google-news-search · rss-to-json