[NewSearch millions of jobs from your AI agent with MCP→](/blog/jobspipe-mcp-server)

[All posts](/blog)

![](/listly/card-field.png)

GuideRecruitee

Guide·Aug 25, 2026·7 min read

# Recruitee API: the careers-site endpoint that needs no key at all

Every Recruitee-hosted careers site exposes its published jobs as public JSON: GET company.recruitee.com/api/offers/, no token, no signup, full description HTML included in the list response. We tested it this week against a live tenant - 56 fields per offer, a department filter that actually works, and a salary object that ships empty. Here is the field-by-field walkthrough, how the public Careers Site API differs from the token-gated ATS API that was rebuilt with rate limits in late 2025, and where the one-tenant-at-a-time model stops working.

![Dvir Atias](/authors/dvir-atias.jpg)

Dvir Atias

Founder, JobsPipe

Two different things answer to **Recruitee API**. One is the ATS API at `api.recruitee.com` - token-gated, customer-scoped, built for a company automating its own hiring. The other is the Careers Site API: every Recruitee-hosted careers site exposes its published jobs as public JSON, no token, no signup, no contract. If what you want is job postings - yours or another company’s - the second one is the endpoint you are looking for, and it is one of the friendliest in the ATS world. We tested it this week against a live tenant. Here is what actually comes back.

## The two Recruitee API surfaces

-   **The Careers Site API** - served under each customer’s careers address at `https://{company}.recruitee.com/api/offers/`. Recruitee’s own docs state it plainly: “This API does not require authorization and is available under your Careers Site address.” It reads published postings and accepts candidate applications, which is why custom career pages are built on it.
-   **The ATS API** - `api.recruitee.com/c/{company_id}/...` with `Authorization: Bearer` and a personal API token. Tokens are generated per user, per company, and carry the exact permission scope of the user who created them - there is no way to scope one down. This is the surface for candidates, pipelines, and requisition management inside your own account.

Recruitee - now branded Tellent Recruitee - documents both at `docs.recruitee.com` and `apidocs.recruitee.com`. The newer docs portal calls itself a work in progress, but the public endpoint has been stable for years.

## One GET, full postings included

We pulled a live Dutch tenant, energy company Vandebron:

```
curl https://vandebron.recruitee.com/api/offers/

{ "offers": [
  { "title": "Sourcing & Pricing Analyst",
    "slug": "sourcing-pricing-analyst",
    "status": "published",
    "department": "Finance & Control",
    "city": "Amsterdam",
    "country_code": "NL",
    "employment_type_code": "fulltime_permanent",
    "category_code": "finance",
    "remote": false, "hybrid": true, "on_site": false,
    "published_at": "2026-08-14 08:23:10 UTC",
    "careers_url": "https://werkenbij.vandebron.nl/o/sourcing-pricing-analyst",
    "description": "<h3>...</h3><p>...</p>",
    ... }, ... ] }
```

Twelve published offers, about 190 KB, one request. The detail that matters if you have integrated other ATSs: the **full description HTML rides along in the list response** - 8,700 characters of it on the first offer we pulled. There is no list-then-fetch-each-job dance. A per-offer endpoint exists at `/api/offers/{slug}` and returns the same record, but you rarely need it.

Three other behaviors we verified: a tenant with nothing published returns `{"offers":[]}` rather than an error, a subdomain that is not a Recruitee customer returns 404, and the endpoint stays live on the `recruitee.com` subdomain even when the company serves its careers page from a custom domain - Vandebron’s `careers_url` points at werkenbij.vandebron.nl, but the API answers on vandebron.recruitee.com.

Query filters are honored, too. Adding `?department=Finance%20%26%20Control` cut the twelve offers to the three in that department, and a nonsense value returns zero. A small thing, until you have met feeds like [RemoteOK’s](/blog/remoteok-api), which accept a tags parameter and silently ignore it.

## The 56 fields, and which ones to trust

Each offer carries 56 fields. The useful core for anyone consuming job data:

-   **Identity and lifecycle** - `id`, `slug`, `guid`, `status` (published offers only on this surface), `created_at`, `published_at`, `updated_at` and `close_at`, timestamped like `2026-08-14 08:23:10 UTC`. Real publish timestamps are rarer in this industry than they should be.
-   **Location** - `city`, `country_code`, `state_code`, `postal_code`, a formatted `location` string, and a `locations` array for multi-site roles.
-   **Classification** - `department`, `category_code`, `employment_type_code` (values like `fulltime_permanent`), `education_code`, `experience_code` and free `tags`.
-   **Work arrangement** - three explicit booleans: `remote`, `hybrid`, `on_site`. Our sample tenant marked every Amsterdam role hybrid.
-   **Content** - `description` as HTML, a separate `requirements` field that in practice often arrives empty with everything folded into the description, and `translations` for multilingual tenants.

The one to distrust: `salary`. The object is always there - `{min, max, period, currency}` - and on every offer of the tenant we sampled, every value was null. Recruitee gives employers the field; European employers mostly decline to fill it. If you need advertised compensation, plan on parsing it from the description text or sourcing it elsewhere.

