UGC Moderate Message

Beta feature

Auto Moderation is currently in beta and available upon request. It may be subject to change and is not recommended for production use without testing. To get access, contact PubNub Support or Sales.

The ugc.moderateMessage API itself isn’t gated, but it relies on an Auto Moderation configuration (configId) created in BizOps Workspace. To use it, ensure Auto Moderation is enabled on your account and a configuration is set up. See Auto Moderation for setup details.

The ugc.moderateMessage module provides a simple, extensible API to moderate user-generated content from within your Function. It wraps an internal moderation service and returns actionable results you can use to block, mask, or otherwise handle content before it is published.

The module lets you add message moderation logic (like word masking or marking messages as spam) by embedding a simple API call within your Function code.

To apply moderation edits or message blocking before a given message is published, you must use a Before Publish or Fire Function type. However, using this API from other Function types is possible and may make sense depending on your channel topology and moderation needs.

It's particularly useful when you already have a Before Publish or Fire Function running on a given channel - since you cannot have two Functions of such type running in parallel on a channel, you cannot create an automatic Auto Moderation Function of type Before Publish or Fire that would handle moderation for you. Instead, you can use Auto Moderation to define the moderation behavior (as configuration) and embed this logic in your currently running Before Publish or Fire Function.

To use this module, you must provide configId—the ID of the moderation configuration you create in BizOps Workspace’s Auto Moderation.

For more information on the ugc.moderateMessage module and BizOps dependencies, refer to the Auto Moderation section.

Import

const ugc = require('ugc');

API

function moderateMessage(req: ModerateMessageRequest): Promise<ModerateMessageResponse>

Input

Provide a ModerateMessageRequest object with the following fields:

FieldTypeRequiredDescription
configId
string
Yes
String (UUID in the uuidv4 version). The ID of your configuration generated by Auto Moderation when defining the moderation behavior (like word masking or AI spam).
message
JSON
Yes
Pass the full publish body. By default, policies look for user text in the top‑level text field, but this is configurable in Auto Moderation. Always send the complete payload so your configuration can extract the right fields.
channel
string
Yes
Channel the message is being published to.
userId
string
Yes
User ID (the uuid parameter) of the publisher.
meta
JSON
No
Optional meta object, like "meta": {"example": "test"}; in Functions this arrives as stringified JSON.

Output

The call returns a ModerateMessageResponse object with the following fields:

FieldTypeRequiredDescription
moderationId
string
Yes
Unique ID for auditing and correlation.
flagged
boolean
Yes
True if any moderation rule was triggered.
actions
string[]
Yes
Actions to take (configuration‑defined), for example: ["block", "mask"/"wordMasked", "report"].
categories
Record<string, CategoryResult>
Yes
Per-category results returned as structured CategoryResult objects.
transform
object
No
Suggested changes to apply. May be an empty object when no changes are needed.
→ message
JSON
No
Message with masks/edits applied.
→ meta
JSON
No
Meta augmented with moderation fields (for example, report identifiers).

CategoryResult

FieldTypeRequiredDescription
flagged
boolean
Yes
Whether this category triggered.
details
object
No
Category-specific details.
→ maskedWords
string[]
No
Present for word-list violations.

Example:

const spam = response.categories.spam; // CategoryResult
const isSpam = spam?.flagged === true;

Usage

The following example shows how to apply the moderation result inside a Before Publish or Fire Function:

export default (request) => {
const ugc = require('ugc');

const metaFromClient = typeof request.params.meta === 'string' ? JSON.parse(request.params.meta) : request.params.meta;

return ugc.moderateMessage({
configId: '<YOUR_MODERATION_CONFIG_ID>', // Moderation config ID (generated by Auto Moderation), like a088649f-cf9d-451c-b6c3-abc1908fc03a
message: request.message, // message body from the publish
userId: request.params.uuid, // publish UUID set by the client
channel: request.channels[0], // channel the message is being published to
meta: metaFromClient, // Functions passes meta as a string; parse to JSON before sending
}).then((res) => {
if (res.flagged && res.actions.includes('block')) {
request.status = 403;
return request.abort('Flagged');
show all 24 lines

Example responses

Unflagged content:

{
"moderationId": "c3b0...",
"flagged": false,
"actions": [],
"categories": { "spam": { "flagged": false }}
}

Flagged content (mask and block):

{
"moderationId": "a1f2...",
"flagged": true,
"actions": ["block", "wordMasked"],
"categories": {
"spam": { "flagged": true },
"wordMasking": { "flagged": true, "details": { "maskedWords": ["word"] } }
},
"transform": {
"message": { "text": "spam spam ****" },
"meta": { "reportTimetoken": "17551044120707427" }
}
}

Validation and errors

The tables below summarize input validation rules and how service and network errors are handled.

Validation (inputs)

FieldConditionError message
configId
Missing
configId must be provided
message
Undefined or null
message must be provided
channel
Missing or not a string
channel must be provided and must be a string
userId
Missing or not a string
userId must be provided and must be a string

Errors (service and transport)

ScenarioBehavior/ResultNotes
Moderation API non-2xx
Promise resolves with parsed error body when available (for example, error)
Built-in retries (default 3)
Network/transport failure
Promise rejects
Counts toward XHR-per-execution

Behavior and limits

These runtime characteristics apply when you call ugc.moderateMessage() from a Function:

  • Moderation policy is defined outside your code - in the Auto Moderation configuration. When the policy changes, you don't need to change your Function—just keep referencing the same configId, or update it if you switch to a different policy.
  • The underlying transport includes built-in retries (default 3).
  • Moderation calls count toward your Function's XHR requests per execution. By default, a Function can make a total of 5 XHR calls per execution (combined internal and regular).

Auto Moderation

The ugc.moderateMessage module and BizOps‑managed Auto Moderation use the same backend and the same pre‑provisioned configurations (identified by configId). This ensures that decisions, actions, and audit IDs remain consistent regardless of which approach you use.

When to choose which approach:

  • Use the ugc.moderateMessage module when you already have a Before Publish or Fire Function and want to evaluate moderation and take action in that same Function with a single call. Read the docs for detailed steps.
  • Use BizOps‑managed Auto Moderation when you prefer PubNub to provision and maintain a dedicated moderation Function for you.
Before Publish or Fire constraint

There can be only one Before Publish or Fire Function per channel on a given keyset. You cannot run a BizOps‑managed Auto Moderation Function and your own Before Publish or Fire Function on the same channel at the same time.

Migration and edge cases:

  • If you currently use BizOps Auto Moderation and need custom logic on those channels, consolidate into a single Before Publish or Fire Function that calls ugc.moderateMessage and implements your logic, then ask BizOps to disable their managed Function for those channels.
  • If you need additional processing that doesn’t have to block messages, add an After Publish or Fire Function for post‑processing; it cannot block or modify the message before delivery.

Best practices

These tips help you implement moderation predictably and keep your Function future‑proof:

  • Always check response.actions to enforce block/mask before publishing.
  • Apply response.transform if present to ensure consistent masking and report handling.
  • Parse request.params.meta to JSON before calling; stringify it when assigning back to request.params.meta after transforms.
  • For category-specific behavior, check response.categories["<name>"].flagged.
Last updated on