Back to Examples

TypeScript / JavaScript

Integrate GuardCrow into your TypeScript or JavaScript applications using native fetch or popular HTTP libraries.

Basic Example

A simple example using the native fetch API:

analyze.tstypescript
interface AnalysisResult {
passed: boolean;
score: number;
sentiment: "positive" | "negative" | "neutral" | "toxic";
description: string;
categories: string[];
processingTimeMs: number;
}
async function analyzeContent(content: string): Promise<AnalysisResult> {
const response = await fetch("https://api.guardcrow.com/v1/analyze", {
method: "POST",
headers: {
"X-API-Key": process.env.GUARDCROW_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({ content }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || "Analysis failed");
}
return response.json();
}
// Usage
const result = await analyzeContent("Hello, this is a test message");
console.log(result.passed ? "Content is safe" : "Content flagged");

With Error Handling

A more robust implementation with proper error handling and retry logic:

guardcrow-client.tstypescript
interface AnalysisResult {
passed: boolean;
score: number;
sentiment: string;
description: string;
categories: string[];
processingTimeMs: number;
}
interface AnalysisError {
error: {
code: string;
message: string;
status: number;
};
}
class GuardCrowClient {
private apiKey: string;
private baseUrl = "https://api.guardcrow.com/v1";
private maxRetries = 3;
constructor(apiKey: string) {
this.apiKey = apiKey;
}
async analyze(
content: string,
metadata?: Record<string, string>
): Promise<AnalysisResult> {
let lastError: Error | null = null;
for (let attempt = 0; attempt < this.maxRetries; attempt++) {
try {
const response = await fetch(`${this.baseUrl}/analyze`, {
method: "POST",
headers: {
"X-API-Key": this.apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({ content, metadata }),
});
if (response.status === 429) {
// Rate limited - wait and retry
const resetTime = response.headers.get("X-RateLimit-Reset");
const waitMs = resetTime
? parseInt(resetTime) * 1000 - Date.now()
: Math.pow(2, attempt) * 1000;
await this.sleep(Math.max(waitMs, 1000));
continue;
}
if (!response.ok) {
const errorData: AnalysisError = await response.json();
throw new Error(errorData.error.message);
}
return response.json();
} catch (error) {
lastError = error as Error;
if (attempt < this.maxRetries - 1) {
await this.sleep(Math.pow(2, attempt) * 1000);
}
}
}
throw lastError || new Error("Analysis failed after retries");
}
private sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
// Usage
const client = new GuardCrowClient(process.env.GUARDCROW_API_KEY!);
try {
const result = await client.analyze("Check this content", {
source: "user-comments",
user_id: "user_123",
});
console.log("Analysis result:", result);
} catch (error) {
console.error("Analysis failed:", error);
}

Next.js API Route

Proxy requests through your Next.js API to keep your API key secure:

app/api/moderate/route.tstypescript
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
const { content } = await request.json();
if (!content) {
return NextResponse.json(
{ error: "Content is required" },
{ status: 400 }
);
}
const response = await fetch("https://api.guardcrow.com/v1/analyze", {
method: "POST",
headers: {
"X-API-Key": process.env.GUARDCROW_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({ content }),
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
}

Express.js Middleware

Create middleware to automatically moderate incoming content:

middleware/moderate.tstypescript
import { Request, Response, NextFunction } from "express";
interface ModerationOptions {
contentField?: string;
blockOnFail?: boolean;
minScore?: number;
}
export function moderateContent(options: ModerationOptions = {}) {
const {
contentField = "content",
blockOnFail = true,
minScore = 7,
} = options;
return async (req: Request, res: Response, next: NextFunction) => {
const content = req.body[contentField];
if (!content) {
return next();
}
try {
const response = await fetch(
"https://api.guardcrow.com/v1/analyze",
{
method: "POST",
headers: {
"X-API-Key": process.env.GUARDCROW_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({ content }),
}
);
const result = await response.json();
// Attach result to request for downstream use
req.moderation = result;
if (blockOnFail && result.score >= minScore) {
return res.status(400).json({
error: "Content blocked by moderation",
reason: result.description,
});
}
next();
} catch (error) {
// Don't block on API errors - let content through
console.error("Moderation error:", error);
next();
}
};
}
// Usage
app.post("/comments", moderateContent(), (req, res) => {
// Content passed moderation
console.log("Moderation result:", req.moderation);
// Save comment...
});

React Hook

A custom React hook for content moderation (calls your backend API):

hooks/useModeration.tstypescript
import { useState, useCallback } from "react";
interface ModerationResult {
passed: boolean;
score: number;
sentiment: string;
description: string;
}
interface UseModerationReturn {
moderate: (content: string) => Promise<ModerationResult>;
isLoading: boolean;
error: string | null;
result: ModerationResult | null;
}
export function useModeration(): UseModerationReturn {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [result, setResult] = useState<ModerationResult | null>(null);
const moderate = useCallback(async (content: string) => {
setIsLoading(true);
setError(null);
try {
// Call your backend API (not GuardCrow directly!)
const response = await fetch("/api/moderate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content }),
});
if (!response.ok) {
throw new Error("Moderation request failed");
}
const data = await response.json();
setResult(data);
return data;
} catch (err) {
const message = err instanceof Error ? err.message : "Unknown error";
setError(message);
throw err;
} finally {
setIsLoading(false);
}
}, []);
return { moderate, isLoading, error, result };
}
// Usage in a component
function CommentForm() {
const { moderate, isLoading, error } = useModeration();
const [content, setContent] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const result = await moderate(content);
if (result.passed) {
// Submit the comment
} else {
alert("Your comment was flagged: " + result.description);
}
} catch {
// Handle error
}
};
return (
<form onSubmit={handleSubmit}>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<button disabled={isLoading}>
{isLoading ? "Checking..." : "Submit"}
</button>
{error && <p className="error">{error}</p>}
</form>
);
}

Type Definitions

Complete TypeScript type definitions for the API:

types/guardcrow.d.tstypescript
// Request types
export interface AnalyzeRequest {
content: string;
metadata?: {
source?: string;
user_id?: string;
[key: string]: string | undefined;
};
}
// Response types
export interface AnalyzeResponse {
passed: boolean;
score: number;
sentiment: Sentiment;
description: string;
categories: Category[];
processingTimeMs: number;
}
export type Sentiment = "positive" | "negative" | "neutral" | "toxic";
export type Category =
| "insult"
| "threat"
| "spam"
| "hate_speech"
| "harassment"
| "self_harm"
| "violence"
| "sexual";
// Error types
export interface APIError {
error: {
code: ErrorCode;
message: string;
status: number;
};
}
export type ErrorCode =
| "MISSING_API_KEY"
| "INVALID_API_KEY"
| "MISSING_CONTENT"
| "CONTENT_TOO_LONG"
| "INVALID_JSON"
| "RATE_LIMIT_EXCEEDED"
| "INTERNAL_ERROR";
// Health check
export interface HealthResponse {
status: "healthy" | "degraded" | "unhealthy";
timestamp: string;
}

Environment Setup

Add your API key to your environment variables:

.env.localbash
GUARDCROW_API_KEY=sk_live_your_api_key_here