Moderation & safety
Reports, bans, server mutes, kicks, priority speakers and the safety pipeline — in the console, over the control-plane API, and on self-hosted cells.
Moderation & safety
Voice without moderation does not survive contact with the public. Aurix ships the moderation primitives in the open-source cell, and Aurix Cloud exposes them per project — in the console under Moderation and over /v1/projects/{id}/moderation/…. Nothing here is a separate "cloud feature": the same calls work against a self-hosted cell with an admin key.
What you get#
| Tool | What it does | Where it is checked |
|---|---|---|
| Report | A player (or your backend) files a report on another player, optionally with a channel, free-form evidence and a recording clip. Creates an open moderation event. | Stored on the cell; shows up in the console and in moderation.* webhooks. |
| Ban | Refuses an account; scope device or ip_address also refuses later accounts from the same device or address (leave the id/address empty to use what the cell has seen of the player). Optional duration. | On every connect, and every live session of the banned player is closed at once. |
| Kick / Kick all | Disconnects a player from one channel or all of them, or empties a channel. Players can rejoin unless banned. | Immediately on the cell. |
| Server mute / Mute all | Drops a player's audio for everyone in the channel; the player is told they are muted and cannot undo it from the game. Mute all takes an except list for hosts and referees. | Immediately on the server mixer. |
| Priority speaker | Everyone else in the channel is ducked while the priority speaker talks (referees, game masters, event hosts). | Server mixer. |
| Resolve | Closes a report with an outcome (dismissed, warned, muted, kicked, banned). | Written to the event and to the organisation's audit log. |
| Safety incidents | The cell's safety pipeline scores transcripts and text chat for toxicity, files incidents with the evidence it kept (text, surrounding messages, an encrypted audio clip with an expiry) and maintains a per-player risk score with exponential decay. | On the cell, per project. |
In the console#
Project → Moderation has five tabs: Reports (open / resolved, resolve with an outcome, mute or ban straight from the row), Bans (active and lifted, lift with one click), Safety incidents (filter, read the evidence export, ban from the row) and Player lookup (risk score, incidents in the window, active bans, and the actions for that player).
Who can do what follows the organisation role: owner, admin and developer can act; viewer sees everything read-only. Every write — ban, lift, mute, kick, priority, resolve, evidence export — lands in Audit log with the acting member, so a moderation team can be held to account.
Over the API#
Project-scoped, same auth as the rest of the control plane (Authorization: Bearer <session or API token>). The control plane forwards to the cell that hosts the project, acting as that project's administrator — your SDK key is never involved, and media never touches the control plane.
GET /v1/projects/{id}/moderation/events?status=open|resolved&page=&per_page=
GET /v1/projects/{id}/moderation/events/{event_id}
POST /v1/projects/{id}/moderation/events/{event_id}/resolve { resolution }
GET /v1/projects/{id}/moderation/bans?user_id=&page=&per_page=
POST /v1/projects/{id}/moderation/bans { user_id, scope: account|device|ip_address, reason, duration_hours?, device_id?, ip_address? }
POST /v1/projects/{id}/moderation/bans/{ban_id}/revoke
POST /v1/projects/{id}/moderation/mute { user_id, channel_id, muted }
POST /v1/projects/{id}/moderation/mute-all { channel_id, muted, except: [user_id] }
POST /v1/projects/{id}/moderation/kick { user_id, channel_id?, reason }
POST /v1/projects/{id}/moderation/kick-all { channel_id, reason }
POST /v1/projects/{id}/moderation/priority { user_id, channel_id, priority }
POST /v1/projects/{id}/moderation/report { target_user_id, reporter_user_id?, channel_id?, reason, evidence?, recording_id? }
GET /v1/projects/{id}/safety/incidents?status=&source=voice|text&user_id=
GET /v1/projects/{id}/safety/incidents/{incident_id}
GET /v1/projects/{id}/safety/incidents/{incident_id}/export
GET /v1/projects/{id}/safety/users/{user_id}/risk
GET /v1/projects/{id}/players/{user_id}/export everything the cell holds about the player (audited)
DELETE /v1/projects/{id}/players/{user_id}?purge_moderation= erase the player; moderation events about them stay unless purge_moderation=true
GET /v1/projects/{id}/recordings?channel_id=&page=&per_page= GET /v1/projects/{id}/recordings/{recording_id} (metadata, consent, download_url with S3)
POST /v1/projects/{id}/recordings/{recording_id}/stop DELETE /v1/projects/{id}/recordings/{recording_id}user_id and channel_id are the UUIDs you put into player tokens and channel names — the console shows them shortened, hover for the full value. Cell-side errors come back unchanged with error.code = cell.
From the game#
Players report each other through the SDK's report(target, reason); the SDK also surfaces you were muted by a moderator and you were kicked so the game can show something sensible instead of silence. Your own backend can call the cell directly with the SDK key (POST {cell}/v1/moderation/report, …/ban, and so on) when the decision is made server-side — the console and the API above are for humans and for your tooling.
Self-hosted#
On your own cell the same endpoints live at {cell}/v1/moderation/… and {cell}/v1/safety/…, authenticated with an admin key that has the moderation:read / moderation:write permissions (the Moderator admin role has both). The safety pipeline's classifier, retention of evidence clips and the risk half-life are configured on the cell.