All platforms

iSolved Hire Jobs API

Query jobs from iSolved Hire boards through one API with ?source=isolved — plus how iSolved Hire's core jobs endpoint really behaves.

?source=isolvedsource reference

iSolved Hire is the recruiting module of isolved, an HCM suite sold to small and mid-sized US employers. Boards live at <tenant>.isolvedhire.com.

The useful thing to know about this platform is that it is not really its own platform. iSolved Hire is ApplicantPro white-labelled — same endpoints, same JSON envelope, same field names, same quirks, on a different hostname. One implementation backs both, and a fix to the shape fixes both at once. If you have read the ApplicantPro page, you have read this one; the only things that differ are the host and the tenant namespace.

That is worth stating plainly because from the outside they look like two integrations to build. They are one.

How iSolved Hire boards actually work#

Three steps, identical to ApplicantPro's with isolvedhire.com swapped in:

BASH
# 1. Bootstrap — the board HTML is the only place `domainId` exists
curl -L "https://<tenant>.isolvedhire.com/jobs/"        # → componentData: { domainId : 4689 }
 
# 2. List — every live posting, no descriptions
curl -L "https://<tenant>.isolvedhire.com/core/jobs/<domainId>?getParams=%7B%7D"
 
# 3. Detail — the body, plus a benefits block
curl -L "https://<tenant>.isolvedhire.com/core/jobs/<domainId>/<jobId>/job-details?getParams=%7B%7D"

The list carries salary (minSalary/maxSalary with payTypeFrame as the unit), employmentType, workplaceType, a structured location and startDateRef/endDateRef. It carries no description, so the body is one detail call per posting.

On the tenant we tested, that returned 49 jobs with 49 descriptions — a small board, fully readable, which is the profile of this platform generally.

The two traps come with it#

`getParams` is required, and omitting it returns 200

Leave getParams off and the API answers HTTP 200 carrying a PHP type error in the body (Argument 1 passed to Awesome\Utils\… must be of the type array, null given). A status check sails straight past it: successful request, empty list, a board that looks like it isn't hiring. getParams={} — url-encoded, %7B%7D — satisfies it.

domainId cannot be derived from the slug. It exists only in the board HTML, as componentData: { domainId : 4689 }, which is why the bootstrap fetch is a required step rather than an optimisation. Churned tenants redirect to /notset.php and yield no domainId, which is at least a clean liveness signal.

orgTitle is not the employer. It's the internal org unit — "Airport", "Data", "Library -Dept #4100" — and mapping it to a company name writes nonsense into your dataset as an employing entity. It belongs in team.

untilFilled makes endDateRef a placeholder, not a deadline. Expire on it and you drop live jobs.

Or use ours#

A bootstrap fetch for a domainId that exists nowhere but the board HTML, a list call whose missing parameter answers 200 with a PHP type error in the body, and a detail call per posting.

You get the domainId bootstrap handled per tenant, getParams always present, descriptions and the benefits block, salary with the unit read off payTypeFrame, orgTitle filed as a team rather than libelling "Data" as an employer, untilFilled postings left unexpired, churned tenants reaped off the /notset.php redirect, ids scoped per tenant, and the company join. One implementation carries all of that for both hostnames at once.

Query it with ?source=isolved, on the same Job shape as everything else on /ats. The white-label original is ?source=applicantpro: the same shape over different tenants, so it's a second source value rather than a second way of asking for these rows. Both keys, and whatever else ?source= accepts at the moment you read it, come from sources on /v1/meta. Quickstart, then pricing.

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

Get an API key