# Lasso Moderation Overview

How the Lasso Moderation platform works and how it connects to your platform.

Lasso's moderation platform is easy to integrate. Below we describe the different parts of the platform, how they work and how they interact with your platform. If you are new to Lasso, start with [Key Concepts](/getting-started/key-concepts) for an introduction to the terms used throughout these docs.

<figure><img src="/files/bMYWFbB7mqqNE9ZeOwHN" alt=""><figcaption><p>An overview of the flow through the platform</p></figcaption></figure>

### Flow

The flow through the platform works in 3 simple steps:

1. [Ingest content through the API](#lasso-api): your platform sends content (text, images, video and audio) and user information to Lasso through the Lasso API or one of our integrations.
2. [Automation](#automation): your moderation rules and AI Moderators automatically take action on incoming content and users. Actions are automatically relayed back to your platform by a webhook call.
3. [Human action](#human-action): not everything can be moderated automatically. Lasso provides an easy-to-use dashboard where your moderators review the content and users that automation flagged for a closer look. Human actions are relayed back to your platform by a webhook call.

### Lasso API

Integrating with Lasso takes a few API endpoints and a webhook.

#### Ingest content

This is the main and most important API endpoint and is used to send content into the Lasso Moderation platform. All content immediately shows up in the dashboard and is automatically analyzed and checked against your moderation rules. There are two ways to send content:

* **Post-moderation**: `POST /api/v1/content` returns immediately and the content is moderated in the background. Decisions arrive through your webhook. This is the standard setup.
* **Pre-moderation**: `POST /api/v1/content/sync` waits for the automated checks and returns the decision in the response, for platforms where content only goes live after approval.

Reference: <https://api-reference.lassomoderation.com/operation/operation-post-content>

If your platform is built on a service such as Stream, TalkJS, CometChat or PubNub, Lasso can also ingest content directly through an integration, without an API integration on your side. Contact us to set this up.

#### Ingest users

This endpoint can be used to update users' information in Lasso. This can be used if important information of a user changes without the user posting any new content. Information about the user can be used for customized moderation rules.

Note: We care a lot about our and your user's privacy, so be careful sending personal identifiable information (PII) to our platform.

Reference: <https://api-reference.lassomoderation.com/group/endpoint-user>

#### User reports

The user reporting endpoint should be called when your users report another user or a piece of content on your platform. These reports automatically show up in the dashboard and can also be used in custom moderation rules.

Reference: <https://api-reference.lassomoderation.com/group/endpoint-user-reports>

#### Webhook

Webhooks are used to communicate back to your platform. Any action (a rule, an AI Moderator or a human moderator) sends a webhook call to your platform with the new status of the content or user. For example, a rule could automatically remove images containing nudity; Lasso then makes a webhook call to your platform letting it know that this content should be removed. Every call is signed, so your platform can verify it came from Lasso.

More information on how to implement the webhook can be found here: [Webhooks](/developers/webhooks)

#### Other API endpoints

A full overview of all API endpoints can be found [here](https://api-reference.lassomoderation.com/).

### Automation

#### AI analysis and classifiers

Every incoming item is analyzed automatically: text receives AI scores for toxicity and related categories, images are scanned for unsafe content and for text they contain, and classifiers check content against policies specific to your platform. These signals do not take action by themselves; your rules and AI Moderators turn them into decisions, so you stay in control of the thresholds and the consequences.

#### Custom moderation rules

Custom moderation rules are a big part of Lasso's moderation platform. Rules are collections of conditions with a certain action. For example, flag (action) users that have signed up in the last 3 hours (condition) and have posted more content containing nudity (conditions).

All rules can be fully customized to your platform. Every platform is different, so we believe every platform should be moderated in a different way.

Rules can also be adjusted on the fly, no coding or deployments needed anymore. Incoming content and users will automatically be evaluated against your (updated) rules.

Read more about [Custom Moderation Rules](/automation-and-review/custom-moderation-rules)

#### AI Moderators

AI Moderators are AI members of your moderation team. An AI Moderator reads your written policy and judges content against it the way a human moderator would, explaining its reasoning with every decision. Depending on its configuration it takes action directly or leaves a recommendation for a human to confirm. The written policy can be adjusted on the fly, and you control which actions the AI Moderator may take and how decisive it is.

### Human Action

Lasso provides an extensive dashboard where human moderators can easily moderate content and users. Human actions are relayed back to your platform by a webhook call. The main sections of the dashboard:

* **Review**: work through flagged content and users in [review queues](/automation-and-review/review-queues)
* **Content** and **Users**: browse and search everything flowing through your platform
* **Rules**, **Policies** and **Lists**: manage your automated moderation
* **User Reports**: triage [reports](/automation-and-review/user-reports) filed by your users
* **Audit Logs**: every action and change in your workspace, by whom, and when
* **Analytics**: insight into the health of your content, users and moderation
* **Team**: manage your moderators and AI Moderators

Each of these concepts is explained in more detail in [Key Concepts](/getting-started/key-concepts).


# Key Concepts

The building blocks of the Lasso Moderation platform, what they are called, and how they fit together.

Lasso is built around a small set of concepts that come back everywhere: in the dashboard, in the API and in webhooks. This page introduces each concept and links to the guide that covers it in depth. If you are new to Lasso, start here, then read the [Lasso Moderation Overview](/) to see how content flows through the platform in practice.

### Workspace

Your platform's environment in Lasso. A workspace holds your content, users, rules, policies, review queues, team and settings. API keys and your webhook are configured per workspace under **Settings → API & Webhooks**.

### Categories and subcategories

Two levels of structure that mirror how your own platform is organized:

* **Category**: a top-level area of your platform, for example a community, a game or a marketplace section.
* **Subcategory**: a place within a category where content is posted, for example a discussion thread, a chat room or a listing.

Every piece of content belongs to a subcategory, and every subcategory belongs to a category. You can use them to filter content, build rule conditions and limit which parts of your platform each moderator can access.

### Content

A single item created by one of your users: a message, a post, a listing or an image. One content item can combine text with images, videos and audio files. Content enters Lasso through the [API](https://api-reference.lassomoderation.com/) or through an integration, and every item is analyzed and checked against your rules as it arrives.

{% hint style="info" %}
Text and image moderation are available in every workspace. Video and audio moderation are enabled per workspace, contact us to turn them on. See [Image Moderation](/content-analysis/image-moderation) and [Video Moderation](/content-analysis/video-moderation).
{% endhint %}

### Users

The people on your platform. Lasso builds a profile for each user from the information you send: their content, signup date, country, tags, custom attributes and more. Users are moderated just like content, manually or automatically, and can also receive temporary bans and strikes. See [User Moderation](/managing-users/user-moderation).

### Statuses

Every content item and every user has one of three statuses:

* **Allowed**: fine to stay on your platform, no action needed.
* **Flagged**: needs a closer look. Flagging an item creates a review for your moderators.
* **Removed** (for users: **Banned**): should be taken down or blocked on your platform. In the API this status is called `hidden`.

Lasso records both the initial status (the outcome of the automated checks when the item arrived) and the current status (after any later decisions), so you can always compare automated and human outcomes. Status labels are configurable per workspace, so your dashboard may show other words, such as "Hidden", "Suspended" or "Deleted".

### Actions

Every moderation decision is recorded as an action: who took it (a moderator, a rule or an AI Moderator), what changed and why. Actions appear on the item's activity timeline and in the audit logs, and they are delivered to your platform through [webhooks](/developers/webhooks) so your platform can enforce them. Lasso never changes anything on your platform directly; your platform decides what a removal or a ban means.

### Policy categories and policies

The **Policies** section of the dashboard contains two related concepts:

* **Policy categories**: the reasons attached to decisions. When a moderator, rule or AI Moderator takes an action, the policy category records which guideline was violated, for example "Hate speech" or "Spam". A category's identifier appears as `policy_id` in the API and in webhooks.
* **Policies**: written policy documents describing your platform's guidelines. AI Moderators read a policy document to decide how to moderate. Policies are versioned, so you can draft changes and publish them when ready.

### Rules

Automated moderation you control. A rule combines conditions with actions: when all conditions match, the actions run. Rules evaluate on incoming content and users, and can change a status, attach a policy category, add tags, give strikes or route reviews to a specific queue. They can be adjusted on the fly, without code changes or deployments. See [Custom Moderation Rules](/automation-and-review/custom-moderation-rules).

### Lists

Reusable sets of words, domains, countries, phone numbers, IP addresses or regex patterns that rule conditions match against. Update a list once and every rule that uses it follows. See [Lists](/automation-and-review/lists).

### AI analysis and classifiers

Lasso analyzes every incoming item automatically: text gets AI scores for toxicity and related categories, images are scanned for unsafe content and for text they contain, and classifiers check content against policies specific to your platform, answering a single question: does this item violate the policy or not? These signals never act on their own. Rules turn them into decisions, so you stay in control of the thresholds and the consequences.

### AI Moderators

AI members of your moderation team. An AI Moderator reads your written policy and judges content against it the way a human moderator would. Depending on its configuration it takes action directly, with the policy category and its reasoning attached, or leaves a recommendation for a human to confirm. You control which actions it may take and how decisive it is (**Cautious**, **Balanced** or **Decisive**) on the **Team** page.

### Reviews and review queues

A review is one item waiting for a human decision. Flagged content and users become reviews, and review queues organize those reviews for your moderators. Routing rules decide which queue each review lands in; anything not matched by a routing rule goes to the Default Queue. Reviews are assigned automatically to the moderators working in a queue. See [Review Queues](/automation-and-review/review-queues) and [Routing Rules](/automation-and-review/review-queues/routing-rules).

### User reports

Reports filed by your users about content or other users, sent to Lasso through the API. Reports show up in **User Reports** in the dashboard, and each report also re-evaluates your rules, so a rule can act on heavily reported items within seconds. See [User Reports](/automation-and-review/user-reports).

### How a decision is made

When a new piece of content arrives, Lasso evaluates it in a fixed order:

1. **Rules run first.** A matching rule can allow, flag or remove the item, attach a policy category, add tags or give a strike.
2. **The AI Moderator runs second.** When it is configured to check incoming content and no rule has already flagged or removed the item, it takes action or leaves a recommendation.
3. **Nothing matched?** The item is allowed.
4. **Flagged items become reviews** and are routed to a review queue for a human decision.
5. **Every action is sent to your platform** through your webhook.

### Tags, custom attributes, strikes and messages

Tools that support day-to-day moderation:

* **Tags**: your own labels on users and content, applied manually or by rules, and usable as filters and rule conditions. See [Tags](/moderator-toolkit/tags).
* **Custom attributes**: extra data fields you send along with content and users, such as "Verified" or "Age", shown in the dashboard and usable in rule conditions. See [Custom Attributes](/moderator-toolkit/custom-attributes).
* **Strikes**: escalating temporary penalties for repeat offences, instead of an immediate permanent ban. See [Strikes](/managing-users/strikes).
* **Messages**: messages sent to your users from Lasso, to explain decisions or share guidelines. See [Sending Messages](/moderator-toolkit/sending-messages).

### The API and webhooks

Content and users flow into Lasso through the REST API, and decisions flow back through your webhook:

* `POST /api/v1/content` sends content asynchronously; the decision arrives later through your webhook. This is the standard setup for post-moderation.
* `POST /api/v1/content/sync` waits for the decision and returns it in the response, for pre-moderation setups where content only goes live after approval.
* Requests authenticate with an API key, created under **Settings → API & Webhooks**.
* The webhook delivers every action with a signature you can verify, so your platform can safely enforce decisions. See [Webhooks](/developers/webhooks).

The full API is documented in the [API Reference](https://api-reference.lassomoderation.com/).

### Team and roles

The **Team** page is where you invite moderators, configure AI Moderators and control access. Admins manage settings and the team, moderators handle day-to-day moderation, and a moderator can be restricted to specific categories when they should only see part of your platform.


# Quickstart: Moderating Your First Content

Send your first piece of content to Lasso, watch it get moderated in the dashboard and receive the decision back on your webhook.

This guide walks you through your first end-to-end moderation flow: create an API key, send a piece of content to Lasso, find it in the dashboard, take a decision and receive that decision on your webhook. It takes about ten minutes with a terminal and `curl`, but any HTTP client works.

You need a Lasso workspace and an admin account. If you are unfamiliar with any of the terms below, see [Key Concepts](/getting-started/key-concepts).

### Step 1: Create an API key

1. Log in to your dashboard and go to **Settings → API & Webhooks**.
2. In the **API Keys** section, enter a name in the **API key name** field, for example "Test key".
3. Click **Create API key**.
4. Copy the key from the notification and store it somewhere safe. Keys start with `lasso.`.

{% hint style="warning" %}
The full key is shown only once, right after creation. Afterwards the dashboard only shows a short hint of it. If you lose the key, create a new one.
{% endhint %}

<figure><img src="/files/m27SutE7DunIZO31NLp4" alt=""><figcaption></figcaption></figure>

### Step 2: Send your first content

Send a piece of content to the API. Replace `lasso.YOUR_API_KEY` with the key from step 1:

```bash
curl -X POST https://api.lassomoderation.com/api/v1/content \
  -H "Authorization: Bearer lasso.YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content_id": "post-1",
    "text": "Hello from my first Lasso integration",
    "user": { "id": "user-1", "name": "Test User" },
    "category": { "id": "forum", "name": "Forum" },
    "subcategory": { "id": "general", "name": "General" }
  }'
```

The response is:

```json
{ "success": true }
```

Lasso accepted the content and moderates it in the background: it is analyzed, checked against your rules and, when configured, judged by your AI Moderator.

About the fields:

* **`content_id`**: your own identifier for the content. Lasso always refers back to content, users, categories and subcategories by the ids you provide.
* **`user`**: the user who created the content. Only `id` is required.
* **`category`** and **`subcategory`**: where the content was posted on your platform. Both are required. The `name` is optional, but send it on the first call so they show up with readable names in the dashboard.
* **`text`**: the content itself, up to 4,000 characters. Instead of (or along with) text you can send `image_urls`, `video_urls` or `audio_urls`. Media URLs must be publicly reachable; for private storage buckets, see [URL Signing](/developers/url-signing).

{% hint style="info" %}
Workspaces on the free plan can send 1,000 content items per 7 days, which is plenty for testing. See [Rate Limits](/developers/rate-limits) for the limits on paid plans.
{% endhint %}

### Step 3: Find it in the dashboard

1. Click **Content** in the sidebar.
2. Your item appears at the top of the feed, usually within a second or two. The feed updates live, so there is no need to refresh.
3. Click the item to open its detail page, where you can see the user who posted it, the automated analysis and the activity timeline.

### Step 4: Take your first decision

1. Hover over the content item. Action buttons appear in its top-right corner: **Allow**, **Flag** and **Remove** (the default names, your workspace may use different words).
2. Click **Remove**.
3. A **Remove Content** dialog opens. Pick a **Policy category** (the reason for the decision) and optionally add **Extra information**.
4. Click **Remove content**.

The status changes to Removed, and the decision is recorded on the item's activity timeline with you as the actor. Once a default policy is configured, you can Shift+Click an action button to act without the confirmation dialog.

### Step 5: Receive decisions on your webhook

Decisions only have effect once your platform enforces them, and that happens through your webhook.

1. Set up an HTTPS endpoint that can receive POST requests. For a quick test, any tool that shows incoming HTTP requests works.
2. Go to **Settings → API & Webhooks**, scroll to the **Webhooks** section, enter your endpoint URL and click **Create webhook**.
3. Take another decision on your test item, for example **Allow** it again.
4. Your endpoint receives a `ChangeStatus` action with the content's id, its new status and the policy category. See [Webhooks](/developers/webhooks) for all payload shapes and for verifying the `X-Lasso-Signature` header with the secret shown in the **Secret** column.

{% hint style="warning" %}
Your endpoint must respond with a `200` status code. If it keeps failing after retries, Lasso reverts the action to keep both systems in sync, so a broken test endpoint can undo your decisions.
{% endhint %}

### Optional: pre-moderation

`POST /api/v1/content` moderates in the background, which suits platforms where content goes live immediately (post-moderation). If content on your platform should only go live after approval, use the synchronous endpoint instead. It runs the automated checks and returns the decision in the response:

```bash
curl -X POST https://api.lassomoderation.com/api/v1/content/sync \
  -H "Authorization: Bearer lasso.YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content_id": "post-2",
    "text": "Another test message",
    "user": { "id": "user-1" },
    "category": { "id": "forum" },
    "subcategory": { "id": "general" }
  }'
```

```json
{
  "success": true,
  "status": "allowed",
  "actions": []
}
```

`status` is the final status of the content: `allowed`, `flagged` or `hidden` (hidden is what the dashboard shows as Removed). `actions` lists what acted on it, in the same shape as webhook payloads; it is empty when no rule or AI Moderator took action.

A few things to know about the synchronous endpoint:

* Text-only content is evaluated before the response returns. Content with media can take longer; after 15 seconds the endpoint returns `{ "success": true, "timeout": true }` and the decision arrives through your webhook instead.
* Videos cannot be ingested synchronously.

### Troubleshooting

* **401 Unauthorized**: the API key is missing or wrong. The header must be `Authorization: Bearer lasso.YOUR_API_KEY`.
* **400 with field errors**: the request body is invalid. The `error` object lists each failing field, for example `{ "category": "Required" }`.
* **400 "Can only update content that match existing user, category and subcategory ids"**: you sent a `content_id` that Lasso already knows, with a different user, category or subcategory. Use a new `content_id` or the original ids.
* **429 Too Many Requests**: you hit a rate limit. Check the `X-RateLimit-Remaining` and `X-RateLimit-Reset` response headers, and see [Rate Limits](/developers/rate-limits).

### Next steps

* Automate decisions with [Custom Moderation Rules](/automation-and-review/custom-moderation-rules) and [Lists](/automation-and-review/lists).
* Put flagged content in front of your moderators with [Review Queues](/automation-and-review/review-queues).
* Let your users report content and other users with [User Reports](/automation-and-review/user-reports).
* Moderate the people behind the content with [User Moderation](/managing-users/user-moderation).
* Read the full [API Reference](https://api-reference.lassomoderation.com/) for every endpoint and field.


# Image Moderation

This documentation outlines the various types of image moderation available in **Lasso Moderation**. Each type helps ensure that the content on your platform is safe, compliant, and adheres to community guidelines.

### Optical Character Recognition (OCR)

**OCR (Optical Character Recognition)** is used for extracting text from images. This is particularly useful for identifying inappropriate or harmful text in images, such as hate speech, explicit language, or spam. OCR can recognize various fonts and text layouts, making it a robust tool for detecting textual content within an image. Example:

**How it works:**

* The image is scanned for areas containing text and extracted from the image.
* This text can then be checked against moderation policies for further action.

### Label Detection

Label detection is used to classify and categorize images into predefined categories and subcategories. Lasso Moderation provides a range of default categories and subcategories that help identify inappropriate content:

#### **Explicit Nudity**

* Explicit Nudity
* Explicit Sexual Activity
* Sex Toys
* Exposed Female Nipples
* Exposed Buttocks
* Exposed Male Genitalia
* Exposed Female Genitalia

#### Non-Explicit Nudity of Intimate Parts and Kissing

* Non-Explicit Nudity
* Obstructed Intimate Parts
* Implied Nudity
* Exposed Male Nipple
* Kissing on the Lips

#### **Swimwear or Underwear**

* Female Swimwear or Underwear
* Male Swimwear or Underwear

#### **Violence**

* Graphic Violence
* Blood & Gore
* Physical Violence
* Weapon Violence
* Weapons
* Self-Harm

#### **Visually Disturbing**

* Death and Emaciation
* Crashes
* Emaciated Bodies
* Corpses
* Air Crash
* Explosions and Blasts

#### **Rude Gestures**

* Rude Gestures
* Middle Finger

#### **Drugs & Tobacco**

* Products
* Pills
* Drug & Tobacco Paraphernalia & Use
* Smoking

#### **Alcohol**

* Alcohol
* Alcohol Use
* Drinking
* Alcoholic Beverages

**Gambling**

#### **Hate Symbols**

* Hate Symbols
* Nazi Party
* White Supremacy
* Extremism

### Custom Labels

Lasso Moderation allows users to create custom labels for detecting specific types of objects or scenes. This feature enables the detection of items like "animals" or "objects" based on your platform's needs. Custom labels are useful for identifying specific content not covered by the default labels.

**Examples of custom labels:**

* Animals (e.g., cats, dogs)
* Vehicles (e.g., cars, trucks)
* Specific objects (e.g., logos, tools)

### Face Detection

The face detection feature identifies faces within images and provides additional information such as:

* **Age estimation**
* **Gender prediction**

Additionally, Lasso Moderation can optionally offer **face similarity detection**, which helps recognize images with specific people in it.

### Celebrity Detection

This feature detects and identifies well-known celebrities in images. It uses a comprehensive database of public figures to provide accurate recognition of individuals in media, entertainment, and other public sectors.

### Similar Image Detection

**Similar Image Detection** identifies if the same or visually similar images have been uploaded previously. This feature is essential for preventing duplicate content and identifying repeated uploads of harmful or inappropriate material.

**How it works:**

* The uploaded image is analyzed and compared against a database of previously submitted images.
* Image features such as patterns, colors, and textures are used to detect similarities, even if the image has been altered (e.g., resized, cropped, or slightly edited).
* If a match or near-match is found, the system can flag the image for review or automatically take action based on predefined rules.

### AI-Generated Image Detection

Lasso Moderation can detect whether an image has been generated using artificial intelligence. This is useful for platforms that need to monitor and filter AI-generated content, particularly in contexts where such images may mislead users or violate platform policies.

### CSAM

Lasso offers CSAM detection for teams that need to flag and triage potential child sexual abuse material. We work with a trusted partner who can identify exact matches as well as modified or distorted variants of known CSAM images and videos.

Each image is assigned a similarity score from **0 to 100**, which reflects how closely the descriptor-based representation of the input aligns with known CSAM content in the matching database. For example, a 40% score indicates that approximately 40% of the visual region in the query image shares matching features with a known CSAM image.

Due to the nature of descriptor-based hashing, this score is continuous and context-sensitive, not based on a fixed classification threshold. Any non-zero score indicates some degree of visual correspondence with known CSAM material, even if partial or subtle.

To protect your team, any image flagged with a non-zero score is **automatically blurred in the dashboard**.

**Match score interpretation guidelines:**

* Matches above 40% should be reviewed and flagged as suspicious. For stricter workflows, this threshold can be lowered.
* Matches above 85% are a very strong match and can be blocked automatically.

These are initial recommendations. We encourage teams to monitor matched content over time and adjust thresholds as needed.

To test the integration with non-CSAM images that are known to trigger high scores, please contact us at <support@lassomoderation.com>.

***

These image moderation tools can be used in combination or individually, based on your platform's specific needs. Lasso Moderation offers comprehensive, customizable, and accurate image analysis to keep your content safe and compliant.


# Video Moderation

This documentation outlines the video moderation capabilities available in **Lasso Moderation**. Video moderation helps ensure that content uploaded to your platform complies with guidelines and community standards. The moderation process includes analyzing videos for inappropriate or harmful content using various labels and generating screenshots for further image analysis.

### Video Labels

Lasso Moderation applies a set of predefined labels to categorize and detect content within videos. These labels help identify a wide range of content, from adult material to potentially harmful or offensive content. Below is a list of available labels:

#### **Video Labels:**

* **Adult Content**: Detects explicit adult content.
* **Suggestive Content**: Identifies content that is suggestive in nature but not explicitly adult.
* **Medical**: Identifies medical procedures or related content.
* **Violence**: Detects violent behavior or imagery.
* **Over 18**: Flags content meant for viewers aged 18 and over.
* **Adult Toys**: Detects the presence of adult toys.
* **Firearms**: Identifies guns and other firearms in the video.
* **Knifes**: Detects the presence of knives.
* **Violent Knifes**: Identifies knives being used in a violent manner.
* **Alcohol**: Detects alcohol or alcoholic beverages.
* **Drinks**: Identifies non-alcoholic beverages.
* **Smoking and Tobacco**: Detects smoking or tobacco-related products.
* **Marijuana**: Identifies marijuana-related content.
* **Pills**: Detects pills or other pharmaceutical products.
* **Recreational Pills**: Identifies recreational drugs in pill form.
* **Confederate Flag**: Detects imagery of the Confederate flag.
* **Pepe Frog**: Identifies the Pepe the Frog meme, often associated with specific ideological contexts.
* **Nazi Swastikas**: Detects Nazi symbolism, such as swastikas.
* **Meme**: Identifies memes present within the video.
* **Face Filter**: Detects the use of face filters in the video.
* **Toxic Text**: Flags text within the video that contains harmful or toxic language.
* **Severe Toxic Text**: Detects text with severe levels of toxicity.
* **Obscene Text**: Identifies obscene language in the video.
* **Insult Text**: Detects insulting text directed at individuals or groups.
* **Identity Hate Text**: Identifies hate speech targeted at specific identities.
* **Threat Text**: Detects threatening language within the video.
* **Sexual Explicit Text**: Identifies sexually explicit language.
* **Children**: Detects the presence of children in the video.
* **Toys**: Identifies toys within the video content.

These labels provide robust content categorization, making it easier to moderate videos effectively according to your platform’s rules and regulations.

### Screenshots

Lasso Moderation has the capability to automatically generate **screenshots** from videos at various intervals. These screenshots can then be analyzed using the same **Image Moderation** techniques that are applied to still images. This allows for deeper content inspection and ensures that inappropriate or harmful content within the video frames can be flagged.

For detailed information on image moderation techniques used on screenshots, refer to the [Image Moderation](/content-analysis/image-moderation) section.


# Custom Moderation Rules

Guide on rulesets, rules and conditions and how they can be used

Custom moderation rules automate moderation on the Lasso platform. Each rule combines a set of conditions with one or more actions. When a piece of content or a user matches all of a rule's conditions, Lasso applies the rule's actions, without a moderator having to look at it first.

> **Note**: Some of the conditions and actions described on this page are not available by default and can be enabled on request. If you don't see one in your dashboard, contact us.

There are three types of rules:

* **Content rules**: run on incoming content (messages, images, videos, audio). They can use both content conditions and conditions about the user who posted the content.
* **User rules**: run on users. They can use user conditions, such as signup date, reports received or content volume.
* **Routing queue rules**: decide which review queue a flagged item goes to. They can use review conditions (priority, policy, review type) as well as user and content conditions.

<figure><img src="/files/GefO8dDzpDvFUP49UicI" alt="An example of a rule targeting images containing nudity"><figcaption><p>An example of a rule targeting images containing nudity</p></figcaption></figure>

### Anatomy of a rule

A rule consists of:

* **Name**: identifies the rule in the dashboard.
* **Notes** (optional): a short explanation of what the rule is for. Helpful when your team maintains many rules.
* **Conditions**: the criteria that must be met. A rule matches only when *all* of its conditions are met (they are combined with AND). To express an OR, create a separate rule.
* **Actions**: what happens when the rule matches. See Actions below.
* **Enabled / Disabled**: the rule is only evaluated when enabled. New and imported rules start disabled, so you can review them before they take effect.

### How rules are evaluated

Rules are evaluated from top to bottom, in the order shown in the rules list. You can drag rules to reorder them, and order matters:

* When a rule's action is **allow** or **remove/ban**, a match stops evaluation. Rules below it are not evaluated for that item.
* When a rule's action is **flag**, evaluation continues. Multiple flagging rules can match the same item, and each can add its own policy, tags and priority.
* A rule that has already been applied to an item is not applied again.
* Decisions made by a human moderator take precedence. If a moderator has removed an item, rules will not overrule that decision.

For routing queue rules, the first matching rule wins and determines the queue.

#### Confirming a rule before it goes live

When you enable or update a rule, Lasso shows a confirmation step that previews how the rule would have matched against your recent content or users, including match counts and percentages. This lets you catch a rule that matches far more (or less) than you intended before it starts taking action.

### Actions

Actions run when all conditions are met.

* **Change status**: the core action of every content and user rule. Sets the item's moderation status to **allowed**, **flagged** or **removed** (for users: **banned**). The exact wording of these statuses can be customized per dashboard.
* **Policy category**: categorizes the action under one of your policies. This is how you track which policy an automated action was taken under, and it is included in webhooks and analytics. Depending on your dashboard settings, a policy can be required for flag/remove actions. You can also add extra policy information as free text.
* **Priority**: shown when the action is *flag*. Sets the review priority of the flagged item: urgent, high, medium (default), low or very low. Routing queue rules can use this priority to route items to different queues.
* **Strike user**: give the user a strike as part of the action. Two variants:
  * **Strike**: adds a strike only if the user has no active strike yet.
  * **Add strike**: always adds a strike, even if the user already has one.
* **Add tags**: add tags to the content and/or the user when the rule matches. Useful for building segments, filtering queues, or feeding follow-up rules that use the *Content tags* / *User tags* conditions.
* **Hide all content** (user rules with a *ban* action): when a user is banned by the rule, all of their existing content is removed as well. You can select a separate policy category for the removed content.
* **Route to queue** (routing queue rules): sends matching items to the selected review queue.

Rule actions trigger the same webhooks as manual moderator actions, so your platform is notified of status changes, strikes and tag updates made by rules.

### Conditions

A rule can have one or more conditions, and conditions from different groups can be combined. For example, to catch potential spam you can combine *Signed up* (in the last 10 minutes) with *User's content volume* (more than 20 messages).

<figure><img src="/files/XsyQBxFP4ZSVnrsjsNQT" alt=""><figcaption><p>Example of a set of conditions targeting recently signed up users that have sent over 20 flagged or removed messages</p></figcaption></figure>

Every condition below lists what it checks and the options you can configure.

#### Text conditions

* **Text**: matches words, phrases, URLs, phone numbers or email addresses in the text. Lasso also extracts text from images, videos and audio, and you choose which of these sources the condition applies to. Matching options:

  * **Contains any word / not contains any word**: matches when the text contains one of your word list entries as a whole word, bounded by spaces, punctuation or the start/end of the text. The list entry "ball" matches "nice ball!" but not "football" or "ballroom". Use this for words that are only a problem on their own: an entry like "ass" won't match "class" or "grass". List entries can also be phrases containing spaces or special characters, such as "free money" or "sh\*t", and these match as a whole phrase.
  * **Contains part of any word / not contains part of any word**: matches when a list entry appears anywhere in the text, including inside longer words. The list entry "ball" also matches "football" and "ballroom". This casts a wider net and is harder to evade with creative spelling, but pick entries with care: short entries can match inside innocent words.
  * **Contains at least X words** and **contains part of any word at least X times**: like the above, but the item must contain a minimum number of (partial) matches. Useful for tolerating a single borderline word while catching repeated use.
  * **Contains regex**: matches patterns from one of your regex lists, for advanced cases that word lists can't express.
  * **Contains a URL / contains any URL / not contains any URL**: detect any link, or match links against one of your domain lists (for example an allowlist of your own domains).
  * **Contains a phone number / contains any phone number / not contains any phone number**: detect any phone number, or match against a phone number list.
  * **Contains an email / not contains an email**: detect email addresses in the text.

  Word matching is case-insensitive. Lasso also matches against a normalized version of the text: accents and look-alike characters are converted to their plain equivalents (for example "bäll", or a Cyrillic "а" styled to look like a Latin "a") and invisible characters are stripped, so common tricks to sneak words past a filter still match.
* **Text length**: the number of characters in the text, longer or shorter than a value you set. For example, flag messages over 300 characters to catch copy-paste spam.
* **Special characters in text**: the number of special characters (anything that is not a letter, number or space). Useful against zalgo text, ASCII art and other obfuscation.
* **Duplicate messages**: matches when the same user has sent the same exact text a minimum number of times within the recent period. A classic spam signal.
* **Language**: the detected language of the text, is (or is not) in a list of languages you select. For example, flag content in languages your moderation team doesn't cover.
* **AI scores**: Lasso's toxicity analysis of the text. Choose a score type (toxicity, threat, identity attack or profanity) and a minimum likelihood (0-100%). For example, remove content with a toxicity score of at least 90%, and flag content with a score of at least 50%.
* **Custom AI scores**: scores from your own custom AI text models. Depending on the model, you either set a minimum likelihood (0-100%) or match on the model's binary outcome (*is a violation* / *is not a violation*).
* **Topic**: the topic assigned to the content is (or is not) in a set of topics you select.

#### Image conditions

* **Image labels**: moderation labels (nudity, violence, drugs, weapons, etc.) that Lasso's AI detects in images. Select one or more labels and a minimum likelihood (0-100%). For example, remove images that are at least 80% likely to contain explicit nudity, and flag from 50%.
* **Custom AI scores (images)**: scores from your own custom AI image models, with a minimum likelihood.
* **Custom image labels**: images do (or do not) contain one of your custom-trained labels, with a minimum likelihood.
* **Image type**: the image's file type is (or is not) in a set you select, for example to treat GIFs differently from photos.
* **Similar images**: the image is the same as, very similar to, or somewhat similar to images that were previously removed, or images posted by banned users. When a moderator removes an image, this condition lets a rule automatically catch reposts of it, including slightly edited versions.
* **Number of people in image(s)**: how many people are detected in the image, compared to a number you set. For example, on a profile photo, require exactly one person.
* **Content's age range**: the estimated age of people in the image, compared to the user's own age or to a custom age you set. For example, flag profile photos where the estimated age is below the user's registered age.
* **QR code**: the image does (or does not) contain a QR code. QR codes are a common way to smuggle links past text filters.
* **Face recognition**: whether all faces in the image match the user's verified photo. Useful for profile photo verification flows.
* **Face close-up**: whether the image is (or is not) a close-up of a face.
* **Celebrity**: the image does (or does not) contain a recognized public figure, with a minimum confidence. Helps catch impersonation and fake accounts using celebrity photos.
* **CSAM**: the image matches (or does not match) known CSAM via industry hash-matching.

#### Video conditions

* **Video labels**: moderation labels detected in videos (similar to image labels), with a minimum likelihood.

#### General content conditions

* **Content type**: the content has text, image(s), video(s) or audio. Best combined with other conditions, for example: flag all images posted by users who signed up within the last day.
* **Project**: the project the content belongs to is (or is not) in a set you select, so you can apply stricter rules to specific projects. (This condition uses whatever name you have given projects in your dashboard, for example "Category" or "Room".)
* **Content tags**: the content's tags are (or are not) in a set you select. Combine with the *Add tags* action to build multi-step rule flows.

#### Report conditions

Available for both content and users:

* **# of times reported**: how often the item or user has been reported. You can count unique reporters or total reports, over all time or within a period, and filter by the type of user who reported (normal user, trusted user, moderator, admin). For example, remove content reported by 3 or more unique users within 24 hours.
* **Reported by**: the type of user the report came from, is (or is not) one of: normal, trusted, moderator, admin. A report from a moderator can be trusted more than one from a normal user, so you can act on it immediately.

User rules only:

* **# of reports made**: the number of reports the user has made, compared to a number you set. Useful for catching users who mass-report others in bad faith.

#### User conditions

These can be used in user rules, and in content rules to check the user who posted the content:

* **Name**: the user's name, with the same matching options as the *Text* condition (word lists, partial matches, regex). For example, flag users with offensive words in their name.
* **Status**: the user's moderation status is (or is not) allowed, flagged or banned. For example, flag all content posted by currently flagged users.
* **Type**: the user's type is (or is not) one of: normal, trusted, moderator, admin, testing. For example, skip moderation for your own moderators and admins.
* **Signed up**: how long ago the user signed up (more or less than a number of seconds, minutes, hours, days or weeks). New accounts are riskier, so many spam rules start here.
* **Signup method**: how the user signed up (email, phone, Google, Facebook, Apple, Twitter, etc.). Users signing up through SSO are less often spammers, so you could allow them without review.
* **Email domain**: the user's email domain, matched against one of your domain lists. For example, flag signups from disposable email domains.
* **Location (country)**: the user's country is (or is not) in one of your location lists.
* **IP address**: the user's IP address is (or is not) in one of your IP lists.
* **Profile image**: the user does (or does not) have a profile image. Accounts without one are more often fake, so this combines well with other signals.
* **Number of strikes**: the user's strike count, compared to a number you set. For example, ban users who reach 3 strikes.
* **User tags**: the user's tags are (or are not) in a set you select.
* **User's project**: the project the user belongs to is (or is not) in a set you select.
* **User's content volume**: how much content the user has posted. Choose what to count (messages, images, videos, or all content), which moderation statuses to include, a comparison and number, and whether to count in total or within a period (up to 30 days). For example, flag users with more than 5 removed messages in the last 7 days.\* **Topic volume**: like content volume, but counted per topic. For example, flag users who posted more than 10 items in a sensitive topic.

#### Review conditions (routing queue rules)

Routing queue rules can additionally match on properties of the review itself:

* **Priority**: the review priority is (or is not) urgent, high, medium, low or very low. For example, route urgent items to a dedicated queue.
* **Review type**: the item under review is content or a user.
* **Policy category**: the policy the item was flagged under is (or is not) in a set you select. For example, route everything flagged under your child safety policy to a specialist queue.

#### Custom attribute conditions

Any custom attributes you send with your content or users show up as conditions automatically, named after the attribute. The available options depend on the attribute's type:

* **Number**: compared to a threshold (greater than, at least, less than, at most). For example, flag marketplace listings with a price above 10,000.
* **Text**: the same matching options as the *Text* condition, including your word lists.
* **True/false**: the attribute is true or is false. For example, only apply a rule when `is_verified` is false.
* **Choice (enum)**: the value is (or is not) in a set of the attribute's possible values.

See [Custom attributes](/moderator-toolkit/custom-attributes) for how to send these with your content and users.


# Lists

Reusable sets of words, domains, countries, phone numbers, IP addresses and regex patterns that your moderation rules match against.

Lists are reusable sets of items that your [custom moderation rules](/automation-and-review/custom-moderation-rules) match against, for example a list of banned words, an allowlist of your own domains, or a set of disposable email domains. Instead of putting the values inside each rule, you keep them in a list and let any number of rules reference it. When you add or remove items, every rule that uses the list picks up the change automatically, without editing the rules.

{% hint style="info" %}
A list has no effect on its own. It only does something once a rule condition references it, for example a **Text** condition set to *contains any word* pointed at your word list. Whether a list acts as a blocklist or an allowlist is decided by the rule that uses it (*contains* versus *not contains*).
{% endhint %}

<figure><img src="/files/Rz3FcolfnPUKaqgcq9h8" alt=""><figcaption></figcaption></figure>

### What you can use them for

* Maintain word and phrase lists for profanity, spam or scam detection, shared across all your text rules.
* Allowlist your own domains, so rules only act on links that point elsewhere.
* Flag signups from disposable email domains, using a domain list with the **Email domain** condition.
* Treat users from specific countries or IP addresses differently, for example for regional compliance.
* Catch structured patterns that word lists can't express, such as ID numbers or obfuscated handles, with regex lists.

### List types

Every list has a type, chosen when you create it, that determines what it can hold and which rule conditions can use it:

* **Text**: words or phrases, including ones with spaces or special characters ("free money", "sh\*t"). Used by the **Text** condition, the user **Name** condition and text [custom attribute](/moderator-toolkit/custom-attributes) conditions.
* **Domains**: websites, entered as URLs (e.g. `https://example.com`). Used to match links in the **Text** condition and by the **Email domain** condition.
* **Phone Numbers**: phone numbers including their country code. Used to match phone numbers found in text.
* **Countries**: countries as ISO 3166-1 alpha-2 codes (e.g. `US`, `GB`, `NL`). Used by the **Location (country)** condition.
* **IP Addresses**: used by the **IP address** condition (available on the Pro and Enterprise plans).
* **Regexes**: regular expression patterns, for cases word lists can't express. Used by the *contains regex* matching option wherever text matching is available.

How matching works (whole word versus partial matching, case-insensitivity, normalization of accents and look-alike characters) is described per condition on the [custom moderation rules](/automation-and-review/custom-moderation-rules) page.

### Creating a list

Open **Lists** in the sidebar. Type a name, pick a type under **Select type of list** and click **Create new list**. The type cannot be changed later; the name can (open the list, change the name and click **Save**).

The number of lists you can create depends on your plan: 5 on the Free and Starter plans, 15 on Pro, and unlimited on Enterprise.

### Adding and removing items

Click a list to open it:

* Type a value in the **Add new item** section and click **Add**.
* An item that is already on the list is skipped ("Item already in list"), so a list never contains duplicates.
* Each item records when it was added and by whom, shown in the **Created At** and **Added By** columns. Changes are also recorded in the audit logs.
* To remove items, select them and click the **Delete** button that appears.
* Use the search box to find items on large lists.

Depending on the list's type, values are validated when you add them:

* **Countries** must be ISO 3166-1 alpha-2 codes, anything else is rejected.
* **Phone numbers** must include a country code. They are stored in a normalized format, so `+1-415-910-7311` is saved as `+14159107311`.
* **Domains** must be valid URLs.
* **Regexes** are validated when added. Invalid patterns, patterns of 200 characters or more, and unsafe patterns (for example with nested quantifiers) are rejected.

A list can hold up to 50,000 items. Regex lists are limited to 100 patterns.

<figure><img src="/files/3otjAxmRR876Kpm4zvr1" alt=""><figcaption></figcaption></figure>

### Uploading a file

To add many items at once, use the **Or upload file** section on the list. Upload a `.txt` file of less than 5 MB with one item per line (a single line of comma-separated values also works). A few things to keep in mind:

* Uploads always append to the list, they never replace it. Items already on the list are skipped.
* The same validation applies as for single items. If any entry in the file is invalid, the whole upload is rejected; fix the file and upload again.

### Adding items while you moderate

Select any text inside a piece of content, anywhere in the dashboard (the content pages, a user's content or a review queue), and a small dialog appears offering to add the selection to a list. Lasso detects what you selected (a country, IP address, phone number, URL or plain text) and only offers lists of the matching type. Pick a list and click the **Add to** button to confirm.

This is handy while reviewing: highlight a new spam phrase and add it to your word list without leaving the queue.

<figure><img src="/files/CIlATFUcPnvT3IIaYHWV" alt=""><figcaption></figcaption></figure>

### Testing a regex list

Regex lists have a **Test word on list** section. Type a value under **Word to test** and click **Test** to see whether it matches, and which of the list's patterns matched it. Use this to check new patterns before a rule starts acting on them.

### Using lists in rules

When you pick a list-based matching option in a [custom moderation rule](/automation-and-review/custom-moderation-rules) condition, a selector appears with your lists of the matching type. A few things to know:

* A condition can select multiple lists, their items are combined.
* Changes to a list apply to every rule that uses it, within seconds.
* Renaming a list is safe. Rules reference the list itself, not its name.
* The **Used in rules** column on the Lists page shows which rules use each list, with links to open them.
* If no list of the right type exists yet, the condition shows **No lists available**. Create the list first.

### Downloading and deleting lists

Admins have two extra controls on each row of the Lists page:

* The download icon saves the list as a `.txt` file with one item per line.
* The trash icon deletes the list, after a confirmation. Deleting a list cannot be undone.

A list that is used by a rule cannot be deleted ("Cannot delete list, it's in use by a rule"). Remove the list from every rule condition that references it first.

### Managing lists through the API

Lists can be managed from your own systems through the API, authenticated with your API key. In the API, the list `type` values are `strings` (Text), `urls` (Domains), `locations` (Countries), `phone_numbers`, `ips` and `regexes`.

**Get all lists** (the `items` field is the item count):

```
GET /api/v1/lists
```

```json
{
  "success": true,
  "lists": [
    {
      "id": "cln4sal9000d6saf8m5g12ifp",
      "createdAt": "2026-07-01T12:00:00.000Z",
      "name": "Banned words",
      "type": "strings",
      "items": 42
    }
  ]
}
```

**Create a list**:

```
POST /api/v1/lists

{ "name": "Banned words", "type": "strings" }
```

Returns `{ "success": true, "listId": "..." }`. Lists created through the API count towards your plan's list limit.

**Get a list with its items**:

```
GET /api/v1/lists/{listId}
```

```json
{
  "success": true,
  "list": {
    "id": "cln4sal9000d6saf8m5g12ifp",
    "createdAt": "2026-07-01T12:00:00.000Z",
    "name": "Banned words",
    "type": "strings",
    "items": ["free money", "spam phrase"]
  }
}
```

**Add items** (appends, never replaces):

```
POST /api/v1/lists/{listId}

{ "items": ["first", "second"] }
```

Returns `{ "success": true, "addedItems": [...] }`. `addedItems` contains only the values that were actually added, values already on the list are skipped silently. The same validation as in the dashboard applies, and an invalid value rejects the whole request with a 400 error.

**Remove items**:

```
DELETE /api/v1/lists/{listId}

{ "items": ["first"] }
```

Returns `{ "success": true, "deletedItems": [...] }`. Items are matched by their exact value.

Renaming and deleting lists is not possible through the API, use the dashboard for that. All endpoints are subject to [rate limits](/developers/rate-limits).

### Lists in webhooks

List changes are sent to your platform as `UpdateList` actions through [webhooks](/developers/webhooks), carrying the list's id and name, plus `words_added` and `words_removed` arrays when items change (the fields are named "words" regardless of the list's type). See the [webhooks](/developers/webhooks) page for the full payload.


# Review Queues

Review Queues organize content reviews into customizable categories that can be assigned to specific moderators or teams.

Review Queues provide a powerful way to organize and streamline the content moderation process by categorizing reviews into specific queues based on their attributes. This feature allows administrators to create multiple queues, each tailored to specific needs, and assign them to moderators with the right expertise.

For instance:

* A **"Spanish Queue"** can be created for content requiring Spanish-speaking moderators.
* A **"High Priority Queue"** can ensure urgent or high-priority reviews are processed promptly.

Administrators can configure each queue with a custom name and either assign all moderators or specify particular ones. The routing of reviews into these queues is controlled by [**Routing Rules**](/automation-and-review/review-queues/routing-rules).

<figure><img src="/files/EFxcq0ovlgvBoqk2qjJ4" alt=""><figcaption><p>Review Queue Overview</p></figcaption></figure>

### **Create and Configure Review Queues**

1. **Navigate to the Queues Section:**
   * In the moderation platform dashboard, click on the **Review** section.
2. **Create a New Queue:**
   * Click the **+** button to create a new queue.
   * Provide a descriptive name for the queue (e.g., "Spanish Queue", "High Priority Queue").
3. **Assign Moderators:**
   * Choose whether **All Moderators** can access this queue or select specific moderators.
4. **Save the Queue:**
   * Once configured, click **Save** to add the queue to your list.

### Example Video

{% embed url="<https://www.youtube.com/watch?v=Mkv8PCfL8_c>" %}
Example of how to set up a review queue with rules
{% endembed %}


# Routing Rules

Routing Rules automate review assignments to queues based on various conditions

Routing Rules determine how reviews are automatically directed to the appropriate queue. These rules use conditions based on the review, user, or content attributes. If no conditions match, reviews are sent to the **Default Queue**.

Examples:

* **Language Rule:** If the language of the content is "Spanish", direct the review to the **Spanish Queue**.
* **Priority Rule:** If the priority is "Urgent" or "High", send the review to the **High Priority Queue**.

Routing rules provide flexibility, allowing administrators to define logic that aligns with their moderation workflow.

<figure><img src="/files/jegqq2SO2lZi3Y2Y08VX" alt=""><figcaption><p>Queue routing rules</p></figcaption></figure>

### Create and configure routing rules

1. **Access Routing Rules:**
   * Click on the **Routing Rules** button in the Review Queues section.
2. **Add a New Rule:**
   * Click **Add Rule** and define a condition. For example:
     * Condition: `Priority` = `Urgent or High`
     * Queue: **High Priority Queue**
3. **Edit Existing Rules:**
   * Click on a rule to modify its conditions or assigned queue.
4. **Test and Save Rules:**
   * Ensure rules cover all necessary scenarios.
   * Click **Save** to apply the changes.

<figure><img src="/files/WHzO9V6l0J9hUg5Sw5jq" alt=""><figcaption><p>Set up a routing rule</p></figcaption></figure>


# User Reports

Let your users report content and other users, and triage those reports in Lasso or act on them automatically with rules.

User reports are reports your own users file about a piece of content or about another user on your platform. Your product sends each report to Lasso through the API, and they show up on the **User Reports** page for your moderators to triage. Reports are also a signal for [custom moderation rules](/automation-and-review/custom-moderation-rules), so you can automatically flag or remove something once enough people have reported it.

{% hint style="info" %}
Lasso does not provide a report button or a reporting form. You build the reporting experience in your own product, and send every report to Lasso through the user reports endpoint.
{% endhint %}

### What you can use them for

* Give moderators a queue of everything your community is complaining about, next to what your automated moderation catches.
* Escalate on volume, for example hide content once 3 different users have reported it within 24 hours.
* Trust some reporters more than others, so a report from a moderator or a trusted user can be acted on immediately while a report from a normal user needs corroboration.
* Catch bad-faith mass reporting by looking at how many reports a user has filed.
* Track what your users report, and how fast your team resolves it, in the analytics.

### Before you start

Two things need to be in place before your product can send reports.

1. **An API key.** Create one under **Settings → API & Webhooks**. Reports are sent with the same key as the rest of the API.
2. **At least one policy category enabled for user reports.** Every report has to name a policy category, which is the reason the user picked ("Spam", "Harassment", and so on). Go to **Policies**, open a policy category and tick the **User Reports** checkbox: "Can this policy category be selected when users are reporting content or other users?". This is off by default, so a fresh workspace has no reasons your users can pick from.

While you are there, fill in the **Information** field of each of these categories. It is meant as guidance for the reporter: "This information helps users understand when to select this policy category while submitting a user report." It is returned by the API together with the category name, so you can show it in your report dialog.

<figure><img src="/files/9lMOphjEsWPJeXfMu1AA" alt=""><figcaption></figcaption></figure>

### Fetching the report reasons

`GET /api/v1/user-reports` returns the list of reasons your users can choose from, so your report dialog stays in sync with the dashboard instead of hardcoding a list. Only categories that are enabled **and** have **User Reports** ticked are returned.

```json
{
  "success": true,
  "policies": [
    {
      "id": "harassment",
      "name": "Harassment",
      "description": "Targeted abuse or bullying of another user."
    }
  ]
}
```

The `id` here is the **Policy Category ID** (also shown as a column on the **Policies** page). That is the value you send back as `policy_id` when the user submits the report. If your workspace has translations enabled, each category also carries a `translations` object with the name and description per language.

### Sending a report

`POST /api/v1/user-reports` records one report. Everything goes inside a `report` object:

| Field              | Required | Description                                                                                                                             |
| ------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `policy_id`        | Yes      | The **Policy Category ID** of the reason the user picked, for example `harassment`.                                                     |
| `reported_by_id`   | Yes      | Your own id of the user filing the report. Max 100 characters.                                                                          |
| `content_id`       | One of   | Your own id of the reported content.                                                                                                    |
| `user_id`          | One of   | Your own id of the reported user.                                                                                                       |
| `reported_by_type` | No       | The type of the reporter: `normal`, `trusted`, `moderator`, `admin` or `testing`. Defaults to the type Lasso already has for that user. |
| `extra_info`       | No       | Free text the reporter added, shown to your moderators next to the report.                                                              |

```json
{
  "report": {
    "policy_id": "harassment",
    "reported_by_id": "user-456",
    "content_id": "comment-123",
    "extra_info": "Keeps calling me names in this thread"
  }
}
```

A successful call returns `{ "success": true }`.

Things worth knowing:

* Send **either** `content_id` **or** `user_id`, never both and never neither. Both cases return a `400`.
* The **reported content must already exist in Lasso**. If Lasso does not know the content id you get a `404` with `Reported Content not found`, so sync your content before you allow it to be reported.
* The **reported user and the reporter are created automatically** if Lasso has not seen them yet. They appear as "Unknown" until you sync their real profile.
* An unknown `policy_id` returns a `400` with `Policy not found`. Use the identifier, not the display name.
* Reports are **not deduplicated**. The same user reporting the same item twice creates two reports. If you only want one report per user per item, enforce that in your own product.
* If the reported user or content is **already hidden** in Lasso, the report is stored as handled straight away and never reaches your moderators' open list.

The endpoint is rate limited to **100 requests per minute** per workspace. See [rate limits](/developers/rate-limits) for the response headers and retry behaviour. Full request and response details are in the [API reference](https://api-reference.lassomoderation.com/group/endpoint-user-reports).

### Handling reports in the dashboard

Reports land on the **User Reports** page in the sidebar. It has two tabs, **Content** and **Users**, each with the number of open reports. The Users tab is only visible to moderators with permission to see user reports.

Each row shows the reported item, its current status, when the report came in, the policy category the reporter picked, their extra information, who reported it, how many times the item has been reported in total, and, once resolved, who handled it.

From a row a moderator can:

* **Take a moderation action** on the reported content or user, with the same action buttons used elsewhere in the dashboard. The report is resolved automatically as soon as a decision is made.
* **Ignore the report** when nothing is wrong with the reported item.
* **Ignore all reports for this content** (or **for this user**) to clear every open report on the same item at once.
* Select several rows and use the **Ignore n reports** button to clear them in bulk.

By default the page only shows open reports. Tick **Show handled reports** to include the ones that are already resolved. Resolved rows carry an icon showing how they were closed: a green check when an action was taken, and a crossed-out eye when the report was ignored.

Reports resolve themselves whenever a moderator or a rule takes a final decision on the reported item. Allowing or removing content or a user marks every open report on it as handled and records which action did it. Flagging is not a final decision, so flagged items keep their reports open until someone decides.

Every report also appears in the activity timeline of the reported user or content, as "Reported by *user* for *policy*", together with the extra information the reporter sent.

### Reacting to reports with rules

A report triggers a re-evaluation of your [custom moderation rules](/automation-and-review/custom-moderation-rules) on the reported user or content, so a rule can act on it within seconds. The report conditions are grouped under **Reports** in the condition list:

* **Content # of Times Reported** and **User # of Times Reported**: compare the number of reports against a number you set. You can count `by unique users` or `in total`, over all time or `over period` with a window like the last 24 hours, and restrict which reporter types count. For example, hide content reported by 3 or more unique users in the last 24 hours.
* **Content Reported By** and **User Reported By**: check whether the report came from a given type of user. A report from a moderator or an admin can be acted on immediately.
* **# of Reports Made By User**: available on user rules, compares how many reports a user has filed. Useful for catching users who mass-report others in bad faith.

The counting conditions look at every report ever filed on the item, including reports that were already handled or ignored.

Rules are also the link between reports and [review queues](/automation-and-review/review-queues). Reports do not create reviews by themselves, but a rule that flags a reported item will put it in front of your moderators through the normal routing rules.

### Reports in analytics

**Analytics → Reports** shows how reporting behaves over time: **Reports by Type** (content versus users), **Reports by Policy**, **Top Reporters**, **Average Handling Time** and **Reports by Decision**, which splits resolved reports into accepted (the item was removed), rejected (the item was allowed) and ignored. Analytics are updated asynchronously, so very recent reports can take a moment to appear.

<figure><img src="/files/Y3Q1rkdTgQ1pShuHrGAS" alt=""><figcaption></figcaption></figure>

The users list also has **# Reported** and **# Reports Made** columns, so you can sort your user base by who gets reported most and who reports most.

### Reports and webhooks

There is no separate webhook for an incoming report, because a report on its own is not a moderation decision. What your platform receives is the outcome: when a rule or a moderator acts on a reported item, the usual action [webhook](/developers/webhooks) is sent with the policy category and the rule that caused it. That keeps your platform in sync with what actually happened, rather than with every complaint your users file.


# User Moderation

Moderate the people on your platform, not just their content. Flag, ban or temporarily ban users, manually or automatically with rules, and keep your platform in sync through webhooks.

Lasso moderates users as well as content. Every user on your platform gets a moderation status in Lasso, and moderators and rules can act on the account as a whole: flag it for review, ban it permanently or temporarily, remove all of its content in one go, or give it a [strike](/managing-users/strikes). This is useful when the problem is the person rather than a single post, for example spammers, scammers and repeat offenders.

{% hint style="info" %}
Lasso does not block the user on your platform itself. Every status change is recorded in Lasso and sent to your platform through [webhooks](/developers/webhooks), and your platform decides what a ban means (blocking sign-in, hiding the profile, and so on). Make sure you have an active webhook configured under **Settings → API & Webhooks**.
{% endhint %}

### What you can use it for

* Ban spammers and repeat offenders, permanently or for a set amount of time.
* Flag suspicious accounts so a moderator reviews them in a [review queue](/automation-and-review/review-queues).
* Act on users automatically with user rules, for example ban users who reach 3 strikes, or flag day-old accounts that already had content removed.
* Clean up after a bad actor by removing all of their content in a single action.
* Keep your own platform in sync with every decision through webhooks.

### User statuses

Every user has one of three statuses:

* **Allowed**: the user is in good standing. This is also the status a user ends up with when they first sync to Lasso and no rule decides otherwise.
* **Flagged**: the user needs a human decision. Flagging a user creates a review in your review queues (if there isn't one open already). Flagging is not a final decision, so it does not resolve open reports on the user.
* **Banned**: the user should no longer take part in your platform. A ban can be permanent or temporary, and can remove all of the user's content at the same time.

The action names can be customized for your workspace (for example **Suspend** or **Delete** instead of **Ban**); reach out to Lasso support if the defaults don't match your product's vocabulary. In the API and in webhook payloads the statuses are always `allowed`, `flagged` and `hidden`, whatever the display names in the dashboard.

### Where to find your users

The **Users** page in the sidebar lists every user synced to Lasso. You can search users, filter on status and tags, and see per user how much content they posted, how often they were reported and how many reports they filed themselves.

Click a user to open their profile. It shows everything Lasso knows about the account (email, signup method, IP address, country, strikes, tags and any [custom attributes](/moderator-toolkit/custom-attributes)), an **Activity** timeline of every action ever taken on the user, and their content history. From the menu on the profile a moderator can also add a note, [send a message](/moderator-toolkit/sending-messages) to the user, or re-evaluate the rules with **Rerun rules on this user**.

If you set a **User link** under **Settings → Moderation Preferences** (for example `https://example.com/users/{id}`), the profile menu also gets a **View user in ...** option that opens the user directly in your own app.

### Taking action on a user

Allow, flag and ban buttons are shown wherever a user appears: on the Users page, on the user's profile, in review queues and on [user reports](/automation-and-review/user-reports). Banning opens a confirmation dialog with:

1. **Policy category**: the policy the user violated. Optional by default; you can make it required per action under **Settings → Moderation Preferences**.
2. **Temporarily ban user**: ban for a limited time instead of permanently (see below).
3. **Remove all user's content**: also removes everything the user has posted, with its own policy category for the content.

Content removed this way stays removed: unbanning the user later, or a temporary ban expiring, does not restore it.

Once a default policy is configured, moderators can Shift+Click an action button to act without the confirmation dialog.

<figure><img src="/files/qcjvO4bu8ftpxyXmMFRw" alt=""><figcaption></figcaption></figure>

### Temporary bans

{% hint style="info" %}
Temporary bans are available on the Pro and Enterprise plans.
{% endhint %}

Instead of banning permanently, tick **Temporarily ban user** in the ban dialog and choose a duration in hours, days or weeks (the default is 3 days; Lasso can configure a different default for your workspace). When the ban expires, Lasso automatically sets the user back to allowed and notifies your platform through the webhook, so the user regains access without a moderator having to remember.

### Moderating users automatically with rules

Under **Rules → Users** you can automate user moderation. A user rule combines conditions about the user (account age, signup method, email domain, IP address, number of strikes, times reported, content volume and more, see the user condition types in [custom moderation rules](/automation-and-review/custom-moderation-rules)) with actions:

* Change the user's status (**Allow**, **Flag** or **Ban**), with a **Policy Category** and, for flag rules, a review **Priority**.
* When banning, optionally **Remove all content**, with its own policy category for the content.
* **Strike user**, to give the user a [strike](/managing-users/strikes).
* Add **User Tags** to the user.

Rules are re-evaluated whenever something about the user changes: when the account is created or updated through the API, when the user posts content, when they are reported, when they receive a strike, and when a moderator chooses **Rerun rules on this user**. Rules run in the order shown on the page; an allow or ban stops the evaluation, while multiple flag rules can all fire. Rules never override a ban a moderator has set by hand.

### Reviewing flagged users

Flagged users land in your [review queues](/automation-and-review/review-queues) next to content reviews. Use [routing rules](/automation-and-review/review-queues/routing-rules) with the **Review Type** condition to send user reviews to a dedicated queue or team.

Inside a review the moderator sees the full user profile, activity timeline and content history, and decides with **Allow** or **Ban** (flagging again is not offered inside a review, and banning from a review always asks for confirmation). The optional **Also apply to all user's content** checkbox removes everything the user posted along with the ban; it can be shown or hidden per moderator in the review settings.

User reviews are always handled by human moderators; the AI Moderator only reviews content.

### Syncing users through the API

Users are created and updated in Lasso through `POST /api/v1/user`; see the [API Reference](https://api-reference.lassomoderation.com/) for the full schema. A few semantics to be aware of:

* Send an update whenever the profile changes (name, email, profile image, IP address and so on); every update re-evaluates your user rules with the fresh data.
* Set the user's `type` (`normal`, `trusted`, `moderator`, `admin` or `testing`) so rules can treat your staff and trusted users differently from normal users.
* The `status` field is only honoured when the user is first created; later values are ignored.
* The user's project (`project_id` / `category_id`) cannot be changed after creation.
* Bulk imports through `POST /api/v1/import/users` skip rule evaluation, so imported users are not run through your rules.
* `GET /api/v1/user/{id}` returns the user's current status, including `temporarily_banned_until` and `strike_until` when applicable, useful when your backend needs to check a user's standing.

### User actions in webhooks

Every user status change is delivered to your webhook as a `ChangeStatus` action with `"type": "user"`. The payload contains your own user id and tags, the new and previous status, the policy that was applied, and a `temporary_ban` object (`until`, `period`, `duration`) when the ban is temporary. When a temporary ban expires, Lasso sends another `ChangeStatus` back to `allowed`. See [webhooks](/developers/webhooks) for the full payloads and signature verification.

If your endpoint keeps failing after retries, Lasso reverts the status change, so Lasso and your platform don't drift apart.

### Configuring user moderation

Under **Settings → Moderation Preferences** you can control:

* **Can ban users** and **Can unban users**: which user actions moderators can take in this workspace. Disabling unbanning also disables temporary bans, since a temporary ban needs to be lifted again.
* **User Policy Defaults**: a default policy per action, and whether a policy is required to allow, flag or ban a user.
* **User link**: the URL template that opens a user's profile in your app.
* Strike settings: see [strikes](/managing-users/strikes) for the escalation ladder and automatic clearing.

### Related features

* [Strikes](/managing-users/strikes): escalating, temporary penalties for repeat offences instead of an immediate ban.
* [Tags](/moderator-toolkit/tags): label users (for example `repeat-offender`) and use the tags in rule conditions and filters.
* [Sending Messages](/moderator-toolkit/sending-messages): explain a decision to the user instead of acting silently.
* [User Reports](/automation-and-review/user-reports): let your community report users, and act on those reports manually or with rules.


# Strikes

Give users escalating, temporary penalties for repeat offences instead of a permanent ban.

Strikes let you discipline repeat offenders with escalating, temporary penalties instead of jumping straight to a permanent ban. Every strike a user receives lasts longer than the previous one, based on an escalation ladder that you configure. This gives users a chance to correct their behavior, while persistent offenders are penalized progressively harder.

{% hint style="info" %}
Strikes are available on the Pro and Enterprise plans.
{% endhint %}

### How strikes work

* You define an ordered list of strike tiers. The first strike a user receives uses the duration of the first tier, the second strike uses the second tier, and so on.
* A user can only have one active strike at a time.
* When a strike's duration passes, the strike automatically ends. It stays on the user's record and still counts towards the escalation ladder, so the user's next strike uses the next tier.
* The number of tiers is also the maximum number of strikes a user can receive. Once a user has run out of strikes, they cannot be striked again. At that point a moderator would typically ban the user.
* Lasso records the strike and notifies your platform through [webhooks](/developers/webhooks#strike-actions). Your platform decides what an active strike means for the user, for example a mute, restricted posting, or a temporary suspension.

### Configuring strikes

Strike settings can be found in **Settings → Moderation Preferences**, under **Strike Escalation**.

Each row in the escalation ladder is one tier, consisting of a duration and a period (minutes, hours, days, weeks or months). For example, a common setup is:

1. 1st strike: 1 day
2. 2nd strike: 1 week
3. 3rd strike: 1 month

Use **Add tier** to extend the ladder, and the trash icon to remove a tier. Changes apply to strikes given from that moment on; strikes that are already active keep their original duration.

#### Automatically clearing strikes

You can reward users for good behavior by automatically removing strikes from their record after a period of good standing. Enable **Automatically clear strikes** and set the period (days, weeks or months).

* The good standing period starts once the user's latest strike has ended, and restarts whenever the user receives a new strike.
* Strikes are cleared one at a time, starting with the most recent one. After a strike is cleared, the user needs to complete another full period of good standing before the next one is cleared.
* Strikes are never cleared while the user has an active strike.

For example, with a clearance period of 4 weeks: a user whose strike ended on March 1st and who stays out of trouble will have that strike removed around March 29th. If they had two strikes, the second one would be removed around April 26th.

### Giving a user a strike

#### Manually

Moderators can strike a user from the user's page or from a review queue using the strike button. Optionally, a policy can be selected to categorize the strike, which is useful for tracking actions taken under specific policy guidelines.

The strike button shows the duration of the user's next strike. It is disabled when the user already has an active strike, or when the user has reached the maximum number of strikes.

#### Automatically with rules

[Custom moderation rules](/automation-and-review/custom-moderation-rules) that target users or content can give strikes automatically via the **Strike User** action. There are two options:

* **Strike**: Adds a strike to the user. No action is taken if the user already has an active strike.
* **Add Strike**: Adds a strike even if the user already has an active strike. The current strike is ended and the next tier starts immediately, effectively extending the penalty. No action is taken if this would be beyond the user's last strike.

### Ending and removing strikes

* **End strike**: A moderator can end a user's active strike early. The strike still stays on the user's record and keeps counting towards the escalation ladder.
* **Remove strike**: Removes the most recent strike from the user's record entirely, lowering the user's strike count. If that strike is still active, it is ended first.
* Strikes that run their full duration end automatically, no moderator action is needed.

### Enforcing strikes on your platform

Lasso does not restrict the user in your product directly. To act on strikes, subscribe to [webhooks](/developers/webhooks#strike-actions) and handle the strike actions:

* `StrikeUser`: A strike was given. The payload includes the user's total strike `count`, the `duration` and `period` of the strike, and `until`, the ISO date when the strike ends.
* `EndStrikeUser`: The user's active strike ended, either automatically or by a moderator.
* `RemoveStrikeUser`: A strike was removed from the user's record. The payload includes the user's new strike `count`.

See the *Strike Actions* example on the [webhooks](/developers/webhooks#strike-actions) page for the full payload.


# Policy Categories

The reasons behind your moderation decisions. Set up policy categories once, then use them in moderation, rules, review queues, user reports and reporting.

A policy category is the reason attached to a moderation decision. When a moderator removes a post, when a rule flags a user, or when an AI Moderator hides a comment, the policy category records which of your guidelines was broken, for example "Harassment", "Spam" or "Underage Protection".

Policy categories are what turn a pile of moderation actions into something you can report on and automate against. They also travel outside Lasso: every category has an identifier that your platform receives in [webhooks](/developers/webhooks) and sends back through the API when your users file a report.

{% hint style="info" %}
The **Policies** page holds two related things. **Categories** are the short reasons described here. A **policy** is the written policy document your AI Moderators read. Categories can be added to a written policy so an AI Moderator can pick them, but they work on their own for human moderators and rules.
{% endhint %}

### What you can use them for

* Record why each decision was taken, so an action taken today is still explainable months later.
* Report on what your moderators actually deal with, in **Analytics → Reports** and **Analytics → Reviews**.
* Drive automation: a rule can apply a category, and routing rules can send everything flagged under one category to a specialist queue.
* Give your users a list of report reasons that stays in sync with the dashboard.
* Tell your platform *why* something was removed, through the `policy_id` field in webhooks.
* Meet compliance obligations: a category can be configured to file [DSA reports](/compliance/dsa-compliance/setup) automatically.

### Where to find them

Policy categories live under **Policies** in the sidebar, in the **Categories** section ("Manage your policy categories"). The table lists every category in your workspace, sorted alphabetically, with its name, its **Policy Category ID**, which types and actions it applies to, its hotkey, the number of rules using it and whether it is available in user reports.

### Creating a policy category

1. Go to **Policies** and click the button to add a category.
2. Fill in the **Policy Category Name** (placeholder: "E.g. Inappropriate Content"). Names are limited to 40 characters.
3. Click **Create new policy category**.

The settings dialog opens straight away so you can finish configuring it.

Two things worth knowing about names:

* The name determines the **Policy Category ID**, which is the identifier used everywhere outside the dashboard. "Inappropriate Content" becomes `inappropriate-content`. Renaming a category later does **not** change its ID, so your integration keeps working.
* Because the ID is derived from the name, two names that produce the same ID are the same category. Creating "Spam!" when "Spam" already exists reuses the existing category instead of creating a second one.

You may also see a category appear that nobody created: **Revert Action**. Lasso adds it the first time your platform rejects a status change through a webhook and Lasso reverts its own decision.

### Category settings

Click any row in the Categories table to open **Policy Category Settings**.

**Information**

* **Name** and **Description**. The description is guidance for whoever picks the category: "This information helps users understand when to select this policy category while submitting a user report." It is up to 400 characters, and it is returned by the user reports API, so it is worth writing properly for anything your users can pick.
* **User Reports**: "Can this policy category be selected when users are reporting content or other users?" Off by default. See [user reports](/automation-and-review/user-reports).

**Settings**

* **Hotkey**: "Use this hotkey to quickly apply this policy category to content." Pick a digit from `0` to `9` and pressing it in the action dialog selects that category. Each digit can only be used by one category, so up to ten categories can have one.
* **Policy can be selected by**: "Can this policy category be selected by moderators or rules?" Choose **Moderators & Rules**, **Only Moderators** or **Only Rules**. Use **Only Rules** for internal bookkeeping categories you do not want your team choosing by hand, and **Only Moderators** for judgement calls you never want automated.
* **Available for types**: "For which types can this be used as a policy category?" Either **All**, or one specific object type (content, users or subcategories, under whatever names your workspace uses). A user-only category like "Repeat Offender" will not clutter the dropdown when a moderator is acting on a post.
* **Enabled for actions**: "For which of the actions can this be used as a policy category?" A checkbox per action, using your workspace's own wording for allow, flag and remove, plus **Strikes** if [strikes](/managing-users/strikes) are enabled. Untick the ones that make no sense, for example an "Approved" category that should only ever be used when allowing content.

The dialog also has a collapsible **Rules with this policy category** section listing every rule that applies it, or "No rules tied to this policy". Click **Update** to save.

If your workspace has multiple languages enabled, the Name and Description fields appear once per language and are translated automatically when you create a category. You can correct any translation by hand.

If you have the Sift integration, a **Sift Decision** field lets you map the category onto a decision in Sift. Lasso forwards it when a user's status changes.

### Using categories while moderating

Wherever a moderator takes an action, the confirmation dialog has a **Policy category** field with the placeholder "Select policy category". Only categories that fit are offered: the object type has to match, the action has to be enabled on the category, the category has to be selectable by moderators, and, in a review queue, the category has to be allowed in that queue.

Under **Settings → Moderation preferences** you can make this smoother:

* Set a **default policy category** per action, so the right one is preselected. Once a default is configured, moderators can Shift+Click an action button to act without opening the dialog at all.
* Make a category **required** for a given action, so no decision is recorded without a reason.

Both are configured separately for content, users and subcategories. See [user moderation](/managing-users/user-moderation) for the user side.

<figure><img src="/files/dPyO3zLLnryNPpVVBuYL" alt=""><figcaption></figcaption></figure>

### Categories in rules

Every rule action that changes a status can carry a policy category, chosen with the **Policy Category** field on the rule. That is how automated decisions end up as explainable as manual ones. A rule that bans a user and removes their content can set a separate **Policy Category Content** for the removals.

Rules count as automation rather than a moderator, so a category set to **Only Moderators** cannot be attached to a rule.

Categories are also something rules can match on. Routing rules for [review queues](/automation-and-review/review-queues) have a **Policy Category** condition ("Condition based on the policy category it got flagged for") with `is in` and `is not in` operators, so you can send everything flagged under your child safety category to a dedicated queue.

When you export and import [custom moderation rules](/automation-and-review/custom-moderation-rules) between workspaces, categories are carried by their ID. Any category the target workspace is missing is created automatically, and the import warns you that it did so.

### Categories in review queues

A review queue can be limited to a subset of categories. On the queue, untick **All policies are available in this queue** and pick the ones you want under **Policies available in this queue**. Moderators working that queue then only see those categories in their action dialog.

### Categories in user reports

Categories with **User Reports** ticked are the reasons your own users choose from when they report something. `GET /api/v1/user-reports` returns them (id, name, description and, with translations enabled, a `translations` object), and you send the id back as `policy_id` when submitting the report. Full details are on the [user reports](/automation-and-review/user-reports) page.

### Categories and AI Moderators

An AI Moderator decides using a written policy, and the sections of that policy are your policy categories. Add a category to a policy document, write the guidance for it there, and the AI Moderator can judge content against it and apply that category to its decisions, along with a short explanation of its reasoning.

A category that is not part of the written policy, or that is in it but has no text, is invisible to the AI Moderator. It still works normally for moderators and rules.

### Categories in the API and webhooks

There is no endpoint for creating or listing all your policy categories. They appear in the API in two places, and always by their **Policy Category ID**, never the display name:

* `POST /api/v1/user-reports` takes `report.policy_id`. An unknown value returns a `400` with `Policy not found`.
* `POST /api/v1/status` takes an optional `policy_id`, so a decision your own platform makes is recorded with the same reason your moderators would use. An unknown value here is ignored silently and the status change still goes through, so check your spelling.

On the way out, every action [webhook](/developers/webhooks) that has a category attached carries:

| Field                | Description                                                                                                  |
| -------------------- | ------------------------------------------------------------------------------------------------------------ |
| `policy_id`          | The Policy Category ID, for example `inappropriate-content`.                                                 |
| `policy_name`        | The display name at the time of the action, for example `Inappropriate Content`.                             |
| `policy_information` | Optional extra reasoning, filled in by AI Moderators and by decisions your platform reverts through the API. |

Do not confuse `policy_id` with the `category_id` and `subcategory_id` fields inside the `content` object of the same payload. Those describe where the content lives on your platform, not why it was actioned. The full payload is documented under [webhooks](/developers/webhooks).

### Reporting on categories

**Analytics → Reports** has **Reports by Policy**, and **Analytics → Reviews** has **Reviews by Policy**, both broken down over time and as a total for the period. Decisions taken without a category are grouped as "No policy", and decisions taken under a category that has since been deleted show as "Deleted Policy".

### Renaming and deleting

Renaming is safe. The Policy Category ID stays the same, past decisions keep pointing at the category, and your integration does not need to change.

Deleting is restricted. The delete button is disabled, with the tooltip "Cannot delete policy category that is used by a rule or in a policy", as long as any rule uses the category or it is part of a written policy. Remove those references first.

When you do delete a category:

* It disappears from every dropdown, but past actions, reports and compliance reports keep their reason. They show up as "Deleted Policy" in analytics.
* Creating a category with the same name again restores the original one, hotkey, settings and history included.

### Choosing your categories

Categories work best when they are few and clearly separated, so a moderator picking one under time pressure does not have to think about it. A set of eight to twelve is typical. Most platforms end up with something close to:

* Harassment and Discrimination
* Hate Speech and Extremism
* Obscenity and Profanity
* Nudity and Sexual Content
* Self-Harm or Threats
* Personal and Sensitive Information
* Fraud and Scams
* Spam
* Underage Protection

Add whatever is specific to your product (cheating and exploits for a game, prohibited goods for a marketplace, misrepresentation for a dating app), plus a couple of internal categories that are not really violations, such as "User Feedback" or a rules-only category for automated cleanup.


# Custom Attributes

Learn how to set up and use Custom Attributes to enrich your content, user profiles, or subcategories with tailored data, enabling enhanced insights and customizable rules.

### **What are Custom Attributes?**

Custom Attributes allow you to enrich your content, user profiles, or subcategories with additional, tailored data points. This feature provides flexibility in tagging and categorizing your data to fit your specific needs, enabling deeper insights and more granular control.

### **Benefits of Custom Attributes**

* **Enhanced Data Enrichment**: Add context-specific information to your content, users, or subcategories.
* **Streamlined Workflows**: Automatically integrate custom attributes into your dashboard, making it easier to visualize and moderate your content/users.
* **Customizable Rules**: Use custom attributes in your moderation rules (found under the "custom" section) for more precise actions and automation.

### Examples of Custom Attributes

* **Verified User**: Marks whether a user has been verified, which can be useful for prioritizing trusted users.
* **User Has Credit Card on File**: Identifies users with linked payment methods for transaction-related rules.
* **# of Connections**: Tracks the number of user connections to target highly networked individuals.
* **Age**: Captures user age for applying age-specific content moderation or analysis.
* **Location**: Stores geographical data for region-based rules or personalized content delivery.

### How to Set Up Custom Attributes

Follow these steps to set up and use Custom Attributes in your dashboard:

#### **Step 1: Add attributes through the API**

1. Add the attributes you would like to use to your API calls to Lasso. An example of adding an attribute to your content can be found [here](https://api-reference.lassomoderation.com/operation/operation-post-content#operation-post-content-body-application-json-metadata).

#### **Step 2: Navigate to the Settings**

1. Log in to your dashboard.
2. Go to **Settings → Tags & Attributes**.

#### **Step 3: Add a Custom Attribute**

1. Scroll to the **Custom Attribute** section.
2. Select your custom attribute in the dropdown (The system will check the last 1,000 items from the previous day to identify which attributes are available)
3. Verify the following details:
   * **Name**: Enter a clear, descriptive name for the attribute.
   * **Type**: Select the appropriate data type (text, number, boolean, enum, user ID, content ID).

<figure><img src="/files/OxqfaxGPrPdobI2mEZny" alt=""><figcaption><p>Example of creating Custom Content Attributes</p></figcaption></figure>

**Step 4: Save and Apply**

1. Save the attribute. Once saved:
   * The custom attribute will be displayed automatically within the dashboard.
   * You can view and manage this data alongside existing content or profiles.

#### **Step 5: Use Custom Attributes in Rules**

1. Go to the **Rules** section in your dashboard.
2. Under the "custom" category, you can incorporate your custom attribute into moderation or workflow rules for more precise automation.


# Tags

Label users and content with your own tags, then use them to filter, build rule conditions and automate moderation workflows.

Tags are descriptive labels you attach to users and content to highlight specific characteristics, themes or behaviors, for example "Suspicious", "VIP" or "Repeat Offender". You define your own set of tags, and moderators, rules and your own systems can then apply them anywhere. Tags power filtering, rule conditions and segmentation across the dashboard.

<figure><img src="/files/E1EQFSYB65JMy9hPSZus" alt=""><figcaption></figcaption></figure>

### What you can use them for

* Segment users, for example marking VIPs, potential spammers or accounts under observation.
* Feed follow-up automation: [custom moderation rules](/automation-and-review/custom-moderation-rules) can check tags in their conditions, so one rule can tag a user and another can act on that tag later.
* Route flagged items to the right team by using tags in routing rules for [review queues](/automation-and-review/review-queues).
* Filter the users and content pages to quickly find everything with (or without) a certain tag.
* Sync context from your own platform, for example tagging your premium users through the API.

### Creating tags

Tags are created by admins under **Settings → Tags & Attributes**, in the **Tags** section. Pick a color, type a name (e.g. "Suspicious") and click **Create tag**.

Each tag has:

* A **name**, shown everywhere in the dashboard. Names are unique per workspace and fixed once created.
* An **identifier**, generated automatically from the name ("Repeat Offender" becomes `repeat-offender`). This is the value used in the API and in webhook payloads.
* A **color**, which you can change at any time by clicking the tag's color dot.

Deleting a tag removes it permanently, including from any rules that use it. This cannot be undone.

<figure><img src="/files/jfmBnHmju597Y0MS033K" alt=""><figcaption></figcaption></figure>

### Tagging users and content

Moderators can tag from a few places:

* **User page**: the analysis panel on a user's page has a **Tags** row. Click **+** to add one of your tags, click an existing tag to remove it.
* **Content**: the analysis panel on a piece of content has the same **Tags** row.
* **Review queues**: while reviewing, use the tag button in the action bar (or press **T**) to tag without leaving the queue. The tag button can be shown or hidden per moderator via the review settings ("Show tag actions").

Every tag change is recorded in the activity timeline and the audit logs, including whether it was done by a moderator or a rule.

### Tagging automatically with rules

[Custom moderation rules](/automation-and-review/custom-moderation-rules) can both apply tags and react to them:

* **As an action**: content and user rules can add tags when they match, via **Add tags to user** and **Add tags to content**. For example, tag users as "Spammer" when they trip your spam rule. Rules only add tags, they never remove them.
* **As a condition**: the **User tags** and **Content tags** conditions check whether the user or content has any of the selected tags (or none of them). This lets rules build on each other: one rule tags, another escalates.
* **In routing rules**: tag conditions are also available when routing reviews to [review queues](/automation-and-review/review-queues), so tagged items can go to a dedicated queue.

Tags applied by a rule are attributed to that rule in the timeline and in webhooks.

### Filtering by tags

* **Users page**: filter with **Filter on tags** and **Exclude tags**. Including multiple tags shows users that have all of them; excluded tags hide any user carrying one. The users table also has a tags column.
* **Content page**: add the **Tags** filter in the filter bar to only show content with the selected tags.

### Setting tags through the API

User tags can be set from your own platform by including a `tags` array of tag identifiers on the user object, in user create, user sync (including the user embedded in content sync) and bulk user import:

```json
{
  "id": "user-123",
  "name": "Ada",
  "tags": ["premium", "beta-tester"]
}
```

A few things to keep in mind:

* Use the tag **identifier** (e.g. `repeat-offender`), not the display name. Identifiers that don't match an existing tag are ignored, the API never creates new tags.
* The array **replaces** the user's full tag set. Send the complete list each time, an empty array clears all tags, and omitting the field leaves the current tags untouched.
* A user can have at most 100 tags.

Content tags cannot be set through the API. Content is tagged by moderators in the dashboard or automatically by rules.

### Tags in webhooks

Tag changes are sent to your platform as `AddTags` and `RemoveTags` actions through [webhooks](/developers/webhooks), so your own systems can react to them. In addition, every content and user webhook payload includes the object's current tags under `content.tags` and `user.tags`, whatever the action type.

See the *Tag Actions* example on the [webhooks](/developers/webhooks) page for the full payload.

### Tags vs custom attributes

Tags and [custom attributes](/moderator-toolkit/custom-attributes) live on the same settings page but serve different purposes. A tag is a simple label that is either present or not, defined in the dashboard and applied by moderators, rules or the API. A custom attribute is a typed key-value data point (string, number, boolean, and so on) that you send along with your API payloads to enrich content and users with structured data. Use tags for moderation workflow labels, use custom attributes for structured facts about your data.


# Sending Messages

Communicate with your platform's users directly from Lasso, to explain decisions, share guidelines or reply to content.

Send Message lets moderators communicate directly with the users of your platform from within Lasso. Instead of silently removing content or banning a user, a moderator can explain a decision, ask for clarification, or point a user to your community guidelines. Messages are delivered on your own platform, for example as a direct message to the user or as a reply under a piece of content.

{% hint style="info" %}
Lasso does not deliver the message to the user itself. The message is sent to your platform through [webhooks](/developers/webhooks#send-message), and your platform decides how to deliver it (as a DM, a reply, an email, and so on). Make sure you have an active webhook configured under **Settings → API & Webhooks** and that your endpoint handles the `SendMessage` action.
{% endhint %}

<figure><img src="/files/iTJLRLe2C1YHhk5WYgud" alt=""><figcaption></figcaption></figure>

### What you can use it for

* Explain why content was removed or a user was sanctioned.
* Send a friendly reminder about your community guidelines before taking harder action.
* Ask a user for more context on a report or a piece of content.
* Post an official moderator reply under a piece of content.

### Where to find it

Send Message is available anywhere you see the **⋯** menu on a user or a piece of content:

* **User page**: open a user and click the **⋯** menu next to their name, then choose **Send Message**. The message is sent to the user directly.
* **Content**: open a piece of content (from the content explorer or a user's content list) and choose **Send Message** from the content's **⋯** menu. The message is sent as a reply to that piece of content.
* **Review queues**: while reviewing, both the content card and the user panel have the same **⋯** menu, so you can message the user without leaving the queue.

<figure><img src="/files/9Zfo4vxMU4i3fnMyWiRZ" alt=""><figcaption></figcaption></figure>

### Sending a message

1. Open the **⋯** menu on the user or content and choose **Send Message**.
2. Optionally pick a saved template from **Template (optional)**. The template's text is loaded into the message field, where you can still edit it before sending.
3. Write or adjust your message. You can use variables to personalize it:
   * `{{user_name}}` is replaced with the recipient's name.
   * `{{moderator_name}}` is replaced with your name.
4. Click **Send message**.

The variables are filled in when the message is sent, so the user receives the final text, for example "Hi Ada, please keep it friendly. Grace, the moderation team".

Every sent message is recorded on the user's or content's activity timeline with a **Messaged** badge, and in the audit logs, so your team can always see who sent what and when.

### Message templates

If your moderators send the same kinds of messages often, admins can create reusable message templates under **Settings → Moderation Preferences → Message Templates**.

* Templates are shared with the whole workspace.
* Each template has a **Name** (shown in the template picker) and a **Message**.
* Templates can contain the `{{user_name}}` and `{{moderator_name}}` variables.
* Moderators can always edit the text after picking a template, so templates work well as a starting point rather than a fixed script.
* Editing or deleting a template does not affect messages that have already been sent.

<figure><img src="/files/dlILNBQAtxwV6zpuS9Cu" alt=""><figcaption></figcaption></figure>

### Delivering messages on your platform

When a moderator sends a message, Lasso sends a `SendMessage` action to your webhook endpoint. The payload contains the final message text (variables already resolved), the moderator who sent it, and either the user to message or the content to reply to. Your endpoint is responsible for delivering the message in your product.

If your webhook rejects the delivery, the failure is recorded on the action in the activity timeline, so moderators can see the message was not delivered.

See the `SendMessage` example on the [webhooks](/developers/webhooks#send-message) page for the full payload and delivery details.


# Webhooks

Guide on how to implement Lasso webhooks for real-time updates

Webhooks allow you to receive real-time notifications about actions taken on the Lasso Moderation platform. By configuring a webhook URL, Lasso Moderation can automatically send a JSON payload to your server whenever a particular event occurs on the platform. Webhooks can be configured under [settings](https://app.lassomoderation.com/settings) in the dashboard.

### Webhook

To set up a webhook, you need to provide a valid URL that can receive HTTPS POST requests. When an event is triggered on the platform, Lasso Moderation will send a JSON payload to the specified URL. This payload contains information about the event that occurred, including any relevant data that you may need to take action.&#x20;

Multiple actions can be sent at once in one HTTP POST request, this is done in case of bulk operation where multiple actions are taken at once. The actions are ordered by when they are taken.

Here are example responses from a webhook that is triggered based on different actions:

{% tabs %}
{% tab title="Status Actions" %}

```json
{
  "actions": [
    {
      "action_type": "ChangeStatus",
      "action_id": "clf10kbhp0012sauvpxlqsb6h", // The Lasso ID of the action
      "action_created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the action was taken
      "type": "user", // The type of object the action is taken on, "user", "content" or "subcategory"
      "status": "hidden", // The status of the object, this can be "allowed", "flagged" or "hidden"
      "previous_status": "flagged", // The status of the object before the action was taken, this can be `null` (when there was not previous status), "allowed", "flagged" or "hidden"
      "actor_id": "cldk3z9ze0004saiy542wfbck", // (optional) The Lasso ID of the moderator who triggered this action. Either actor_id or rule_id is set.
      "rule_id": "clyhppfjy00574ohv9uigmnia", // (optional) The Lasso ID of the rule which triggered this action. Either actor_id or rule_id is set.
      // (optional) user is only sent when type === "user"
      "user": {
        "id": "cldk3z9ze0004saiy542wfbck", // The product's ID of the user
        "tags": ["potential-spammer"] // Custom tags attached to the user
      },      
      // (optional) content is only sent when type === "content"
      "content": {
        "id": "cldk3zadj019wsaiyudwdtxtr", // The product's ID of the content
        "created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the content was created
        "user_id": "cldk3z9ze0004saiy542wfbck", // The ID of the user who sent the content
        "subcategory_id": "cldvl1z2l002xsaykyoje94od", // The ID of the subcategory the content is part of
        "category_id": "cldq51mh005fjsaw2y0fx3t5c" // The ID of the category the content is part of
        "tags": ["explicit-content"] // Custom tags attached to the content
      },      
      // (optional) subcategory is only sent when type === "subcategory"
      "subcategory": {
        "id": "cldvl1z2l002xsaykyoje94od" // The product's ID of the subcategory
      },
      // (optional) when the user is temporarily banned
      "temporary_ban": {
        "until": "2023-12-18T17:42:38.558Z",
        "period": "week",
        "duration": 1
      },      
      "policy_id": "inappropriate-content", // (optional) The ID of the policy that was used when taking this action
      "policy_name": "Inappropriate Content", // (optional) The name of the policy that was used when taking this action
      "policy_information": "This content contains XXX" // (optional) Extra information that was given when the action was taken
    }
  ]
}
```

{% endtab %}

{% tab title="Tag Actions" %}

```json
{
  "actions": [
    {
      "action_type": "AddTags", // Or "RemoveTags"
      "action_id": "clf10kbhp0012sauvpxlqsb6h", // The Lasso ID of the action
      "action_created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the action was taken
      "type": "user", // The type of object the tag was added to, "user" or "content"
      "tags_added": ["tags-slug1","tag-slug2"], // (optional, only when action type is "AddTags"
      "tags_removed": ["tags-slug1","tag-slug2"], // (optional, only when action type is "RemoveTags"
      "actor_id": "cldk3z9ze0004saiy542wfbck", // (optional) The Lasso ID of the moderator who triggered this action. Either actor_id or rule_id is set.
      "rule_id": "clyhppfjy00574ohv9uigmnia", // (optional) The Lasso ID of the rule which triggered this action. Either actor_id or rule_id is set.
      // (optional) user is only sent when type === "user"
      "user": {
        "id": "cldk3z9ze0004saiy542wfbck", // The product's ID of the user
        "tags": ["potential-spammer"] // Custom tags attached to the user
      },      
      // (optional) content is only sent when type === "content"
      "content": {
        "id": "cldk3zadj019wsaiyudwdtxtr", // The product's ID of the content
        "created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the content was created
        "user_id": "cldk3z9ze0004saiy542wfbck", // The ID of the user who sent the content
        "subcategory_id": "cldvl1z2l002xsaykyoje94od", // The ID of the subcategory the content is part of
        "category_id": "cldq51mh005fjsaw2y0fx3t5c" // The ID of the category the content is part of
        "tags": ["explicit-content"] // Custom tags attached to the content
      }
    }
  ]
}
```

{% endtab %}

{% tab title="List Actions" %}

```json
{
  "actions": [
    {
      "action_type": "UpdateList",
      "action_id": "clf10kbhp0012sauvpxlqsb6h", // The Lasso ID of the action
      "action_created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the action was taken
      "actor_id": "cldk3z9ze0004saiy542wfbck", 
      "list": {
        "id": "cln4sal9000d6saf8m5g12ifp",
        "name": "banned words",
        // (optionally in case items are added to the list)
        "words_added": [
          "F you!"
        ],
        // (optionally in case items are removed from list)
        "words_added": [
          "Hello!"
        ]
      },
      
    }
  ]
}
```

{% endtab %}

{% tab title="Strike Actions" %}

```json
{
  "actions": [
    {
      "action_type": "StrikeUser", // or "EndStrikeUser", "RemoveStrikeUser"
      "action_id": "clf10kbhp0012sauvpxlqsb6h", // The Lasso ID of the action
      "action_created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the action was taken
      "type": "user",
      "actor_id": "cldk3z9ze0004saiy542wfbck", // (optional) The Lasso ID of the moderator who triggered this action. Either actor_id or rule_id is set.
      "rule_id": "clyhppfjy00574ohv9uigmnia", // (optional) The Lasso ID of the rule which triggered this action. Either actor_id or rule_id is set.
      "user": {
        "id": "cldk3z9ze0004saiy542wfbck", // The product's ID of the user
        "tags": ["potential-spammer"] // Custom tags attached to the user
      },
      // (optional) only on "StrikeUser" or "RemoveStrikeUser"
      "strike": {
        "count": 2, // The total number of strikes the user has
        // (optional) only on "StrikeUser"
        "duration": 3 // The number of periods the user will be given a strike, in this case 3 hours
        // (optional) only on "StrikeUser"
        "period": "hour", // "minute", "hour", "day", "week" or "month"
        // (optional) only on "StrikeUser"
        "until": "2023-03-11T18:02:13.178Z", // ISO date of when the strike ends
      }
    }
  ]
}
```

{% endtab %}

{% tab title="Send Message" %}
The `SendMessage` action is sent when a moderator sends a message to a user, or posts a reply to a piece of content, from the Lasso platform. Your webhook endpoint is responsible for actually delivering that message on your product (e.g. as a DM to the user or a reply under the content).

Messages are always initiated by a moderator, so `actor_id` is set (`rule_id` is never used for this action).

The `message` field contains the **final text to deliver** — any `{{user_name}}` / `{{moderator_name}}` Lasso has already substituted template variables, so you can deliver it verbatim.

```json
{
  "actions": [
    {
      "action_type": "SendMessage",
      "action_id": "clf10kbhp0012sauvpxlqsb6h", // The Lasso ID of the action
      "action_created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the action was taken
      "type": "user", // The type of object the message is sent to, "user" or "content"
      "message": "Hi Ada, please follow the community guidelines.", // The message to deliver, with variables already resolved
      "actor_id": "cldk3z9ze0004saiy542wfbck", // The Lasso ID of the moderator who sent the message
      // (optional) user is only sent when type === "user"
      "user": {
        "id": "cldk3z9ze0004saiy542wfbck", // The product's ID of the user to send the message to
        "tags": ["potential-spammer"] // Custom tags attached to the user
      },
      // (optional) content is only sent when type === "content" (a reply to that content)
      "content": {
        "id": "cldk3zadj019wsaiyudwdtxtr", // The product's ID of the content being replied to
        "created_at": "2023-03-11T15:02:13.178Z", // ISO date of when the content was created
        "user_id": "cldk3z9ze0004saiy542wfbck", // The ID of the user who sent the content (the reply recipient)
        "subcategory_id": "cldvl1z2l002xsaykyoje94od", // The ID of the subcategory the content is part of
        "category_id": "cldq51mh005fjsaw2y0fx3t5c" // The ID of the category the content is part of
        "tags": ["explicit-content"] // Custom tags attached to the content
      }
    }
  ]
}
```

{% endtab %}
{% endtabs %}

### Response&#x20;

The webhook does not expect a certain response, except for a valid `200` status code when action is handled by your product.

When the product does not respond a `200` status after all [retries](#retries) the action(s) will be automatically reverted in Lasso.

### Invalid actions

In case there is an invalid action taken (e.g. when an action leads to an error), you can revert the action(s). This will make sure the status of the object remains in sync between the product and Lasso. You can revert actions by returning a list of action ids.

{% code title="Webhook response" %}

```json
{
   revert: ["action_id_1","action_id_2"]
}
```

{% endcode %}

### Retries

In case the webhook fails and receives an error code (`3XX`, `4XX`, `5XX`), it will automatically be retried with exponential backoff. Lasso will try to deliver the webhook at most 5 times over the course of a minute.

### Security (optional, but recommended)

When Lasso Moderation sends a webhook to your server, it includes a digital signature that you can use to ensure that the payload has not been tampered with.&#x20;

To verify the signature, you need to compute a hash of the payload using a secret key that you share with Lasso Moderation. The secret key can be found under [settings](https://app.lassomoderation.com/settings) in the Lasso Moderation dashboard. The hash should be computed using the SHA-256 hashing algorithm.

Once you have computed the hash, you can compare it to the signature included in the `X-Lasso-Signature` header of the webhook request. If the two values match, you can be confident that the payload has not been modified in transit.

Here are some examples of how you might verify the signature of a webhook payload:

{% tabs %}
{% tab title="Javascript" %}

```javascript
import * as crypto from "crypto";

function verifySignature(
  payload, // body of the request
  signature, // X-Lasso-Signature from the header
): boolean {
  const secret = process.env.LASSO_WEBHOOK_SECRET // You need to set this environment variable.
  const hmac = crypto.createHmac("sha256", secret);
  const hash = hmac.update(payload).digest("base64");
  const expectedSignature = `sha256=${hash}`;
  return expectedSignature === signature;
}
```

{% endtab %}

{% tab title="Python" %}

```python
import hmac
import hashlib
import base64

def verify_signature(payload: str, signature: str) -> bool:
    """
    Verifies the signature of a webhook request payload.

    Args:
        payload (str): The request payload as a string.
        signature (str): The X-Lasso-Signature header value as a string.

    Returns:
        bool: True if the signature is valid, False otherwise.
    """
    # You need to set this environment variable.
    secret = os.environ['LASSO_WEBHOOK_SECRET'] 
    
    # Compute the HMAC digest of the payload using the secret and SHA256 algorithm
    hmac_digest = hmac.new(secret.encode('utf-8'), payload.encode('utf-8'), hashlib.sha256).digest()

    # Encode the HMAC digest using base64
    expected_signature = f'sha256={base64.b64encode(hmac_digest).decode("utf-8")}'

    # Compare the computed signature with the signature received in the header
    return expected_signature == signature
```

{% endtab %}

{% tab title="PHP" %}

```php
function verify_signature($payload, $signature) {
  /**
   * Verifies the signature of a webhook request payload.
   *
   * @param string $payload The request payload as a string.
   * @param string $signature The X-Lasso-Signature header value as a string.
   *
   * @return bool True if the signature is valid, False otherwise.
   */
  // You need to set this environment variable.
  $secret = getenv('LASSO_WEBHOOK_SECRET');
  
  // Compute the HMAC digest of the payload using the secret and SHA256 algorithm
  $hmac_digest = hash_hmac('sha256', $payload, $secret, true);

  // Encode the HMAC digest using base64
  $expected_signature = 'sha256=' . base64_encode($hmac_digest);

  // Compare the computed signature with the signature received in the header
  return $expected_signature === $signature;
}
```

{% endtab %}

{% tab title="Java" %}

```java
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class SignatureVerifier {

    /**
     * Verifies the signature of a webhook request payload.
     *
     * @param payload The request payload as a string.
     * @param signature The X-Lasso-Signature header value as a string.
     * @return True if the signature is valid, False otherwise.
     */
    public static boolean verifySignature(String payload, String signature) {
        // You need to set this environment variable.
        String secret = System.getenv("LASSO_WEBHOOK_SECRET");

        try {
            // Create a new Mac instance specifying the HMAC SHA256 algorithm
            Mac sha256HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256HMAC.init(secretKey);

            // Compute the HMAC digest of the payload using the secret
            byte[] hmacDigest = sha256HMAC.doFinal(payload.getBytes());

            // Encode the HMAC digest using base64
            String expectedSignature = "sha256=" + Base64.getEncoder().encodeToString(hmacDigest);

            // Compare the computed signature with the signature received in the header
            return expectedSignature.equals(signature);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
            return false;
        }
    }
}

```

{% endtab %}
{% endtabs %}

#### Other languages

Please reach out to <info@lassomoderation.com> in case you would like a code example in a different language.


# Rate Limits

To ensure fair use and maintain performance across our platform, we apply rate limits to specific actions such as content syncing, user creation, and content submission. These limits vary depending on your plan (free vs. paid) and can be customized for enterprise customers.

#### Standard Limits

| Action                              | Default Limit  |
| ----------------------------------- | -------------- |
| Content Create/Update               | 300 per minute |
| Content Create/Update Synchronously | 120 per minute |
| User Create/Update                  | 300 per minute |

> **Note:** Limits are subject to change. Enterprise customers can request custom rate limits via support.

#### Headers

All rate-limited responses include headers that provide visibility into your usage:

| Header                  | Description                                          |
| ----------------------- | ---------------------------------------------------- |
| `X-RateLimit-Limit`     | Total allowed requests in the current interval       |
| `X-RateLimit-Remaining` | Number of remaining requests in the current interval |
| `X-RateLimit-Reset`     | Milliseconds until the rate limit resets             |

#### Exceeding Limits

If a rate limit is exceeded, you’ll receive a `429 Too Many Requests` response:

```json
{
  "error": "Too many requests, check headers for limits"
}
```

Use the response headers to determine when you can retry your request.

#### Best Practices

* Implement client-side backoff based on the `X-RateLimit-Reset` header.
* Monitor rate-limiting headers in your integration to prevent service disruption.
* If you're regularly hitting limits, consider upgrading or contacting support for a custom plan.

#### Need Higher Limits?

Enterprise customers may configure custom rate limits per action. Reach out to your account representative to discuss your needs.


# URL Signing

Discover how URL signing enhances content security by providing temporary, secure access through seamlessly integrated signed URLs.

**What is URL Signing?**

URL signing is a security enhancement that restricts access to private content such as images, videos, or audio files. Instead of making content publicly accessible, signed URLs allow temporary, secure access by appending a signature to the URL. This ensures that only authorized users can view or download the content during a specified time window.

**Benefits of URL Signing**

* **Enhanced Security**: Protect sensitive content from unauthorized access.
* **Temporary Access**: Define how long the URL remains valid, limiting exposure.
* **Flexible Integration**: Supports multiple cloud storage providers, including AWS S3, Google Cloud Storage, and Azure Blob Storage.
* **Transparent Process**: Lasso seamlessly handles the signing process for your content, ensuring that secure URLs are automatically generated when needed.

***

**How URL Signing Works**

1. **Detection**: When content is sent to Lasso, the platform checks if it originates from a domain requiring signatures.
2. **Signing**: If signing is required, Lasso generates a signed URL using the credentials provided in your integration settings.
3. **Usage**: The signed URL is used to analyze the content and display it securely in the dashboard.
4. **Regeneration**: Signed URLs are not stored and are regenerated upon expiration, ensuring ongoing security.

***

#### Setting Up URL Signing

To set up URL signing for your content, follow the steps for your preferred cloud provider. Each provider requires specific credentials and configuration. Use the links below to navigate to the setup instructions:

* [AWS S3 URL Signing](/developers/url-signing/aws-s3-url-signing)
* [GCP Storage URL Signing](/developers/url-signing/gcp-storage-url-signing)
* [Azure Storage Blob URL Signing](/developers/url-signing/azure-storage-blob-url-signing)
* Looking for another cloud provider? Reach out to <support@lassomoderation.com> and we can help you out.


# AWS S3 URL Signing

Set up AWS S3 with Lasso to enable automatic URL signing for secure and temporary access to your private content.

Our AWS S3 URL signing integration allows you to securely sign URLs for content stored in your S3 buckets. We use AWS AssumeRole to temporarily access your S3 resources without requiring long-term credentials. Follow these steps:

#### **Step 1: Create an IAM Role**

1. Please reach out to our support for our AWS account ID.
2. Create a new IAM role with the following custom trust policy, make sure to replace the account ID and external ID:

   ```json
   {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": {
                   "AWS": "arn:aws:iam::{AWS account ID Lasso}:root"
               },
               "Action": "sts:AssumeRole",
               "Condition": {
                   "StringEquals": {
                       "sts:ExternalId": "{random string, min 20 characters. See Lasso UI to generate external ID.}"
                   }
               }
           }
       ]
   }
   ```
3. Create a new policy and assign the following minimum policy to allow Lasso to generate signed URLs:

   ```json
   {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject"
               ],
               "Resource": "arn:aws:s3:::{your-image-bucket}/*"
           }
       ]
   }
   ```
4. Assign the policy to the role.
5. Copy the **ARN** of the newly created role, e.g. `arn:aws:iam::1234567890987:role/LassoModerationBucketAccess`

#### **Step 2: Add Signing Information in Lasso**

1. Navigate to **Settings → Integrations** in Lasso.
2. Select **AWS S3** and fill in the following fields:
   * **Domain**: The domain where your content resides (e.g., `https://your-image-bucket.s3.amazonaws.com`).
   * **Region**: The AWS region of your bucket.
   * **Bucket**: The name of your S3 bucket. (e.g., `your-image-bucket`)
   * **Role ARN**: The **ARN** of the newly created role.
   * **External ID**: The **External ID** you used when creating the role.
   * **TTL**: The time-to-live for the signed URL (minimum 15 minutes). This is the amount of time a URL will be valid for.
   * **Example URL**: Provide an example URL to validate your credentials.

#### **Step 3: Automatic Signing for AWS S3 Content**

Once the integration is set up:

* Any content from the specified **Domain** (e.g., `https://your-image-bucket.s3.amazonaws.com`) will automatically be signed by Lasso when required.
* Lasso dynamically generates a signed URL whenever it needs to access the content, ensuring secure and temporary access.
* This signed URL is used for analyzing the content or displaying it securely in the dashboard. You do not need to update or manage URLs manually.
* If the signed URL expires, Lasso regenerates it automatically when the content is accessed again.


# GCP Storage URL Signing

Configure Google Cloud Storage with Lasso to automatically generate signed URLs for secure access to your GCS content.

Google Cloud Storage URL Signing integration allows you to sign URLs for content stored in GCS buckets. Follow these steps:

#### **Step 1: Create a Service Account**

1. Follow [this guide](https://cloud.google.com/iam/docs/service-accounts-create) to create a service account in Google Cloud or use an existing account.
2. Assign the `roles/storage.objectViewer` role to the service account. This role allows read access to objects in your bucket.
3. Generate a key for the service account and download the JSON key file. You’ll need this file for the next steps.

#### **Step 2: Add Signing Information in Lasso**

1. Navigate to **Settings → Integrations** in Lasso.
2. Select **Google Cloud Storage** and provide the following details:
   * **Domain**: The domain where your content resides (e.g., `https://storage.googleapis.com/your-bucket`).
   * **Bucket**: The name of your bucket.
   * **Service Account Key**: Upload the JSON key file for the service account.
   * **TTL**: The time-to-live for the signed URL (minimum 15 minutes).
   * **Example URL**: Provide an example URL to validate your credentials.

#### **Step 3: Automatic Signing for Google Cloud Storage Content**

After completing the setup:

* All content originating from the specified **Domain** (e.g., `https://storage.googleapis.com/your-bucket`) will be signed automatically by Lasso when accessed.
* Lasso uses the provided **Service Account Key** to generate a secure, time-limited signed URL dynamically.
* This signed URL ensures secure access during analysis and dashboard display, without exposing your private content.
* Expired URLs are seamlessly regenerated as needed, requiring no manual intervention.


# Azure Storage Blob URL Signing

Integrate Azure Blob Storage with Lasso to enable automatic signed URLs for secure and time-limited access to your content.

Azure Blob Storage URL Signing integration enables signing URLs for content stored in Azure blob containers. Follow these steps:

#### **Step 1: Create an Azure Storage Account and Configure Access**

1. Follow [this guide](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-create) to create a storage account in Azure or use an existing account.
2. Obtain the **Access Key** for your storage account:
   * Go to your storage account in the Azure portal.
   * Navigate to **Access keys** under **Settings**.
   * Copy one of the **Access keys** and note the **Storage account name**.

#### **Step 2: Add Signing Information in Lasso**

1. Navigate to **Settings → Integrations** in Lasso.
2. Select **Azure Blob Storage** and fill in the following fields:
   * **Domain**: The domain where your content resides (e.g., `https://youraccount.blob.core.windows.net`).
   * **Account Name**: The name of your Azure storage account.
   * **Access Key**: The key for your Azure storage account.
   * **Container**: The name of the blob container.
   * **TTL**: The time-to-live for the signed URL (minimum 15 minutes).
   * **Example URL**: Provide an example URL to validate your credentials.

#### **Step 3: Automatic Signing for Azure Blob Storage Content**

Once configured:

* All content from the specified **Domain** (e.g., `https://youraccount.blob.core.windows.net`) will be signed automatically by Lasso.
* Lasso uses the **Account Name** and **Access Key** to generate a secure, temporary signed URL for any required content.
* Signed URLs are used to securely access the content for analysis and dashboard display without making the content public.
* When a signed URL expires, Lasso regenerates it on demand, ensuring continuous secure access without additional setup.


# Laravel URL Signing

Sign media URLs with your Laravel application's signing key so Lasso can securely display your private content.

Our Laravel URL signing integration allows Lasso to securely access media that your Laravel application serves behind signed URLs. Lasso signs URLs the same way Laravel's `URL::temporarySignedRoute` does, so your application can validate them with `$request->hasValidSignature()`. No credentials are exchanged at request time, your application stays in control of every download.

{% hint style="info" %}
URL signing is available as an add-on. Contact us to enable it for your workspace.
{% endhint %}

#### **Step 1: Prepare Your Laravel Application**

1. Serve your media through a route that validates signed URLs, for example:

   ```php
   Route::get('/media/{path}', [MediaController::class, 'show'])
       ->where('path', '.*')
       ->middleware(ValidateSignature::class);
   ```

   The route must allow both **GET** and **HEAD** requests. Lasso uses HEAD requests to check content before downloading it.
2. Choose the signing key you will share with Lasso. This can be your `APP_KEY`, but we recommend a dedicated key so you do not have to share your application key. On Laravel 11 and newer, register a key resolver that returns both keys, so your own signed routes (password resets, unsubscribe links) keep working:

   ```php
   // app/Providers/AppServiceProvider.php
   public function boot(): void
   {
       URL::setKeyResolver(fn () => [
           config('app.key'),
           config('services.lasso.signing_key'),
       ]);
   }
   ```

   On Laravel 10 and older the key resolver returns a single key, so either share your `APP_KEY` or validate the Lasso key in middleware scoped to the media route.

{% hint style="warning" %}
The signing key is used exactly as written. If your key starts with `base64:`, that prefix is part of the key, Laravel never decodes it. Copy the key verbatim when adding it to Lasso.
{% endhint %}

#### **Step 2: Add Signing Information in Lasso**

1. Navigate to **Settings → Integrations** in Lasso.
2. Select **Laravel Signatures**, click **New signature** and fill in the following fields:
   * **Domain**: The domain where your content resides (e.g. `https://media.your-platform.com`). Every URL on this domain will be signed.
   * **Signing key**: The key your application validates signed URLs with. It is stored encrypted and never shown again, only a masked hint appears in the dashboard.
   * **TTL**: The time-to-live for the signed URL (minimum 15 minutes). This is the amount of time a URL will be valid for.
   * **Example URL**: Provide an example URL on your domain. Lasso signs it and requests it with GET and HEAD to verify your application accepts the signature. The signature is only saved when both requests succeed.

<figure><img src="/files/EAAgWhk0ZjngK1pydHx4" alt=""><figcaption></figcaption></figure>

#### **Step 3: Automatic Signing for Your Content**

Once the integration is set up:

* Any content from the specified **Domain** will automatically be signed by Lasso when required.
* Lasso appends two query parameters to the URL: `expires` (a Unix timestamp) and `signature` (a lowercase hex HMAC-SHA256 over the URL, computed the same way Laravel computes it). Existing query parameters are preserved.
* The signed URL is used for analyzing the content or displaying it securely in the dashboard. You do not need to update or manage URLs manually.
* If the signed URL expires, Lasso regenerates it automatically when the content is accessed again.


# DSA Compliance

The **Digital Services Act (DSA)** introduces obligations for online platforms to ensure transparency, accountability, and compliance around content moderation decisions. One of the requirements is that platforms must **report moderation actions** to the [DSA Transparency Database](https://transparency.dsa.ec.europa.eu/).

The reports must include structured information about why content or a user was restricted, along with metadata such as the territorial scope, the applicable terms of service, and categorization of the policy.

You can explore the reporting requirements and examples of reports from other platforms directly in the [DSA Transparency Database](https://transparency.dsa.ec.europa.eu/).


# Setup

#### 2.1 Credentials

Before you can send reports, you need credentials from the DSA Transparency Database.

1. Request credentials from the DSA team. See [onboarding documentation](https://transparency.dsa.ec.europa.eu/page/onboarding-documentation) for more information.
2. Go to [Compliance Settings](https://app.lassomoderation.com/settings/compliance).
3. Add new credentials:
   * **Environment**: `sandbox` or `production`. Use the sandbox environment for testing to validate reports before switching to production.
   * **API tokens**: The credentials you obtained in step 1.
   * **Terms of Service**: A URL pointing to your terms and conditions.
   * **Territorial scope**: By default, all countries in the European Economic Area (EEA) are included. You can limit this to specific countries if needed.
   * **Categories**: If you manage multiple brands under one workspace, you can configure separate credentials per category. Otherwise, select **Use credentials for all categories**.

#### 2.2 Reports per policy

Once credentials are configured, you can enable automatic reporting per policy category.

1. Go to [Policies](https://app.lassomoderation.com/policies)
2. Select the **policy category** you want to send reports for.
3. Choose the policy type: `user` or `content`. Reporting requires a policy to be explicitly marked as one of these types.
4. Enable **DSA reporting for this policy**.
5. Fill in the required fields. Details about these fields can be found in the [DSA API documentation](https://transparency.dsa.ec.europa.eu/page/api-documentation#statement-attributes). For inspiration, check out example reports at the [Transparency Database](https://transparency.dsa.ec.europa.eu/statement).
6. Done! Any time a user or piece of content is removed/banned under this policy, a report will automatically be created.
7. Go to the [Compliance Overview](https://app.lassomoderation.com/compliance) to view all pending/submitted reports.


# Reporting Exceptions

We do not automatically submit reports in the following cases:

#### 3.1 User types

Reports are only submitted for regular users. Actions against users marked as `admin`, `moderator`, `trusted`, or `testing` are excluded. The type of user can be determined via the `type` field:

* [User creation with `type` ](https://api-reference.lassomoderation.com/operation/operation-post-user#operation-post-user-body-application-json-user-type)

#### 3.2 Unpublished content/users

If a user or content item is not yet **published**, no report will be sent. Learn more about publishing via our API:

* [User creation with `published_at`](https://api-reference.lassomoderation.com/operation/operation-post-user#operation-post-user-body-application-json-user-published_at)
* [Publishing a user](https://api-reference.lassomoderation.com/operation/operation-publish-user)

#### 3.3 User location

Reports are only submitted for users located within the **territorial scope** you defined. The location is determined via the `country_code` field:

* [User creation with ](https://api-reference.lassomoderation.com/operation/operation-post-user#operation-post-user-body-application-json-user-country_code)[`country_code`](https://api-reference.lassomoderation.com/operation/operation-post-user#operation-post-user-body-application-json-user-country_code)

#### 3.4 Overwritten reports

Reports are initially created as pending and automatically submitted after a period of time. When a moderator makes a mistake or overwrites a previous decision, these reports will automatically be cancelled and not submitted.


