Job boards

Publish the jobs, not the scams dressed as jobs

Job ads and the messages between employers and candidates, checked before anyone reads them. ToxicFilter catches the offer that charges the applicant to start, the cheque to cash and send back, the parcels to forward and the ad that shuts people out by sex or age, and tells you why in a sentence you can show the employer.

What goes wrong on platforms like yours

Jobs that cost the applicant money

A training kit to buy before the first day, a refundable registration fee, a cheque to deposit and the difference to send back, parcels to receive at home and forward abroad. The people these ads reach are the ones who most need a job to be real, and they find out it was not after paying.

Ads that shut candidates out

"Male candidates only", "under 30 years old", "no foreigners", "no family commitments". Excluding candidates by who they are is illegal in the EU, and your board is the one publishing it, however ordinary the rest of the ad reads.

Scams that read like honest remote work

"No experience needed" and an interview over a chat app are how plenty of genuine delivery and hospitality jobs are advertised. A filter that refuses them costs real candidates real jobs; one that ignores them misses the scam that starts exactly that way.

Explaining every removal

An employer whose ad disappears wants to know why, and in the EU you owe them a statement saying what was done, on what grounds and how to contest it. Writing that by hand for every refused ad does not scale.

What it decides, on content like yours

Judged right now by the engine the API uses, under the template for this kind of platform, with no model involved.

  1. 01 A job that charges to start
  2. 02 Parcels to forward and a cheque to cash
  3. 03 An ad that excludes by sex and age
  4. 04 The same ad with an equal-opportunity footer
  5. 05 An honest job ad

A job that charges to start POST /v1/text

Remote data entry assistant, no experience needed. Before you start you pay a refundable fee of 60 € for your training kit, and the interview is on Telegram.

block 40 ms
  • Reads like a job scam: it asks the applicant to pay before starting, promises easy pay with no experience and holds the interview over a chat app.

Paying before starting beside a promise that no experience is needed is the shape of the scam, so the job board template refuses it. "No experience needed" alone is in every honest waiter job and passes.

