API Reference
Method signatures and parameters for the Respectify client libraries. For response field details, see the Schema Reference.
Methods
| Method | Description |
|---|---|
| Constructor | Create a client instance |
| init_topic_from_text | Initialize a topic from text content |
| init_topic_from_url | Initialize a topic from a URL |
| evaluate_comment | Full comment quality analysis |
| check_spam | Spam detection |
| check_relevance | On-topic and banned topics check |
| check_dogwhistle | Coded language detection |
| megacall | Multiple analyses in one call |
| check_user_credentials | Verify API credentials |
| run | Execute event loop (PHP only) |
- TypeScript
- Python
- PHP
import { RespectifyClient } from "@respectify/client";
All methods are async and return promises. The client uses the native fetch API (Node.js 18+).
from respectify import RespectifyClient
from respectify import RespectifyAsyncClient
Network calls take time. The async client lets your code do other things while waiting, via other coroutines. The blocking client is simpler for straightforward code where parallel requests, or waiting for network responses, isn't an issue. If you're unsure, start with the blocking client.
use Respectify\RespectifyClientAsync;
The PHP client is async, built on ReactPHP. API calls return promises; call $client->run() to execute the event loop.
Constructor
- TypeScript
- Python
- PHP
RespectifyClient
const client = new RespectifyClient({
email: string,
apiKey: string,
baseUrl?: string, // defaults to "https://app.respectify.ai"
version?: string, // defaults to "0.2"
timeout?: number, // defaults to 30000 (ms)
website?: string
});
- Blocking Client
- Async Client
RespectifyClient
client = RespectifyClient(
email: str,
api_key: str,
base_url: Optional[str] = None,
version: Optional[str] = None,
timeout: float = 30.0,
website: Optional[str] = None
)
RespectifyAsyncClient
client = RespectifyAsyncClient(
email: str,
api_key: str,
base_url: Optional[str] = None,
version: Optional[str] = None,
timeout: float = 30.0,
website: Optional[str] = None
)
RespectifyClientAsync
$client = new RespectifyClientAsync(
string $email,
string $apiKey,
?string $baseUrl = null,
?float $version = null,
?string $website = null
);
| Parameter | Description |
|---|---|
email | Your registered email address |
api_key / apiKey / $apiKey | Your API key from the dashboard |
base_url / baseUrl / $baseUrl | Override the API endpoint (optional) |
version | API version, defaults to 0.2 (optional) |
timeout | Request timeout in seconds (Python) or milliseconds (TypeScript) |
website | Your website domain, included in API calls (optional) |
Initialize Topic from Text
Initialize a topic from plain text or Markdown content. You can also initialize from a URL instead. See examples of initializing topics.
- TypeScript
- Python
- PHP
- REST
initTopicFromText
async initTopicFromText(
text: string,
topicDescription?: string
): Promise<InitTopicResponse>
const response = await client.initTopicFromText(
"Article content here...",
"Optional context about the article"
);
const articleId = response.article_id;
- Blocking Client
- Async Client
init_topic_from_text
def init_topic_from_text(
text: str,
topic_description: Optional[str] = None
) -> InitTopicResponse
response = client.init_topic_from_text(
text="Article content here...",
topic_description="Optional context about the article"
)
article_id = response.article_id
init_topic_from_text
async def init_topic_from_text(
text: str,
topic_description: Optional[str] = None
) -> InitTopicResponse
response = await client.init_topic_from_text(
text="Article content here...",
topic_description="Optional context about the article"
)
article_id = response.article_id
initTopicFromText
public function initTopicFromText(
string $text,
?string $topicDescription = null
): PromiseInterface<string>
$client->initTopicFromText($text, $topicDescription)
->then(function ($articleId) {
// Store $articleId for later use
});
$client->run();
| Parameter | Description |
|---|---|
text | The text content to initialize the topic from |
topic_description / topicDescription | Additional context about the topic (optional) |
Returns: InitTopicResponse containing the article_id UUID.
Initialize Topic from URL
Initialize a topic from a URL pointing to HTML, Markdown, PDF, or plain text. You can also initialize from text instead. See examples of initializing topics.
- TypeScript
- Python
- PHP
- REST
initTopicFromUrl
async initTopicFromUrl(
url: string,
topicDescription?: string
): Promise<InitTopicResponse>
const response = await client.initTopicFromUrl(
"https://example.com/article",
"Blog post about AI safety"
);
const articleId = response.article_id;
- Blocking Client
- Async Client
init_topic_from_url
def init_topic_from_url(
url: str,
topic_description: Optional[str] = None
) -> InitTopicResponse
response = client.init_topic_from_url(
url="https://example.com/article",
topic_description="Blog post about AI safety"
)
article_id = response.article_id
init_topic_from_url
async def init_topic_from_url(
url: str,
topic_description: Optional[str] = None
) -> InitTopicResponse
response = await client.init_topic_from_url(
url="https://example.com/article",
topic_description="Blog post about AI safety"
)
article_id = response.article_id
initTopicFromUrl
public function initTopicFromUrl(
string $url,
?string $topicDescription = null
): PromiseInterface<string>
$client->initTopicFromUrl($url, $topicDescription)
->then(function ($articleId) {
// Store $articleId for later use
});
$client->run();
| Parameter | Description |
|---|---|
url | URL to fetch content from (must be publicly accessible) |
topic_description / topicDescription | Additional context about the topic (optional) |
Returns: InitTopicResponse containing the article_id UUID.
Throws: UnsupportedMediaTypeError / UnsupportedMediaTypeException if the URL points to an unsupported format (images, video, .docx, etc).
Evaluate Comment
Evaluates a comment in the context of the article or topic the conversation is about, and optionally the comment it is replying to. This is Respectify's main API and the one you will likely call the most.
It returns:
-
A list of any common logical fallacies that seem present, with the goal of educating the commenter on traps they may be falling into. This includes the fallacy name, the quoted part of their comment that demonstrates it, an explanation, and sometimes a suggested rewrite (only if the commenter's intent was very clear).
-
Any objectionable or rude phrases, including what they are, why we assessed them as such, and very rarely a suggested rewrite.
-
Any negative tone phrases. These aren't objectionable or rude, but are phrases that don't contribute to the conversation. Note that Respectify encourages friendly (genuine, well-intentioned) disagreement and healthy sharing of different opinions and views. Sometimes disagreement can be done in an unhealthy way and this section identifies those.
-
If the comment appears 'low effort' (usually short comments that don't add to the conversation, e.g., "me too").
-
Toxicity score (0-1): Targets attacks on people, not ideas. Attacking a policy harshly scores low; attacking the person making it scores high.
-
health_items: For each comment health item not turned off (the nine problem categories andquality), a score from 1 to 5, the minimum its level accepts, and whether it is acceptable. The quality score, how well the comment engages and contributes to the conversation, ishealth_items.quality.score. -
An overall score (1-5): Comment health, combining quality with the worst problem found.
health_scoregives the same as a number from 1.0 to 5.0. -
exceeds_tolerance: Whether the comment is beyond what your site's tolerances accept. Each finding also carries aseverity, and each phrase acategory. Useexceeds_tolerance, rather thantoxicity_scoreoroverall_scorealone, to decide what to do with a comment.
The idea is to use this not to censor but to educate and encourage better discussion. We hope that over time, as a result of feedback, your users will proactively write better comments without needing to be prompted.
See examples of scoring comments.
- TypeScript
- Python
- PHP
- REST
evaluateComment
async evaluateComment(
comment: string,
articleId: string,
replyToComment?: string,
tolerances?: ModerationTolerances
): Promise<CommentScore>
const result = await client.evaluateComment(
"This is a thoughtful response...",
articleId
);
console.log(`Comment health: ${result.overall_score}/5`);
console.log(`Toxicity: ${result.toxicity_score}`);
- Blocking Client
- Async Client
evaluate_comment
def evaluate_comment(
comment: str,
article_id: UUID,
reply_to_comment: Optional[str] = None,
tolerances: Optional[ModerationTolerances] = None
) -> CommentScore
result = client.evaluate_comment(
comment="This is a thoughtful response...",
article_id=article_id
)
print(f"Comment health: {result.overall_score}/5")
print(f"Toxicity: {result.toxicity_score}")
evaluate_comment
async def evaluate_comment(
comment: str,
article_id: UUID,
reply_to_comment: Optional[str] = None,
tolerances: Optional[ModerationTolerances] = None
) -> CommentScore
result = await client.evaluate_comment(
comment="This is a thoughtful response...",
article_id=article_id
)
print(f"Comment health: {result.overall_score}/5")
print(f"Toxicity: {result.toxicity_score}")
evaluateComment
public function evaluateComment(
string $articleContextId,
string $comment,
?string $replyToComment = null,
?ModerationTolerances $tolerances = null
): PromiseInterface<CommentScore>
$client->evaluateComment($articleId, $comment)
->then(function (CommentScore $result) {
echo "Comment health: " . $result->overallScore . "/5\n";
echo "Toxicity: " . $result->toxicityScore . "\n";
});
$client->run();
| Parameter | Description |
|---|---|
comment | The comment text to evaluate |
article_id / articleId / $articleContextId | UUID from topic initialization |
reply_to_comment / replyToComment / $replyToComment | The parent comment, for context (optional) |
tolerances / tolerances / $tolerances | The comment health level for each item named; items left out are standard (optional). Items: the nine problem categories and quality. Levels: off, permissive, relaxed, standard, strict, zero_tolerance; floored categories accept only standard or stricter. REST: send the request as JSON to include it. |
Returns: CommentScore with comment health (health_items, health_score, overall_score), fallacies, tone analysis, and exceeds_tolerance.
Check Spam
Decides if a comment is spam. The article context is optional; if omitted, the comment is evaluated for spam on its own.
The definition of spam is broad: from obvious commercial sales, through to probable malware (signs of it in the comment, but do not rely on this for security), through to SEO or link spam, phishing attempts, crypto scams, fake reviews, AI-generated nonsense, and much more.
There are three outcomes: spam (is_spam true: delete it), suspected spam (suspected_spam true: send it back to the commenter with the suggestion), and not spam (publish it). See First-Pass Screening.
See examples of spam detection.
- TypeScript
- Python
- PHP
- REST
checkSpam
async checkSpam(
comment: string,
articleId?: string
): Promise<SpamDetectionResult>
const result = await client.checkSpam(comment, articleId);
if (result.is_spam) {
console.log(`Spam detected: ${result.reasoning}`);
}
| Parameter | Description |
|---|---|
comment | The comment text to check. |
articleId | UUID from topic initialization (optional). |
Returns: SpamDetectionResult with is_spam, suspected_spam, suggestion and reasoning.
- Blocking Client
- Async Client
check_spam
def check_spam(
comment: str,
article_id: UUID
) -> SpamDetectionResult
result = client.check_spam(comment, article_id)
if result.is_spam:
print(f"Spam detected: {result.reasoning}")
check_spam
async def check_spam(
comment: str,
article_id: UUID
) -> SpamDetectionResult
result = await client.check_spam(comment, article_id)
if result.is_spam:
print(f"Spam detected: {result.reasoning}")
| Parameter | Description |
|---|---|
comment | The comment text to check. |
article_id | UUID from topic initialization. |
Returns: SpamDetectionResult with is_spam, suspected_spam, suggestion and reasoning.
checkSpam
public function checkSpam(
string $comment,
?string $articleContextId = null
): PromiseInterface<SpamDetectionResult>
$client->checkSpam($comment, $articleId)
->then(function (SpamDetectionResult $result) {
if ($result->isSpam) {
echo "Spam: " . $result->reasoning . "\n";
}
});
$client->run();
| Parameter | Description |
|---|---|
$comment | The comment text to check. |
$articleContextId | UUID from topic initialization (optional). |
Returns: SpamDetectionResult with isSpam boolean and reasoning.
Check Relevance
Evaluates the relevance of a comment to the article it's commenting on, plus checks for topics the site admin does not want discussed.
This is intended to help keep conversations relevant or on-topic, plus to allow site admins to disallow conversation on specific topics. (Our use case here is how legitimate-sounding comments with dog whistles or what-abouts can simply be disallowed.)
Returns two assessments, each with a boolean result and confidence score (0-1):
- On-topic: Is the comment plausibly related to the article? Even poor-quality comments are marked on-topic if they're about the subject.
- Banned topics: Does the comment discuss any topics from your banned list? Also includes what proportion of the comment is about banned topics.
See examples of relevance checking.
- TypeScript
- Python
- PHP
- REST
checkRelevance
async checkRelevance(
comment: string,
articleId: string,
bannedTopics?: string[]
): Promise<CommentRelevanceResult>
const result = await client.checkRelevance(
comment,
articleId,
["politics", "religion"]
);
console.log(`On topic: ${result.on_topic.on_topic}`);
- Blocking Client
- Async Client
check_relevance
def check_relevance(
comment: str,
article_id: UUID,
banned_topics: Optional[List[str]] = None
) -> CommentRelevanceResult
result = client.check_relevance(
comment=comment,
article_id=article_id,
banned_topics=["politics", "religion"]
)
print(f"On topic: {result.on_topic.is_on_topic}")
check_relevance
async def check_relevance(
comment: str,
article_id: UUID,
banned_topics: Optional[List[str]] = None
) -> CommentRelevanceResult
result = await client.check_relevance(
comment=comment,
article_id=article_id,
banned_topics=["politics", "religion"]
)
print(f"On topic: {result.on_topic.is_on_topic}")
checkRelevance
public function checkRelevance(
string $articleContextId,
string $comment,
?array $bannedTopics = null
): PromiseInterface<CommentRelevanceResult>
$client->checkRelevance($articleId, $comment, ['politics', 'religion'])
->then(function (CommentRelevanceResult $result) {
echo "On topic: " . ($result->onTopic->isOnTopic ? 'Yes' : 'No') . "\n";
});
$client->run();
| Parameter | Description |
|---|---|
comment | The comment text to check |
article_id / articleId / $articleContextId | UUID from topic initialization |
banned_topics / bannedTopics / $bannedTopics | Topics to flag (optional) |
Returns: CommentRelevanceResult with on-topic and banned topics analysis.
Check Dogwhistle
Detects coded language (dogwhistles) that appears innocuous but carries hidden meanings to specific groups.
Dogwhistles can be subtle: numbers with hidden meanings (like "88" or "1488"), coded racial terms ("urban youths", "globalists"), extremist phrases, conspiracy markers ("just asking questions", "do your research"), and more. The detection is context-aware: discussing renewable energy policy is legitimate, but "green agenda pushed by globalists" is a dogwhistle.
Returns:
- Detection: Whether dogwhistles were found, with reasoning and confidence (0-1).
- Details (if detected): The specific terms found, their categories, how subtle they are (0-1), and harm potential (0-1).
You can provide sensitive_topics to focus detection on specific areas, and dogwhistle_examples if you know specific coded phrases used in your community.
See examples of dogwhistle detection.
- TypeScript
- Python
- PHP
- REST
checkDogwhistle
async checkDogwhistle(
comment: string,
articleId: string,
sensitiveTopics?: string[],
dogwhistleExamples?: string[]
): Promise<DogwhistleResult>
const result = await client.checkDogwhistle(
comment,
articleId,
["extremism"]
);
if (result.detection.dogwhistles_detected) {
console.log(`Dogwhistle detected: ${result.details?.dogwhistle_terms}`);
}
- Blocking Client
- Async Client
check_dogwhistle
def check_dogwhistle(
comment: str,
article_id: UUID,
sensitive_topics: Optional[List[str]] = None,
dogwhistle_examples: Optional[List[str]] = None
) -> DogwhistleResult
result = client.check_dogwhistle(
comment=comment,
article_id=article_id,
sensitive_topics=["extremism"]
)
if result.detection.contains_dogwhistle:
print(f"Dogwhistle detected: {result.details.dogwhistle_terms}")
check_dogwhistle
async def check_dogwhistle(
comment: str,
article_id: UUID,
sensitive_topics: Optional[List[str]] = None,
dogwhistle_examples: Optional[List[str]] = None
) -> DogwhistleResult
result = await client.check_dogwhistle(
comment=comment,
article_id=article_id,
sensitive_topics=["extremism"]
)
if result.detection.contains_dogwhistle:
print(f"Dogwhistle detected: {result.details.dogwhistle_terms}")
checkDogwhistle
public function checkDogwhistle(
string $articleContextId,
string $comment,
?array $sensitiveTopics = null,
?array $dogwhistleExamples = null
): PromiseInterface<DogwhistleResult>
$client->checkDogwhistle($articleId, $comment, ['extremism'])
->then(function (DogwhistleResult $result) {
if ($result->detection->containsDogwhistle) {
echo "Detected: " . implode(', ', $result->details->dogwhistleTerms) . "\n";
}
});
$client->run();
| Parameter | Description |
|---|---|
comment | The comment text to analyze |
article_id / articleId / $articleContextId | UUID from topic initialization |
sensitive_topics / sensitiveTopics / $sensitiveTopics | Topics to watch for (optional) |
dogwhistle_examples / dogwhistleExamples / $dogwhistleExamples | Known examples to detect (optional) |
Returns: DogwhistleResult with detection status and details.
Megacall
Run any combination of comment scoring, spam detection, relevance checking, and dogwhistle detection in a single API call.
A single request is faster than multiple requests for each kind of analysis. It's also more cost-effective: you're charged for fewer API calls than the individual features in the megacall.
Each analysis type is optional. Only request what you need to minimize latency and cost. At least one feature flag must be set.
See examples of using megacall and selecting which checks to run.
- TypeScript
- Python
- PHP
- REST
megacall
async megacall(options: MegacallOptions): Promise<MegaCallResult>
const result = await client.megacall({
comment: comment,
articleId: articleId,
includeSpam: true,
includeCommentScore: true,
includeRelevance: true,
});
if (result.spam_check) {
console.log(`Spam: ${result.spam_check.is_spam}`);
}
if (result.comment_score) {
console.log(`Score: ${result.comment_score.overall_score}`);
}
- Blocking Client
- Async Client
megacall
def megacall(
comment: str,
article_id: Optional[UUID] = None,
include_spam: bool = False,
include_relevance: bool = False,
include_comment_score: bool = False,
include_dogwhistle: bool = False,
include_perspective_analyze_comment: bool = False,
banned_topics: Optional[List[str]] = None,
sensitive_topics: Optional[List[str]] = None,
dogwhistle_examples: Optional[List[str]] = None,
reply_to_comment: Optional[str] = None,
context_comments: Optional[List[str]] = None,
tolerances: Optional[ModerationTolerances] = None
) -> MegaCallResult
result = client.megacall(
comment=comment,
article_id=article_id,
include_spam=True,
include_comment_score=True,
include_relevance=True
)
if result.spam_check:
print(f"Spam: {result.spam_check.is_spam}")
if result.comment_score:
print(f"Score: {result.comment_score.overall_score}")
megacall
async def megacall(
comment: str,
article_id: Optional[UUID] = None,
include_spam: bool = False,
include_relevance: bool = False,
include_comment_score: bool = False,
include_dogwhistle: bool = False,
include_perspective_analyze_comment: bool = False,
banned_topics: Optional[List[str]] = None,
sensitive_topics: Optional[List[str]] = None,
dogwhistle_examples: Optional[List[str]] = None,
reply_to_comment: Optional[str] = None,
context_comments: Optional[List[str]] = None,
tolerances: Optional[ModerationTolerances] = None
) -> MegaCallResult
result = await client.megacall(
comment=comment,
article_id=article_id,
include_spam=True,
include_comment_score=True,
include_relevance=True
)
if result.spam_check:
print(f"Spam: {result.spam_check.is_spam}")
if result.comment_score:
print(f"Score: {result.comment_score.overall_score}")
megacall
public function megacall(
string $comment,
?string $articleContextId = null,
array $services = ['spam', 'relevance', 'commentscore'],
?array $bannedTopics = null,
?string $replyToComment = null,
?array $sensitiveTopics = null,
?array $dogwhistleExamples = null,
?ModerationTolerances $tolerances = null
): PromiseInterface<MegaCallResult>
$client->megacall($comment, $articleId, ['spam', 'commentscore', 'relevance'])
->then(function (MegaCallResult $result) {
if ($result->spamCheck) {
echo "Spam: " . ($result->spamCheck->isSpam ? 'Yes' : 'No') . "\n";
}
if ($result->commentScore) {
echo "Score: " . $result->commentScore->overallScore . "\n";
}
});
$client->run();
| Parameter | Description |
|---|---|
comment | The comment text to analyze |
article_id / articleId / $articleContextId | UUID from topic initialization |
include_* / include* / $services | Which analyses to run |
banned_topics / bannedTopics / $bannedTopics | For relevance check (optional) |
sensitive_topics / sensitiveTopics / $sensitiveTopics | For dogwhistle check (optional) |
dogwhistle_examples / dogwhistleExamples / $dogwhistleExamples | For dogwhistle check (optional) |
tolerances / tolerances / $tolerances | The comment health level for each item named, for the comment score; items left out are standard (optional). Used only when the comment score is requested. |
Returns: MegaCallResult containing only the requested analyses (others are null). When spam is requested and first-pass screening is confident the comment is spam, only spam_check is returned and every other analysis is null (a suspected-spam comment is not spam, so every requested analysis is returned); see First-Pass Screening.
Check User Credentials
Verify your API credentials and get subscription status. See Verifying Credentials.
- TypeScript
- Python
- PHP
- REST
checkUserCredentials
async checkUserCredentials(): Promise<UserCheckResponse>
const result = await client.checkUserCredentials();
console.log(`Active: ${result.active}`);
console.log(`Plan: ${result.plan_name}`);
console.log(`Endpoints: ${result.allowed_endpoints}`);
- Blocking Client
- Async Client
check_user_credentials
def check_user_credentials() -> UserCheckResponse
result = client.check_user_credentials()
print(f"Active: {result.active}")
print(f"Plan: {result.plan_name}")
print(f"Endpoints: {result.allowed_endpoints}")
check_user_credentials
async def check_user_credentials() -> UserCheckResponse
result = await client.check_user_credentials()
print(f"Active: {result.active}")
print(f"Plan: {result.plan_name}")
print(f"Endpoints: {result.allowed_endpoints}")
checkUserCredentials
public function checkUserCredentials(): PromiseInterface<array>
$client->checkUserCredentials()
->then(function ($result) {
echo "Active: " . ($result['active'] ? 'Yes' : 'No') . "\n";
echo "Plan: " . $result['plan_name'] . "\n";
});
$client->run();
Returns: UserCheckResponse with subscription status, plan details, and allowed endpoints.
Run Event Loop (PHP only)
Execute the ReactPHP event loop. You must call this after API methods for promises to resolve.
run
public function run(): void
$client->checkSpam($comment, $articleId)->then(/* ... */);
$client->evaluateComment($articleId, $comment)->then(/* ... */);
$client->run(); // Execute all pending requests
See Also
- Schema Reference - Field-by-field documentation for all response types
- Error Handling - Exception types and how to handle them