// documentation
alpha 1.2
The only content moderation API built for Hinglish + English. 3-Tier Stealth AI Pipeline — Node-1 rewrites toxic text contextually (~300ms), Node-2 is the HA fallback, Node-3 is a blazing-fast boolean scanner (<50ms) for high-volume pipelines.
detect_only skips Node-1 & Node-2 entirely — hits Node-3 directly for <50ms boolean results.Make your first moderation request in under 60 seconds.
npm install raiplus-moderation
const Raiplus = require('raiplus-moderation'); const client = new Raiplus('rp_alpha_xxxxxxxxxxxxxxxx'); // Full mode — detect + contextual rewrite (~300ms) const result = await client.moderate('ye code ekdum bakwas hai bkl'); console.log(result.isToxic); // true console.log(result.cleanText); // 'ye code thoda aur accha ho sakta hai yaar' console.log(result.confidence); // 0.97 // Fast mode — boolean detect only (<50ms) const scan = await client.detect('bhai kya scene hai'); console.log(scan.isToxic); // false
# 1. Register curl -X POST https://raiplus.in/api/auth/register \ -H "Content-Type: application/json" \ -d '{"email":"you@example.com","password":"yourpassword","username":"devbhai"}' # 2. Verify OTP curl -X POST https://raiplus.in/api/auth/verify-otp \ -H "Content-Type: application/json" -c cookies.txt \ -d '{"email":"you@example.com","otp":"123456"}' # 3. Moderate curl -X POST https://raiplus.in/api/demo/moderate \ -H "Content-Type: application/json" -b cookies.txt \ -d '{"text":"ye frontend walo ka code ekdum bakwas hai bkl","mode":"full"}'
const res = await fetch('https://raiplus.in/api/demo/moderate', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: 'your text here', mode: 'full' }) }); const data = await res.json(); console.log(data.clean_text, data.action_taken, data.telemetry);
import requests session = requests.Session() session.post('https://raiplus.in/api/auth/login', json={'email':'you@example.com','password':'pw'}) res = session.post('https://raiplus.in/api/demo/moderate', json={'text':'ye code bakwas hai bkl','mode':'full'}) print(res.json()['clean_text'])
Two auth methods. API keys for all programmatic usage. httpOnly session cookies for the browser playground — JWT is never exposed to JavaScript.
// SDK — pass key to constructor const client = new Raiplus('rp_alpha_xxxxxxxxxxxxxxxx'); // Or raw fetch with Authorization header const res = await fetch('https://raiplus.in/api/demo/moderate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.RAIPLUS_API_KEY}` }, body: JSON.stringify({ text: 'some text', mode: 'full' }), });
The core endpoint. Detects toxicity and optionally rewrites it. Two modes: full (detect + rewrite) and detect_only (boolean only, <50ms).
| Field | Type | Required | Description |
|---|---|---|---|
| text | string | yes | Text to moderate. Max 500 chars. |
| mode | string | no | full or detect_only. Default: full |
{
"text": "ye frontend walo ka code ekdum bakwas hai bkl",
"mode": "full"
}
POST /api/demo/moderate HTTP/1.1
Content-Type: application/json
Cookie: rp_token=eyJhbGci... # set automatically by browser
Enterprise-grade JSON with full telemetry. Both camelCase (SDK) and snake_case (raw API) fields returned simultaneously on every response.
{
"success": true,
"is_toxic": true,
"isToxic": true, // SDK alias
"confidence": 1.0,
"original_text":"ye frontend walo ka code bakwas hai bkl",
"clean_text": "ye frontend walo ka code thoda aur improve ho sakta hai",
"cleanText": "ye frontend...", // SDK alias
"action_taken": "sanitized_by_node",
"tags": { "profanity":true, "insult":false, "threat":false },
"telemetry": {
"node1_latency_ms": 43, "node2_latency_ms": null,
"total_latency_ms": 43, "nodes_hit": ["Node-1"],
"circuit_breaker": "closed",
"rate_limit": { "limit":30, "remaining":28, "reset":1711245600 }
}
}
| Value | Meaning |
|---|---|
| clean | Not toxic — returned as-is |
| front_door_blocked | Instant keyword match — confidence=1.0, routed to Node-1/2 |
| pure_abuse_refused | Short abuse (≤3 words) — rewrite refused, returns polite template |
| sanitized_by_node | Node-1 or Node-2 rewrote the text contextually |
| soft_toxic_flagged | Heuristic soft-toxic detected after LLM said clean |
| detection_only | mode=detect_only — Node-3, no rewrite |
| fallback_detection_only | Node-1 & Node-2 failed — emergency Node-3 fallback |
| circuit_breaker_bypass | Circuit breaker open — Node-3 used until 60s reset |
| obfuscation_blocked | Mixed-script injection (Latin + Devanagari) blocked by Layer 0 |
| unsupported_language | Non-Latin/non-Hinglish script — not processed |
X-RateLimit-Remaining: 49 X-RateLimit-Reset: 1711245600 X-RateLimit-Tier: alpha
All errors return success: false with a machine-readable error field. Always check retry_after on 429s.
| HTTP | error | Cause | Fix |
|---|---|---|---|
| 400 | invalid_input | Empty text or over 500 chars | Trim input |
| 401 | unauthorized | No session cookie | Login first |
| 401 | token_invalid | Cookie expired or tampered | Re-login |
| 403 | account_banned | User is banned | Contact support |
| 429 | rate_limit_exceeded | Quota hit | Wait retry_after seconds |
| 503 | node1_unavailable | Classifier Node unavailable | Retry after 30s |
| 500 | internal_error | Unexpected server error | Report via /report |
{ "success":false, "error":"rate_limit_exceeded", "retry_after":47 }
if (res.status === 429) { const { retry_after } = await res.json(); console.log(`Rate limited. Retry in ${retry_after}s`); }
Official raiplus-moderation npm package. Zero dependencies. Node ≥ 18 required (uses built-in fetch).
const Raiplus = require('raiplus-moderation'); const client = new Raiplus('rp_alpha_xxxxxxxxxxxxxxxx'); const result = await client.moderate('ye code ekdum bakwas hai bkl'); console.log(result.isToxic); // true console.log(result.confidence); // 0.97 console.log(result.cleanText); // 'ye code thoda aur accha ho sakta hai yaar' console.log(result.actionTaken); // 'sanitized_by_node' console.log(result.tags); // { profanity: true, insult: false, threat: false } console.log(result.telemetry); // { total_latency_ms: 310, nodes_hit: ['Node-1'], ... }
const scan = await client.detect('bhai kya scene hai'); console.log(scan.isToxic); // false — scan.cleanText is undefined (Node-3 never rewrites)
const results = await client.batch([ 'ye code bakwas hai bkl', 'nice work bhai, accha hai', ], { mode: 'detect_only' }); // 300/min burst results.forEach((r, i) => console.log(`[${i}] toxic: ${r.isToxic}`));
const { RateLimitError, AuthError, ValidationError, NetworkError } = require('raiplus-moderation'); try { const result = await client.moderate(text); } catch (e) { if (e instanceof RateLimitError) console.log(`Retry in ${e.retryAfter}s`); if (e instanceof AuthError) console.log('Check your API key'); if (e instanceof NetworkError) console.log('Server unreachable'); }
| Method | Description |
|---|---|
| register(email, password, username) | Create account. Follow with verifyOtp(). |
| verifyOtp(email, otp) | Verify OTP. Stores session cookie. |
| login(email, password) | Login. Stores cookie internally. |
| logout() | Clear stored cookie. |
| me() | Get user profile (quota, role, etc.). |
const client = new Raiplus('rp_alpha_xxx', { baseUrl: 'https://staging.raiplus.in', // default: 'https://raiplus.in' timeout: 15000, // ms, default: 30000 debug: true, // log requests (dev only) });
Full TypeScript declarations ship in src/index.d.ts. No @types/ package needed.
import Raiplus, { RaiplusClient, ModerationResult, DetectResult } from 'raiplus-moderation'; const client: RaiplusClient = new Raiplus('rp_alpha_xxx'); const result: ModerationResult = await client.moderate('ye code bakwas hai bkl'); console.log(result.cleanText); // string | null console.log(result.isToxic); // boolean console.log(result.confidence); // number (0–1)
interface ModerationResult { isToxic: boolean; confidence: number; originalText: string; cleanText: string | null; actionTaken: string; tags: { profanity: boolean; insult: boolean; threat: boolean }; telemetry: Record<string, unknown>; } interface DetectResult { isToxic: boolean; confidence: number; actionTaken:string; }
Two limit axes — per-minute burst and per-day quota. Mode-based: detect_only gets 10× more burst because Node-3 is ~6× cheaper to run.
| Tier | Mode | Per-min | Per-day | Keyed by | On exceed |
|---|---|---|---|---|---|
| guest | any | 20/min | 100/day | IP | 429 + signup nudge |
| alpha | full | 30/min | 500/day | User ID | 429 + retry_after |
| alpha | detect_only | 300/min | 5,000/day | User ID | 429 + retry_after |
| email OTP | — | 5 emails/hr | — | Silent block | |
| report | — | 2/day | — | IP | 429 + Discord link |
Multiple layers prevent cascading failures. Even during a full LLM outage, every request gets a usable answer via Node-3 fallback.
Live status at raiplus.in/status — auto-refreshes every 30s with a public incident history.
detect_only mode has never been affected by Node-1/Node-2 incidents.Accuracy and latency from our internal test suite. Alpha numbers — we publish these so you can make an informed decision.
| Metric | Hinglish | English | Mixed |
|---|---|---|---|
| Precision | 92.4% | 94.1% | 91.8% |
| Recall | 89.7% | 91.2% | 88.3% |
| F1 Score | 91.0% | 92.6% | 90.0% |
| False Positive Rate | 3.2% | 2.8% | 4.1% |
| False Negative Rate | 7.6% | 5.9% | 8.9% |
| Metric | Value | Notes |
|---|---|---|
| Precision | 88.5% | Speed-optimized — slightly lower than Node-1 |
| Recall | 94.2% | Higher recall — fewer misses on toxic content |
| F1 Score | 91.2% | — |
| False Positive Rate | 5.8% | Use full mode for final decisions |
| p50 / p95 / p99 | 32ms / 48ms / 61ms | — |
| Mode | p50 | p90 | p95 | p99 |
|---|---|---|---|---|
| full (Node-1 hit) | 280ms | 340ms | 410ms | 820ms |
| full (Node-2 fallback) | 340ms | 450ms | 560ms | 1100ms |
| detect_only (Node-3) | 32ms | 44ms | 48ms | 61ms |
Honest comparison. We built Raiplus to fill a gap — not to claim we're better at everything.
| Feature | Raiplus (Alpha) | OpenAI Moderation | Perspective API |
|---|---|---|---|
| Hinglish detection | Native ✓ | Poor ✗ | Poor ✗ |
| English detection | Good ✓ | Excellent ✓ | Excellent ✓ |
| Leet-speak / obfuscation | Layer 0 Armor ✓ | Partial | Partial |
| Text rewrite / sanitize | Yes — contextual ✓ | No ✗ | No ✗ |
| detect_only (<50ms) | Yes ✓ | ~100–300ms | ~80–200ms |
| Cost | Free (alpha) | Free but rate-limited | Free tier |
| Production SLA | Beta Q3 2026 | 99.9% ✓ | 99.9% ✓ |
detect_only as a Hinglish pre-screen layer alongside OpenAI moderation for English. Our API is designed to compose.What we do to protect your requests, credentials, and infrastructure. Found a bug? Responsible disclosure is always rewarded — see Hall of Fame.
Explicit line-by-line breakdown of what we collect, store, and how it's used. No vague policy language.
| Data point | Logged? | Purpose |
|---|---|---|
| Hashed IP (SHA-256) | Yes | Rate limiting only |
| is_toxic / confidence | Yes | Analytics |
| latency_ms / action_taken | Yes | Telemetry |
| Raw input text | Flywheel only | Model training (see below) |
What changed and when.
userId ObjectId/string mismatch in MongoDB)fireAsyncLogs — isolated try/catch per branch prevents silent suppressiontotalRequests race condition with atomic $inc{...} fallbackaction_taken values: soft_toxic_flagged, circuit_breaker_bypass, obfuscation_blocked, unsupported_languageraiplus-moderation)detect_only mode — bypasses Node-1 & Node-2, hits Node-3 at <50msaction_taken + telemetry