The answer, abridged
{
  "decision": "block",
  "flagged": [
    "scam"
  ],
  "scores": {
    "scam": 0.7
  },
  "signals": [
    {
      "category": "scam",
      "score": 0.7,
      "reason": "Reads like a job scam: it asks the applicant to pay before starting, promises easy pay with no experience and holds the interview over a chat app.",
      "evidence": [
        "refundable fee",
        "no experience needed",
        "interview is on telegram"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 40
}

Parcels to forward and a cheque to cash POST /v1/text

Package handler from home. You receive parcels at home and forward the packages to our clients abroad. We will send you a cheque: deposit the cheque and send back the difference.

block 8 ms
  • Reads like a job scam: it involves a cheque to cash and money to send back and asks the applicant to receive and forward parcels.

Two of the strong families together: goods and money flowing the wrong way. Either one beside a weak tell is already refused under this template.

The answer, abridged
{
  "decision": "block",
  "flagged": [
    "scam"
  ],
  "scores": {
    "scam": 0.9
  },
  "signals": [
    {
      "category": "scam",
      "score": 0.9,
      "reason": "Reads like a job scam: it involves a cheque to cash and money to send back and asks the applicant to receive and forward parcels.",
      "evidence": [
        "send you a cheque",
        "deposit the cheque",
        "send back the difference",
        "receive parcels at home",
        "forward the packages"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 8
}

An ad that excludes by sex and age POST /v1/text with surface: job

Warehouse assistant in Leeds. Male candidates only, under 30 years old. Full-time, morning shifts.

review 9 ms
  • Excludes candidates by sex and age.

Held for a person, never refused on its own. Genuine occupational requirements exist (an actress for a female role, staff for a women's shelter), and telling them apart from an exclusion is a person's call.

The answer, abridged
{
  "decision": "review",
  "flagged": [
    "hate"
  ],
  "scores": {
    "hate": 0.65
  },
  "signals": [
    {
      "category": "hate",
      "score": 0.65,
      "reason": "Excludes candidates by sex and age.",
      "evidence": [
        "male candidates only",
        "under 30 years old"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 9
}

The same ad with an equal-opportunity footer POST /v1/text with surface: job

Warehouse assistant in Leeds. Male candidates only, under 30 years old. Full-time, morning shifts. We are an equal opportunity employer and welcome applicants regardless of age or gender.

review 8 ms
  • Excludes candidates by sex and age.

The ad is read sentence by sentence, and equal-opportunity wording only silences the sentence it is in. A footer appended to every ad does not launder the exclusion two lines above it.

The answer, abridged
{
  "decision": "review",
  "flagged": [
    "hate"
  ],
  "scores": {
    "hate": 0.65
  },
  "signals": [
    {
      "category": "hate",
      "score": 0.65,
      "reason": "Excludes candidates by sex and age.",
      "evidence": [
        "male candidates only",
        "under 30 years old"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 8
}

An honest job ad POST /v1/text with surface: job

Junior accountant in Bristol, 32,000 GBP a year plus pension. At least two years of experience with payroll required. Apply with your CV by 30 October.

allow 8 ms

Nearly every ad looks like this: a salary, a requirement of experience, a deadline. It is settled by the free checks in about a millisecond, and "30 October" is not read as an age.

The answer, abridged
{
  "decision": "allow",
  "flagged": [],
  "signals": [],
  "model": {
    "read": false
  },
  "took_ms": 8
}

What it decides, on content like yours

Judged right now by the engine the API uses, under the template for this kind of platform, with no model involved.

A job that charges to start POST /v1/text

Remote data entry assistant, no experience needed. Before you start you pay a refundable fee of 60 € for your training kit, and the interview is on Telegram.

block 40 ms
  • Reads like a job scam: it asks the applicant to pay before starting, promises easy pay with no experience and holds the interview over a chat app.

Paying before starting beside a promise that no experience is needed is the shape of the scam, so the job board template refuses it. "No experience needed" alone is in every honest waiter job and passes.

The answer, abridged
{
  "decision": "block",
  "flagged": [
    "scam"
  ],
  "scores": {
    "scam": 0.7
  },
  "signals": [
    {
      "category": "scam",
      "score": 0.7,
      "reason": "Reads like a job scam: it asks the applicant to pay before starting, promises easy pay with no experience and holds the interview over a chat app.",
      "evidence": [
        "refundable fee",
        "no experience needed",
        "interview is on telegram"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 40
}

Parcels to forward and a cheque to cash POST /v1/text

Package handler from home. You receive parcels at home and forward the packages to our clients abroad. We will send you a cheque: deposit the cheque and send back the difference.

block 8 ms
  • Reads like a job scam: it involves a cheque to cash and money to send back and asks the applicant to receive and forward parcels.

Two of the strong families together: goods and money flowing the wrong way. Either one beside a weak tell is already refused under this template.

The answer, abridged
{
  "decision": "block",
  "flagged": [
    "scam"
  ],
  "scores": {
    "scam": 0.9
  },
  "signals": [
    {
      "category": "scam",
      "score": 0.9,
      "reason": "Reads like a job scam: it involves a cheque to cash and money to send back and asks the applicant to receive and forward parcels.",
      "evidence": [
        "send you a cheque",
        "deposit the cheque",
        "send back the difference",
        "receive parcels at home",
        "forward the packages"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 8
}

An ad that excludes by sex and age POST /v1/text with surface: job

Warehouse assistant in Leeds. Male candidates only, under 30 years old. Full-time, morning shifts.

review 9 ms
  • Excludes candidates by sex and age.

Held for a person, never refused on its own. Genuine occupational requirements exist (an actress for a female role, staff for a women's shelter), and telling them apart from an exclusion is a person's call.

The answer, abridged
{
  "decision": "review",
  "flagged": [
    "hate"
  ],
  "scores": {
    "hate": 0.65
  },
  "signals": [
    {
      "category": "hate",
      "score": 0.65,
      "reason": "Excludes candidates by sex and age.",
      "evidence": [
        "male candidates only",
        "under 30 years old"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 9
}

The same ad with an equal-opportunity footer POST /v1/text with surface: job

Warehouse assistant in Leeds. Male candidates only, under 30 years old. Full-time, morning shifts. We are an equal opportunity employer and welcome applicants regardless of age or gender.

review 8 ms
  • Excludes candidates by sex and age.

The ad is read sentence by sentence, and equal-opportunity wording only silences the sentence it is in. A footer appended to every ad does not launder the exclusion two lines above it.

The answer, abridged
{
  "decision": "review",
  "flagged": [
    "hate"
  ],
  "scores": {
    "hate": 0.65
  },
  "signals": [
    {
      "category": "hate",
      "score": 0.65,
      "reason": "Excludes candidates by sex and age.",
      "evidence": [
        "male candidates only",
        "under 30 years old"
      ]
    }
  ],
  "model": {
    "read": false
  },
  "took_ms": 8
}

An honest job ad POST /v1/text with surface: job

Junior accountant in Bristol, 32,000 GBP a year plus pension. At least two years of experience with payroll required. Apply with your CV by 30 October.

allow 8 ms

Nearly every ad looks like this: a salary, a requirement of experience, a deadline. It is settled by the free checks in about a millisecond, and "30 October" is not read as an age.

The answer, abridged
{
  "decision": "allow",
  "flagged": [],
  "signals": [],
  "model": {
    "read": false
  },
  "took_ms": 8
}

What it looks for

Each a score of its own, with its own lines, and the reason in a sentence whenever one acts.

The template you start from

Pick it when you create a policy and these rules are written for you, ready to edit. Everything it does not mention keeps following our defaults.

  • Scam holds at 0.30 · refuses at 0.60
  • Toxicity holds at 0.30 · never refuses
  • Harassment holds at 0.30 · refuses at 0.65
  • Hate speech holds at 0.25 · refuses at 0.70
  • Violence holds at 0.25 · refuses at 0.60

Set by the template

One call before you publish

Send the text with where it will appear, and act on the decision.

The request

curl https://toxicfilter.com/api/v1/text \
  -H "Authorization: Bearer $TOXICFILTER_KEY" \
  -d content="Remote data entry assistant, no experience needed. Before you start you pay a refundable fee of 60 € for your training kit, and the interview is on Telegram." \
  -d surface=job
The full reference →

A month, in numbers

Items checked
80,000
Read by the model
6,000
Images
2,000
Credits, about
142,000

Fits in the Pro plan. See the plans →

A guide to moderating a job board

What to check, when to check it and how to set the rules, for job ads and the messages between employers and candidates.

How to moderate job ads before they are published

Call the API when an employer submits an ad, with surface: job, and act on one of three answers: publish it, hold it for a person, or refuse it. The surface matters: the check for discriminatory wording only runs on ads, because "only women" about a choir or a shared flat is not an exclusion from a job. Most ads are a salary, a list of tasks and a deadline, and the free checks settle them in about a millisecond. What arrives in review waits in a queue, in your dashboard or through the API, and a signed webhook tells your site when somebody approves it.

How to detect job scams

A job scam needs the applicant's money or help before it pays anything. ToxicFilter reads three strong families of that (paying for training, a kit or a fee before starting; a cheque to deposit and the difference to send back; parcels to receive at home and forward) and two weak ones ("no experience needed", an interview over Telegram or WhatsApp). Under the job board template, two strong families or one strong and one weak are refused as scam. Two weak ones together are held for review and never refused, because that is also how an honest delivery job reads. The same checks run on a message between an employer and a candidate, so the fee asked for after the ad was approved is caught too.

Discriminatory job ads: held for a person, never refused

"Male candidates only", "under 30 years old", "no foreigners", "no family commitments": each is an exclusion by who somebody is, and it lands in hate with a reason that names what the ad excludes by. One excluded characteristic scores 0.60, several 0.65, and two stand-ins such as "good appearance" and "young and dynamic team" 0.45. All of them stay under the 0.70 block line, on purpose: genuine occupational requirements exist, and telling them apart is a person's call. The job board template keeps that line where it is, so these ads always reach a person.

The ad is read sentence by sentence. Equal-opportunity wording ("regardless of age or gender") silences only the sentence it is in, so a footer your board appends to every ad cannot launder "male candidates only" two lines above it. Wording that turns a phrase inclusive ("men or women", "with or without") is blanked before anything is searched, and a nationality named in the same sentence as a right to work ("or a valid work permit") describes who may legally be hired, so it is not flagged.

How ages are read

Ages written as numbers count only as an age: a limit or a range on an adult age, with a unit, or right after who is being sought ("women under 30"), and not "30 years of experience" or "under 30 hours". The instant checks settle these in about a millisecond, in eight languages; what depends on context is the model's to read with effort: high, and because an exclusion is held rather than refused, a person on your side always has the last word.

Choosing the thresholds for your job board

Start from the job board template, which lowers the lines for scams, harassment and threats and keeps discriminatory ads in review. Then try any change as a second policy running in parallel with the one in force: both verdicts are computed on your own traffic, only one acts, and the dashboard shows where they disagree before you switch.

Frequently asked questions

How do you detect fake job offers?

By the shape of the offer rather than a single word. ToxicFilter looks for strong families (paying before starting, a cheque to cash and money to send back, parcels to receive and forward) and weak ones (no experience needed, an interview over a chat app). Two strong families, or one strong and one weak, are refused under the job board template. Two weak ones are held for review and never refused, because honest delivery and hospitality ads are written that way too.

Can it detect discriminatory job ads?

Yes, when you send the ad with the job surface. It recognises exclusions by sex, age, origin or nationality, religion, family situation and disability, and two of the usual stand-ins together ("good appearance" and "young and dynamic team"). Ages count only as an age: "under 30 years old" is one, "30 years of experience" is not. A nationality next to a right to work is the law and is not flagged.

Why are discriminatory ads held and not refused?

Because genuine occupational requirements exist, and the same words describe them: an actress for a female role, staff for a women's shelter, a legal age limit on an apprenticeship. Every score stays under the block line, so a person on your side decides. The job board template keeps that line where it is so these ads always reach somebody.

Does a candidate reporting a scam get flagged as one?

No. A message asking "is this a scam?" about an employer who wants a registration fee silences the job scam check entirely, because warning about a scam must never look like running one.

Does it work for job ads in Spanish and other languages?

The instant checks carry phrase lists for job scams and discriminatory ads in English, Spanish, Portuguese, French, Italian, German, Catalan and Dutch. The model reads many more. Outside those eight, effort high has the model read every ad.

Do I have to tell an employer why their ad was removed?

In the EU, yes: article 17 of the Digital Services Act requires a statement of reasons for every removal or restriction, whatever the size of the platform. ToxicFilter can write it with every blocked ad and take the employer's appeal.

Try it on your own traffic

2,000 credits a month on the free plan, no card. Enough to send a week of your own content and see what it says about it.