<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paxmod</title>
    <description>The latest articles on DEV Community by Paxmod (@paxmod).</description>
    <link>https://dev.to/paxmod</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4140375%2Fe34e40fb-3660-4a21-b92d-02b9798c6d4e.png</url>
      <title>DEV Community: Paxmod</title>
      <link>https://dev.to/paxmod</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paxmod"/>
    <language>en</language>
    <item>
      <title>Perspective API shuts down Dec 31: what breaks on January 1</title>
      <dc:creator>Paxmod</dc:creator>
      <pubDate>Thu, 08 Oct 2026 05:16:20 +0000</pubDate>
      <link>https://dev.to/paxmod/perspective-api-shuts-down-dec-31-what-breaks-on-january-1-1lh3</link>
      <guid>https://dev.to/paxmod/perspective-api-shuts-down-dec-31-what-breaks-on-january-1-1lh3</guid>
      <description>&lt;p&gt;Google's Perspective API stops working after &lt;strong&gt;December 31, 2026&lt;/strong&gt;. Jigsaw stopped taking usage and quota-increase requests after February 2026, so whatever quota you have now is what you'll have until the end. The default is an average of 1 query per second per project.&lt;/p&gt;

&lt;p&gt;The shutdown itself is easy to understand. The dangerous part is what your code does when the call stops working, because a lot of moderation code is written to never get in the user's way. When that code fails, it lets everything through and doesn't tell anyone.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: we build &lt;a href="https://www.paxmod.com" rel="noopener noreferrer"&gt;Paxmod&lt;/a&gt;, a moderation API, and we mention it at the end. Everything else here applies whatever you replace Perspective with.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Assume it fails quietly
&lt;/h2&gt;

&lt;p&gt;We don't know exactly what &lt;code&gt;commentanalyzer.googleapis.com&lt;/code&gt; will return on January 1. It could be an HTTP error, a timeout or a DNS failure. Your code has to treat all three as "moderation is down", not "this comment is fine".&lt;/p&gt;

&lt;p&gt;Here's what two popular integrations do today, from reading their source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discourse's official plugin&lt;/strong&gt; turns any response without &lt;code&gt;attributeScores&lt;/code&gt; into a score of &lt;code&gt;0.0&lt;/code&gt;. An HTTP error body has no scores, so every post looks clean and nothing gets flagged. Only connection failures raise an error. If you have backfill on, it also stores those &lt;code&gt;0.0&lt;/code&gt; scores against old posts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coral Talk&lt;/strong&gt; logs "could not determine comment toxicity" and lets the comment through unflagged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your own code probably has the same habit. Look for patterns like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;attributeScores&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;TOXICITY&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;summaryScore&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of these turn an outage into an "everything is clean" result. Make the failure explicit instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributeScores&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;moderation.failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ModerationUnavailable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then decide on purpose, for each surface, whether a failed check lets the message through, holds it for review, or blocks it. Live game chat usually allows it and logs. A kids' platform or a comment section with legal exposure might hold it.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Rehearse January 1 now
&lt;/h2&gt;

&lt;p&gt;You don't have to wait. In staging, make Perspective unreachable and watch what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Option A: break DNS for the host (staging box only)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"127.0.0.1 commentanalyzer.googleapis.com"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/hosts

&lt;span class="c"&gt;# Option B: swap in a bad key, which gives you an error body instead of a dead host&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PERSPECTIVE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;invalid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then post something nasty and check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Did anything get flagged, held or logged?&lt;/li&gt;
&lt;li&gt;[ ] Did an alert fire?&lt;/li&gt;
&lt;li&gt;[ ] Did the service still start? If you build a Google API client at startup with &lt;code&gt;googleapiclient.discovery.build("commentanalyzer", ...)&lt;/code&gt;, that call fetches Perspective's discovery document over the network (the Python client doesn't ship a copy for this API), so it can fail before your app handles a single request.&lt;/li&gt;
&lt;li&gt;[ ] Did a queue or retry loop start hammering the API?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Undo the change afterwards.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Find every call site
&lt;/h2&gt;

