Moderate content
Every comment box, chat feature or user-generated field is an open invitation for the worst thing someone could type, and this endpoint reads each submission before a human has to, flagging toxicity, hate speech and harassment with a severity score attached. It's the layer that lets a community stay open without a moderator reading every single post first.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The problem underneath the feature request
Nobody builds a comment section hoping for a moderation queue, but the moment real users show up, some fraction of what they post will be harassment, slurs or coordinated pile-ons, and manual review alone cannot keep pace with volume. text/moderate exists to catch that fraction automatically, flagging it for removal, review or rate limiting before it's visible to anyone else, rather than after a report comes in.
What happens on each call
Send text items to POST /text/moderate and receive a task_id immediately while the job runs asynchronously against our global edge. The finished result, delivered by signed webhook or a signed link valid for 24 hours, returns a category breakdown — things like hate speech, harassment, and severe toxicity — with a score per category, so you can set your own threshold for auto-removal versus queueing for human review rather than accepting a single blunt yes/no.
Why moderation is judged in categories, not one score
Early spam and profanity filters worked off blocklists of banned words, which broke constantly — they missed creative misspellings and flagged completely innocent words that happened to contain a forbidden substring. Modern moderation reads meaning instead of matching strings, and separates categories because a swear word aimed at nobody is not the same problem as a targeted threat, and treating them identically either over-blocks harmless speech or under-catches real harassment.
Who builds this into their stack
Community platforms that need every post screened before it goes live, not after a user reports it. Marketplaces filtering seller and buyer messages for harassment before a dispute escalates. Comment sections on media sites that want automated pre-screening ahead of a smaller human moderation team. Any product accepting free-text input from strangers at any volume.
Where it sits in an automated pipeline
Because the endpoint is asynchronous, it fits naturally as a pre-publish gate: submit the content, hold it in a pending state, let the webhook return category scores, and publish, hold or discard based on thresholds you control per category. Failed tasks retry automatically up to three times and are never billed, so a moderation gate never becomes a single point of failure that silently drops content instead of checking it.
What you can do with it
Pre-publish comment screening
Hold every new comment in a pending state until moderation scores return, publishing instantly when clean and routing flagged ones to a human queue.
Marketplace message filtering
Screen buyer-seller messages for harassment and threats before they're delivered, catching disputes turning abusive before either side has to report it.
Community pile-on prevention
Monitor a fast-moving comment thread for a spike in hate speech or harassment scores and slow posting automatically before a moderator would even notice.
User-generated content backlog cleanup
Re-scan years of archived forum posts against current moderation categories to find and remove content that was never properly reviewed.
FAQ
How does the content moderation API work?
You send text to POST /text/moderate, receive a task_id right away, and get back category-level toxicity, hate speech and harassment scores by webhook or a signed 24-hour link once the async job completes.
What categories of harmful content does it detect?
It scores text across categories such as hate speech, harassment and severe toxicity, returning individual scores per category so you can decide thresholds independently rather than getting one blunt flag.
Is there a free trial for testing moderation rules?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How much does content moderation cost?
$0.003 per request plus $0.0135 per item, so screening 5,000 comments costs the base fee plus $65, billed only for items that complete.
Can it moderate content in bulk, like an old comment archive?
Yes, the endpoint accepts batches and runs asynchronously, which makes it well suited to re-scanning large archives without holding up any live traffic.
Does it just block banned words?
No, it reads meaning rather than matching a blocklist of words, which avoids both the false positives of flagging innocent text containing a flagged substring and the false negatives of missed creative misspellings.
Can I set my own thresholds for what gets removed?
Yes, since each category returns its own score, you decide what score triggers auto-removal, a review queue, or no action at all, per category.
What happens to flagged content and data afterward?
Submitted text is deleted after the retention window and never used for training; failed items retry automatically up to three times before returning a clear error, and a failed task is never charged.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/text/moderate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"items":["valor-1","valor-2"]}'const res = await fetch("https://api.kit.forhosting.com/text/moderate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": [
"valor-1",
"valor-2"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/text/moderate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"items": [
"valor-1",
"valor-2"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/text/moderate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"items":["valor-1","valor-2"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"items":["valor-1","valor-2"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/text/moderate", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"items": [
"valor-1",
"valor-2"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "text.moderate",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_tokens | 20000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |