# iCIMS Jobs API

> Query jobs from iCIMS boards through one API with ?source=icims — plus how iCIMS's card HTML and iframe JSON-LD really behave.

Source: https://hyperjobs.io/ats/icims

iCIMS is one of the oldest and largest enterprise applicant tracking systems, and
the ATS behind a lot of household-name hiring: Disney, Kroger, AT&T, Visa. Each
customer's board lives at `careers-<slug>.icims.com`, and it's served as plain
server-rendered HTML rather than a JSON API. There are 11,997 iCIMS postings in
this dataset — a number that moves hourly, so read it from
[`/v1/meta`](/docs/api-reference/meta) rather than trusting this sentence.

## Try it

```bash
curl -G https://api.hyperjobs.io/v1/jobs \
  -H "Authorization: Bearer $HYPERJOBS_KEY" \
  --data-urlencode "source=icims" \
  --data-urlencode "time_frame=7d" \
  --data-urlencode "limit=2"
```

```json title="Illustrative — the shape, not a live response"
{
  "data": [
    {
      "id": "icims:2891447",
      "title": "Store Operations Manager",
      "company": {
        "slug": "harborline-retail",
        "name": "Harborline Retail",
        "domain": "harborline.com",
        "website": "https://harborline.com",
        "logo": "https://media.licdn.com/dms/image/…",
        "industry": "Retail",
        "employee_count": 47000
      },
      "location": {
        "remote": false,
        "countries": ["United States"],
        "cities": ["Columbus"],
        "regions": ["Ohio"],
        "raw": ["US-OH-Columbus"]
      },
      "employment_type": ["FULL_TIME"],
      "work_arrangement": "On-site",
      "seniority": null,
      "salary": {
        "min": 190000,
        "max": 200000,
        "currency": "USD",
        "unit": "YEAR",
        "annual_min": 190000,
        "annual_max": 200000,
        "summary": "USD $190,000.00 - USD $200,000.00 /Yr."
      },
      "skills": ["merchandising", "p&l"],
      "taxonomies": ["Operations"],
      "apply_url": "https://careers-harborline.icims.com/jobs/2891447/store-operations-manager/job",
      "url": "https://careers-harborline.icims.com/jobs/2891447/store-operations-manager/job",
      "source": "icims",
      "posted_at": "2026-07-08T14:00:00.000Z",
      "expires_at": null,
      "updated_at": "2026-07-13T21:07:31.000Z"
    }
  ],
  "total": 2,
  "limit": 2,
  "offset": 0
}
```

## How iCIMS boards actually work

A paginated HTML search, then one iframe per posting:

```bash
# 1. List — HTML cards, 25 per page
curl "https://careers-<slug>.icims.com/jobs/search?ss=1&pr=0&in_iframe=1"

# 2. Detail — the description is in the iframe's schema.org JSON-LD
curl "https://careers-<slug>.icims.com/jobs/2891447/store-operations-manager/job"
```

Each posting on the list is an `<li class="iCIMS_JobCardItem">` carrying id,
title, location and date. The full body only exists on the detail page, inside a
`JobPosting` JSON-LD block. The `in_iframe=1` parameter matters: iCIMS boards are
usually embedded in the employer's own careers page, and that's the surface that
renders cleanly.

### The card is worth more than it looks

This is the part that makes iCIMS survivable, and it's easy to miss. Each card
carries a `<dl>` of structured `<dt>`/`<dd>` pairs at **list** time — requisition
id, Category, Remote/Telecommute, sometimes Clearance Level. No detail fetch
needed.

That matters because of the next section. When a tenant's detail pages are
blocked, the cards still yield a real requisition id, a department and a work
arrangement. You lose the description, not the posting.

| Field | List card | Detail JSON-LD |
| --- | --- | --- |
| Description | A short summary | **The full body** |
| Department | `Category`, ~61% | `occupationalCategory`, ~94% |
| Requisition id | **The only source** | Not present on any tenant sampled |
| Work arrangement | `Remote` Yes/No | `TELECOMMUTE`, rare |

Note the third row. iCIMS's JSON-LD carries no `identifier` on any tenant we've
sampled, so the employer's own requisition number exists **only** in the card's
header tags. Skip the cards and go straight to the detail pages and you lose it
permanently.

## What bites you

<Warning title="`icims.com` in a URL does not make it a board">
  A board is a **tenant host**. A rule that claims any string containing
  `icims.com` will happily accept `www.icims.com/legal/privacy-notice` and store
  the raw URL as a board token, at which point the discovery queue is full of the
  vendor's own marketing and legal pages. Match on the hostname, reject the
  vendor's own subdomains, and normalise to the origin so a deep job link
  resolves back to its tenant rather than seeding a new one.
</Warning>

**Many enterprise tenants are Cloudflare-gated.** On a datacenter IP they return
**zero cards** and a `200`. Not an error, not a challenge page you'd notice in a
log: an empty board. A TLS-impersonation tier clears some of them and residential
IPs clear more, but a naive crawler simply records "this Disney-sized employer has
no jobs today" and moves on.

**Card markup is not uniform.** The location and date regexes are tuned to the
common variant, and some tenants ship a different card layout that silently drops
both. Title and URL always survive, which is exactly why it's hard to notice —
you get a posting that looks fine and has no location. Location lands on about
64% of iCIMS postings, and that's the platform, not a parser bug.

**Pay-transparency tenants hide the range in the wrong field.** The clean source
is `baseSalary`. But some tenants leave that empty and put the range in
`salaryCurrency` as a formatted string: `USD $190,000.00 - USD $200,000.00 /Yr.`.
It's a structured key holding prose. Reading it adds roughly five points of salary
coverage.

**The board token is a hostname, so the fallback company name is a slug.** The
real employer name comes off the detail's JSON-LD `hiringOrganization`, not from
`careers-360care.icims.com`.

## Or use ours

iCIMS is two surfaces that each know something the other doesn't, one of which is
gated on a lot of the tenants you most want.

You get the description from the JSON-LD where it's reachable and the card's
fields where it isn't, the requisition id that only exists in the card headers,
salary recovered from the string field that pay-transparency tenants misuse, work
arrangement assembled from a rare JSON-LD flag plus the card's explicit Yes/No,
the employer's real name rather than a hostname, and the [company
join](/docs/objects/company). Descriptions land on 92.5% of the iCIMS rows we
serve; the shortfall is the Cloudflare-gated detail pages, and we'd rather tell
you that than round it up.

iCIMS sits in the heavy refresh tier, attempted every third cycle — see
[coverage](/docs/reference/coverage).

Query it with `?source=icims`.
[Quickstart](/docs/quickstart) · [Pricing](/pricing)
