Manatal Jobs API
Query jobs from Manatal boards through one API with ?source=manatal — plus how Manatal's paginated API really behaves.
Manatal is AI-assisted recruitment software sold to agencies and small businesses,
with a customer base that leans APAC and EU. Every board is backed by one public,
unauthenticated Django REST Framework API that serves postings with their
descriptions already inline. There are 48,926 Manatal postings in this dataset —
a number that moves hourly, so read it from /v1/meta
rather than trusting this sentence.
Try it#
curl -G https://api.hyperjobs.io/v1/jobs \
-H "Authorization: Bearer $HYPERJOBS_KEY" \
--data-urlencode "source=manatal" \
--data-urlencode "time_frame=7d" \
--data-urlencode "limit=2"{
"data": [
{
"id": "manatal:northwind_48213",
"title": "Recruitment Consultant",
"company": {
"slug": "northwind",
"name": "Northwind",
"domain": "northwind.io",
"website": "https://northwind.io",
"logo": "https://media.licdn.com/dms/image/…",
"industry": "Staffing and Recruiting",
"employee_count": 44
},
"location": {
"remote": false,
"countries": ["Singapore"],
"cities": ["Singapore"],
"regions": null,
"raw": ["Singapore, Singapore"]
},
"employment_type": ["FULL_TIME"],
"work_arrangement": null,
"seniority": null,
"salary": null,
"skills": ["sourcing", "client management"],
"taxonomies": ["Human Resources"],
"apply_url": "https://www.careers-page.com/northwind/job/L9V8R7Q6",
"url": "https://www.careers-page.com/northwind/job/L9V8R7Q6",
"source": "manatal",
"posted_at": "2026-07-11T04:02:19.000Z",
"expires_at": null,
"updated_at": "2026-07-14T08:31:07.000Z"
}
],
"total": 2,
"limit": 2,
"offset": 0
}How Manatal boards actually work#
One API backs every board, and it needs no auth:
curl "https://www.careers-page.com/api/v1.0/c/<slug>/jobs/?page=1"It's plain Django REST Framework, so the envelope is the one you'd guess:
{ count, next, previous, results[] }. Descriptions arrive inline on the list
rows, which puts Manatal ahead of most of this pool — there is no detail fetch
and no HTML to parse.
<slug> is the tenant. Manatal renders boards two ways, <slug>.careers-page.com
and careers-page.com/<slug>, and the two are mutually exclusive per tenant:
top-careers.careers-page.com 404s while careers-page.com/top-careers returns
200. That looks like it matters and it doesn't. The API answers for every slug
either way, so you can ignore the board themes entirely and use the slug.
page_size is ignored, and that is the whole problem#
The server caps the page at 20 no matter what you ask for
Request page_size=50 and you get 20. No error, no warning, no hint in the
envelope that your parameter went in the bin — just a valid 200 with 20 rows on
it.
The failure this creates is silent and total. An adapter that trusts its own
page_size, sees a full-looking page and stops has kept 20 of 221 jobs on
the board we measured. That's 9% of the board, delivered as a clean success with
no error anywhere to alert you.
The count field tells you the truth, and next is the only reliable way to
reach the tail. Follow the server's cursor; never assume a page size you chose.
# Wrong: looks fine, keeps 9% of the board
curl "…/api/v1.0/c/<slug>/jobs/?page_size=50" # → 20 rows
# Right: follow `next` until it's null
curl "…/api/v1.0/c/<slug>/jobs/?page=1" # → { count: 221, next: "…page=2" }What a posting row carries#
position_name is the title. description is inline HTML and is the reason this
platform is worth having. Location arrives both pre-formatted as
location_display and split into city, state, country, address and
zipcode, so you can take the board's own string or rebuild it from the parts.
hash is what builds the public URL at careers-page.com/<slug>/job/<hash>.
What bites you#
There is no date. Anywhere in the API. Not on the row, not in the envelope.
Manatal's API rows carry no created, posted or updated timestamp at all. The
subdomain theme's JSON-LD has one, but that's an N+1 per job for a single field,
which is a poor trade on a board this cheap to fetch. So posted_at on a Manatal
row is our first-seen stamp, not the employer's publish date — we'd rather
tell you that than let you build a freshness window on a date the source never
gave us.
Job ids are tenant-local, not global. Two Manatal boards will both happily
hand you a job 1. The id has to be scoped by tenant before it can be a dedup
key, and if it isn't, boards silently overwrite each other.
A count of 221 does not mean one request of 221. It means twelve requests of
20. On a platform where the fetch looks like a one-liner, the pagination is the
entire job.
Or use ours#
The fetch is genuinely easy here. The scale isn't: Manatal has no public index of its customers, so the tracked board list is assembled rather than fetched, and our queue currently holds 1,080 Manatal boards. That list is the part that took the time.
You get every board followed to its real tail rather than truncated at 20, descriptions carried through, ids scoped per tenant so boards don't collide, locations normalised out of the parts, Manatal rows deduplicated against the same job on LinkedIn or wherever else it's cross-posted, and expiry by board diffing so a pulled role disappears.
The company join is the honest gap on this platform: a Manatal board tells you a slug, and the API publishes no employer domain, so the identity has to be resolved rather than read. That resolution is work we do and don't always win.
Query it with ?source=manatal.
Quickstart, then pricing.
Every source above normalises onto the same schema, with the hiring company already joined onto each posting.
Get an API key