- API reference
- Endpoints
Dataset metadata
Live counts, per-field coverage, the freshness timestamp, and the exact source vocabulary.
https://api.hyperjobs.io/v1/metaLive dataset statistics: how many jobs, how many companies, how fresh, the
breakdown by source — and coverage_pct, the measured fill rate of every
enriched field. One cheap request, no parameters.
curl -H "Authorization: Bearer $HYPERJOBS_KEY" https://api.hyperjobs.io/v1/metaQuery parameters#
None. The endpoint takes no input; anything you send is ignored.
It does require a key, unlike /v1/health, and it
counts against your rate limit and monthly quota like any
other authenticated call.
Response#
jobsLive postings — non-duplicate and non-expired. This is the population
/v1/jobs searches, and it's
the same number /v1/health reports.
companiesCompanies with an enriched profile. See the Company object.
newestISO 8601 timestamp of the most recent posting — the freshness signal. The index refreshes hourly.
sourcesMap of public source slug to posting count, sorted descending by
count. The keys are the exact valid values for ?source= — lever, not
the stored lever.co.
coverage_pctLive per-field fill rates, as percentages of the searchable pool: country,
skills, work_arrangement, seniority, taxonomies, salary,
education, language. Remeasured roughly every 15 minutes — see
below.
full_text_searchWhether Google-style and advanced text search (title, description,
title_advanced, description_advanced) is active on this deployment.
versionAPI version, e.g. "1.0.0".
{
"jobs": 596768,
"companies": 158545,
"newest": "2026-07-16T09:48:15.000Z",
"sources": {
"smartrecruiters": 216791,
"linkedin": 87462,
"lever": 74374
},
"coverage_pct": {
"country": 96.8,
"skills": 83.7,
"work_arrangement": 91.2,
"seniority": 88.7,
"taxonomies": 63.9,
"salary": 36.0,
"education": 71.5,
"language": 94.2
},
"full_text_search": true,
"version": "1.0.0"
}That's the entire shape — there are no other keys.
The sources keys are the ?source= vocabulary#
The keys are public slugs — lever, not the stored value lever.co
that an early draft of this API exposed — and they are exactly what ?source= on
/v1/jobs accepts and what the source
field on every Job payload carries: one vocabulary everywhere.
(?source=lever.co still works as input for backward compatibility, but
you'll never see it in a response.)
So /v1/meta remains the authoritative answer to "what can I pass to
?source=" — read the keys rather than guessing:
const { sources } = await (await fetch(url, { headers })).json();
if (!(userInput in sources)) {
throw new Error(`Unknown source. Valid: ${Object.keys(sources).join(", ")}`);
}That check is still worth writing: source is an open vocabulary rather than a
fixed enum, so an unrecognized value returns an empty result instead of a
400. The sources reference has the
prose version, including which ATS each slug corresponds to.
Published coverage#
coverage_pct is the honesty feature: we publish the fill rate of every
enriched field, measured live against the searchable pool, refreshed about
every 15 minutes. When salary coverage is 36.6%, the API says 36.6 — you can
size a has_salary=true result set before you query, and you never have to
wonder whether a low fill rate is your filter or our data.
Read it before building on any enriched field, and see dataset coverage for what drives each number.
`jobs` matches /v1/health
In a pre-release draft, /v1/health counted every row —
duplicates and expired included — and reported a higher number than /v1/meta.
Both endpoints report the same live
(non-duplicate, non-expired) count. Quote it from either.
Use it instead of hardcoding numbers#
The dataset grows hourly. Anything that states a count — a dashboard, a landing page, a "we track N jobs" line — should read it from here at build or request time rather than baking in a number that starts rotting immediately.
newest is the freshness check: if it drifts more than a couple of hours from
now, ingestion is behind, and that's more diagnostic than any count.
Errors#
| Status | Cause |
|---|---|
401 | Missing, unknown, or revoked key. |
429 | Rate limit exceeded, or monthly quota spent. |
500 | Server error. Retry with backoff. |
No 400 — there's nothing to send that could be malformed.