Spam Detection
Discuse spam detection classifies text as spam or not, with a confidence score. Send text to POST https://api.discuse.com/api/v2/check with check_spam enabled, and read the verdict back from results.spamfinder. It catches the promotional spam, scams, and bot-generated noise that simple keyword filters miss.
What does spam detection catch?
The model is trained on the high-volume patterns that evade blocklists:
- Promotional spam and unsolicited advertising
- Scam and phishing messages
- Bot-generated and copy-paste content
It returns a single label (such as spam or ham) plus a confidence score, so you can decide how strict to be.
How do I run a spam check?
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": "CONGRATULATIONS! You won $10,000! Click here to claim: bit.ly/fake"
},
"settings": {
"check_spam": true
}
}'
Response format
{
"has_violations": true,
"cached": false,
"message": "Spam content detected",
"results": {
"hits": true,
"spamfinder": {
"text": "CONGRATULATIONS! You won $10,000! Click here to claim: bit.ly/fake",
"label": "spam",
"confidence": 0.97,
"is_spam": true,
"hit": true
}
},
"usage": {
"api_requests_used": 8,
"api_requests_limit": 5000,
"api_requests_remaining": 4992
}
}
What fields does the spam result return?
| Field | Type | Meaning |
|---|---|---|
text |
string | The text that was classified |
label |
string | Model classification (e.g. spam, ham) |
confidence |
number | Model confidence in the label (0.0–1.0) |
is_spam |
bool | Raw model verdict — label == spam, threshold-unaware |
hit |
bool | Threshold-aware decision — is_spam AND confidence ≥ your project's spam threshold |
is_spam vs hit
is_spam is the raw verdict: the model labelled the text as spam regardless of how confident it was. hit additionally requires the confidence to clear your project's configured spam threshold. Gate moderation actions on hit, not on is_spam, so a low-confidence spam label does not punish a borderline message.
How do I interpret the confidence score?
confidence reflects how certain the model is of its label:
- 0.0 – 0.3: very low — likely legitimate.
- 0.3 – 0.5: low — borderline.
- 0.5 – 0.7: moderate — suspicious.
- 0.7 – 0.9: high — very likely spam.
- 0.9 – 1.0: very high — almost certainly spam.
Recommended thresholds
Set your project's spam threshold to match your platform's tolerance:
const SPAM_THRESHOLDS = {
strict: 0.5, // professional platforms, financial services
standard: 0.7, // social media, forums
permissive: 0.85 // creative platforms, open communities
};
Use cases
Comment sections
async function moderateComment(comment) {
const result = await checkSpam(comment.text);
const spam = result.results.spamfinder;
if (spam.hit) {
if (spam.confidence > 0.9) {
return { action: 'reject', reason: 'spam_detected' };
}
return { action: 'review', reason: 'possible_spam' };
}
return { action: 'approve' };
}
User registration
def validate_registration(user_data):
bio = user_data.get('bio')
if bio:
result = check_spam(bio)
if result['results']['spamfinder']['hit']:
return {'approved': False, 'reason': 'Spam content detected in profile'}
return {'approved': True}
Messaging platforms
async function filterMessage(message, sender) {
const result = await checkSpam(message.text);
const spam = result.results.spamfinder;
if (spam.hit) {
await incrementSpamCount(sender.id);
const spamCount = await getSpamCount(sender.id);
if (spamCount > 3) {
await banUser(sender.id, 'repeated_spam');
}
return { delivered: false, reason: 'Message filtered as spam' };
}
return { delivered: true };
}
Combining with other checks
Run spam alongside sentiment and language in one request:
{
"content": {
"text": "Check out this amazing deal! Click here: example.com/offer"
},
"settings": {
"check_spam": true,
"check_sentiment": true,
"check_language": true
}
}
The response then carries results.spamfinder, results.sentiment, and results.language together.
Best practices
Use graded responses
Instead of binary block/allow, branch on confidence:
function handleSpamResult(spam) {
if (!spam.hit) return 'allow';
if (spam.confidence > 0.95) return 'silent_delete';
if (spam.confidence > 0.8) return 'block_notify';
if (spam.confidence > 0.6) return 'flag_for_review';
return 'apply_friction';
}
Track repeat offenders
async function assessUser(userId, spam) {
if (spam.hit) {
await incrementUserSpamScore(userId, spam.confidence);
}
const userScore = await getUserSpamScore(userId);
if (userScore > 10.0) await autoSuspendUser(userId);
else if (userScore > 5.0) await flagForManualReview(userId);
}
Whitelist trusted users
Skip the spam check for verified or high-trust accounts to cut false positives and save quota:
function shouldCheckSpam(user) {
if (user.isVerified) return false;
if (user.trustScore > 0.9) return false;
return true;
}
Usage limits
Spam detection draws from your sentiment-analysis quota:
| Plan | Monthly Analyses | Notes |
|---|---|---|
| Basic | 1,000 | Includes spam + sentiment |
| Gold | 5,000 | Includes spam + sentiment |
| Platinum | 15,000 | Includes spam + sentiment |
| Ultimate | 30,000 | Includes spam + sentiment |
Cached responses do not count against your quota.
Integration examples
Express.js middleware
const spamFilter = async (req, res, next) => {
if (req.body.text) {
const result = await checkSpam(req.body.text);
if (result.results.spamfinder.hit) {
return res.status(400).json({
error: 'spam_detected',
message: 'Your message was flagged as spam'
});
}
}
next();
};
app.post('/api/comments', spamFilter, createComment);
Python Flask
from functools import wraps
from flask import request, jsonify
def spam_filter(f):
@wraps(f)
def decorated(*args, **kwargs):
text = request.json.get('text')
if text:
result = check_spam(text)
if result['results']['spamfinder']['hit']:
return jsonify({
'error': 'spam_detected',
'message': 'Your message was flagged as spam'
}), 400
return f(*args, **kwargs)
return decorated
@app.route('/api/comments', methods=['POST'])
@spam_filter
def create_comment():
pass
Next steps
- Text Analysis - combine spam with sentiment scoring
- Language Detection - detect and enforce content language
- Quick Start Guide - get your first API key