&lt;p&gt;Perspective tends to show up in more places than the one service you remember.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code and config:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rg &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"commentanalyzer|perspectiveapi|comments:analyze|suggestscore|PERSPECTIVE_API"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
rg &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"perspective-api-client|google-api-python-client|peRspective"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  package.json package-lock.json yarn.lock pnpm-lock.yaml requirements&lt;span class="k"&gt;*&lt;/span&gt;.txt pyproject.toml poetry.lock DESCRIPTION 2&amp;gt;/dev/null
rg &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"perspective"&lt;/span&gt; .env&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.tf &lt;span class="k"&gt;*&lt;/span&gt;.yaml &lt;span class="k"&gt;*&lt;/span&gt;.yml 2&amp;gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Across your GitHub org:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh search code &lt;span class="s2"&gt;"commentanalyzer"&lt;/span&gt; &lt;span class="nt"&gt;--owner&lt;/span&gt; YOUR_ORG
gh search code &lt;span class="s2"&gt;"perspectiveapi"&lt;/span&gt; &lt;span class="nt"&gt;--owner&lt;/span&gt; YOUR_ORG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In Google Cloud.&lt;/strong&gt; The API is enabled per project, so this lists every project that can still call it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;p &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;gcloud projects list &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value(projectId)"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;gcloud services list &lt;span class="nt"&gt;--enabled&lt;/span&gt; &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value(config.name)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; commentanalyzer &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check the traffic graph for each one in the console under APIs and Services. If a project shows traffic you can't explain, something you forgot is still calling it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In apps you didn't write.&lt;/strong&gt; These keep their Perspective settings in the app, not in your repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discourse: the &lt;code&gt;discourse-perspective-api&lt;/code&gt; plugin, with its key in site settings.&lt;/li&gt;
&lt;li&gt;Coral Talk: Configure, Moderation, the Perspective toxicity filter.&lt;/li&gt;
&lt;li&gt;Minecraft servers: chat plugins like ChatProtect and AutoMod can be set up to use Perspective.&lt;/li&gt;
&lt;li&gt;Discord and Telegram bots, browser extensions, and research notebooks (the &lt;code&gt;peRspective&lt;/code&gt; R package is common in academic work).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. List what you'll lose
&lt;/h2&gt;

