ledger
Employer opt-out and takedowns
How a site owner removes themselves, why the removal is verified rather than taken on trust, and how it propagates to every endpoint.
1Removing your site
Go to /optout, enter your domain and an email address at that domain, and return the six-digit code. The removal takes effect immediately.
In depthWhy it exists, what it is not, what people get wrong
Vacancies here are read from employers' own public careers pages and from the systems they publish into, and we send candidates to the employer's own application page. The default is therefore to include. An owner who objects has to be able to act immediately, though — not email somebody and wait — so the removal is self-service and takes effect the moment it is verified.
It is verified because an unverified opt-out form is a denial-of-service button: anyone could remove a competitor's listings with a form submission. So a request is only honoured once a code sent to an address at that domain is returned, which is something only someone controlling the domain can do.
Exact contractTypes, defaults, ranges, errors, edge cases
POST /public/optout/requestwith the domain and an email address on it. The domain is normalised first — scheme,www., path, port and query are all stripped, and it is lowercased — sohttps://www.Acme.com/careersandacme.comare the same request.- A six-digit code is generated with a cryptographic random source (a broken RNG fails the request rather than falling back to something guessable) and mailed to the address. Only its salted hash is stored, salted with the domain so a leaked hash cannot be replayed against a different one.
POST /public/optout/verifywith the domain and the code. Five attempts, then the code is dead. The code expires after 30 minutes, and a fresh one cannot be requested more often than every 2 minutes.- On success the domain is marked opted out. Its rows move to
optout_hiddenin the withheld population and stop being served everywhere.
The email address must be at the domain being removed — that is the whole verification. An address at a different domain is refused, not silently accepted.
2How it propagates
Opted-out rows leave every endpoint at once — live, closed and the change feeds — and no parameter re-admits them.
In depthWhy it exists, what it is not, what people get wrong
A removal that leaked through one endpoint would not be a removal. So it is applied at the serving predicate rather than per handler: the rows are excluded from the served set itself, which every listing endpoint, every detail endpoint and every feed reads from.
If you are mirroring this data, an opt-out reaches you as a withdrawn change on /v1/changes — the same kind used when we withdraw a row for any other reason. Treat it as you treat delisted: stop serving the row. That is the mechanism by which somebody else's opt-out becomes your obligation too, and it is why an integration that ignores unknown change values is a problem rather than an inconvenience.
Exact contractTypes, defaults, ranges, errors, edge cases
| Surface | Effect of an opt-out |
|---|---|
/v1/jobs, /public/jobs | Rows disappear. They are counted in withheld_reasons.optout_hidden. |
/v1/jobs/{id}, /public/jobs/{slug} | 404. |
/v1/jobs/closed, /v1/jobs/expired | Rows disappear from the closure feeds as well. |
/v1/changes | The row is reported once with change: "withdrawn", then never again. |
/v1/companies, /public/companies | The company's open_roles falls; the company disappears once it has none. |
/v1/export | Rows are not written into the stream. |
| The website | /job/<slug> and /company/<slug> 404, and the sitemap stops listing them. |
| Future fetching | The domain is not re-fetched, so the rows do not come back on the next refresh. |
3Corrections and takedowns for a single listing
One wrong row does not need a domain-wide opt-out. Write to us with the listing URL and what is wrong with it.
In depthWhy it exists, what it is not, what people get wrong
Opting out removes everything from a domain, which is the right response to “do not carry us” and the wrong response to “this one row is stale” or “this salary is wrong”. For the second kind, the correction route is /contact?topic=data, which reaches a person rather than a queue.
The most useful thing to send is the listing URL on this site (or its id) and the specific field that is wrong. If the row is stale — the vacancy is filled — saying so gets it closed with a reason rather than deleted, which is the correct outcome for a ledger.
Exact contractTypes, defaults, ranges, errors, edge cases
- A whole domain
- /optout — self-service, verified, immediate.
- One listing, wrong data
- /contact?topic=data.
- One listing, already filled
- Same route. It will be closed with a reason, not deleted — see Closed roles.
- A legal request
- /contact, or
[email protected]. Both are monitored; the address is published on every page of the site. - Privacy
- There is no personal data in the ledger — a row names a company, not a person. The privacy policy covers what the website itself collects.
This page was rendered 11 September 2026, 03:39 UTC. Every figure on it comes from the endpoint named beside it, and every published request is re-sent against the live API before this site is allowed to build. If something here is wrong, the thumbs-down above reaches a person.