roles

List Public Roles

THE PUBLIC JOB BOARD. The most important open-data surface in this product.

Everything else in this file exists to fill this endpoint, and everything about it is chosen on the assumption that its primary consumer is not a browser. It is what external agents read: an agent watching for senior Rust roles above a salary floor is the canonical use of this product, and its experience of Parlel is this JSON. Treat a change here the way you would treat a change to a published API, because that is what it is.

Three consequences follow, and they are the reason this docstring is long.

It is anonymous, and it stays anonymous. No OptionalUserId, no per-viewer field, nothing that varies by who is asking -- which is what lets the whole response be stored by a shared cache and served from it. An agent polling every five minutes should be absorbed by a CDN, not by this process. The day somebody adds a "saved" flag to these cards, every one of those polls starts hitting Postgres.

It is keyset paged, not offset paged. (published_at DESC, id DESC), over-fetched by one. An agent walking the whole board while companies publish into it is the exact workload offset paging gets wrong -- rows shift under the reader and the page after an OFFSET 24 silently skips whatever landed above it. A cursor cannot skip.

Its filters are narrow on purpose. Title text, remote mode, seniority, location substring, and a compensation floor. Location uses the same LIKE pattern as the company directory (acceptable at current board size; revisit with an index if the table grows large). Full-text search over descriptions and skill filters still wait on dedicated indexes.

What is on the board, and what is not

status == "open" AND the company is public. Both halves, joined in one statement rather than filtered in Python, because "the row never leaves the database" is a stronger guarantee than "the serialiser remembered".

A draft is a role its owner has not decided to show anybody. A role belonging to a private company is unreachable even when open -- the company page it links to 404s -- so listing it would be advertising a dead end. A closed role stays readable at its own URL and never appears here; that split is the whole point of having three statuses.

The compensation filter, and its honest sharp edge

comp_min=130000 returns roles whose comp_max clears the floor OR whose comp_min does. The first is the main clause: a role paying 120k-150k clears a 130k floor and a filter that compared only against the bottom of the band would hide it. The second catches a role that published only a floor.

The sharp edge: a role that published NO compensation at all is excluded, and that is a real exclusion -- possibly a large one, since many companies post no salary. It is still the right answer. Including them would mean answering "show me roles above 130k" with a list that mostly cannot be checked, and a filter that silently returns things it did not verify is worse than one that returns fewer things. Currency is deliberately NOT converted: comparing a number against a floor in another currency would be a made-up exchange rate, so the caller filters on the amount and reads the currency off each card.

Query budget

Two statements, constant in the page size: the page (roles joined to their companies) and one batched skill read. There is no third for the company details because the join already carries them -- a per-card company lookup is the N+1 this endpoint would otherwise ship on the one page designed to be crawled.

get/api/public/roles

Request

  • Base URL: https://api.parlel.com (the document declares no server; this is the origin it was published from)
  • URL: https://api.parlel.com/api/public/roles
  • Auth: none declared

Query parameters

limitinteger
cursorstring nullable
qstring nullable
remote'onsite' | 'hybrid' | 'remote' nullable
seniority'intern' | 'junior' | 'mid' | 'senior' | 'staff' | 'principal' | 'exec' nullable
locationstring nullable
comp_mininteger nullable

Response

Successful Response

object required

Changes

No recorded changes to this operation across all 1 revision of this API.