All platforms

Kula Jobs API

How Kula's job boards actually work, why its board page is the wrong thing to scrape, and what ?source=kula returns in the HyperJobs API.

?source=kulasource reference

Kula is a sourcing and recruiting CRM suite that also hosts real public job boards, mostly for engineering-heavy companies in India, the US and Southeast Asia. Boards live at careers.kula.ai/<account>, and the underlying feed is one of the cheapest in this pool: an unauthenticated JSON call returns up to 100 postings with every description already inline. No detail pass, no auth, no cookies.

What the board looks like#

The board page at careers.kula.ai/<account> is a Next.js app-router app, and it renders into an RSC flight payload. That payload is the tempting thing to scrape, and it is the wrong one. The right target is the plain JSON endpoint the board's own filter dropdown calls:

BASH
curl "https://careers.kula.ai/api/internal/ats_job_posts\
?accountName=<account>&type=ats_job_post.index&items=100&page=1"

type is mandatory — without it the API returns a 400 with err_invalid_type. items is clamped to 100 server-side (ask for 1,000 and you get 100, honestly echoed back in the response's meta), and meta.pages tells you when to stop.

Some Kula boards render client-side, so the flight payload is empty

This is the failure that looks like success. sarvam-ai's board page ships a layout-only payload with zero postings in it — while the JSON endpoint returns its 34 jobs, all with descriptions. A scraper built on the flight payload reads that board as empty at HTTP 200 and never errors.

The flight payload is worse in three quieter ways too: it is coupled to the Next.js build id and re-escapes between releases; its descriptions are lazy $60-style references into byte-length-delimited chunks that chain with no newline between them, so a line-anchored parse finds exactly one of 48; and that declared length is in bytes rather than characters, so character-slicing resolves none of them. All of that work, to get less data than the documented route hands over for free.

What bites you#

ats_department is an object, not a string. It's {id, name, depth}. This is the exact shape that, on another platform in this pool, wrote an object into a scalar column and zeroed a whole board while a truthiness probe cheerfully reported the department field at 100% fill. Take .name.

office.name is a label, not a location. An office literally named "Remote" has location: "Toronto, Ontario, Canada". Others read "Kula Chennai", "New york", "San Francisco ,USA". The location field beside it is Google-Places-normalised and was filled on 149 of 149 office rows, so name is only ever a last resort for a board that leaves the structured parts blank.

The job-level workplace field contradicts the office-level one, and the job is right. workplace is a clean three-way office | remote | hybrid. An office named "Kula Chennai" carries workplace: "remote" alongside remote: false. Read the job's field, not the office's boolean.

There is no posting date. At all. Not on the list, not on the job page, no JSON-LD anywhere. The only created_at in the payload belongs to the board's font theme. Any date you see on a Kula posting was inferred by whoever indexed it, not published by Kula.

A churned customer returns 403, not 404. The body says err_account_terminated. That is a permanently dead board rather than a block — Kula fronts no WAF — so treating the 403 as a bot wall means retrying a cancelled account forever.

Salary has a real stated period, which is rare and worth using. interval is an enum running from hourly to yearly, plus quarterly and one_time. The amounts arrive as decimal strings. The last two are the interesting ones: a quarterly figure annualised naively lands 4x too low, and a one-off bonus isn't a salary at all, so both keep their text and no structured number.

Where this stands#

Query it with ?source=kula. Measured across live tenants: 238 jobs and 238 descriptions, averaging around 6,000 characters each. On the boards measured end to end, descriptions, country and department all come back at 100%, and Kula is one of the stronger platforms for the company join.

That is a measurement rather than a ceiling, and it moves as boards are added — read the live numbers off /v1/metasources, which is the only vocabulary worth coding against.

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