All platforms

HiringThing Jobs API

Query jobs from HiringThing boards through one API with ?source=hiringthing — plus how HiringThing's RSS feed really behaves.

?source=hiringthingsource reference

HiringThing is a white-label applicant tracking system. Small businesses buy it directly, but a lot of its footprint arrives the other way round: HiringThing is the hiring engine other software companies rebrand and sell as their own, so a board can be sitting under a name that isn't HiringThing's. The tell is the host. Every tenant lives at <tenant>.hiringthing.com, whatever the logo says.

Each tenant publishes an RSS feed that carries every open job with its full description inline. One unauthenticated call, no token, no detail pass, no pagination — the best per-request economics in this corner of the pool. On the board we tested it was 15 jobs, all 15 with descriptions. Fifteen. That is not a number worth writing a scraper for, and it's the point of this page.

How HiringThing boards actually work#

One GET, no auth, the whole board:

BASH
curl "https://<tenant>.hiringthing.com/api/rss.xml"

<tenant> is the subdomain. The response is ordinary RSS: an <item> per job, with <title>, a <link> to the posting, and a <location> element. The link looks like /job/23414/candidate-pool, and the number in it is the job id — tenant-local, so two HiringThing boards can both have a job 23414 and you need the tenant in your key or they'll collide.

The description is a decoy#

This is the one thing that matters on this platform, and it is the kind of bug that ships and stays shipped.

The standard RSS <description> is truncated at around 200 characters and ends in an ellipsis. The full body lives in <media:description>, in the Yahoo Media RSS namespace, and the difference is not subtle:

ElementLength on the board we measured
<description>193 characters
<media:description>664 characters

We cross-checked media:description against the same posting's detail-page JSON-LD and they matched exactly, character for character, at 4,555 each. So media:description is the real body, not another partial.

Nothing alerts you here. The feed returns 200. <description> is populated, is plausible prose, and reads like a job description because it is the first paragraph of one. Every fill-rate check you run says 100%. You just ship truncated jobs forever, and the field you'd use to notice is the field that's lying.

What bites you#

An invalid tenant returns 403, not 404. Which is convenient once you know it — a forbidden means the subdomain isn't a board, so slugs are cheap to verify in bulk — and misleading if you don't, because 403 reads as "we're blocked" and sends you off to buy proxies for a tenant that never existed.

There is no posting date. The feed exposes no publish date at all, so posted_at is null on this source. Same gap as Pinpoint and Trakstar Hire: a time_frame filter can only work off when we first saw the job, not when the employer posted it.

A board tells you the subdomain and not much else. The feed carries no employer identity beyond what's in the tenant name, which for a white-labelled platform is exactly where identity is least reliable. Resolving a HiringThing board to a real company with a domain is a separate problem from reading it, and it's the one that takes the time.

Or use ours#

One unauthenticated GET returns a whole HiringThing board with its bodies inline. If you have a handful of tenants, the curl above is the entire integration and you should just use it — this page exists partly to make that easy.

?source=hiringthing is served, and what it buys you is the part that isn't the fetch. HiringThing publishes no customer index, every board is its own subdomain, and the white-labelling means the name on the page frequently isn't the vendor's — so the board list, and resolving each tenant to a real company with a domain, is the work. That's what the company join does here. We read media:description rather than the truncated <description>, so the body you get is the whole body rather than its first paragraph. And the rows arrive in the same Job shape as every other source on /ats.

The date gap we can't fill: posted_at is null because the feed never published one, and we'd rather say so than derive a plausible date you'd then chart. Note too that /v1/metasources is the authority on what you can filter on — source is a csv filter, not an enum, so a miscased ?source=HiringThing returns an empty array rather than a 400.

Every source above normalises onto the same schema, with the hiring company already joined onto each posting.

Get an API key