All pages

POST /api/v1/name

Check a name

Usernames and display names, including the ones spelled to slip past filters.

Usernames and display names, including the ones spelled to slip past a word list. Check it at registration, and again when somebody changes it.

Parameters

FieldTypeRequired
namestringyesUp to 200 characters.
localesstring[]noYour site's languages, up to ten.
aibooleanno No model reads a name, so this is false and cannot be turned on. Sending "ai": true is refused with 422 ai_unavailable rather than accepted and ignored.
referencestringno Your own id for the thing being judged, up to 120 characters. Never parsed, stored and handed back, so a verdict is findable later by the name you already use for it.
policystringno Which of your policies to judge under. Absent means the project's policy, then your default; an account with none gets the shipped thresholds.
projectstringno Which of your projects the verdict is filed under. Absent means your default project.
actorstringno Your own id for whoever wrote it. Filed with the verdict, and used to move the line when a policy asks for reputation.

Request

curl https://toxicfilter.com/api/v1/name \
  -H "Authorization: Bearer tf_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "name": "H4t3R_88", "locales": ["en"] }'

Response

{
  "decision": "review",
  "flagged": ["evasion"],
  "scores": { "evasion": 0.74 },
  "signals": [
    {
      "category": "evasion",
      "score": 0.74,
      "detector": "evasion",
      "reason": "Full-width characters and digit substitution used to obscure a word.",
      "evidence": ["H4t3R"]
    }
  ],
  "used_ai": false,
  "took_ms": 3,
  "credits": { "remaining": 4890, "renews_at": "2026-09-30T00:00:00+00:00" }
}

Evasion is its own answer

evasion is scored separately from whatever was being hidden, and that is useful on its own: leetspeak, homoglyphs, full-width characters and invisible codepoints in a username are a signal about intent even when the underlying word is ambiguous. A name written to get past a filter tells you something a clean name does not.

Why no model reads it

A name is a shape, not a piece of writing: there is no argument to follow, no sarcasm and no target, and the question is whether the characters were chosen to get past a list. The normaliser and the word lists answer that, and they answer it in under a millisecond for one credit. A model would add a sentence of prose and several credits to the same answer.

So ai here is not a default you can override. It is refused, because the one thing it must not be is accepted and ignored: used_ai: false with nothing anywhere saying why is how a caller pays for a habit and believes they bought something. The same is true of an address and a link. A bio is writing, so a signup can ask for the model.

Names are short, so context is thin and false positives cost more here than anywhere else. Treat review on a name as "look at it", never as "reject it": plenty of real people have names a filter finds interesting.