MisarMisar Docs

Moderation

The MisarBlog reporting flow and the admin moderation queue — a unified view of content reports and comment flags with audit-logged actions.

MisarBlog lets any signed-in reader report content, and gives platform admins a single queue to review reports and comment flags and act on them. Every moderator action is audit-logged.

These are first-party MisarBlog web-app endpoints — session-authenticated and CSRF-protected. The admin queue is additionally gated to platform admins. They are not part of the public API-key surface (api.misar.io/blog/v1/*). Paths are relative to the app origin (www.misar.blog).

Reporting content

Any signed-in reader can report an article, series, or profile.

POST/api/moderation/report

Files a content report. On success, moderators and the content owner are notified via the content_reported notification (fire-and-forget). Rate-limited to 20 reports / hour per user+IP. A user can report the same content only once (a duplicate returns 400).

Request body

content_typestringbodyrequired

One of article, series, profile.

content_idstring (UUID)bodyrequired

The reported content's id.

reasonstringbodyrequired

One of spam, misinformation, harassment, adult_content, hate_speech, copyright, other.

detailsstringbody

Optional free-text context, ≤ 500 characters.

Response fields

successboolean

true when the report is recorded.

Request
curl -X POST "https://www.misar.blog/api/moderation/report" \
  -H "Content-Type: application/json" \
  -H "x-csrf-token: <token>" \
  -H "Cookie: <session>" \
  -d '{
    "content_type": "article",
    "content_id": "550e8400-e29b-41d4-a716-446655440000",
    "reason": "spam"
  }'
200 — Reported
{ "success": true }

Admin moderation queue

Platform admins review a unified queue that merges content reports and comment flags (flags grouped per comment with a count).

GET/api/moderation/admin

Returns the merged moderation queue, newest first. Admin-only. Rate-limited to 120 requests / hour.

Query parameters

statusstringquerydefault: pending

Filter: pending, resolved, or all.

pagenumberquerydefault: 1

Page number.

limitnumberquerydefault: 50

Page size (max 100).

Response fields

itemsQueueItem[]

Each item carries source (content_report | comment_flag), content_type, content_id, reason, status, created_at, the reporter, resolved context (label + URL), and flag_count for grouped comment flags.

totalnumber

Total items across all pages for the filter.

pagenumber

Echoed page number.

limitnumber

Echoed page size.

Request
curl "https://www.misar.blog/api/moderation/admin?status=pending&page=1&limit=50" \
  -H "Cookie: <admin-session>"
200 — Queue
{
  "items": [
    {
      "source": "content_report",
      "id": "…",
      "content_type": "article",
      "content_id": "…",
      "reason": "spam",
      "status": "pending",
      "created_at": "2026-07-26T10:00:00Z",
      "reporter": { "username": "alice", "display_name": "Alice" },
      "context": { "label": "Ship faster", "url": "https://www.misar.blog/@you/articles/ship-faster" }
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 50
}

Taking action

POST/api/moderation/admin

Performs a moderation action. Admin-only, CSRF-protected, and audit-logged to admin_audit_log (SOC 2 CC6.1).

Request body

actionstringbodyrequired

One of the actions below.

target_idstring (UUID)bodyrequired

The report id (for *_report), comment id (for comment actions and resolve_flags), or article id (for *_article).

redact_textstringbody

Optional replacement text for redact_comment (≤ 500 chars). Defaults to [Removed by moderator].

Actions

resolve_report / dismiss_reportreport

Mark a content report reviewed or dismissed.

resolve_flagscomment

Resolve all open flags on a comment.

hide_comment / unhide_commentcomment

Hide or unhide a comment.

redact_commentcomment

Replace a comment's text with redaction text.

delete_commentcomment

Delete a comment.

archive_article / unarchive_articlearticle

Archive (hide from public) or restore an article.

Request
curl -X POST "https://www.misar.blog/api/moderation/admin" \
  -H "Content-Type: application/json" \
  -H "x-csrf-token: <token>" \
  -H "Cookie: <admin-session>" \
  -d '{ "action": "archive_article", "target_id": "550e8400-e29b-41d4-a716-446655440000" }'
200 — Done
{ "ok": true }

Status codes

  • 401 — not signed in.
  • 403 — invalid CSRF token, or the caller is not a platform admin.
  • 400 — invalid body / unknown action / bad target_id.
  • 429 — rate limit exceeded (Retry-After header included).
  • 500 — action failed.