Skip to main content

Introduction

The Comment Moderation API provides tools for managing comment quality, handling spam, processing user reports, and maintaining a healthy community discussion environment.
All moderation actions are tracked with moderator information and timestamps for audit purposes.

Comment Status Lifecycle

Comments flow through different statuses based on moderation actions:

Status Types

status
enum
pending: Awaiting moderation review (default for new comments)approved: Approved by moderator and visible to usersspam: Marked as spam and hidden from viewrejected: Rejected by moderator (not spam, but violates guidelines)

Update Comment Status

Moderate a comment by updating its status with optional moderation notes.

Endpoint

PATCH /api/comments/{commentId}/moderate

Function Signature

updateCommentStatus(
  commentId: number,
  newStatus: 'pending' | 'approved' | 'spam' | 'rejected',
  notes?: string
): Promise<Comment | null>

Parameters

commentId
number
required
ID of the comment to moderate
status
string
required
New status: pending, approved, spam, or rejected
moderated_by
number
required
ID of the moderator performing the action (auto-populated from auth)
moderation_notes
string
Optional notes explaining the moderation decision

Response

id
number
Comment ID
status
string
Updated status
moderated_by
number
ID of the moderator who performed the action
moderated_at
string
ISO 8601 timestamp of moderation action
moderation_notes
string | null
Moderation notes (if provided)
Returns the updated comment object with moderation fields populated, or null if the comment was not found.

Example Request

const updated = await updateCommentStatus(
  123,
  'approved',
  'Content is appropriate and adds value'
);

if (updated) {
  console.log(`Comment ${updated.id} approved`);
  console.log(`Moderated by: ${updated.moderatedBy}`);
  console.log(`At: ${updated.moderatedAt}`);
}
Moderation actions are permanent and cannot be undone automatically. Always include clear moderation notes to document decisions for future reference.

Report Comment

Allow users to report inappropriate comments for moderator review.

Endpoint

POST /api/comments/{commentId}/report

Function Signature

reportComment(
  commentId: number,
  reportData: {
    reason: string;
    description?: string;
  }
): Promise<boolean>

Parameters

commentId
number
required
ID of the comment being reported
reason
string
required
Primary reason for the report
description
string
Optional detailed description providing additional context

Common Report Reasons

  • spam: Commercial spam or promotional content
  • harassment: Personal attacks or harassment
  • hate-speech: Hate speech or discriminatory content
  • inappropriate: Sexual or otherwise inappropriate content
  • misinformation: False or misleading information
  • off-topic: Unrelated to the discussion
  • other: Other violations (requires description)

Response

Returns true if the report was successfully submitted, false otherwise.
Reports are queued for moderator review. The comment remains visible until a moderator takes action.

Example Request

const reported = await reportComment(789, {
  reason: 'harassment',
  description: 'Contains personal attacks against another user'
});

if (reported) {
  console.log('Report submitted successfully');
}

Batch Moderation Operations

Approve Multiple Comments

Efficiently approve multiple comments at once.
// Approve all pending comments for a specific post
const pendingComments = getPendingComments();
const postComments = pendingComments.filter(c => c.postId === 42);

for (const comment of postComments) {
  await updateCommentStatus(
    comment.id,
    'approved',
    'Bulk approval after review'
  );
}

Mark Multiple as Spam

Bulk mark comments as spam based on pattern matching.
// Mark all comments from a specific user as spam
const userComments = commentsStore.filter(c => c.authorId === 999);

for (const comment of userComments) {
  await updateCommentStatus(
    comment.id,
    'spam',
    'User account identified as spam bot'
  );
}
Batch operations should be used carefully. Always verify the selection criteria before executing bulk moderation actions.

Moderation Dashboard Data

Get Pending Comments

Retrieve all comments awaiting moderation.
getPendingComments(): Comment[]
Returns an array of all comments with status === 'pending'.

Example Usage

const pending = getPendingComments();
console.log(`${pending.length} comments awaiting moderation`);

// Sort by creation date (oldest first)
const sorted = pending.sort((a, b) => 
  new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
);

// Display for moderator review
sorted.forEach(comment => {
  console.log(`[${comment.id}] ${comment.author.name}: ${comment.content}`);
});

Moderation Statistics

Get detailed statistics about comment moderation activity.

General Statistics

const stats = await getCommentsStats();

console.log(`Total comments: ${stats.total}`);
console.log(`Approved: ${stats.approved} (${(stats.approved/stats.total*100).toFixed(1)}%)`);
console.log(`Pending: ${stats.pending}`);
console.log(`Spam: ${stats.spam}`);

Moderation Metrics

total
number
Total number of comments in the system
approved
number
Comments that passed moderation
pending
number
Comments awaiting moderator review
spam
number
Comments marked as spam
approval_rate
number
Percentage of approved vs total moderated comments

Moderation Best Practices

1. Review Guidelines

Approve: Content that adds value, follows guidelines, and is respectfulReject: Guideline violations that aren’t spam (off-topic, low-quality)Spam: Commercial spam, bot-generated content, malicious links

