Skip to main content
The Clair Job Search API exposes one bounded, market-wide search over active job postings: Clair reads a validated registry of employer boards in the background. Public requests query Clair’s database only. They do not contact an employer site, talk to an ATS, or fetch a caller-supplied URL. That separation keeps request latency bounded by infrastructure Clair controls. It also gives every result the same filters, pagination, freshness signals, and error contract.

Base URL and authentication

The Jobs API is distributed through RapidAPI. Send your key and the Jobs API host on every request:
RapidAPI owns key issuance, plan quotas, rate limiting, and billing. There is no separate Clair account.
Use the exact host shown on the RapidAPI listing. The News API is a separate listing with a separate host, even when you use the same RapidAPI key.
q is a case-insensitive substring filter over the posting title. It determines which postings match; sort still controls their order. Use the structured filters below for company, department, skills, compensation, and other normalized fields. Structured filters let you narrow the result set without parsing source text:
  • Company, free-form location, and ISO 3166-1 alpha-2 country.
  • Normalized workplace_type: remote, hybrid, or onsite.
  • Derived seniority and career track.
  • Department or team.
  • Skills requiring either every requested value with skills_all or at least one with skills_any.
  • Compensation range, currency, and interval.
  • Publisher time with posted_after or Clair discovery time with first_seen_after.
  • ATS provider and board identifier for advanced provenance filtering.
See Search jobs and internships for the complete parameter reference.

Jobs and internships share one resource

An internship is a posting, so it uses the same endpoint and schema as every other role. Set:
The title classifier recognizes internships, co-ops, apprenticeships, working-student roles, and placements. You can combine the filter with q, country, workplace_type, skills, or discovery time:

The normalized job schema

Every result includes:
  • A stable Clair id.
  • title, company, department, and team.
  • The primary location, all published locations, derived country, and normalized workplace_type.
  • Source-provided employment_type.
  • Validated HTTPS posting_url and apply_url; every returned posting has at least one, while either field can be null when the source exposes only the other.
  • Publisher timestamps, Clair discovery and verification timestamps.
  • Normalized compensation with its extraction source.
  • Derived seniority, track, title_family, and canonical skills.
  • description_available, plus an optional 2,000-character plain-text description_excerpt.
  • Source provider, board, and external posting ID.
Nullable values are intentional. Clair returns null when a source did not state a value or it could not be derived safely. It does not invent an employment type, country, salary, publication date, or company name. In particular, a source board identifier is never substituted for a missing company. An indexed record with neither a valid HTTPS posting link nor a valid HTTPS application link is omitted from search until a later crawl repairs it. It is not presented as a closed job merely because one source response was incomplete. employment_type reflects what the source adapter could normalize. Some publishers expose free-form values, so do not treat it as a closed enum.

Compensation semantics

Salary bounds use overlap matching:
  • salary_min=150000 keeps a posting whose stated maximum is at least 150,000.
  • salary_max=200000 keeps a posting whose stated minimum is at most 200,000.
currency is required whenever you send a salary bound. If you omit salary_interval, bounds default to annual compensation. You can explicitly filter year, hour, month, week, or day. The nested compensation.source explains provenance: Clair does not convert between currencies or silently annualize hourly pay.

Provenance and time

The timestamps answer different questions: Use posted_after for publication-date research. Use first_seen_after for alerts or incremental discovery, because it remains available when a publisher omits posted_at. Each job also carries:
Pair this source identity with posting_url, apply_url, and last_verified_at when auditing a result.

Index freshness

Every successful response includes an index object inside meta:
as_of is the most recent successful board crawl recorded. It is not a claim that every board was crawled at the same instant. stale_boards is the number of enabled boards that have missed two of their own configured crawl intervals, have never completed, or most recently failed. Use per-job last_verified_at when the exact freshness of one posting matters.

Cursor pagination

Pages are ordered newest first with a stable ID tiebreaker. sort=posted_at uses the publisher time and falls back to first_seen_at when the publisher supplied no date. sort=first_seen_at is useful for ingestion and alerting. If meta.has_more is true, pass meta.next_cursor unchanged:
A cursor is bound to the filters and sort that created it. Changing either while reusing the cursor returns bad_cursor. Stop when has_more is false and next_cursor is null. Exact totals require an additional distinct-count query, so they are opt-in. Set include_total=true to populate meta.total. Otherwise total is null and total_is_exact is false.

Deduplication

One requisition can appear on several career sites owned by the same ATS tenant. Clair retains source rows for crawling, then applies provider-aware identity to search results. Workday uses tenant plus external requisition ID. Reviewed Recruitee aliases also require the same exact link, while a SmartRecruiters copy must agree on board, exact link, title, company, and location. Clair does not use fuzzy title similarity that could merge distinct openings. Optional meta.total counts canonical postings rather than storage rows.

Description excerpts

Descriptions are excluded by default. Set include_description=true to return description_excerpt, a plain-text preview capped at 2,000 characters. The field is a preview, not a complete or archival copy. Follow posting_url for the publisher’s current description.

Errors

Branch on the stable error code. detail is human-readable and may change. Validation failures return an array of details; typed failures return a string. Origin responses include X-Request-ID. Include it when reporting a problem. Honor Retry-After on 503 responses and retry with backoff.