All platforms

TikTok Jobs API

Query TikTok's postings through one API with ?source=tiktok — plus the website-path header its API 400s without.

?source=tiktoksource reference

TikTok is not a platform. It's one employer with a bespoke careers site at lifeattiktok.com, and this adapter reaches TikTok's postings and nothing else. One Workday adapter reaches every Workday tenant; this one reaches one company.

It's here because TikTok is large enough for its jobs to matter on their own, and because a bespoke site has no vendor fingerprint for platform discovery to find. The price is a dedicated adapter, owned forever, breaking on TikTok's schedule.

How TikTok's careers API actually works#

A POST, not bot-protected, descriptions and structured salary inline:

BASH
curl -X POST "https://api.lifeattiktok.com/api/v1/public/supplier/search/job/posts" \
  -H "website-path: tiktok" \
  -H "origin: https://lifeattiktok.com" \
  -H "referer: https://lifeattiktok.com/" \
  -d '{"keyword":"","limit":100,"offset":0}'

Header-gated, not bot-protected

There's no Akamai here, no browser needed, no TLS impersonation — plain HTTP works. But the request is header-gated: website-path: tiktok plus a matching origin and referer are required, and without them the API returns 400.

That's the good kind of quirk, at least: it fails loudly. Contrast Apple, where a missing block returns zero results and a clean 200. A 400 tells you something is wrong; a silent zero doesn't.

website-path exists because the same backend serves several ByteDance career sites. You're telling it which brand you're asking about.

What the adapter reads#

Everything comes back in one page, no detail call:

FieldWhat it becomes
title, description, requirementBody assembled as description + a Requirements section
codeThe requisition id ("A220892")
job_category.en_nameDepartment
job_subject.en_nameTeam
recruit_type.en_name"Regular", "Intern" — employment type and commitment
job_post_info{ min_salary, max_salary, currency } — structured pay
city_infoA nested location chain (see below)
publish_timeEpoch timestamp

The description is two fields, not one: description plus requirement, reassembled with a heading. Read description alone and you get the pitch without the requirements — the same split Lever and Amazon have, in a third arrangement. en_name throughout is the tell that this is a bilingual system with English alongside Chinese.

Locations are a linked list#

city_info isn't a string or a flat object. It's a parent chain: a city node whose parent is a region whose parent is a country. Getting a location means walking the chain to the root and joining what you find.

Read city_info.en_name and stop, and every location loses its country — leaving you a bare city to geocode, which is how Cambridge becomes the wrong one.

What bites you#

publish_time is an epoch with no declared unit. Sometimes seconds, sometimes milliseconds. Treat seconds as milliseconds and the posting lands in 1970; treat milliseconds as seconds and it lands tens of thousands of years from now. The adapter switches on magnitude — under a trillion means seconds. There's nothing in the payload that tells you which you're holding.

The salary has no period

job_post_info gives a min, a max and a currency. It does not say whether that range is annual, monthly or hourly.

The numbers are real and their unit isn't in the data. A range that's monthly in one market and annual in another looks identical in the payload, and annualising the wrong one is off by a factor of twelve. The adapter stores the unit as null rather than guessing, because a wrong unit is worse than a missing one.

One adapter, one company, forever. Same deal as Apple, Amazon, Uber, Google, Microsoft and IBM: a dedicated adapter maintained indefinitely, breaking independently, for one employer's jobs.

Or use ours#

Three headers, offset pagination, a two-part body reassembled, a parent chain walked to a country, an epoch disambiguated by size, and a salary whose period isn't stated left honestly unitless — with TikTok'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=tiktok — 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