Migrate from Google Perspective API
Google is sunsetting the Perspective API on December 31, 2026. Sieve offers a compatibility endpoint that accepts Perspective API request format, so you can migrate by changing a single URL.
One-URL Migration
Section titled “One-URL Migration”Sieve’s /v1/perspective/analyze endpoint accepts the same request format as the Perspective API. For many applications, migration is a one-line change.
const response = await fetch( 'https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze?key=YOUR_GOOGLE_KEY', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ comment: { text: 'This is a comment to analyze' }, requestedAttributes: { TOXICITY: {}, SEVERE_TOXICITY: {}, IDENTITY_ATTACK: {}, INSULT: {}, PROFANITY: {}, THREAT: {}, }, }), });const response = await fetch( 'https://api.getsieve.dev/v1/perspective/analyze', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer mod_live_your_key', }, body: JSON.stringify({ comment: { text: 'This is a comment to analyze' }, requestedAttributes: { TOXICITY: {}, SEVERE_TOXICITY: {}, IDENTITY_ATTACK: {}, INSULT: {}, PROFANITY: {}, THREAT: {}, }, }), });What changed:
- The URL:
commentanalyzer.googleapis.com/...toapi.getsieve.dev/v1/perspective/analyze - Authentication: Google API key in the URL to Sieve Bearer token in the header
- That’s it. The request body and response format are the same.
Attribute Mapping
Section titled “Attribute Mapping”Sieve maps Perspective API attributes to its own categories:
| Perspective Attribute | Sieve Category | Notes |
|---|---|---|
TOXICITY | toxicity | Direct mapping |
SEVERE_TOXICITY | toxicity (high threshold) | Mapped to toxicity with higher score threshold |
IDENTITY_ATTACK | hate_speech | Broader detection including non-identity-based hate |
INSULT | harassment | Includes bullying and personal attacks |
PROFANITY | toxicity | Rolled into toxicity scoring |
THREAT | violence | Includes doxxing and swatting threats |
SEXUALLY_EXPLICIT | sexual | Direct mapping |
FLIRTATION | sexual (lower scores) | Mapped to sexual with reduced scores |
Code Migration Examples
Section titled “Code Migration Examples”// Before: Google Perspective APIconst { google } = require('googleapis');const client = await google.discoverAPI( 'https://commentanalyzer.googleapis.com/$discovery/rest?version=v1alpha1');const result = await client.comments.analyze({ key: process.env.PERSPECTIVE_API_KEY, resource: { comment: { text: userComment }, requestedAttributes: { TOXICITY: {}, THREAT: {} }, },});const toxicityScore = result.data.attributeScores.TOXICITY.summaryScore.value;
// After: Sieve (compatibility endpoint)const result = await fetch('https://api.getsieve.dev/v1/perspective/analyze', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.SIEVE_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ comment: { text: userComment }, requestedAttributes: { TOXICITY: {}, THREAT: {} }, }),}).then(r => r.json());const toxicityScore = result.attributeScores.TOXICITY.summaryScore.value;# Before: Google Perspective APIfrom googleapiclient import discovery
client = discovery.build( "commentanalyzer", "v1alpha1", developerKey=os.environ["PERSPECTIVE_API_KEY"],)result = client.comments().analyze(body={ "comment": {"text": user_comment}, "requestedAttributes": {"TOXICITY": {}, "THREAT": {}},}).execute()toxicity = result["attributeScores"]["TOXICITY"]["summaryScore"]["value"]
# After: Sieve (compatibility endpoint)import requests
result = requests.post( "https://api.getsieve.dev/v1/perspective/analyze", headers={ "Authorization": f"Bearer {os.environ['SIEVE_API_KEY']}", "Content-Type": "application/json", }, json={ "comment": {"text": user_comment}, "requestedAttributes": {"TOXICITY": {}, "THREAT": {}}, },).json()toxicity = result["attributeScores"]["TOXICITY"]["summaryScore"]["value"]Differences in Scoring
Section titled “Differences in Scoring”While the compatibility endpoint returns scores in Perspective format, there are some differences to be aware of:
| Aspect | Perspective API | Sieve |
|---|---|---|
| Score range | 0.0 - 1.0 | 0.0 - 1.0 (same) |
| Granularity | 6 attributes | 7 categories + sub-scores |
| Spam detection | Not available | Built-in spam/RMT detection |
| Context awareness | None | Context multipliers (username, chat, forum) |
| Custom rules | Not available | Wordlist, regex, allowlist rules |
| Latency | 200-500ms | ~180ms blended (60-70% resolved locally) |
| Gaming context | Poor | Gaming mode with banter awareness |
Full Migration (Recommended)
Section titled “Full Migration (Recommended)”While the compatibility endpoint gets you migrated quickly, switching to Sieve’s native API gives you access to all features:
Start with compatibility endpoint
Section titled “Start with compatibility endpoint”Change the URL and auth. Verify scores are comparable. This takes minutes.
Switch to native endpoint
Section titled “Switch to native endpoint”Move to POST /v1/moderate/text for new features: contexts, custom rules, and action recommendations (allow/flag/block).
Add contexts
Section titled “Add contexts”Tag your content with the right context (forum_post, comment, username) for threshold tuning.
Configure custom rules
Section titled “Configure custom rules”Add platform-specific allowlists and blocklists via the Custom Rules API.
// Native Sieve API (full features)const result = await fetch('https://api.getsieve.dev/v1/moderate/text', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.SIEVE_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ text: userComment, context: 'comment', username: authorUsername, }),}).then(r => r.json());
// Native response includes action recommendationif (result.action === 'block') { hideComment();} else if (result.action === 'flag') { queueForReview();}