All platforms

Deel Jobs API

How Deel's job boards actually work, what its RSC flight payload really contains, and what ?source=deel returns in the HyperJobs API.

?source=deelsource reference

Deel is best known as an Employer of Record and global payroll platform, and as of 2026 it runs a real multi-tenant ATS of its own. Customer boards live at jobs.deel.com/<slug> — Klarna, Dott and Offensive Security among them — and the boards are genuinely public: one unauthenticated GET returns a whole board with every description already in the response. No auth, no pagination, no detail pass.

What the board looks like#

BASH
curl "https://jobs.deel.com/job-boards/<slug>"   # 301 → /<slug>

There is no JSON API — robots.txt disallows /api/ — and no JSON-LD. The board is a Next.js app, and the data arrives as an RSC flight payload: a run of self.__next_f.push([1,"…"]) chunks embedded in the HTML. Everything is in there, including all the bodies. Klarna's board is 81 jobs and 81 descriptions from that one call.

Parsing it is the whole job, and it bites in three places:

  1. Decode and concatenate before parsing anything. The chunks are JS string literals that split at arbitrary offsets — mid-row, mid-token, even mid-escape-sequence. Parse a chunk on its own and you get garbage.
  2. The rows are not newline-delimited. They look like {hexId}:T{hexLength},{payload}, and the next row starts immediately after the payload with no newline between them. On Klarna, one newline precedes the first row and then 272,733 characters run with none. A newline-anchored scan finds the first description and nothing else, which reads as "the list ships one body and the other 80 need a detail fetch". It doesn't. It ships all 81.
  3. That length is in bytes, not characters. Descriptions are full of multi-byte UTF-8 — curly quotes, "Nykøbing Falster", "Düsseldorf". Slice by character count and the parser desynchronises on the first one and silently corrupts every row after it.

Descriptions themselves are lazy references: a posting carries richtextDescription: "$23", which points at row 23 in the same payload. Get the three above right and all of them resolve locally, with no second request.

Pagination doesn't exist, and that was proven rather than assumed: ?page=2, ?offset=50 and ?limit=5 all return a byte-identical board. The completeness was checked against an independent oracle — the per-org sitemap that robots.txt advertises — at 81/81, 29/29 and 21/21 across three tenants.

What bites you#

The location is often a legal entity, not a place. Deel is an EoR, so the field carries the contracting entity the employer typed: CellPoint Digital India LLP, Natural Capital Research Limited, Head Office - Calgary. Fed straight to a location parser, 12 of 95 distinct values wrote company names into the cities column. Stripping the org's own tokens and the entity suffix recovers the real signal those strings carry — India, Calgary — rather than throwing them away.

The workplace type is hidden in that same string. Deel publishes no structured remote/hybrid field at all. What it has is Brussels, Belgium (Hybrid), Tbilisi On-site, Remote - US. If you don't lift it out of the location, the arrangement is simply lost.

Compensation has no period, and the periods are mixed on one board

currentCompensation is {currency, minAmount, maxAmount} and there is no frequency key anywhere in the payload. Klarna lists SEK 55,206 (monthly) beside SEK 752,814 (annual) in the same field, same currency, with nothing distinguishing them. Assume a period and you store a Stockholm engineer's monthly pay as their annual salary — a 12x error large enough to clear every sanity check. Deel's own front-end renders these ranges period-less too.

So a Deel posting gets its compensation as text and no structured salary. A wrong salary is worse than none.

An unknown tenant returns HTTP 200, never a 404. It's a ~15KB shell. The only failure signal is the absence of the board props. A real but empty board is distinguishable — it ships its settings plus an empty postings array — but you have to look for the difference rather than trust the status code.

Deel itself is not a tenant of Deel. jobs.deel.com/deel redirects off the platform to www.deel.com/careers, because Deel hires through Ashby.

What you get#

The flight payload parsed rather than worked around: every description resolved out of the one call its posting already came in, no detail pass, and after geocoding, full country coverage — 100% on both, measured across 29 tenants and 349 jobs. Deel is also one of the better platforms for the company join: about 46% of tenants publish a privacy-policy link that resolves to the employer's own domain, which is the only employer-domain signal the board exposes.

Query it with ?source=deel. The counts above are a measurement rather than a promise, and they move — /v1/metasources is the live vocabulary and the honest place to read both the value and the size of it off.

See all platforms · coverage

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

Get an API key