&lt;p&gt;Write down exactly what you use, because a replacement won't match it one for one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Attributes.&lt;/strong&gt; The production ones were TOXICITY, SEVERE_TOXICITY, IDENTITY_ATTACK, INSULT, PROFANITY and THREAT, and SEXUALLY_EXPLICIT and FLIRTATION were experimental (English only). Note which ones you request and which ones you actually act on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thresholds.&lt;/strong&gt; A 0.8 from Perspective doesn't mean 0.8 anywhere else. Every threshold has to be re-tuned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Span scores.&lt;/strong&gt; If you highlight the offending part of a comment, you're using &lt;code&gt;spanScores&lt;/code&gt;, and most replacements don't return them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Languages.&lt;/strong&gt; Check which languages your traffic is actually in, not which ones you configured.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stored scores.&lt;/strong&gt; Dashboards, trust levels and "toxicity over time" charts built on stored scores will flatline, or worse, fill with zeros from failed calls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feedback.&lt;/strong&gt; If you send moderator decisions back with &lt;code&gt;comments:suggestscore&lt;/code&gt; (Coral's "send feedback" option does this), that loop ends too.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Shadow-run before you switch
&lt;/h2&gt;

&lt;p&gt;This is the step that makes the cutover boring. It only works while Perspective is still answering, so it has to happen before December 31.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wrap your moderation call so it sends each message to Perspective and to the replacement. Keep acting on Perspective's answer.&lt;/li&gt;
&lt;li&gt;Log both results, plus how long each took and whether either one errored.&lt;/li&gt;
&lt;li&gt;Because you can't get more quota, sample traffic if you're near your limit (on the default 1 QPS, that means sampling). A few thousand real messages is enough to compare.&lt;/li&gt;
&lt;li&gt;Review the cases where they disagree. That's where you set the new thresholds, and where you find out what the replacement catches that Perspective didn't.&lt;/li&gt;
&lt;li&gt;Switch which answer you act on, keep logging both for a few days, then remove Perspective and delete the key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aim to finish well before the holidays. Nobody wants to debug moderation on December 31.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Paxmod fits
&lt;/h2&gt;

&lt;p&gt;If you're choosing a replacement, Paxmod is built for real-time chat and comments. It takes one call per message with a &lt;code&gt;user_id&lt;/code&gt; and &lt;code&gt;context_id&lt;/code&gt;, returns a &lt;code&gt;flagged&lt;/code&gt; or &lt;code&gt;not_flagged&lt;/code&gt; decision with per-category scores, and catches personal information like "where do you live", which Perspective never scored. It has its own format, so you'll change the request and response code, not just the URL. Plans start at $29/month for 50,000 messages, with a 14-day trial that includes 10,000 messages (card required, no free plan).&lt;/p&gt;

&lt;p&gt;The step-by-step migration, with the attribute mapping and before and after code, is in our guide: &lt;a href="https://www.paxmod.com/blog/perspective-api-alternative" rel="noopener noreferrer"&gt;Perspective API alternative: migrate before Dec 31&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Perspective API alternative: how to migrate before the Dec 31 shutdown (with code)</title>
      <dc:creator>Paxmod</dc:creator>
      <pubDate>Thu, 08 Oct 2026 04:51:40 +0000</pubDate>
      <link>https://dev.to/paxmod/perspective-api-alternative-how-to-migrate-before-the-dec-31-shutdown-with-code-39md</link>
      <guid>https://dev.to/paxmod/perspective-api-alternative-how-to-migrate-before-the-dec-31-shutdown-with-code-39md</guid>
      <description>&lt;p&gt;Google's Perspective API stops working after &lt;strong&gt;December 31, 2026&lt;/strong&gt;. Jigsaw closed usage and quota requests in February 2026 and isn't offering migration support. If your forum, comment section or game chat calls &lt;code&gt;commentanalyzer.googleapis.com&lt;/code&gt;, that call starts failing on January 1.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: we build &lt;a href="https://www.paxmod.com" rel="noopener noreferrer"&gt;Paxmod&lt;/a&gt;, a content moderation API for real-time chat, so this guide migrates you to Paxmod. The checklist at the end works whichever API you pick.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Short version
&lt;/h2&gt;

&lt;p&gt;Paxmod isn't a drop-in clone of Perspective. The request and response look different. But in most codebases the switch is one function:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Perspective&lt;/th&gt;
&lt;th&gt;Paxmod&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Endpoint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST https://www.paxmod.com/api/v1/text&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;?key=KEY&lt;/code&gt; query param&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Authorization: Bearer KEY&lt;/code&gt; header&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text field&lt;/td&gt;
&lt;td&gt;&lt;code&gt;comment.text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;message&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Who and where&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;sessionId&lt;/code&gt; (optional)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;user_id&lt;/code&gt; and &lt;code&gt;context_id&lt;/code&gt; (optional, recommended)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attributes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;requestedAttributes&lt;/code&gt; on every request&lt;/td&gt;
&lt;td&gt;Categories and thresholds set per project in the console&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Score you read&lt;/td&gt;
&lt;td&gt;&lt;code&gt;attributeScores.TOXICITY.summaryScore.value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;content_moderation.categories["Harassment"].score&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decision&lt;/td&gt;
&lt;td&gt;You compare scores to thresholds&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;result&lt;/code&gt; is &lt;code&gt;"flagged"&lt;/code&gt; or &lt;code&gt;"not_flagged"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max length&lt;/td&gt;
&lt;td&gt;20 KB&lt;/td&gt;
&lt;td&gt;5,000 characters (split longer text)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use the &lt;code&gt;www&lt;/code&gt; host. The apex domain redirects, and plenty of POST clients won't follow it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapping Perspective attributes to Paxmod categories
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Perspective&lt;/th&gt;
&lt;th&gt;Paxmod&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TOXICITY&lt;/td&gt;
&lt;td&gt;Harassment, Hate and Discrimination, Profanities&lt;/td&gt;
&lt;td&gt;Take the highest, or just use &lt;code&gt;result&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEVERE_TOXICITY&lt;/td&gt;
&lt;td&gt;Threatening, Violence, Hate and Discrimination&lt;/td&gt;
&lt;td&gt;Take the highest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDENTITY_ATTACK&lt;/td&gt;
&lt;td&gt;Hate and Discrimination&lt;/td&gt;
&lt;td&gt;Direct match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INSULT&lt;/td&gt;
&lt;td&gt;Harassment&lt;/td&gt;
&lt;td&gt;Harassment is a little broader&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;THREAT&lt;/td&gt;
&lt;td&gt;Threatening, Violence&lt;/td&gt;
&lt;td&gt;Take the highest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PROFANITY&lt;/td&gt;
&lt;td&gt;Profanities&lt;/td&gt;
&lt;td&gt;Dictionary matcher: 0.8 on a match, 0 otherwise, so keep the threshold below 0.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEXUALLY_EXPLICIT&lt;/td&gt;
&lt;td&gt;Sexual&lt;/td&gt;
&lt;td&gt;Direct match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FLIRTATION&lt;/td&gt;
&lt;td&gt;none fixed&lt;/td&gt;
&lt;td&gt;Write it as a plain-English rule in Advanced mode&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Don't copy your thresholds across.&lt;/strong&gt; Paxmod's scores come from different models, so a 0.8 in Perspective isn't a 0.8 in Paxmod. Each category has its own threshold (default 0.5, flagged when the score goes above it).&lt;/p&gt;

&lt;h2&gt;
  
  
  Before and after: curl
&lt;/h2&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze?key=&lt;/span&gt;&lt;span class="nv"&gt;$PERSPECTIVE_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "comment": { "text": "you are trash, uninstall" },
    "languages": ["en"],
    "requestedAttributes": { "TOXICITY": {}, "INSULT": {}, "THREAT": {} }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://www.paxmod.com/api/v1/text"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$PAXMOD_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "message": "you are trash, uninstall",
    "user_id": "player_123",
    "context_id": "lobby_7"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Before and after: Node
&lt;/h2&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;`https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze?key=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PERSPECTIVE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;requestedAttributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;TOXICITY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isToxic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributeScores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TOXICITY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summaryScore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.paxmod.com/api/v1/text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PAXMOD_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;context_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;channelId&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isToxic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flagged&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;harassment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content_moderation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Harassment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Before and after: Python
&lt;/h2&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PERSPECTIVE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;languages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requestedAttributes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TOXICITY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;is_toxic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attributeScores&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TOXICITY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summaryScore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.paxmod.com/api/v1/text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PAXMOD_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;is_toxic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flagged&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What the Paxmod response looks like
&lt;/h2&gt;

&lt;p&gt;Example values. You get back the categories enabled on your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5f0c2a8e-1d9b-4c47-9a51-3c1f6f2b7e10"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pax"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"original_message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"you are trash, uninstall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"processed_message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"you are trash, uninstall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-08T02:00:00.000Z"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flagged"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Content flagged for Harassment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"degraded"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"unavailable_categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content_moderation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"flagged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Harassment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"flagged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"threshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.93&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Threatening"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"flagged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"threshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Personally Identifiable Information"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"flagged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"threshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;result&lt;/code&gt; is &lt;code&gt;flagged&lt;/code&gt; when any enabled category goes above its threshold, and &lt;code&gt;reason&lt;/code&gt; names which ones.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;degraded: true&lt;/code&gt; means an upstream classifier was briefly unavailable, and the categories listed in &lt;code&gt;unavailable_categories&lt;/code&gt; weren't scored on that call.&lt;/li&gt;
&lt;li&gt;Errors look like &lt;code&gt;{"status": "error", "error": {"code": "INVALID_API_KEY", ...}}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The 6-step migration plan
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start a trial&lt;/strong&gt; and create a project. Copy the API key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn on the categories&lt;/strong&gt; that match the Perspective attributes you used. For game chat, start with the Gaming chat preset.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap the request:&lt;/strong&gt; new URL, Bearer header, &lt;code&gt;message&lt;/code&gt; plus &lt;code&gt;user_id&lt;/code&gt; and &lt;code&gt;context_id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap the parsing:&lt;/strong&gt; read &lt;code&gt;content_moderation.categories[...]&lt;/code&gt;, or act on &lt;code&gt;result&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shadow-run until December 31.&lt;/strong&gt; Send the same messages to both APIs, compare decisions on real traffic, and set thresholds from that. This is the step people skip, and it only works while Perspective is still answering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cut over&lt;/strong&gt; and delete the Perspective key before January 1, 2027.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What Perspective never did
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Personal information.&lt;/strong&gt; "where do you live" gets flagged under Personally Identifiable Information. Perspective had no attribute for that, and in kids' game chat it matters more than swearing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Game chat.&lt;/strong&gt; Paxmod runs on custom Minecraft servers and Roblox games, with a Roblox module and a Unity integration. If you run a Minecraft plugin that used Perspective (ChatProtect and AutoMod both can), there's a &lt;a href="https://www.paxmod.com/integrations/minecraft-perspective-api" rel="noopener noreferrer"&gt;Minecraft-specific guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Player-aware moderation.&lt;/strong&gt; Each message carries a &lt;code&gt;user_id&lt;/code&gt; and a &lt;code&gt;context_id&lt;/code&gt;. The Studio plan adds conversation context, which checks a message against the player's recent history instead of on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your own rules.&lt;/strong&gt; Advanced mode checks messages against a policy you write in plain English.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harder to dodge.&lt;/strong&gt; Text is normalised before scoring, including Unicode lookalike characters and hidden zero-width characters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;Perspective was free, and Paxmod isn't. Indie is $29/month with 50,000 message credits, and Studio is $149/month with 500,000. Every plan starts with a 14-day free trial that includes 10,000 messages and every feature. Full details are on the &lt;a href="https://www.paxmod.com/pricing" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist, whatever API you pick
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Find every call to &lt;code&gt;commentanalyzer.googleapis.com&lt;/code&gt; (code, plugins, config).&lt;/li&gt;
&lt;li&gt;[ ] Note which attributes and thresholds each one uses.&lt;/li&gt;
&lt;li&gt;[ ] Check how your code handles errors. Plenty of integrations treat a failed call as "clean", so moderation can quietly stop on January 1.&lt;/li&gt;
&lt;li&gt;[ ] Shadow-run the replacement while Perspective still works.&lt;/li&gt;
&lt;li&gt;[ ] Cut over before December 31.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full guide, with the mapping table and FAQ, is on &lt;a href="https://www.paxmod.com/blog/perspective-api-alternative" rel="noopener noreferrer"&gt;paxmod.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>gamedev</category>
      <category>javascript</category>
      <category>python</category>
    </item>
    <item>
      <title>Community Sift Is Sunsetting: Use Paxmod for Unity and Roblox Chat Moderation (2026)</title>
      <dc:creator>Paxmod</dc:creator>
      <pubDate>Sat, 26 Sep 2026 04:37:26 +0000</pubDate>
      <link>https://dev.to/paxmod/community-sift-is-sunsetting-use-paxmod-for-unity-and-roblox-chat-moderation-2026-1kh3</link>
      <guid>https://dev.to/paxmod/community-sift-is-sunsetting-use-paxmod-for-unity-and-roblox-chat-moderation-2026-1kh3</guid>
      <description>&lt;p&gt;Community Sift (and Indie Sift) is sunsetting. If your studio still routes live game chat through it, you need a replacement on the critical path, not a six-week enterprise RFP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Unity, Roblox, and custom multiplayer chat, use &lt;a href="https://www.paxmod.com/services/game-moderation?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Paxmod&lt;/a&gt;.&lt;/strong&gt; It is a self-serve game chat moderation API built for live lobbies, party chat, and COPPA-shaped risk. Get a key the same day, wire moderate-on-submit, keep Roblox TextFilter as a first layer, and stop waiting on sales-gated filters.&lt;/p&gt;

&lt;p&gt;This post is from the Paxmod team. We built the product for this exact migration. Below is why studios pick us over GGWP, Azure AI Content Safety, OpenAI Moderation, and other "Sift alternative" lists, plus the afternoon checklist to prove it on your own sample.&lt;/p&gt;

&lt;h3&gt;
  
  
  What your Sift replacement actually has to do
&lt;/h3&gt;

&lt;p&gt;Sift won gaming trust and safety on three things: chat-tuned text classification, policy around the score, and someone to call when production broke. Those criteria still matter. The market around them changed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure Content Moderator is also retiring (Microsoft points teams to Azure AI Content Safety, sunset &lt;strong&gt;15 March 2027&lt;/strong&gt;). Microsoft stacks get a second forced move.&lt;/li&gt;
&lt;li&gt;Indie and mid-size teams cannot wait on custom pricing when chat is in the match loop.&lt;/li&gt;
&lt;li&gt;Kids and mixed-age titles need &lt;strong&gt;PII detection&lt;/strong&gt; and &lt;strong&gt;grooming-risk&lt;/strong&gt; signals, not only a toxicity label.&lt;/li&gt;
&lt;li&gt;On Roblox, TextFilter / TextChatService is mandatory. Anything that claims to &lt;em&gt;replace&lt;/em&gt; Roblox filtering is the wrong architecture. You want a second layer on top.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you are not shopping for "any moderation API." You are shopping for a &lt;strong&gt;game chat moderation API&lt;/strong&gt; that replaces Sift-shaped workflows without freezing chat.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Paxmod is the default pick after Sift
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.paxmod.com/services/game-moderation?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Paxmod&lt;/a&gt; is API-first trust and safety with gaming as the beachhead. Live multiplayer chat is the product, not a general comment filter bolted onto games later.&lt;/p&gt;

&lt;p&gt;What that means in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hot-path REST (and WebSocket)&lt;/strong&gt; aimed at ~500ms responses so moderation does not stall match flow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gaming-trained classifiers&lt;/strong&gt; for slang, evasion, and lobby/party policy categories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COPPA-oriented tooling on every plan&lt;/strong&gt;: PII detection, stricter age thresholds, grooming-risk scoring (research collaboration with the Australian Institute for Machine Learning). Compliance stays your legal call; the API is the technical layer. Details: &lt;a href="https://www.paxmod.com/coppa?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;COPPA chat moderation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Roblox as a layer, not a replacement&lt;/strong&gt;: keep TextFilter; add Paxmod for grooming patterns, PII, and custom policy. Guide: &lt;a href="https://www.paxmod.com/integrations/roblox?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Roblox chat moderation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unity path&lt;/strong&gt; for server-side moderate-on-submit: &lt;a href="https://www.paxmod.com/integrations/unity-chat-moderation?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Unity chat moderation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public pricing, same-day key&lt;/strong&gt;: Standard $0.25 per 1,000 messages, Advanced $0.40 per 1,000, free tier to test. &lt;a href="https://www.paxmod.com/pricing?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Pricing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Production shape from one live multiplayer client (kids-oriented chat, 30 days ending 13 September 2026), published as the &lt;a href="https://www.paxmod.com/research/game-chat-index?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Game Chat Index&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;12.8M+ messages scanned&lt;/li&gt;
&lt;li&gt;1.04% flag rate&lt;/li&gt;
&lt;li&gt;Largest flag share suggestive/sexual (33.2%), then kids-adjacent and PII, not only slurs&lt;/li&gt;
&lt;li&gt;Client-reported 87% toxicity reduction under its live policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That mix is why a free general moderation endpoint often fails week one: it over-mutes banter and under-weights contact-seeking and grooming-adjacent patterns.&lt;/p&gt;

&lt;p&gt;Full matrix (Paxmod vs GGWP vs Azure AI Content Safety vs Hive): &lt;a href="https://www.paxmod.com/blog/content-moderation-api-comparison-guide-2025?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Gaming moderation API comparison 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the other options compare (and when they are wrong for you)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;What it is good at&lt;/th&gt;
&lt;th&gt;Why it is usually the wrong Sift swap for Unity/Roblox chat&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Paxmod&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-serve game chat API, Unity/Roblox paths, COPPA-oriented tools, public price&lt;/td&gt;
&lt;td&gt;This is the path we recommend for indie to mid-size multiplayer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GGWP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Large T&amp;amp;S orgs that want reputation, voice, reports, ops dashboards&lt;/td&gt;
&lt;td&gt;Sales-gated and heavy. Fine if you are buying a full platform and have budget/time. Overkill if you need an API this month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Azure AI Content Safety&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Azure-centric stacks leaving Content Moderator&lt;/td&gt;
&lt;td&gt;General-purpose. Not COPPA-optimized. Gaming slang false positives are common&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lasso&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Broad content API (text/image/video) and Sift-shaped migration docs&lt;/td&gt;
&lt;td&gt;Verify kids-safety depth and gaming chat latency before you bet the lobby on it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenAI Moderation / Perspective&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prototypes and non-game UGC&lt;/td&gt;
&lt;td&gt;Weak on gaming banter. No kids stack. Not a Sift replacement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you are an enterprise buying a full reputation suite with a large human ops room on day one, talk to GGWP-shaped platforms. If you are all-in on Azure SLAs above gaming-specific accuracy, stay on Azure unless kids-safety forces a split. Everyone else migrating off Sift for &lt;strong&gt;live Unity or Roblox chat&lt;/strong&gt;: start with Paxmod.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migration checklist (one afternoon + one week)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Afternoon (prove it on your data)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export 500–2,000 recent chat messages (redact user IDs).&lt;/li&gt;
&lt;li&gt;Score the same sample on your current Sift (or interim) path and on Paxmod.&lt;/li&gt;
&lt;li&gt;Measure three things only: missed severe harm, false mutes on banter, p50 latency.&lt;/li&gt;
&lt;li&gt;If you have under-13 audiences, force-test PII prompts ("what's your Discord / phone") and multi-turn grooming-adjacent patterns.&lt;/li&gt;
&lt;li&gt;Confirm fail-open: on timeout, allow the message and log. Never hard-block the whole channel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Week (ship)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a project and API key in the &lt;a href="https://www.paxmod.com/console?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Paxmod console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Wire server-side moderate-on-submit for one chat surface (global or party).&lt;/li&gt;
&lt;li&gt;Map Sift-style severity buckets to warn / mute / escalate actions you already run.&lt;/li&gt;
&lt;li&gt;Keep Roblox TextFilter if you are on Roblox. Add Paxmod after it.&lt;/li&gt;
&lt;li&gt;Mirror thresholds into staging, then promote.&lt;/li&gt;
&lt;li&gt;Keep a human review queue for edge categories for the first two weeks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You do not need a perfect taxonomy on day one. You need a hot-path decision and a log.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start here
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Get a key and wire one chat surface: &lt;a href="https://www.paxmod.com/services/game-moderation?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Game chat moderation API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Compare vendors on paper: &lt;a href="https://www.paxmod.com/blog/content-moderation-api-comparison-guide-2025?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Content moderation API comparison&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;See live flag mix: &lt;a href="https://www.paxmod.com/research/game-chat-index?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Game Chat Index&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Roblox layering: &lt;a href="https://www.paxmod.com/integrations/roblox?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;Roblox integration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Kids-oriented controls: &lt;a href="https://www.paxmod.com/coppa?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=sift_alternative_2026" rel="noopener noreferrer"&gt;COPPA&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Community Sift is leaving. Paxmod is the replacement we built for Unity and Roblox chat. Run the sample test, then ship.&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>roblox</category>
      <category>api</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Best Moderation API for Unity and Roblox Chat (2026): OpenAI Moderation Alternatives That Actually Fit Games</title>
      <dc:creator>Paxmod</dc:creator>
      <pubDate>Thu, 24 Sep 2026 04:40:30 +0000</pubDate>
      <link>https://dev.to/paxmod/best-moderation-api-for-unity-and-roblox-chat-2026-openai-moderation-alternatives-that-actually-11f1</link>
      <guid>https://dev.to/paxmod/best-moderation-api-for-unity-and-roblox-chat-2026-openai-moderation-alternatives-that-actually-11f1</guid>
      <description>&lt;p&gt;If you ship multiplayer chat in Unity or Roblox, moderation is not a nice-to-have. It is retention, app-store risk, and (for younger audiences) a COPPA-shaped product requirement.&lt;/p&gt;

&lt;p&gt;Most teams start with whatever is free and fast to wire: OpenAI Moderation, Perspective API, or a general cloud content-safety endpoint. That gets a demo green. It often fails the first week of live traffic.&lt;/p&gt;

&lt;p&gt;This guide is a buyer checklist for production game chat. It covers what breaks with generic tools, what to demand from a vendor, how Paxmod fits those criteria, and a short comparison table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primary CTA:&lt;/strong&gt; &lt;a href="https://www.paxmod.com/console?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;Start in the Paxmod console&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: game chat is not comment-section toxicity
&lt;/h2&gt;

&lt;p&gt;Game chat mixes trash talk, slang, rapid-fire pings, multilingual abuse, and (in kids-oriented titles) attempts to exchange contact info. A single-message "toxicity score" is a blunt instrument.&lt;/p&gt;

&lt;p&gt;In production data from one live multiplayer gaming client (Paxmod &lt;a href="https://www.paxmod.com/research/game-chat-index?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;Game Chat Index&lt;/a&gt;, 30 days ending 13 September 2026):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;12.8M+ messages scanned&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1.04% flag rate&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Largest flag share was &lt;strong&gt;suggestive/sexual (33.2%)&lt;/strong&gt;, then kids-adjacent and PII, not just slurs&lt;/li&gt;
&lt;li&gt;That client measured &lt;strong&gt;87% toxicity reduction&lt;/strong&gt; under its live policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That mix is why "drop in OpenAI Moderation and ship" underperforms. Your false-positive rate on harmless trash talk climbs, while grooming-adjacent patterns and PII slips get under-weighted.&lt;/p&gt;

&lt;h2&gt;
  
  
  What breaks with OpenAI Moderation and generic tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Gaming slang looks like severity
&lt;/h3&gt;

&lt;p&gt;OpenAI Moderation and similar general-purpose classifiers are strong on clear hate and sexual content. They are weaker at separating competitive banter from harassment in context. Studios then either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;raise thresholds and miss real harm, or&lt;/li&gt;
&lt;li&gt;lower thresholds and mute players who were just trash-talking after a round&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either outcome burns player trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Latency and fail behavior matter in the hot path
&lt;/h3&gt;

&lt;p&gt;Chat sits on the critical path. If moderation adds multi-second delay, players feel it. If the API times out and you fail closed, you brick chat. If you fail open with no logging, you fly blind.&lt;/p&gt;

&lt;p&gt;Paxmod is built for real-time game chat with &lt;strong&gt;~500ms&lt;/strong&gt; responses and documented fail-open patterns on integrations like &lt;a href="https://www.paxmod.com/integrations/roblox" rel="noopener noreferrer"&gt;Roblox&lt;/a&gt; (Roblox TextFilter still runs; Paxmod layers on top).&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Kids products need more than a toxicity label
&lt;/h3&gt;

&lt;p&gt;COPPA-oriented games need PII detection, age-appropriate thresholds, and grooming-risk signals. A free moderation endpoint that returns "sexual / hate / violence" scores is not a kids-safety stack.&lt;/p&gt;

&lt;p&gt;Paxmod ships COPPA-oriented tooling (PII detection, configurable thresholds, grooming-risk scoring developed with the Australian Institute for Machine Learning). Details: &lt;a href="https://www.paxmod.com/coppa" rel="noopener noreferrer"&gt;COPPA chat moderation&lt;/a&gt;. Compliance remains your legal call; the API is the technical layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Roblox already has a mandatory filter
&lt;/h3&gt;

&lt;p&gt;On Roblox, TextFilter / TextChatService is required. Replacing it is the wrong architecture. You want a second layer for grooming patterns, PII, and custom policy that the baseline filter will not catch. Paxmod is designed as that layer, not a replacement.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Sales-gated enterprise platforms slow indie and mid-size studios
&lt;/h3&gt;

&lt;p&gt;Some gaming T&amp;amp;S platforms are excellent for large ops teams and are sales-gated with custom pricing. If you need to wire an API this week, transparent self-serve pricing matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buyer criteria checklist
&lt;/h2&gt;

&lt;p&gt;Use this when you evaluate any moderation API for Unity or Roblox chat:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gaming-aware models&lt;/strong&gt; (slang, trash talk vs harassment), not only general web toxicity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time latency&lt;/strong&gt; suitable for chat (target sub-second; Paxmod targets ~500ms)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail-open guidance&lt;/strong&gt; so an outage does not freeze chat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PII and grooming-risk&lt;/strong&gt; for younger audiences, with configurable thresholds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unity and Roblox paths&lt;/strong&gt; (SDKs, server modules, or clear REST examples)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-serve + public pricing&lt;/strong&gt; so you are not blocked on a sales cycle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human review / queue&lt;/strong&gt; for edge cases, not scores alone&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auditability&lt;/strong&gt; (logged decisions you can show to trust &amp;amp; safety or compliance)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regional / security posture&lt;/strong&gt; (encryption, GDPR-ready processes; Paxmod states SOC 2 Type II)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear migration story&lt;/strong&gt; if you are leaving Community Sift / Indie Sift or Azure Content Moderator (Azure Content Moderator retires &lt;strong&gt;15 March 2027&lt;/strong&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a vendor fails half of these, keep looking.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Paxmod fits
&lt;/h2&gt;

&lt;p&gt;Paxmod is an &lt;strong&gt;API-first trust &amp;amp; safety&lt;/strong&gt; stack with &lt;strong&gt;gaming as the beachhead&lt;/strong&gt;: real-time chat moderation for Unity, Roblox, and other multiplayer titles, with the same infrastructure usable later for social, marketplaces, and forums.&lt;/p&gt;

&lt;p&gt;What you get in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REST API&lt;/strong&gt; you can call from game servers; Unity and Roblox integration paths documented&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~500ms&lt;/strong&gt; moderation for chat-scale traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text (and broader media) detection&lt;/strong&gt; across toxicity, spam, CSAM, PII, and custom categories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COPPA-oriented controls&lt;/strong&gt; without a separate "COPPA plan"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage pricing:&lt;/strong&gt; Standard &lt;strong&gt;$0.25 per 1,000 messages&lt;/strong&gt;, Advanced &lt;strong&gt;$0.40 per 1,000 messages&lt;/strong&gt;, free tier to test (&lt;strong&gt;100 messages/month&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Console&lt;/strong&gt; for keys, testing, analytics, and review workflows: &lt;a href="https://www.paxmod.com/console?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;open the console&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deep dive comparison (Paxmod vs GGWP vs Azure AI Content Safety vs Hive): &lt;a href="https://www.paxmod.com/blog/content-moderation-api-comparison-guide-2025?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;Gaming moderation API comparison 2026&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Production category mix and volumes: &lt;a href="https://www.paxmod.com/research/game-chat-index?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;Game Chat Index&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short comparison table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;OpenAI Moderation / Perspective&lt;/th&gt;
&lt;th&gt;Azure AI Content Safety&lt;/th&gt;
&lt;th&gt;Sales-gated gaming T&amp;amp;S platforms&lt;/th&gt;
&lt;th&gt;Paxmod&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gaming-trained context&lt;/td&gt;
&lt;td&gt;General-purpose&lt;/td&gt;
&lt;td&gt;General-purpose&lt;/td&gt;
&lt;td&gt;Usually yes&lt;/td&gt;
&lt;td&gt;Yes (gaming-native beachhead)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-serve + public price&lt;/td&gt;
&lt;td&gt;Free / usage&lt;/td&gt;
&lt;td&gt;Azure billing&lt;/td&gt;
&lt;td&gt;Often sales-gated&lt;/td&gt;
&lt;td&gt;Yes ($0.25-$0.40 / 1K)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unity / Roblox focus&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;Documented integrations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;COPPA-oriented tools&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Not kids-optimized&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;PII, thresholds, grooming-risk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time chat design&lt;/td&gt;
&lt;td&gt;Possible&lt;/td&gt;
&lt;td&gt;Possible&lt;/td&gt;
&lt;td&gt;Ops-heavy&lt;/td&gt;
&lt;td&gt;~500ms API + fail-open patterns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Prototypes, non-game UGC&lt;/td&gt;
&lt;td&gt;Azure-centric stacks&lt;/td&gt;
&lt;td&gt;Large T&amp;amp;S orgs&lt;/td&gt;
&lt;td&gt;Indie to mid-size game studios&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenAI Moderation remains useful for prototypes and non-game UGC. For live Unity/Roblox chat with younger players, a gaming-native API usually wins on false positives, kids-safety signals, and time-to-integrate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended evaluation path (one afternoon)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;List your chat surfaces (global chat, party, DMs, Roblox TextChat channels).&lt;/li&gt;
&lt;li&gt;Pull 500-2,000 real recent messages (redact user IDs). Score them with your current tool and with Paxmod side by side.&lt;/li&gt;
&lt;li&gt;Measure three things only: &lt;strong&gt;missed severe harm&lt;/strong&gt;, &lt;strong&gt;false mutes on banter&lt;/strong&gt;, and &lt;strong&gt;p50 latency&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If you have under-13 audiences, force-test PII prompts ("what's your Discord / phone") and grooming-adjacent multi-turn patterns.&lt;/li&gt;
&lt;li&gt;Wire fail-open: on timeout, allow message + log; never hard-block the whole chat channel.&lt;/li&gt;
&lt;li&gt;Decide pricing against expected messages/day using &lt;a href="https://www.paxmod.com/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When not to choose Paxmod
&lt;/h2&gt;

&lt;p&gt;Be honest with your stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need a full enterprise reputation suite and a large human ops room on day one (some platforms optimize for that workflow).&lt;/li&gt;
&lt;li&gt;You are all-in on Azure and want Microsoft SLAs above gaming-specific accuracy.&lt;/li&gt;
&lt;li&gt;Your only need is occasional comment moderation on a marketing site (a free general API may be enough).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For live game chat, especially Unity or Roblox with COPPA-shaped risk, start with a gaming-native API.&lt;/p&gt;

&lt;h2&gt;
  
  
  CTA: try it on your traffic
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a project and API key in the console:
&lt;strong&gt;&lt;a href="https://www.paxmod.com/console?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;https://www.paxmod.com/console?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Read the full vendor matrix:
&lt;a href="https://www.paxmod.com/blog/content-moderation-api-comparison-guide-2025?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;Content moderation API comparison guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inspect live production flag mix:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.paxmod.com/research/game-chat-index?utm_source=devto&amp;amp;utm_medium=parasite&amp;amp;utm_campaign=game_chat_mod_api_2026" rel="noopener noreferrer"&gt;Game Chat Index&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Roblox layering notes: &lt;a href="https://www.paxmod.com/integrations/roblox" rel="noopener noreferrer"&gt;Roblox integration&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kids-oriented controls: &lt;a href="https://www.paxmod.com/coppa" rel="noopener noreferrer"&gt;COPPA&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Paxmod is built so engineering can ship moderation without waiting on a sales call. Open the console, send your first messages, and keep the checklist above as your go / no-go.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paxmod&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gamedev</category>
      <category>api</category>
      <category>unity3d</category>
      <category>roblox</category>
    </item>
  </channel>
</rss>