The rest of the 56 are application-form plumbing - `options_cv`, `options_cover_letter`, `open_questions`, `dynamic_fields` - which matter only if you are building an apply flow, plus social `sharing_*` images and titles.

## The gated ATS API changed in late 2025

If you are a Recruitee customer integrating your own account, the picture moved recently. Recruitee introduced rate limiting on the ATS API in October 2025, and on December 1, 2025 shipped a rebuilt `/offers` endpoint with more filtering options - the old reference is now flagged as a legacy endpoint, and the classic examples (`GET /c/{company_id}/offers?scope=active&view_mode=brief`, where the subdomain works in place of the numeric company id) sit under a migration notice. Custom integrations written before late 2025 may need code changes. The public Careers Site API is not part of that migration.

## Where the one-tenant model stops

In the taxonomy of [public versus gated ATS APIs](/blog/public-vs-gated-ats-apis), Recruitee lands in the best tier: genuinely public postings, no key at all - friendlier than [Teamtailor’s clean but key-per-tenant API](/blog/teamtailor-api-jobs). The structural limit is the same as every per-company surface. The endpoint answers “what is company X hiring?” perfectly, one X at a time. It cannot answer “which companies are hiring data engineers in the Netherlands right now?” - there is no cross-tenant search and no directory of Recruitee customers to enumerate. You discover subdomains one by one, and you poll each one yourself.

## Cross-company search is a different product

That aggregation layer is what JobsPipe sells. We index live postings from 11 source platforms - LinkedIn, Indeed, Workday, Greenhouse and the other majors - where the companies you would poll tenant-by-tenant cross-post the same roles, normalized into one schema with skills, ISCO-08 occupation codes and industry classification attached:

```
curl https://api.jobspipe.dev/v1/jobs/search \
  -H "Authorization: Bearer jp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "job_title_or": ["data engineer"],
    "job_country_code_or": ["NL", "DE"],
    "posted_at_max_age_days": 14,
    "limit": 25
  }'
```

One request, every company hiring for the role across sources - scope to a single employer with `company_name_partial_match_or` when you do want the one-company view. The free tier includes 1,000 jobs per month, and the wider market is compared in [the best jobs APIs of 2026](/blog/best-jobs-api-2026).

A fair split: the Recruitee Careers Site API is exactly right for rendering one company’s openings on a custom site - public, stable, full descriptions in one call. The moment the question becomes who is hiring rather than what X is hiring, you need an aggregator.

Cross-company job search over 11 platforms - full postings, free tier included.

## Skip the scraper - try the API right now

Live, normalized postings from 30+ ATS feeds and job boards in one JSON schema. No key, no signup - this sandbox returns sample data in the exact live shape.

Job title WorkplaceRemote onlyAny Results3510Test search

Results

Press **Test search** to see normalized job records rendered here, and the raw JSON on the right.

JSON response`POST /v1/sandbox/jobs/search`

```
{
  "job_title_or": [
    "software engineer"
  ],
  "limit": 3,
  "remote": true
}
```

Advanced: edit the raw request, or copy it as curl

{ "job\_title\_or": \[ "software engineer" \], "limit": 3, "remote": true }

```
curl -X POST https://api.jobspipe.dev/v1/sandbox/jobs/search \
  -H "Content-Type: application/json" \
  -d '{"job_title_or":["software engineer"],"remote":true,"limit":5}'
```

For live results, [get a free key](/signup) (1,000 jobs/month) and swap `/v1/sandbox/jobs/search` for `/v1/jobs/search` with an `Authorization: Bearer` header - request and response shapes are identical.

[

Next →

RemoteOK API: the free remote-jobs feed, and its 100-job window

](/blog/remoteok-api)

---
Canonical URL: https://jobspipe.dev/blog/recruitee-api-jobs
Title: Recruitee API: the careers-site endpoint that needs no key at all
Description: Every Recruitee-hosted careers site exposes its published jobs as public JSON: GET company.recruitee.com/api/offers/, no token, no signup, full description HTML included in the list response. We tested it this week against a live tenant - 56 fields per offer, a department filter that actually works, and a salary object that ships empty. Here is the field-by-field walkthrough, how the public Careers Site API differs from the token-gated ATS API that was rebuilt with rate limits in late 2025, and where the one-tenant-at-a-time model stops working.

---
Building this integration yourself? The steps above work. The alternative is one API over this source and 30+ others, already normalized and deduplicated. Try it right now - no key, no signup:

```bash
curl -X POST https://api.jobspipe.dev/v1/sandbox/jobs/search \
  -H "Content-Type: application/json" \
  -d '{"job_title_or":["software engineer"],"limit":5}'
```

Sample data, exact live schema. For live data get a free key (1,000 jobs/month) at https://jobspipe.dev/signup, then swap /v1/sandbox/jobs/search for /v1/jobs/search with an Authorization: Bearer header. Full agent index: https://jobspipe.dev/llms.txt?src=md-twin