Skip to content

Labelers

Labelers are external services that apply content labels to records. They operate out-of-band: labeler data does not appear in repos or flow through relays. HappyView can subscribe to labelers and store the labels they emit, which the admin dashboard shows on records and scripts can read.

A labeler is identified by its DID. When you subscribe to a labeler, HappyView connects directly to the labeler’s WebSocket and streams label events in real time. Each label targets a URI, usually a record’s, and carries a value like nudity, spam, or any custom string the labeler defines.

Labels are stored in a happyview_labels table in the database. HappyView tracks a cursor per labeler subscription so it can resume from where it left off after a restart.

Records can also have self-labels: labels applied by the record’s author and embedded directly in the record’s labels.values array. These are not managed by external labelers but are displayed alongside external labels in the dashboard.

  1. Go to Integrations > Labelers in the dashboard sidebar
  2. Click Add Labeler
  3. Enter the labeler’s DID (e.g., did:plc:ar7c4by46qjdydhdevvrndac)
  4. Click Add

HappyView begins consuming labels from the labeler immediately. The subscription appears in the table with an active status.

You can also add a labeler via the API:

const TOKEN = "hv_..."; // your API key
const headers = {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
};
const response = await fetch("http://127.0.0.1:3000/admin/labelers", {
method: "POST",
headers,
body: JSON.stringify({ did: "did:plc:ar7c4by46qjdydhdevvrndac" }),
});

You can pause a labeler subscription to temporarily stop consuming labels without losing your cursor position. Click the pause icon next to the labeler in the table, or use the API:

const TOKEN = "hv_..."; // your API key
const response = await fetch(
"http://127.0.0.1:3000/admin/labelers/did:plc:ar7c4by46qjdydhdevvrndac",
{
method: "PATCH",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ status: "paused" }),
},
);

Resume by clicking the play icon or sending { "status": "active" }.

Deleting a labeler removes the subscription and all labels it has emitted. This cannot be undone.

  1. Click the trash icon next to the labeler
  2. Confirm in the dialog

Or via the API:

const response = await fetch(
"http://127.0.0.1:3000/admin/labelers/did:plc:ar7c4by46qjdydhdevvrndac",
{
method: "DELETE",
headers: { Authorization: `Bearer ${TOKEN}` },
},
);

Labels appear in the Labels column on the Records page as color-coded badges:

  • Red: content warnings: nudity, sexual, graphic-media, violence, gore
  • Amber: moderation labels: spam, impersonation
  • Neutral: everything else

Self-labels (applied by the record author) use an outline badge style to distinguish them from external labels. Hover over a badge to see the source labeler’s DID.

Labels are also available in the records API response and in scripts via get_labels and get_labels_batch on the happyview.atproto library.

Labeler subscriptions give your app content moderation signals without building your own moderation system. A query script can exclude or down-rank flagged content: it checks labels with get_labels and filters results before returning them.

You can subscribe to any labeler that implements the atproto labeler spec, including community-run labelers or one you operate yourself for domain-specific moderation, such as labeling game content by age rating.

ActionPermission
View labeler listlabelers:read
Add or pause/resumelabelers:create
Delete a labelerlabelers:delete
  • Admin API: Labelers: full endpoint documentation
  • Libraries: happyview.atproto, which exposes get_labels and get_labels_batch to scripts
  • Permissions: manage operator access to labeler operations