BetterJobs index
betterjobsOur own job sources: an owned crawl of employer career pages and ATSs.
A provider is one upstream source of job data. BetterJobs can route a search to seven of them: its own index and six partner providers. You never call a provider yourself. You send one request, BetterJobs asks the providers your plan enables, merges what they return and bills you 1 credit per unique job.
One signup, one key, one invoice. Not a separate signup, key and invoice for every provider.
betterjobsOur own job sources: an owned crawl of employer career pages and ATSs.
reqbeatDeduplicated, normalized job postings and hiring events from ATSs, job boards and aggregators.
signalsapiRecruiter-focused hiring signals plus the hiring owner's verified work email.
theirstackGlobal job postings, technographics inferred from job text, buying intent and firmographics.
jobspipeNormalized job postings from 30+ sources with 12 months of history.
coresignalLarge historical job-posting dataset plus company and employee records.
techmapHigh-volume job feeds from ATSs, job boards and public employment offices (jobdatafeeds.com).
Each card links to the provider’s page. Provider facts there are the provider’s own published claims, attributed to them. They are not BetterJobs measurements.
| Source | Slug | Refresh (as published) | Cheapest plan |
|---|---|---|---|
| BetterJobs index | betterjobs | Published at GA. Each job carries first_seen_at, last_seen_at and last_verified_at. (BetterJobs) | Free |
| Reqbeat | reqbeat | Corpus refreshed every 3 hours (per Reqbeat docs) | Growth |
| SignalsAPI | signalsapi | Sources rechecked every 15 minutes (per SignalsAPI docs) | Growth |
| TheirStack | theirstack | 73% of jobs discovered the same day, 91% by the end of the next day (per TheirStack docs) | Growth |
| JobsPipe | jobspipe | Under 6h on Builder, under 1h on Scale (per JobsPipe docs) | Growth |
| Coresignal | coresignal | Active postings rechecked within 24h (per Coresignal docs) | Growth |
| Techmap | techmap | Daily country feeds via AWS Data Exchange (per Techmap (jobdatafeeds.com)) | Growth |
| Plan | Price / month | Credits / month | $ / 1k credits | Providers | Includes |
|---|---|---|---|---|---|
| Free | $0 | 1,000 | — | Own job sources only | 1,000 credits to test, No card required |
| Starter | $19 | 5,000 | $3.80 | Own job sources only | No partner providers |
| Growth | $49 | 10,000 | $4.90 | Own sources + 2 partner providers | API, CSV, MCP |
| Pro | $199 | 60,000 | $3.32 | Max coverage: all six providers | Everything in Growth, plus Webhooks, CRM sync |
| Scale | $599 | 250,000 | $2.40 | All six providers | Everything in Pro, plus Bring your own provider keys, Priority support |
| Enterprise | from $1,500 | Custom | — | Contact sales | — |
Your key’s exact set is live data, not a table on this page. GET /v1/providers returns every source with enabled_on_your_plan and its live status. GET /v1/account returns the same set as providers_enabled.
curl https://api.betterjobs.cc/v1/providers \ -H "Authorization: Bearer $BETTERJOBS_API_KEY" \ -H "BetterJobs-Version: 2026-10-01"import osimport requests
resp = requests.get( "https://api.betterjobs.cc/v1/providers", headers={ "Authorization": f"Bearer {os.environ['BETTERJOBS_API_KEY']}", "BetterJobs-Version": "2026-10-01", },)resp.raise_for_status()for p in resp.json()["data"]: print(p["slug"], p["enabled_on_your_plan"], p["status"])const resp = await fetch('https://api.betterjobs.cc/v1/providers', { headers: { Authorization: `Bearer ${process.env.BETTERJOBS_API_KEY}`, 'BetterJobs-Version': '2026-10-01', },});if (!resp.ok) throw new Error(`BetterJobs ${resp.status}`);const { data } = await resp.json();for (const p of data) console.log(p.slug, p.enabled_on_your_plan, p.status);The call is free. Illustrative response, seen from a Growth plan:
{ "data": [ { "slug": "betterjobs", "name": "BetterJobs index", "enabled_on_your_plan": true, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" }, { "slug": "theirstack", "name": "TheirStack", "enabled_on_your_plan": true, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" }, { "slug": "coresignal", "name": "Coresignal", "enabled_on_your_plan": false, "status": "degraded", "last_checked_at": "2026-10-11T09:00:00Z" } ]}Trimmed to three rows. The full example is in List providers.
You do not pick providers per request unless you want to. The waterfall.strategy on the request decides which sources are asked and in what order. The default is cheapest_first: it starts with the BetterJobs index and adds partner providers only until the page is full. max_coverage asks every provider on your plan. own_only asks the BetterJobs index only.
To pin sources yourself, list them in waterfall.providers:
"waterfall": { "providers": ["betterjobs", "theirstack"], "max_credits": 100 }Every slug must be enabled on your plan. If one is not, the request returns 403 plan_required with required_plan and upgrade_url. See plan_required.
Each source gets the query translated into its own grammar and field names. Records that describe the same opening merge into one canonical job. sources[] on each job lists every provider that saw it and the fields it contributed. The full flow is in The waterfall. For picking a strategy, see Choose a strategy.
A failing or slow provider never fails your request. You still get 200. The response tells you what happened:
metadata.status is partial instead of complete.metadata.providers.failed lists each provider that dropped out, with code provider_timeout (it missed waterfall.timeout_ms) or provider_error."metadata": { "status": "partial", "credits_charged": 1, "providers": { "tried": ["betterjobs", "techmap", "theirstack", "coresignal"], "hit": ["betterjobs", "techmap", "theirstack"], "failed": [{ "provider": "coresignal", "code": "provider_timeout" }], "contributions": { "betterjobs": 1, "techmap": 0, "theirstack": 0 } }}Illustrative, from the spec’s partial example.
Async searches report the same way: GET /v1/searches/{id} finishes with status: partial when a provider failed. See Errors and partial results.
Check status in GET /v1/providers: operational, degraded or down, with last_checked_at. How to use it, and what we publish about provider health, is on Provider status.
sources[]