All platforms

Uber Jobs API

Query Uber's postings through one API with ?source=uber — plus the pagination footgun that returns the same 1,000 jobs every call.

?source=ubersource reference

Uber is not a platform. It's one employer running a bespoke careers site, and this adapter reaches Uber's postings and nobody else's. Everywhere else, an adapter is leverage: write Greenhouse once and you reach every company that bought Greenhouse. Write this one and you reach Uber.

It exists because Uber is big enough for its jobs to matter on their own, and because a bespoke careers site is invisible to platform discovery — there's no vendor fingerprint to detect. The cost is an adapter per company, maintained forever, breaking on that company's schedule.

How Uber's careers API actually works#

A POST, no real authentication, full job objects with markdown descriptions inline:

BASH
curl -X POST "https://www.uber.com/api/loadSearchJobsResults?localeCode=en" \
  -H "x-csrf-token: x" \
  -d '{"params":{},"page":0,"limit":100}'

The x-csrf-token header is required and its value is not checked. A literal x is accepted. It's a gate that only stops requests that don't know the gate exists.

Descriptions come inline as markdown — not HTML, which is unusual in this pool and means no detail call and no tag soup.

Nest `limit` and `page` under `params` and you get the same jobs forever

limit and page must be top-level keys in the body, sitting beside params, not inside it.

Put them inside params — which is exactly where they look like they belong — and the API doesn't reject them. It ignores them, falls back to its default page of around a thousand results, and returns that same page for every call you make. Your loop runs, every request succeeds, every response is full of real jobs, and you collect the same rows over and over into a duplicate storm.

Nothing errors. The only symptom is a job count that climbs while the number of distinct ids doesn't.

totalResults is a 64-bit envelope#

The total isn't a number. It's an object, and the value lives at totalResults.low:

JSON
"totalResults": { "low": 4123, "high": 0, "unsigned": false }

That's a 64-bit integer serialisation leaking through the JSON layer. Read totalResults as a number and you get an object where you expected an integer; compare it against your offset and the loop's termination condition is nonsense. The adapter reads .low.

What the adapter reads#

FieldWhat it becomes
id, titleIdentity. Rows missing either are dropped
descriptionThe body, inline, as markdown
department, teamTwo levels of grouping, both structured
timeType"Full-Time", "Intern" — employment type and commitment
creationDateThe posted timestamp, already ISO
location, allLocations[]City / region / country objects, joined

allLocations[] is preferred over location when present, so a posting open in several cities keeps all of them instead of collapsing to the first. creationDate arriving as a real ISO string is worth appreciating quietly — it's the field that goes wrong on Amazon and is absent entirely on IBM, whose search endpoint publishes no posting date at all.

What bites you#

The duplicate storm is silent. Worth repeating, because it's the failure mode that produces a confident, wrong dataset instead of an error. Every request returns 200 and real data.

There's no salary. Nothing structured in the payload. Whatever comp exists is prose inside the markdown.

A placeholder CSRF token is an invitation to change. x-csrf-token: x working is a quirk of today's gate, not a contract — precisely the sort of thing that gets tightened without notice, and when it does, this adapter is what breaks.

One adapter, one company, forever. Same deal as Apple, Amazon, TikTok, Google, Microsoft and IBM: a dedicated adapter, its own schedule of breakage, one employer's jobs at the end of it.

Or use ours#

Top-level pagination keys, .low read out of the envelope, allLocations preferred over location, markdown kept intact — with Uber's rows in the same Job shape as every other source, dedup against the same role on LinkedIn, expiry by board diffing since the payload declares none, and a single-company adapter's upkeep being ours rather than yours.

Query it with ?source=uber — the same string that keys /v1/metasources. That endpoint is the live vocabulary and carries the counts as they move; it's worth reading rather than trusting a list on a page.

Sources · Quickstart

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

Get an API key