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".
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{
"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.
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 viaGET /posts/:id(you'll seestatus: "hidden"in the response), it just stops appearing in feeds and non-author listings. - remove / restore — set / clear
status="removed"(a stricter soft-delete thanhidden). A removed post returns404fromGET /posts/:identirely.restorebrings it back topublished. - 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.
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{
"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.
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.