Babel Shield API Reference
Canonical source for public endpoint behavior. When API routes change, update this file first, then sync any other API documentation accordingly.
Complete reference for the Babel Shield content moderation API. These examples use cURL and JavaScript. The API is language-agnostic and works with any HTTP client.
Base URL and Headers
Base URL:
https://api.babelshield.ai/api/v1
All endpoint paths in this document are relative to this base URL. For example, GET /health means
GET https://api.babelshield.ai/api/v1/health.
Required headers for all requests:
Accept: application/json
Additional headers for authenticated requests:
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Security: All requests MUST be made over HTTPS. HTTP transmits tokens and credentials in plaintext.
Response Format
All API responses follow a standardized format.
Success response (moderation):
{
"results": {
...
},
"meta": {
"version": "v1",
"timestamp": "2026-02-27T12:00:00.000000Z",
...
}
}
Error response:
{
"success": false,
"error": "Human-readable error message",
"errors": {},
"meta": {
"version": "v1",
"timestamp": "2026-02-27T12:00:00.000000Z"
}
}
The meta.version and meta.timestamp fields appear in all responses. Exception: The GET /health endpoint
returns a flat response (status, timestamp, version at root level) without the meta wrapper, as it does not
require authentication. The errors object contains field-specific details for validation errors (422).
Authentication
Bearer Tokens
Babel Shield uses Bearer token authentication. Include your API token in the Authorization header:
Authorization: Bearer YOUR_API_TOKEN
Tokens are opaque strings. Store them securely and never expose them in client-side source code or application logs.
Token Abilities
Tokens are scoped to specific abilities based on the creating user's role:
| Ability | Description |
|---|---|
moderate content |
Submit content for moderation |
view tokens |
List all tokens for the user |
revoke tokens |
Delete tokens |
Abilities are automatically assigned when a token is created. Downgrading a user's role immediately restricts their existing tokens -- abilities are validated on every request.
Host-Restricted Tokens
For browser-based applications, tokens can be restricted to specific domains. When configured, the API validates the
request's Origin header against the token's allowed host.
Host restrictions are configured in the dashboard after token creation (not available via the API).
Important: Host restrictions can be bypassed by non-browser clients using spoofed headers. They are a defense-in-depth measure, not a primary security control. Use minimal-ability tokens for browser-side code.
Browser Integration
CORS configuration is separate from host restrictions. If you receive CORS errors when calling the API from a browser, contact your API administrator.
Token Lifecycle
- Creation: Via the dashboard (recommended) or
POST /tokensendpoint - Expiration: Optional, configured in the dashboard
- Revocation: Via
DELETE /tokens/{id}or the dashboard
Endpoints
Health Check
Check if the API is available and responding.
Endpoint: GET /health
Authentication: Not required
cURL:
curl https://api.babelshield.ai/api/v1/health \
-H "Accept: application/json"
JavaScript:
const response = await fetch("https://api.babelshield.ai/api/v1/health", {
headers: {"Accept": "application/json"}
});
const data = await response.json();
Response:
{
"status": "ok",
"timestamp": "2026-02-27T12:00:00.000000Z",
"version": "v1"
}
Use this as a cheap readiness check before making authenticated requests.
Login
Validate user credentials and retrieve user/account information without generating a token.
Endpoint: POST /login
Authentication: Not required (credentials in body)
Rate Limited: 6 requests per minute per IP
Request fields:
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User's email address |
password |
string | Yes | User's password |
cURL:
curl -X POST https://api.babelshield.ai/api/v1/login \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"email": "[email protected]", "password": "your-password"}'
JavaScript:
const response = await fetch("https://api.babelshield.ai/api/v1/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
email: "[email protected]",
password: "your-password"
})
});
const data = await response.json();
Response (200):
{
"user": {
"name": "Jane Smith",
"email": "[email protected]"
},
"account": {
"name": "Acme Corp",
"company": "Acme Inc"
}
}
Errors: 401 (invalid credentials), 422 (missing fields), 429 (rate limited)
Security: This endpoint transmits credentials in the request body. Only use over HTTPS. Never call from client-side code.
Create Token
Generate a new API token using user credentials.
Endpoint: POST /tokens
Authentication: Not required (credentials in body)
Rate Limited: 6 requests per minute per IP
Request fields:
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User's email address |
password |
string | Yes | User's password |
name |
string | Yes | Descriptive name for the token |
cURL:
curl -X POST https://api.babelshield.ai/api/v1/tokens \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"email": "[email protected]", "password": "your-password", "name": "Production API"}'
JavaScript:
const response = await fetch("https://api.babelshield.ai/api/v1/tokens", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
email: "[email protected]",
password: "your-password",
name: "Production API"
})
});
const data = await response.json();
Response (200):
{
"token": "your-new-api-token-string",
"user": {
"name": "Jane Smith",
"email": "[email protected]"
},
"account": {
"name": "Acme Corp",
"company": "Acme Inc"
}
}
Errors: 401 (invalid credentials), 422 (missing fields), 429 (rate limited)
Important: Store the token value securely. It cannot be retrieved again. Token abilities are automatically scoped
to the user's role permissions.
Security: This endpoint transmits credentials. Only use from server-side environments. For interactive use, prefer the dashboard.
Get Current User
Retrieve information about the authenticated user, including usage limits and current token details.
Endpoint: GET /user
Authentication: Required
Required Ability: None -- any valid token can access this endpoint
cURL:
curl https://api.babelshield.ai/api/v1/user \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
JavaScript:
const response = await fetch("https://api.babelshield.ai/api/v1/user", {
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Accept": "application/json"
}
});
const data = await response.json();
Response (200):
{
"user": {
"name": "Jane Smith",
"email": "[email protected]",
"current_usage": 42,
"hard_limit": 200,
"soft_limit": 150
},
"account": {
"name": "Acme Corp",
"company": "Acme Inc"
},
"token": {
"name": "Production API",
"abilities": [
"moderate content",
"view tokens"
],
"last_used_at": "2026-02-27T11:30:00.000000Z",
"expires_at": null
}
}
Errors: 401 (invalid token), 403 (user suspended)
Use this endpoint to validate your token and check remaining quota before batch operations.
List Tokens
Retrieve all tokens for the authenticated user.
Endpoint: GET /tokens
Authentication: Required
Required Ability: view tokens
cURL:
curl https://api.babelshield.ai/api/v1/tokens \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
JavaScript:
const response = await fetch("https://api.babelshield.ai/api/v1/tokens", {
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Accept": "application/json"
}
});
const data = await response.json();
Response (200):
{
"tokens": [
{
"id": 1,
"name": "Production API",
"abilities": [
"moderate content",
"view tokens",
"revoke tokens"
],
"last_used_at": "2026-02-27T11:30:00.000000Z",
"expires_at": null,
"created_at": "2026-01-15T10:00:00.000000Z"
},
{
"id": 2,
"name": "Development",
"abilities": [
"moderate content"
],
"last_used_at": "2026-02-26T15:30:00.000000Z",
"expires_at": "2026-12-31T23:59:59.000000Z",
"created_at": "2026-02-01T08:00:00.000000Z"
}
]
}
Errors: 401 (invalid token), 403 (insufficient permissions or user suspended)
Delete Token
Delete a specific token by its ID.
Endpoint: DELETE /tokens/{id}
Authentication: Required
Required Ability: revoke tokens
cURL:
curl -X DELETE https://api.babelshield.ai/api/v1/tokens/2 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
JavaScript:
const response = await fetch("https://api.babelshield.ai/api/v1/tokens/2", {
method: "DELETE",
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Accept": "application/json"
}
});
const data = await response.json();
Response (200):
{
"message": "Token deleted successfully"
}
Errors: 400 (cannot delete current token), 401 (invalid token), 403 (insufficient permissions), 404 (token not found)
You cannot delete the token you are currently using to make the request. To rotate tokens: create a new token, update your integration, then delete the old one.
Moderate Content
Submit content for AI-powered moderation analysis. This is the core endpoint.
Endpoint: POST /moderate
Authentication: Required
Required Ability: moderate content
Request fields:
| Field | Type | Required | Description |
|---|---|---|---|
payload |
string, number, boolean, array, or object | Yes | The content to moderate |
req-id |
string | No | Your tracking ID for this request (max 50 chars) |
service-ip |
string (IP) | No | Source IP address for logging |
categories |
array of strings | No | Filter analysis to specific categories |
options.use_pipeline |
boolean | No | Enable pipeline processing |
options.cache_ttl |
integer (60-86400) | No | Cache duration in seconds |
options.thresholds |
object | No | Per-category threshold overrides (0-100) |
cURL:
curl -X POST https://api.babelshield.ai/api/v1/moderate \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"payload": "Check out this amazing deal! Click here now!!!",
"categories": ["spam", "profanity"],
"options": {
"cache_ttl": 3600
}
}'
JavaScript (with error handling):
async function moderateContent(content) {
const response = await fetch("https://api.babelshield.ai/api/v1/moderate", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({payload: content})
});
if (!response.ok) {
const error = await response.json();
throw new Error(`${response.status}: ${error.error}`);
}
return response.json();
}
// Usage
try {
const result = await moderateContent("Check out this amazing deal!");
if (result.meta.flagged) {
console.log("Content flagged:", result.meta.categories_flagged);
}
}
catch (err) {
console.error("Moderation failed:", err.message);
}
Response (200):
{
"results": {
"category_scores": {
"spam": 85,
"profanity": 0,
"sexual": 0,
"offensive": 0,
"violence": 0,
"hate": 0,
"harassment": 0,
"self-harm": 0,
"deception": 0,
"garbage": 0,
"crypto": 0,
"illicit": 0,
"injection": 0
},
"primary_category": "spam",
"response_summary": "The content contains promotional language with urgency indicators and a call to action."
},
"meta": {
"req_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"service_ip": null,
"response_time_ms": 1850,
"flagged": true,
"categories_flagged": [
"spam"
],
"effective_thresholds": {
"spam": 80,
"profanity": 80
},
"primary_category": "spam",
"primary_score": 85,
"pii": {
"sanitized": false,
"counts": { "creditCard": 0, "ssn": 0, "phone": 0, "ipAddress": 0, "email": 0 }
},
"relevance_flag": false,
"version": "v1",
"timestamp": "2026-02-27T12:00:00.000000Z"
}
}
Here
effective_thresholdsandcategories_flaggedlist onlyspamandprofanitybecause the request scopedcategoriesto that set.category_scoresstill returns all 13 canonical categories regardless — the filter narrows flagging, not the returned scores.
Errors: 401 (invalid token), 403 (insufficient permissions or user suspended), 422 (validation failed or payload too large), 429 (usage limit exceeded)
Payload size limits: The raw request body cannot exceed 20,480 bytes. The processed content cannot exceed 10,000 characters. Both limits return 422 if exceeded.
Some content may be analyzed faster when known patterns are detected. In these cases, the response will include
additional pattern-specific fields in results (such as total_score, max_severity, and detected_items).
Moderation Categories
The API analyzes content against 13 categories. Each request returns a score (0-100) for every category.
| Category | Name | Description | Example Triggers |
|---|---|---|---|
spam |
Spam & Marketing | Unwanted promotional or repetitive content | SEO spam, phishing links, "buy now" pressure, bulk messages |
profanity |
Profanity | Vulgar language and explicit words | Swearing, slurs, crude language |
sexual |
Sexual Content | Adult or sexually explicit content | Explicit descriptions, suggestive material |
offensive |
Offensive | Generally offensive or inappropriate content | Insults, slurs, demeaning language |
violence |
Violence | Content depicting or promoting violence | Threats, graphic descriptions, incitement |
hate |
Hate Speech | Content promoting hatred against groups | Discrimination, supremacist language, dehumanization |
harassment |
Harassment | Targeted harassment or bullying content | Personal attacks, intimidation, doxxing |
self-harm |
Self-Harm | Content related to self-harm or suicide | Suicide methods, self-injury encouragement |
deception |
Deception | Misleading or fraudulent content | Misinformation, impersonation, fake claims |
garbage |
Low Quality | Low-quality or nonsensical content | Gibberish, random characters, fake form data |
crypto |
Crypto & Financial Fraud | Cryptocurrency scams and financial schemes | Pump-and-dump schemes, fake ICOs, wallet scams |
illicit |
Illegal Content | Content promoting illegal activities | Drug sales, weapons trafficking, dangerous goods |
injection |
Prompt Injection | Attempts to override or manipulate the AI moderation instructions | "Ignore previous instructions", jailbreak prompts |
Understanding Scores
category_scorescontains the 13 canonical categories, each scored 0-100. Acategoriesfilter does not narrow this object -- it only scopes which categories are evaluated for flagging (meta.effective_thresholdsandmeta.categories_flaggedare drawn from the requested set). As a defensive practice, still default any missing key to 0 (e.g.scores.spam ?? 0) -- pattern-match short-circuit responses can return a reduced set.primary_category/primary_scoreidentify the highest-scoring category. They are mirrored in bothresultsandmeta.- Multiple detection methods may contribute to a single category. The highest score wins.
Scoring and Thresholds
Score Scale
All scores are on a 0-100 scale:
| Score Range | Interpretation | Typical Action |
|---|---|---|
| 0-20 | Very unlikely to contain this category | Auto-approve |
| 21-50 | Low confidence | Usually safe, monitor if needed |
| 51-79 | Moderate confidence | Queue for human review |
| 80-100 | High confidence | Flag or block |
Threshold Resolution
Thresholds determine the flagged outcome. They are resolved in this order:
- Request-level override -- via
options.thresholdsin the request body - Account configuration -- set by your administrator in the dashboard
- System default -- category-specific (e.g., spam=70, profanity=50, hate=30, crypto=90, injection=80; most others 75)
Content is flagged when any category score meets or exceeds its threshold.
Recommended Thresholds by Use Case
| Use Case | Recommended Threshold | Rationale |
|---|---|---|
| Children's platform | 40-60 | Err on the side of caution |
| General community | 70-80 (default) | Balanced precision and recall |
| Adult/permissive platform | 85-95 | Fewer false positives |
| Logging only (no flagging) | 100 | Score everything, flag nothing |
You can override thresholds per-request to test different sensitivity levels:
{
"payload": "Content to moderate",
"options": {
"thresholds": {
"spam": 60,
"profanity": 50
}
}
}
Caching
Identical requests return cached results for faster response times and reduced costs.
- Default cache duration: 1800 seconds (30 minutes)
- Configurable per-request: Set
options.cache_ttlbetween 60 and 86,400 seconds (1 minute to 24 hours) - Cached responses don't count toward usage limits
To force a fresh analysis, either change the content slightly or wait for the cache to expire.
Usage Limits
Each user has two usage thresholds:
| Limit | Default | Behavior |
|---|---|---|
| Soft limit | 150 | Warning threshold. The API continues working, but a notification may be triggered. |
| Hard limit | 200 | Blocks requests. Returns 429 Too Many Requests. |
Check your remaining quota with GET /user:
{
"user": {
"current_usage": 142,
"hard_limit": 200,
"soft_limit": 150
}
}
When you exceed the hard limit, wait for the usage to reset or contact your administrator.
Error Reference
All errors follow this format:
{
"success": false,
"error": "Human-readable error message",
"errors": {
"field": [
"Specific validation error"
]
},
"meta": {
"version": "v1",
"timestamp": "2026-02-27T12:00:00.000000Z"
}
}
The errors object is populated for validation errors (422) and empty for other error types.
HTTP Status Codes
| Status | Meaning | Common Cause | Resolution |
|---|---|---|---|
| 200 | Success | Request completed | Process the response |
| 401 | Unauthorized | Invalid, missing, or expired token | Check the Authorization header. Create a new token if expired. |
| 402 | Payment Required | No active subscription | Subscribe or renew. This status is only returned when subscription validation is enabled. |
| 403 | Forbidden | User suspended or token lacks required ability | If suspended, contact your administrator. If permissions, check that your token has the required ability. |
| 404 | Not Found | Resource doesn't exist (e.g., token ID) | Verify the resource ID. Use GET /tokens to list valid IDs. |
| 422 | Unprocessable Entity | Validation failed, malformed JSON, or payload too large | Check the errors object for field-specific details. Verify JSON syntax. Check payload size limits. |
| 429 | Too Many Requests | Usage limit exceeded or rate limited | For usage limits, check quota with GET /user. For rate limiting (credential endpoints), wait 1 minute. |
| 500 | Internal Server Error | Server-side failure | Retry with exponential backoff. If persistent, contact your administrator. |
Security Best Practices
HTTPS is mandatory. All requests MUST be made over HTTPS. HTTP transmits tokens and credentials in plaintext.
Avoid exposing unrestricted tokens in client-side code. When calling the API from browsers, use host-restricted
tokens with minimal abilities. The official babel-shield.js library handles this securely. For custom integrations,
prefer a server-side proxy. Tokens without host restrictions are extractable by anyone viewing page source.
Never log tokens. Tokens should not appear in application logs, browser console, or error reporting services.
Use host-restricted tokens for browser apps. Configure allowed hosts in the dashboard. These provide defense-in-depth but can be bypassed by non-browser clients -- they are not a primary security control.
Create separate tokens per environment. Use different tokens for production, staging, and development.
Token rotation: Create a new token, update your integration to use it, then delete the old token. Use GET /tokens
to list tokens and DELETE /tokens/{id} to revoke.
Error handling: Retry on 5xx errors with exponential backoff. Do not retry on 4xx errors (except 429 -- wait and
retry). On 422, check the errors object for field-specific details.
Usage optimization: Check your limits with GET /user before batch operations. Leverage caching (
options.cache_ttl) for repeated content to reduce costs.
Debug Mode
When your API instance runs in debug mode, the moderation response includes additional diagnostic fields in meta (such
as cache status, provider details, and handler execution data). These fields are stripped in production and should not
be relied upon in application logic.