ModerateAPI Documentation
ModerateAPI provides intelligent content moderation through a simple REST API. Protect your platform from toxic content, spam, and harmful material with AI-powered detection.
Base URL
https://moderateapi.com/api/v1
Quick Start
Get started in 3 steps
- Register for a free account to get your API key
- Make your first API call to moderate content
- Integrate into your application
1. Get Your API Key
Register for an account to receive your API key:
curl -X POST https://moderateapi.com/api/v1/register \
-H "Content-Type: application/json" \
-d '{
"email": "your@email.com",
"password": "your_secure_password"
}'
{
"success": true,
"message": "User created successfully",
"user_id": 123,
"api_key": {
"key": "mk_abc123...",
"name": "Default Key",
"prefix": "mk_abc12"
},
"plan": "free",
"monthly_limit": 1000
}
2. Make Your First Request
Test the moderation API with some content:
curl -X POST https://moderateapi.com/api/v1/moderate \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"text": "This is a test message",
"context": "comment"
}'
{
"safe": true,
"confidence": 0.95,
"issues": [],
"suggested_action": "approve",
"from_cache": false,
"request_id": "unique_id",
"response_time_ms": 85,
"text_length": 21
}
Authentication
ModerateAPI uses API keys for authentication. Include your API key in the request header:
API Key Format
API keys start with mk_ followed by 64 characters.
Example: mk_abc123def456...
Header Authentication
Include your API key in the X-API-Key header:
POST /api/v1/moderate HTTP/1.1
Host: moderateapi.com
Content-Type: application/json
X-API-Key: mk_your_api_key_here
{
"text": "Content to moderate"
}
Bearer Token Authentication
Alternatively, use the Authorization header with Bearer token format:
POST /api/v1/moderate HTTP/1.1
Host: moderateapi.com
Content-Type: application/json
Authorization: Bearer mk_your_api_key_here
{
"text": "Content to moderate"
}
Security
- Never expose API keys in client-side code
- Store API keys securely in environment variables
- Use separate API keys for different environments
- Rotate API keys regularly
Rate Limits
Rate limits are enforced per API key and vary by subscription plan. When you exceed the rate limit, you'll receive a 429 Too Many Requests response.
| Plan | Monthly Limit | Rate Limit | Price |
|---|---|---|---|
| Free | 1,000 req/mo | 10/min | $0 |
| Starter | 10,000 req/mo | 50/min | $19/mo |
| Growth | 100,000 req/mo | 200/min | $99/mo |
| Scale | 500,000 req/mo | 500/min | $299/mo |
Rate Limit Headers
All API responses include rate limit information in the headers:
HTTP/1.1 200 OK
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1640995200
X-RateLimit-Limit— Maximum requests per minute for your planX-RateLimit-Remaining— Requests remaining in current windowX-RateLimit-Reset— Unix timestamp when the rate limit resets
Error Handling
ModerateAPI uses conventional HTTP response codes to indicate the success or failure of API requests.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Everything worked as expected |
| 400 | Bad Request | Invalid request (missing parameters, malformed JSON, etc.) |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | Subscription cancelled or suspended |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Something went wrong on our end |
Error Response Format
All error responses include a JSON object with an error message:
{
"error": "API key required",
"request_id": "req_abc123",
"timestamp": "2024-01-15T10:30:00Z"
}
Handling Errors in Code
Always check the HTTP status code and handle errors gracefully:
try {
const response = await fetch('https://moderateapi.com/api/v1/moderate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'your-api-key'
},
body: JSON.stringify({ text: 'Content to moderate' })
});
if (!response.ok) {
if (response.status === 429) {
console.log('Rate limit exceeded, please wait');
return;
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
console.log('Moderation result:', result);
} catch (error) {
console.error('Moderation failed:', error.message);
}
User Registration
Create a new user account and generate an API key. New accounts start with the free tier.
/api/v1/register
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | ✓ | Valid email address | |
| password | string | ✓ | Minimum 8 characters |
Example Request
curl -X POST https://moderateapi.com/api/v1/register \
-H "Content-Type: application/json" \
-d '{
"email": "developer@example.com",
"password": "secure_password123"
}'
Example Response
{
"success": true,
"message": "User created successfully",
"user_id": 123,
"api_key": {
"key": "mk_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7a8b9c0d1e2f3g4h",
"name": "Default Key",
"prefix": "mk_1a2b3c"
},
"plan": "free",
"monthly_limit": 1000,
"usage": {
"current_month": 0,
"remaining": 1000
}
}
Content Moderation
The core endpoint for moderating text content. Analyzes text for toxicity, spam, inappropriate content, and other policy violations.
/api/v1/moderate
Request Headers
Content-Type: application/json
X-API-Key: mk_your_api_key_here
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| text | string | ✓ | Content to moderate (max 50,000 characters) |
| context | string | — | Context hint (comment, review, message, etc.) |
Example Request
curl -X POST https://moderateapi.com/api/v1/moderate \
-H "Content-Type: application/json" \
-H "X-API-Key: mk_your_api_key_here" \
-d '{
"text": "Hey everyone! Check out this amazing product, click here to win $1000 now!",
"context": "comment"
}'
Example Response
{
"safe": false,
"confidence": 0.87,
"issues": [
{
"type": "spam",
"severity": "medium",
"confidence": 0.85
},
{
"type": "urgency_scam",
"severity": "high",
"confidence": 0.78
}
],
"suggested_action": "block",
"from_cache": false,
"request_id": "req_abc123def456",
"response_time_ms": 152,
"text_length": 79
}
Response Fields
| Field | Type | Description |
|---|---|---|
| safe | boolean | Whether the content is considered safe |
| confidence | float | Confidence score (0.0 – 1.0) |
| issues | array | List of detected issues |
| suggested_action | string | approve, warn, or block |
| from_cache | boolean | Whether result was served from cache |
Issue Types
Content Issues
- toxicity
- hate_speech
- harassment
- profanity
Spam & Scams
- spam
- urgency_scam
- contact_info
- blocked_word
Usage Statistics
Get detailed usage statistics for your account, including current month usage, limits, and API key information.
/api/v1/usage
Request Headers
X-API-Key: mk_your_api_key_here
Example Request
curl -X GET https://moderateapi.com/api/v1/usage \
-H "X-API-Key: mk_your_api_key_here"
Example Response
{
"user_id": 123,
"plan": {
"name": "growth",
"display_name": "Growth Plan",
"monthly_limit": 100000,
"rate_limit": 200
},
"current_month": {
"calls_used": 15420,
"calls_limit": 100000,
"remaining_calls": 84580,
"usage_percentage": 15.42,
"period_start": "2024-01-01T00:00:00Z",
"period_end": "2024-01-31T23:59:59Z"
},
"api_keys": [
{
"name": "Production Key",
"prefix": "mk_1a2b3c",
"created": "2024-01-01T10:30:00Z",
"last_used": "2024-01-15T14:22:33Z",
"status": "active",
"calls_this_month": 15420
}
],
"billing": {
"subscription_status": "active",
"next_billing_date": "2024-02-01T00:00:00Z",
"amount": 99.00,
"currency": "USD"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| plan | object | Current subscription plan details |
| current_month | object | Current billing period usage |
| api_keys | array | List of API keys for this account |
| billing | object | Billing and subscription information |
Code Examples
JavaScript
Node.js with fetch
const API_KEY = 'mk_your_api_key_here';
const BASE_URL = 'https://moderateapi.com/api/v1';
async function moderateContent(text, context = null) {
try {
const response = await fetch(`${BASE_URL}/moderate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
},
body: JSON.stringify({
text: text,
...(context && { context })
})
});
if (!response.ok) {
if (response.status === 429) {
throw new Error('Rate limit exceeded. Please wait before making more requests.');
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
return result;
} catch (error) {
console.error('Moderation failed:', error.message);
throw error;
}
}
// Usage example
async function main() {
try {
const result = await moderateContent(
"This is some content to moderate",
"comment"
);
console.log('Safe:', result.safe);
console.log('Confidence:', result.confidence);
console.log('Action:', result.suggested_action);
if (result.issues.length > 0) {
console.log('Issues found:');
result.issues.forEach(issue => {
console.log(`- ${issue.type} (${issue.severity}): ${issue.confidence}`);
});
}
} catch (error) {
console.error('Error:', error.message);
}
}
main();
Client class with retry logic
class ModerateAPIClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://moderateapi.com/api/v1';
this.rateLimitRetries = 3;
}
async moderate(text, context = null, retryCount = 0) {
try {
const response = await fetch(`${this.baseUrl}/moderate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': this.apiKey
},
body: JSON.stringify({
text: text,
...(context && { context })
})
});
if (response.status === 429 && retryCount < this.rateLimitRetries) {
// Exponential backoff for rate limiting
const delay = Math.pow(2, retryCount) * 1000;
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
return this.moderate(text, context, retryCount + 1);
}
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || `HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
if (error.name === 'TypeError' && error.message.includes('fetch')) {
throw new Error('Network error. Please check your connection.');
}
throw error;
}
}
async getUsage() {
const response = await fetch(`${this.baseUrl}/usage`, {
headers: { 'X-API-Key': this.apiKey }
});
if (!response.ok) {
throw new Error(`Failed to get usage: ${response.status}`);
}
return await response.json();
}
}
// Usage
const client = new ModerateAPIClient('mk_your_api_key_here');
client.moderate('Content to check')
.then(result => {
if (result.safe) {
console.log('Content is safe');
} else {
console.log('Content flagged:', result.issues);
}
})
.catch(error => console.error('Error:', error.message));
Python
Using requests library
import requests
import time
from typing import Optional, Dict, Any
class ModerateAPIClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = 'https://moderateapi.com/api/v1'
self.session = requests.Session()
self.session.headers.update({
'X-API-Key': api_key,
'Content-Type': 'application/json'
})
def moderate(self, text: str, context: Optional[str] = None,
max_retries: int = 3) -> Dict[str, Any]:
payload = {'text': text}
if context:
payload['context'] = context
for attempt in range(max_retries + 1):
try:
response = self.session.post(
f'{self.base_url}/moderate',
json=payload,
timeout=30
)
if response.status_code == 429: # Rate limited
if attempt < max_retries:
delay = 2 ** attempt # Exponential backoff
print(f"Rate limited. Waiting {delay}s before retry...")
time.sleep(delay)
continue
else:
raise requests.RequestException("Rate limit exceeded")
response.raise_for_status()
return response.json()
except requests.RequestException as e:
if attempt == max_retries:
raise
print(f"Request failed (attempt {attempt + 1}): {e}")
time.sleep(1)
def get_usage(self) -> Dict[str, Any]:
response = self.session.get(f'{self.base_url}/usage')
response.raise_for_status()
return response.json()
def register_user(self, email: str, password: str) -> Dict[str, Any]:
response = requests.post(
f'{self.base_url}/register',
json={'email': email, 'password': password}
)
response.raise_for_status()
return response.json()
# Usage example
def main():
client = ModerateAPIClient('mk_your_api_key_here')
try:
result = client.moderate(
"This is some text to check for safety",
context="comment"
)
print(f"Safe: {result['safe']}")
print(f"Confidence: {result['confidence']:.2f}")
print(f"Suggested action: {result['suggested_action']}")
if result['issues']:
print("\nIssues detected:")
for issue in result['issues']:
print(f" - {issue['type']} ({issue['severity']}): "
f"{issue['confidence']:.2f}")
usage = client.get_usage()
print(f"\nAPI Usage: {usage['current_month']['calls_used']} / "
f"{usage['current_month']['calls_limit']}")
except requests.RequestException as e:
print(f"API Error: {e}")
if __name__ == "__main__":
main()
Async with aiohttp
import aiohttp
import asyncio
from typing import Optional, Dict, Any, List
class AsyncModerateAPIClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = 'https://moderateapi.com/api/v1'
self.headers = {
'X-API-Key': api_key,
'Content-Type': 'application/json'
}
async def moderate(self, text: str, context: Optional[str] = None) -> Dict[str, Any]:
payload = {'text': text}
if context:
payload['context'] = context
async with aiohttp.ClientSession() as session:
async with session.post(
f'{self.base_url}/moderate',
json=payload,
headers=self.headers
) as response:
if response.status == 429:
raise aiohttp.ClientResponseError(
None, None, status=429,
message="Rate limit exceeded"
)
response.raise_for_status()
return await response.json()
async def moderate_batch(self, texts: List[str],
context: Optional[str] = None) -> List[Dict[str, Any]]:
tasks = [self.moderate(text, context) for text in texts]
return await asyncio.gather(*tasks, return_exceptions=True)
# Usage example
async def main():
client = AsyncModerateAPIClient('mk_your_api_key_here')
# Single moderation
result = await client.moderate("Text to moderate")
print(f"Result: {result['safe']}")
# Batch moderation
texts = [
"First comment to check",
"Second comment to check",
"Third comment to check"
]
results = await client.moderate_batch(texts, context="comment")
for i, result in enumerate(results):
if isinstance(result, Exception):
print(f"Text {i+1} failed: {result}")
else:
print(f"Text {i+1}: {'Safe' if result['safe'] else 'Flagged'}")
# asyncio.run(main())
PHP
Using cURL
<?php
class ModerateAPIClient {
private $apiKey;
private $baseUrl;
public function __construct($apiKey) {
$this->apiKey = $apiKey;
$this->baseUrl = 'https://moderateapi.com/api/v1';
}
public function moderate($text, $context = null) {
$data = ['text' => $text];
if ($context) {
$data['context'] = $context;
}
return $this->makeRequest('POST', '/moderate', $data);
}
public function getUsage() {
return $this->makeRequest('GET', '/usage');
}
public function registerUser($email, $password) {
$data = ['email' => $email, 'password' => $password];
return $this->makeRequest('POST', '/register', $data, false);
}
private function makeRequest($method, $endpoint, $data = null, $useAuth = true) {
$url = $this->baseUrl . $endpoint;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $this->getHeaders($useAuth),
CURLOPT_SSL_VERIFYPEER => true,
]);
if ($data && in_array($method, ['POST', 'PUT', 'PATCH'])) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new Exception("cURL Error: " . $error);
}
$decodedResponse = json_decode($response, true);
if ($httpCode >= 400) {
$errorMessage = isset($decodedResponse['error'])
? $decodedResponse['error']
: "HTTP $httpCode";
throw new Exception($errorMessage);
}
return $decodedResponse;
}
private function getHeaders($useAuth = true) {
$headers = ['Content-Type: application/json'];
if ($useAuth) {
$headers[] = 'X-API-Key: ' . $this->apiKey;
}
return $headers;
}
}
// Usage example
try {
$client = new ModerateAPIClient('mk_your_api_key_here');
$result = $client->moderate(
"This is some content to check",
"comment"
);
echo "Safe: " . ($result['safe'] ? 'Yes' : 'No') . "\n";
echo "Confidence: " . round($result['confidence'], 2) . "\n";
echo "Action: " . $result['suggested_action'] . "\n";
if (!empty($result['issues'])) {
echo "\nIssues detected:\n";
foreach ($result['issues'] as $issue) {
echo "- {$issue['type']} ({$issue['severity']}): " .
round($issue['confidence'], 2) . "\n";
}
}
$usage = $client->getUsage();
echo "\nAPI Usage: {$usage['current_month']['calls_used']} / " .
"{$usage['current_month']['calls_limit']}\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>
cURL
Basic moderation request
# Basic content moderation
curl -X POST https://moderateapi.com/api/v1/moderate \
-H "Content-Type: application/json" \
-H "X-API-Key: mk_your_api_key_here" \
-d '{
"text": "This is content to moderate",
"context": "comment"
}'
User registration
# Register new user
curl -X POST https://moderateapi.com/api/v1/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "secure_password123"
}'
Get usage statistics
# Get account usage
curl -X GET https://moderateapi.com/api/v1/usage \
-H "X-API-Key: mk_your_api_key_here"
With error handling (bash script)
#!/bin/bash
API_KEY="mk_your_api_key_here"
BASE_URL="https://moderateapi.com/api/v1"
moderate_content() {
local text="$1"
local context="${2:-}"
local payload="{\"text\": \"$text\""
if [ -n "$context" ]; then
payload="$payload, \"context\": \"$context\""
fi
payload="$payload}"
response=$(curl -s -w "%{http_code}" -X POST "$BASE_URL/moderate" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d "$payload")
http_code="${response: -3}"
body="${response%???}"
case $http_code in
200) echo "Success: $body" ;;
400) echo "Bad Request: $body"; exit 1 ;;
401) echo "Unauthorized: Check your API key"; exit 1 ;;
429) echo "Rate limited: Please wait before trying again"; exit 1 ;;
*) echo "Error $http_code: $body"; exit 1 ;;
esac
}
# Usage
moderate_content "Content to check" "comment"
Best Practices
Security
- Store API keys in environment variables, never in code
- Use different API keys for dev, staging, and production
- Rotate API keys regularly and when team members leave
- Never expose API keys in client-side JavaScript
Performance
- Cache results locally to reduce API calls
- Use batch processing for multiple items when possible
- Implement request timeouts to handle slow responses
- Monitor your usage to optimize plan selection
Error Handling Strategies
Implement Robust Error Handling
Rate Limiting (429 errors)
Use exponential backoff with jitter. Wait 1s, 2s, 4s, etc. before retrying.
Network Failures
Implement timeouts and retry logic. Consider circuit breaker patterns for high-volume applications.
API Errors (4xx/5xx)
Log errors with context, but don't retry 4xx errors except for 429.
Content Moderation Strategies
Pre-moderation
Check content before it's published or visible to users.
Use cases: User-generated content, comments, reviews
Post-moderation
Content is published first, then checked asynchronously.
Use cases: High-volume platforms, real-time chat
Response Interpretation
Integration Patterns
Middleware Pattern
Integrate moderation as middleware in your application pipeline.
// Express.js middleware example
const moderationMiddleware = async (req, res, next) => {
if (req.body.content) {
try {
const result = await moderateAPI.moderate(req.body.content);
if (result.suggested_action === 'block') {
return res.status(400).json({
error: 'Content violates community guidelines'
});
}
if (result.suggested_action === 'warn') {
req.moderationWarning = true;
}
req.moderationResult = result;
} catch (error) {
console.error('Moderation failed:', error);
// Continue without blocking if moderation service is down
}
}
next();
};
Queue-based Processing
Use message queues for high-volume or non-blocking moderation.
# Python with Celery example
from celery import Celery
app = Celery('moderation')
@app.task
def moderate_content_async(content_id, text):
try:
result = moderate_api.moderate(text)
# Update database with moderation result
update_content_status(content_id, result)
if not result['safe']:
# Notify moderators or take action
handle_flagged_content(content_id, result)
except Exception as e:
# Handle error and possibly retry
logger.error(f"Moderation failed for {content_id}: {e}")
raise
Webhooks
Webhooks allow you to receive real-time notifications when moderation events occur. This enables you to build reactive systems that respond immediately to content moderation results.
Coming Soon
Webhook functionality is currently in development and will be available in a future release.
Planned Webhook Events
moderation.completed
Triggered when content moderation is completed
{
"event": "moderation.completed",
"data": {
"request_id": "req_abc123",
"safe": false,
"confidence": 0.96,
"suggested_action": "block"
}
}
usage.limit_reached
Triggered when usage limits are approached or exceeded
{
"event": "usage.limit_reached",
"data": {
"user_id": 123,
"usage_percentage": 90,
"calls_remaining": 100
}
}
Webhook Configuration
When available, webhooks will be configurable through the dashboard. You'll be able to:
- —Set webhook URLs for different event types
- —Configure retry policies for failed deliveries
- —Test webhook endpoints with sample payloads
- —View delivery logs and debugging information
- —Secure webhooks with signature verification
Want to be notified when webhooks are available? Contact us to join our early access list.
Changelog
Stay up-to-date with the latest changes, improvements, and new features in ModerateAPI.
Current Status
ModerateAPI is actively in development. This changelog will be updated as new versions are released.
Upcoming Features
- Webhooks — Real-time notifications for moderation events
- Custom Rules — User-defined moderation criteria
- Bulk API — Process multiple items in a single request
- Advanced Analytics — Detailed usage insights and trends
- Invoice History — Payment history and invoice management
Support & Resources
Get Help
-
Interactive Dashboard
Test API calls and monitor usage
-
Email Support
support@moderateapi.com
Additional Resources
-
API Changelog
Latest updates and changes
Ready to get started?
Sign up for a free account and get 1,000 API calls per month at no cost.
Start Building