Text Analysis: Sentiment, Spam, and Language in One Call
Discuse text analysis scores a message for toxicity, spam, and language in a single POST https://api.discuse.com/api/v2/check request. Send your text in content.text, authenticate with the X-API-Key header, and read the per-check results back under results.
What does the text endpoint check?
One /api/v2/check call can run three text checks at once:
- Sentiment: toxicity, profanity, threat, and insult scoring, plus a negative/toxic verdict.
- Spam: promotional spam, scams, and bot-generated text, returned as a
labelplus a confidence score. - Language: the detected language code, with optional enforcement against an expected language.
Each check runs only when enabled, either in your project settings or via the per-request settings object.
How do I call the text endpoint?
curl -X POST https://api.discuse.com/api/v2/check \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"content": {
"text": "This is an example message to analyze"
},
"settings": {
"check_sentiment": true,
"check_spam": true,
"check_language": true
}
}'
content.text accepts up to 10,000 characters. The API key can be sent in the X-API-Key header or as api_key in the request body.
Response
{
"has_violations": false,
"cached": false,
"message": "Content appears safe",
"results": {
"hits": false,
"sentiment": {
"hit": false,
"is_negative": false,
"is_toxic": false,
"score": 0.04,
"toxicity": 0.02,
"toxic": 0.02,
"profanity": 0.01,
"threat": 0.00,
"insult": 0.03
},
"spamfinder": {
"text": "This is an example message to analyze",
"label": "ham",
"confidence": 0.12,
"is_spam": false,
"hit": false
},
"language": {
"language": "en",
"confidence": 0.98,
"hit": false
}
},
"usage": {
"api_requests_used": 41,
"api_requests_limit": 5000,
"api_requests_remaining": 4959
}
}
has_violations mirrors results.hits: it is true when any enabled check fires its hit flag. processing_time_ms is only present when timing is enabled in your project settings.
Sentiment analysis
The sentiment check returns both a verdict and per-dimension scores from 0.0 to 1.0.
| Field | Type | Meaning |
|---|---|---|
is_negative |
bool | Message reads as negative |
is_toxic |
bool | Message crosses the toxicity threshold |
score |
number | Overall sentiment/severity score |
toxicity |
number | Toxicity confidence (0.0–1.0) |
toxic |
number | Toxicity confidence (legacy alias of toxicity) |
profanity |
number | Explicit-language confidence |
threat |
number | Threat-of-harm confidence |
insult |
number | Personal-attack confidence |
hit |
bool | True when the message violates the sentiment thresholds |
message |
string | Optional explanation |
How do I interpret a sentiment score?
A score is the model's confidence that the dimension applies:
- 0.0 – 0.3: low, generally safe.
- 0.3 – 0.6: moderate, may warrant review.
- 0.6 – 0.8: high, likely problematic.
- 0.8 – 1.0: very high, almost certainly violating.
Example: toxic content
Request:
{
"content": {
"text": "You're the worst person I've ever met. I hate everything about you."
},
"settings": { "check_sentiment": true }
}
Response:
{
"has_violations": true,
"results": {
"hits": true,
"sentiment": {
"hit": true,
"is_negative": true,
"is_toxic": true,
"score": 0.91,
"toxicity": 0.89,
"toxic": 0.89,
"profanity": 0.15,
"threat": 0.22,
"insult": 0.95
}
}
}
Spam detection
The spam check classifies text and returns a single label with a confidence score. It catches the patterns that evade keyword blocklists: promotional spam, scams and phishing, and bot-generated text.
Example: spam content
Request:
{
"content": {
"text": "CONGRATULATIONS! You've won $10,000! Click here to claim: www.fake-prize.com"
},
"settings": { "check_spam": true }
}
Response:
{
"has_violations": true,
"results": {
"hits": true,
"spamfinder": {
"text": "CONGRATULATIONS! You've won $10,000! Click here to claim: www.fake-prize.com",
"label": "spam",
"confidence": 0.97,
"is_spam": true,
"hit": true
}
}
}
is_spam is the raw model verdict (the model labelled the text as spam). hit is the threshold-aware decision: it is true only when is_spam is true and confidence clears your project's spam threshold. Gate moderation on hit, not on is_spam. See the Spam Detection guide for details.
Language detection
Set check_language to detect the language code of content.text. The result is in results.language.language (for example "en", "fr", "es").
Request:
{
"content": { "text": "Bonjour, comment allez-vous aujourd'hui?" },
"settings": { "check_language": true }
}
Response:
{
"results": {
"language": {
"language": "fr",
"confidence": 0.99,
"hit": false
}
}
}
To flag content that is not in your expected language, set expected_language. When the detected language differs, language.hit is true and expected/detected are populated:
{
"content": { "text": "Hola, cómo estás?" },
"settings": { "check_language": true, "expected_language": "en" }
}
{
"results": {
"language": {
"language": "es",
"detected": "es",
"expected": "en",
"confidence": 0.95,
"hit": true
}
}
}
See Language Detection for the full language list and enforcement patterns.
Which checks can I toggle?
The optional settings object overrides your project defaults for a single request. The text-relevant toggles are:
| Setting | Type | Effect |
|---|---|---|
check_sentiment |
bool | Run sentiment analysis |
check_spam |
bool | Run spam detection |
check_language |
bool | Run language detection |
check_badwords |
bool | Run the badwords blocklist |
expected_language |
string | Language code to enforce (e.g. "en") |
{
"content": { "text": "Your message here" },
"settings": {
"check_sentiment": true,
"check_spam": true,
"check_language": true,
"expected_language": "en"
}
}
Usage limits
Sentiment, spam, and language detection draw from the per-plan sentiment-analysis quota:
| Plan | Sentiment Analyses/Month |
|---|---|
| Basic | 1,000 |
| Gold | 5,000 |
| Platinum | 15,000 |
| Ultimate | 30,000 |
Cached responses do not count against your quota. The usage object in every response reports api_requests_used, api_requests_limit, and api_requests_remaining.
Best practices
Set thresholds per platform
Apply different sentiment cutoffs for different audiences:
const THRESHOLDS = {
kids: { toxicity: 0.3, profanity: 0.2, threat: 0.2, insult: 0.3 },
general: { toxicity: 0.5, profanity: 0.5, threat: 0.4, insult: 0.5 },
adult: { toxicity: 0.7, profanity: 0.8, threat: 0.5, insult: 0.7 }
};
Account for context
Clinical, journalistic, and fiction content can trip toxicity and profanity scores legitimately. Combine automated scoring with human review for borderline cases:
const sentiment = result.results.sentiment;
if (sentiment.toxicity > 0.9) {
await removeContent(contentId); // high confidence: auto-remove
} else if (sentiment.toxicity > 0.5) {
await queueForReview(contentId); // borderline: human review
} else {
await approveContent(contentId);
}
Integration examples
JavaScript
async function analyzeText(text) {
const response = await fetch('https://api.discuse.com/api/v2/check', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.DISCUSE_API_KEY
},
body: JSON.stringify({
content: { text },
settings: { check_sentiment: true, check_spam: true, check_language: true }
})
});
return response.json();
}
const result = await analyzeText('Hello, how are you?');
console.log(result.has_violations); // false
Python
import os
import requests
def analyze_text(text):
response = requests.post(
'https://api.discuse.com/api/v2/check',
headers={
'Content-Type': 'application/json',
'X-API-Key': os.environ['DISCUSE_API_KEY']
},
json={
'content': {'text': text},
'settings': {
'check_sentiment': True,
'check_spam': True,
'check_language': True
}
}
)
return response.json()
result = analyze_text('Hello, how are you?')
print(result['has_violations']) # False
Ready to implement text analysis? See the Quick Start Guide for step-by-step setup.