Build a social app
09 · Moderation

A queue, an action log, and an auto-hide threshold.

End-users file flags from your backend (PAK lane). Your team works the queue from the admin lane (cookie / PlatformUser bearer). Every action is recorded in an append-only audit table.


1

File a flag

PAK lane. Idempotent on (reporter, target) while the flag is open — re-submitting returns the existing flag with created: false. target_kind is "post" or "comment".

bash
curl -X POST -H "Authorization: Bearer pcft_live_..." \
  -H "content-type: application/json" \
  -d '{
    "reporter_actor_id": "<bob>",
    "target_kind": "post",
    "target_id": "<post-uuid>",
    "reason": "Off-topic for the community"
  }' \
  https://agora.productcraft.co/v1/communities/<c>/flags
response.json
{
  "flag": {
    "id": "9d584af5-980f-423b-9360-84b566b3b3d1",
    "target_kind": "post",
    "target_id": "<post-uuid>",
    "reporter_actor_id": "<bob>",
    "reason": "Off-topic for the community",
    "status": "open",
    "created_at": "2026-05-02T19:36:05.521Z",
    "updated_at": "2026-05-02T19:36:05.521Z"
  },
  "created": true,
  "auto_hidden": false
}

2

Auto-hide threshold

When the number of distinct reporters on the same target hits community.settings.auto_hide_flag_threshold (default 3), Agora flips the target to status="hidden" and the response carries auto_hidden: true. Hidden content stops appearing in feeds and is invisible to non-author requesters until a moderator restores it.


3

Work the queue (admin lane)

The admin endpoints are workspace-scoped and authenticate via the platform session cookie or a PlatformUser bearer — not a PAK. Required permission: agora.moderation.queue.read.

bash
curl -H "Cookie: auth_token=<your-platform-session>" \
  "https://agora.productcraft.co/v1/workspaces/<ws>/communities/<c>/moderation/flags?status=open&limit=20"

# Filter by status: open | dismissed | actioned
# Cursor-paginated, newest first.

4

Apply an action

One action resolves the flag — and resolves every other open flag on the same target in one transition, so the queue self-clears.

  • hide / unhide — set / clear status="hidden" on the post or comment. A hidden post is still readable via GET /posts/:id (you'll see status: "hidden" in the response), it just stops appearing in feeds and non-author listings.
  • remove / restore — set / clear status="removed" (a stricter soft-delete than hidden). A removed post returns 404 from GET /posts/:id entirely. restore brings it back to published.
  • warn / ban — audit-only today; no automated user-level side-effects yet.
  • dismiss — close the flag without touching the target.

A flag transitions to actioned on its first non-dismiss action. Subsequent actions on the same flag record additional moderation_action rows but don't move the flag back to open — handy for a moderator who hides → unhides as their thinking evolves, all under one flag thread.

bash
curl -X POST -H "content-type: application/json" \
  -H "Cookie: auth_token=<your-platform-session>" \
  -d '{
    "action": "dismiss",
    "notes": "Reviewed — content is on-topic."
  }' \
  https://agora.productcraft.co/v1/workspaces/<ws>/communities/<c>/moderation/flags/<flag-uuid>/actions
response.json
{
  "flag": { "status": "dismissed", ... },
  "moderation_action": {
    "id": "7c4461e6-4904-4627-ad3e-ec80212b0f5a",
    "flag_id": "<flag-uuid>",
    "target_kind": "post",
    "target_id": "<post-uuid>",
    "moderator_account_id": "<your-platform-user-id>",
    "action": "dismiss",
    "notes": "Reviewed — content is on-topic.",
    "created_at": "2026-05-02T19:36:06.506Z"
  }
}

5

Audit trail

Append-only record of every moderator action. Required permission: agora.moderation.audit.read.

bash
curl -H "Cookie: auth_token=<your-platform-session>" \
  "https://agora.productcraft.co/v1/workspaces/<ws>/communities/<c>/moderation/audit?limit=50"

Wrap-up

You've covered the whole surface

That's every Agora primitive — actors, posts, comments, reactions, follows, mutes, blocks, feeds, stories, polls, notifications, flags, audits. From here:

  • The full request/response schemas live on the API reference, generated from the live OpenAPI spec.
  • The console at console.productcraft.co/agora gives your moderation team a UI on top of these admin endpoints — list flags, apply actions, read the audit.
  • When you're ready to wire actor identity into Heimdall (so end-user signin auto-creates an actor), tick Connect to a Heimdall app when creating a new community. Existing standalone communities keep working unchanged.