Perspective API - Analyze
Drop-in replacement for Google's Perspective API. Use the same request format to analyze text for toxicity, profanity, threats, and more.
Google Perspective API compatible. Existing Perspective API integrations work with moder8r by changing only the base URL. The same moder8r API keys (m8r_sk_...) are used for authentication.
/v1alpha1/comments:analyzeAnalyze Comment
Analyze text for harmful attributes using the Google Perspective API request format. Accessible via subdomain (perspective.moder8r.app) or path (/api/perspective/v1alpha1/comments:analyze).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
comment | object | Required | Object with a "text" field (required, max 3,000 characters) and optional "type" field ("PLAIN_TEXT" or "HTML"). Example: { "text": "Hello world", "type": "PLAIN_TEXT" } |
requestedAttributes | object | Required | Map of attribute names to configuration objects. At least one attribute is required. Each value can specify scoreType and scoreThreshold. Example: { "TOXICITY": {}, "INSULT": { "scoreThreshold": 0.8 } } |
languages | string[] | Optional | ISO 631-1 language codes. Currently accepted but not used for scoring. Example: ["en"] |
doNotStore | boolean | Optional | If true, the request is not logged to the request_log table. Defaults to false. Example: true |
clientToken | string | Optional | An opaque token echoed back in the response for client-side correlation. Example: "my-request-123" |
communityId | string | Optional | Identifier for the community or context. Stored with feedback if provided. Example: "my-forum" |
spanAnnotations | boolean | Optional | If true, the response includes per-span scores showing which parts of the text triggered each attribute. Example: true |
Base URLs
| Method | URL |
|---|---|
| Subdomain (recommended) | https://perspective.moder8r.app/v1alpha1/comments:analyze |
| Path-based | https://moder8r.app/api/perspective/v1alpha1/comments:analyze |
Authentication
| Method | Example | Notes |
|---|---|---|
| Query parameter | ?key=m8r_sk_... | Google-compatible method |
| Bearer token | Authorization: Bearer m8r_sk_... | Recommended |
Request
curl -X POST 'https://perspective.moder8r.app/v1alpha1/comments:analyze?key=m8r_sk_your_key_here' \
-H "Content-Type: application/json" \
-d '{
"comment": { "text": "You are an idiot and nobody likes you." },
"requestedAttributes": {
"TOXICITY": {},
"PROFANITY": {},
"INSULT": {}
}
}'Response
{
"attributeScores": {
"TOXICITY": {
"summaryScore": { "value": 0.8723456, "type": "PROBABILITY" }
},
"PROFANITY": {
"summaryScore": { "value": 0.05, "type": "PROBABILITY" }
},
"INSULT": {
"summaryScore": { "value": 0.9134567, "type": "PROBABILITY" }
}
},
"languages": ["en"]
}Supported Attributes
All attributes also support an _EXPERIMENTAL suffix (e.g., TOXICITY_EXPERIMENTAL) which returns the same score.
| Attribute | Description |
|---|---|
TOXICITY | Rude, disrespectful, or unreasonable comment likely to make people leave a discussion |
SEVERE_TOXICITY | Very hateful, aggressive, or disrespectful comment very likely to make people leave |
IDENTITY_ATTACK | Negative or hateful comment targeting someone because of their identity |
INSULT | Insulting, inflammatory, or negative comment towards a person or group |
PROFANITY | Swear words, curse words, or other obscene or profane language |
THREAT | Describes an intention to inflict pain, injury, or violence against a person or group |
SEXUALLY_EXPLICIT | Contains references to sexual acts, body parts, or other lewd content |
FLIRTATION | Pickup lines, complimenting appearance, subtle sexual innuendos |
SPAM | Irrelevant, promotional, or nonsensical content |
OBSCENE | Offensive or disgusting language or imagery |
ATTACK_ON_COMMENTER | Attack directed at another commenter in the discussion |
ATTACK_ON_AUTHOR | Attack directed at the author of the original content |
INCOHERENT | Difficult to understand or nonsensical |
INFLAMMATORY | Intended to provoke or inflame |
LIKELY_TO_REJECT | Likely to be rejected by a human moderator |
UNSUBSTANTIAL | Trivial or short comment that lacks substance |
Response Fields
attributeScoresMap of requested attribute names to their score objects. Each contains a summaryScore with value (0.0 to 1.0) and type ("PROBABILITY").
attributeScores.*.spanScoresOnly present when spanAnnotations: true. Array of per-span scores with begin and end character offsets and a score object.
languagesEchoed from the request if provided. Defaults to ["en"].
clientTokenEchoed from the request if provided. Useful for correlating requests and responses.
Code Examples
JavaScript / Node.js
// JavaScript / Node.js
const response = await fetch(
'https://perspective.moder8r.app/v1alpha1/comments:analyze',
{
method: 'POST',
headers: {
'Authorization': 'Bearer m8r_sk_your_key_here',
'Content-Type': 'application/json',
},
body: JSON.stringify({
comment: { text: 'Is this comment toxic?' },
requestedAttributes: {
TOXICITY: {},
SEVERE_TOXICITY: {},
PROFANITY: {},
},
}),
}
);
const data = await response.json();
console.log(data.attributeScores.TOXICITY.summaryScore.value);Python
# Python
import requests
url = 'https://perspective.moder8r.app/v1alpha1/comments:analyze'
headers = {
'Authorization': 'Bearer m8r_sk_your_key_here',
'Content-Type': 'application/json',
}
data = {
'comment': { 'text': 'Is this comment toxic?' },
'requestedAttributes': {
'TOXICITY': {},
'SEVERE_TOXICITY': {},
'PROFANITY': {},
},
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
print(result['attributeScores']['TOXICITY']['summaryScore']['value'])Span Annotations
// Request with span annotations
const response = await fetch(
'https://perspective.moder8r.app/v1alpha1/comments:analyze',
{
method: 'POST',
headers: {
'Authorization': 'Bearer m8r_sk_your_key_here',
'Content-Type': 'application/json',
},
body: JSON.stringify({
comment: { text: 'You are terrible. Have a nice day.' },
requestedAttributes: { TOXICITY: {} },
spanAnnotations: true,
}),
}
);
// Response includes spanScores:
// {
// "attributeScores": {
// "TOXICITY": {
// "summaryScore": { "value": 0.65, "type": "PROBABILITY" },
// "spanScores": [
// { "begin": 0, "end": 18, "score": { "value": 0.92, "type": "PROBABILITY" } },
// { "begin": 19, "end": 35, "score": { "value": 0.05, "type": "PROBABILITY" } }
// ]
// }
// }
// }Migration from Google Perspective API
Minimal changes required. Replace Google's base URL with https://perspective.moder8r.app and swap your Google API key for a moder8r API key. The request and response format is identical.
| Detail | Google Perspective | moder8r |
|---|---|---|
| Base URL | commentanalyzer.googleapis.com | perspective.moder8r.app |
| Auth | ?key=AIza... | ?key=m8r_sk_... or Bearer token |
| Max text length | 20,480 bytes | 3,000 characters |
| Attributes | 6 production + 10 experimental | All 16 supported (production and experimental return the same score) |
| Rate limits | QPS-based | Per-minute sliding window (same as native API) |
| Error format | Google API errors | Google API errors (same shape) |