2. Documentation

Always include moderation notes for:
  • Rejected comments (explain guideline violation)
  • Spam markings (describe spam pattern)
  • Edge cases (document reasoning for future reference)
// Good: Clear documentation
await updateCommentStatus(
  123,
  'rejected',
  'Violates rule 3: Personal attacks. User targeted specific individual.'
);

// Bad: No documentation
await updateCommentStatus(123, 'rejected');

3. Consistency

Maintain consistent moderation standards:
// Create reusable moderation reasons
const MODERATION_REASONS = {
  SPAM_COMMERCIAL: 'Commercial spam - promotional content without value',
  HARASSMENT: 'Rule violation - harassment or personal attacks',
  OFF_TOPIC: 'Off-topic - not relevant to post discussion',
  LOW_QUALITY: 'Low quality - no substantive content'
};

await updateCommentStatus(
  commentId,
  'spam',
  MODERATION_REASONS.SPAM_COMMERCIAL
);

4. Timeliness

Prioritize moderation queue by:
  1. High-traffic posts: More visibility = higher priority
  2. Reported comments: User reports require prompt attention
  3. Age: Older pending comments should be reviewed first
const pending = getPendingComments();

// Sort by priority
const prioritized = pending.sort((a, b) => {
  // Reported comments first
  if (a.reported && !b.reported) return -1;
  if (!a.reported && b.reported) return 1;
  
  // Then by age (oldest first)
  return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
});

5. User Communication

When rejecting comments, consider notifying users:
const rejected = await updateCommentStatus(
  commentId,
  'rejected',
  'Contains personal attacks (Rule 3)'
);

if (rejected) {
  // Send notification to user
  await notifyUser(rejected.authorId, {
    type: 'comment_rejected',
    reason: rejected.moderationNotes,
    commentId: rejected.id
  });
}

Automated Moderation

Spam Detection

Implement automated spam detection patterns:
function detectSpam(comment: Comment): boolean {
  const content = comment.content.toLowerCase();
  
  // Check for common spam indicators
  const spamPatterns = [
    /buy now/i,
    /click here/i,
    /limited time offer/i,
    /(http|www).*\.(pharmacy|casino|forex)/i
  ];
  
  return spamPatterns.some(pattern => pattern.test(content));
}

// Auto-moderate on comment creation
const newComment = await createComment(commentData);

if (detectSpam(newComment)) {
  await updateCommentStatus(
    newComment.id,
    'spam',
    'Automated spam detection: Commercial keywords'
  );
}

Rate Limiting

Detect and moderate suspicious activity:
async function checkRateLimit(userId: number): Promise<boolean> {
  const recentComments = commentsStore.filter(c => 
    c.authorId === userId &&
    new Date(c.createdAt) > new Date(Date.now() - 60000) // Last minute
  );
  
  // Flag if more than 5 comments in 1 minute
  return recentComments.length > 5;
}

const isSpamming = await checkRateLimit(userId);
if (isSpamming) {
  // Auto-flag for review
  await updateCommentStatus(
    commentId,
    'pending',
    'Auto-flagged: Suspicious activity rate'
  );
}

Moderation API Reference Summary

EndpointMethodPurpose
/api/comments/{id}/moderatePATCHUpdate comment status
/api/comments/{id}/reportPOSTReport inappropriate comment
/api/comments/{id}DELETEPermanently delete comment
/api/comments/stats/generalGETGet moderation statistics

Audit Trail

All moderation actions include tracking fields:
moderated_by
number
ID of the moderator who took action
moderated_at
string
ISO 8601 timestamp of the moderation action
moderation_notes
string
Notes explaining the moderation decision

Example Audit Query

// Get all comments moderated by a specific moderator
const moderatorActions = commentsStore.filter(c => 
  c.moderatedBy === 42 && c.moderatedAt
);

// Group by action type
const byStatus = moderatorActions.reduce((acc, comment) => {
  acc[comment.status] = (acc[comment.status] || 0) + 1;
  return acc;
}, {} as Record<string, number>);

console.log('Moderation summary:', byStatus);
// Output: { approved: 145, spam: 23, rejected: 8 }

Integration with Comment Lifecycle

Moderation status affects comment visibility and behavior:
// Only show approved comments to regular users
function getVisibleComments(postId: number, isModeratorView: boolean): Comment[] {
  const comments = getCommentsByPost(postId);
  
  if (isModeratorView) {
    return comments; // Show all comments to moderators
  }
  
  return comments.filter(c => c.status === 'approved');
}

Status-Based Styling

function getCommentClassName(comment: Comment): string {
  switch (comment.status) {
    case 'pending':
      return 'comment-pending'; // Yellow background
    case 'approved':
      return 'comment-approved'; // Normal display
    case 'spam':
      return 'comment-spam'; // Red background, strikethrough
    case 'rejected':
      return 'comment-rejected'; // Gray background
  }
}

Build docs developers (and LLMs) love