Content APIs

1. Overview

This page contains the APIs that are used to send content to CleanSpeak for moderation and filtering. Here are the APIs:

Note: Null values in JSON are not allowed on any of the CleanSpeak APIs. If you are looking to pass in a null value, simply omit it from your request instead. This will allow Passport to handle default values correctly.

2. Moderate Content

This API is used to send new content to CleanSpeak to be moderated. To make updates to content that has already been sent into CleanSpeak use the Update Content API.

Like the Filter Content API the same filtering is performed on content sent to this API. The difference is that instead of returning all matches found in the content, the Application filter rules are first applied to determine what action should be taken. Using this API allows you to modify the filter behavior without changing the way you send content to the filter. This allows for a much more powerful integration.

Important At least one Application must be configured prior to sending content to the Moderate API. See the Applications setup page for details on configuring applications with the Management Interface or the Application API.

Transient vs Persistent Content

CleanSpeak will store all content whether it is transient or persistent so long as the Store Content? configuration is enabled for the Application. The difference in the two content types is whether the content is eligible for moderation. Moderation actions include placing the content in an Approval Queue or editing/deleting the content after it’s been published.

Transient content is not be eligible for moderation but the user that generated the content can be moderated (actioned). The most common example of transient content is real-time chat, which disappears from the users' perspectives after a short amount of time. This type of content can’t be edited or deleted since it disappears so quickly. Also, the real-time nature of chat means it would never require pre-approval.

Persistent content such as forum posts must include a content ID (UUID) in order for CleanSpeak to communicate content moderation events back to the client application with the Notification System.

2.1. Request

For Transient content, do not provide a unique identifier on the API request, CleanSpeak will generate this on your behalf.

URI

POST /content/item/moderate

For persistent content you will need to provide a unique identifier (UUID) on the API request. When using this API with persistent content you’ll need to first ensure your Application configuration is set to Persistent Content Type. If you have not done this the API request will fail with an error message indicating you have not yet configured your Application.

URI

POST /content/item/moderate/{contentItemId}

Table 1. Request Parameters

contentItemId [UUID] Required

The Id of the Content Item.

Table 2. Request Body

content [Object] Required

The piece of content being moderated.

content.applicationId [UUID] Required

The Id of the application that corresponds to the content source.

content.createInstant [Long] Required

The instant that the content was generated.

content.location [String] Optional

Specifies the location within the application that the content was generated. For example, you might use a chat room name, area Id for a game, or a thread Id for a forum. This parameter is used by CleanSpeak to display conversational views of content with the [Context View] feature.

content.parts [Array] Required

An array that contains one to many content parts. If your content only has a single part, such as a chat message, the array will only contain a single text entry. The reason you would send in multiple content parts within a single request is to ensure the moderation decision affects each part.

For example, you may send in an image for moderation, the image has a title and a description field. You would send this to CleanSpeak with three content parts, the image and two text parts. If the content of the image title is rejected the entire content needs to be rejected wholesale, the title, description and the image. In this case it would make sense to treat all three parts as an atomic unit of content.

If individual content parts are not related and can be rejected or approved separately then you should send them to CleanSpeak as separate requests.

content.parts[x].content [String] Required

The content to be filtered. The content type will indicate what type of content is expected in this parameter.

Content Types

Type Description

text

The content to be filtered.

bbcode

Text content to be filtered that may contain BBCode.

html

Text content to be filtered that may contain HTML. Available Since 3.19.0

attribute

A simple attribute of the content. This is an arbitrary string and will not be filtered.

hyperlink

Fully qualified URL to an external web page.

image

Fully qualified URL of the image to be displayed.

video

Fully qualified URL of the video to be displayed.

audio

Fully qualified URL of the audio file to be moderated.

content.parts[x].name [String] Optional

The name of the content part. This value is optional an intended to better identify the context when you have more than one content part. For example this could be Title, Message Body or Image.

content.parts[x].type [String] Required

The type of this content part. Possible values:

  • text

  • bbcode

  • html Available Since 3.19.0

  • attribute

  • hyperlink

  • image

  • video

  • audio

content.receiverDisplayName [String] Optional

The display name of the user that received the content. This parameter should only be set if this piece of content was a private message between two users.

content.receiverId [UUID] Optional

The Id of the user that received of the content. This parameter should only be set if this piece of content was a private message between two users.

content.senderDisplayName [String] Optional

The display name (username or whatever is displayed to other users in the game/forum) that generated the content.

content.senderId [UUID] Required

The Id of the user that generated the content. This parameter is required so that CleanSpeak can analyze and associate the content with the user that generated it.

moderation [String] Optional

Tells CleanSpeak to forcibly put the content into a queue (Approval, User Alert or Content Alert). This overrides the configuration you have setup for the Application in the Management Interface.

  • requiresApproval

  • generatesAlert

  • generatesContentAlert

Example Request JSON
{
  "content": {
    "applicationId": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
    "createInstant": 13405983821,
    "location": "threadId_42",
    "parts": [
      {
        "content": "Smurf off",
        "name": "Body",
        "type": "text"
      }
    ],
    "senderDisplayName": "PapaSmurf",
    "senderId": "f6d3df91-ed4b-48ad-810f-05a367d328c2"
  }
}

2.2. Response

Table 3. Response Codes
Code Description

200

The request was successful. The response will contain a JSON body.

400

The request was invalid and/or malformed. The response will contain an Errors JSON Object with the specific errors.

401

You did not supply a valid Authorization header. The header was omitted or your API key was not valid. The response will be empty. See Authentication.

402

Your license has expired. The response will be empty. Contact sales@inversoft.com for assistance.

500

There was an internal error. A stack trace is provided and logged in the CleanSpeak log files. The response will be empty.

Table 4. Response Body

content [Object]

The piece of content being moderated.

content.id [UUID]

The id of the piece of content. This might have been passed in on the request or generated by CleanSpeak.

content.parts [Array]

The list of parts of content.

content.parts[x].imageConfidence [Integer]

The confidence level of an image result (if the part was an image). The confidence is on a scale of 0 to 100 and is largely dependent on the image api in use.

content.parts[x].name [String]

The name of the part of the content.

content.parts[x].replacement [String]

The replacement text generated by CleanSpeak after applying the filter rules to this part.

contentAction [String]

The action that the client should take with the content. Possible values:

Content Actions

Action Description

allow

The content should be allowed.

authorOnly

The content should be allowed but only the author of the content should be allowed to view the content.

replace

The content should be allowed, but utilize the replacement text provided in the response.

queuedForApproval

The content has been queued for approval and should not be displayed to other users until it has been approved by a moderator.

reject

The content should be rejected.

moderationAction [String]

The action that was taken on the content. Possible values:

  • requiresApproval

  • generatesAlert

  • generatesContentAlert

stored [Boolean]

This value indicates if the content was stored by CleanSpeak.

Example Response JSON
{
  "content": {
    "id": "99f2c4e8-961a-4a34-b9b9-43fc3f3b43ec"
  },
  "contentAction": "allow",
  "moderationAction": "generatesAlert",
  "stored": true
}
Example Response JSON with replacements
{
  "content": {
    "id": "99f2c4e8-961a-4a34-b9b9-43fc3f3b43ec",
    "parts" : [{
      "name" : "body",
      "replacement" : "**** off"
    }]
  },
  "contentAction": "replace",
  "moderationAction": "generatesAlert",
  "stored": true
}

3. Update Content

This API is used to send updates to existing content to CleanSpeak to be moderated. Only persistent content can be updated in CleanSpeak.

Like the Filter Content API the same filtering is performed on content sent to this API. The difference is that instead of returning all matches found in the content, the Application filter rules are first applied to determine what action should be taken. Using this API allows you to modify the filter behavior without changing the way you send content to the filter. This allows for a much more powerful integration.

3.1. Request

You need to provide the unique identifier (UUID) of the content being updated on the API request.

URI

PUT /content/item/moderate/{contentItemId}

Table 5. Request Parameters

contentItemId [UUID] Required

The Id of the Content Item.

Table 6. Request Body

content [Object] Required

The piece of content being moderated.

content.applicationId [UUID] Required

The Id of the application that corresponds to the content source.

content.createInstant [Long] Required

The instant that the content was generated.

content.location [String] Optional

Specifies the location within the application that the content was generated. For example, you might use a chat room name, area Id for a game, or a thread Id for a forum. This parameter is used by CleanSpeak to display conversational views of content with the [Context View] feature.

content.parts [Array] Required

An array that contains one to many content parts. If your content only has a single part, such as a chat message, the array will only contain a single text entry. The reason you would send in multiple content parts within a single request is to ensure the moderation decision affects each part.

For example, you may send in an image for moderation, the image has a title and a description field. You would send this to CleanSpeak with three content parts, the image and two text parts. If the content of the image title is rejected the entire content needs to be rejected wholesale, the title, description and the image. In this case it would make sense to treat all three parts as an atomic unit of content.

If individual content parts are not related and can be rejected or approved separately then you should send them to CleanSpeak as separate requests.

content.parts[x].content [String] Required

The content to be filtered. The content type will indicate what type of content is expected in this parameter.

Content Types

Type Description

text

The content to be filtered.

bbcode

Text content to be filtered that may contain BBCode.

html

Text content to be filtered that may contain HTML. Available Since 3.19.0

attribute

A simple attribute of the content. This is an arbitrary string and will not be filtered.

hyperlink

Fully qualified URL to an external web page.

image

Fully qualified URL of the image to be displayed.

video

Fully qualified URL of the video to be displayed.

audio

Fully qualified URL of the audio file to be moderated.

content.parts[x].name [String] Optional

The name of the content part. This value is optional an intended to better identify the context when you have more than one content part. For example this could be Title, Message Body or Image.

content.parts[x].type [String] Required

The type of this content part. Possible values:

  • text

  • bbcode

  • html Available Since 3.19.0

  • attribute

  • hyperlink

  • image

  • video

  • audio

content.receiverDisplayName [String] Optional

The display name of the user that received the content. This parameter should only be set if this piece of content was a private message between two users.

content.receiverId [UUID] Optional

The Id of the user that received of the content. This parameter should only be set if this piece of content was a private message between two users.

content.senderDisplayName [String] Optional

The display name (username or whatever is displayed to other users in the game/forum) that generated the content.

content.senderId [UUID] Required

The Id of the user that generated the content. This parameter is required so that CleanSpeak can analyze and associate the content with the user that generated it.

moderation [String] Optional

Tells CleanSpeak to forcibly put the content into a queue (Approval, User Alert or Content Alert). This overrides the configuration you have setup for the Application in the Management Interface.

  • requiresApproval

  • generatesAlert

  • generatesContentAlert

Example Request JSON
{
  "content": {
    "applicationId": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
    "createInstant": 13405983821,
    "location": "threadId_42",
    "parts": [
      {
        "content": "Smurf off",
        "name": "Body",
        "type": "text"
      }
    ],
    "senderDisplayName": "PapaSmurf",
    "senderId": "f6d3df91-ed4b-48ad-810f-05a367d328c2"
  }
}

3.2. Response

Table 7. Response Codes
Code Description

200

The request was successful. The response will contain a JSON body.

400

The request was invalid and/or malformed. The response will contain an Errors JSON Object with the specific errors.

401

You did not supply a valid Authorization header. The header was omitted or your API key was not valid. The response will be empty. See Authentication.

402

Your license has expired. The response will be empty. Contact sales@inversoft.com for assistance.

500

There was an internal error. A stack trace is provided and logged in the CleanSpeak log files. The response will be empty.

Table 8. Response Body

content [Object]

The piece of content being moderated.

content.id [UUID]

The id of the piece of content. This might have been passed in on the request or generated by CleanSpeak.

content.parts [Array]

The list of parts of content.

content.parts[x].imageConfidence [Integer]

The confidence level of an image result (if the part was an image). The confidence is on a scale of 0 to 100 and is largely dependent on the image api in use.

content.parts[x].name [String]

The name of the part of the content.

content.parts[x].replacement [String]

The replacement text generated by CleanSpeak after applying the filter rules to this part.

contentAction [String]

The action that the client should take with the content. Possible values:

Content Actions

Action Description

allow

The content should be allowed.

authorOnly

The content should be allowed but only the author of the content should be allowed to view the content.

replace

The content should be allowed, but utilize the replacement text provided in the response.

queuedForApproval

The content has been queued for approval and should not be displayed to other users until it has been approved by a moderator.

reject

The content should be rejected.

moderationAction [String]

The action that was taken on the content. Possible values:

  • requiresApproval

  • generatesAlert

  • generatesContentAlert

stored [Boolean]

This value indicates if the content was stored by CleanSpeak.

Example Response JSON
{
  "content": {
    "id": "99f2c4e8-961a-4a34-b9b9-43fc3f3b43ec"
  },
  "contentAction": "allow",
  "moderationAction": "generatesAlert",
  "stored": true
}
Example Response JSON with replacements
{
  "content": {
    "id": "99f2c4e8-961a-4a34-b9b9-43fc3f3b43ec",
    "parts" : [{
      "name" : "body",
      "replacement" : "**** off"
    }]
  },
  "contentAction": "replace",
  "moderationAction": "generatesAlert",
  "stored": true
}

4. Filter Content

This API is used to send content to CleanSpeak to be filtered. Content sent to this API is not persisted by CleanSpeak and does not use the CleanSpeak Application filter rules. To use Application filter rules and other more advanced features of CleanSpeak see Moderate Content.

This API should be avoided unless you have a very specific need to only perform filtering and want all of the filter matches back. For most situations, the Moderate Content API should be used instead.

4.1. Request

URI

POST /content/item/filter

Table 9. Request Body

blacklist [Object] Optional

Object that defines the blacklist filter options.

blacklist.dictionaryTags [Array<String>] Optional

A list of dictionary tags to apply to the filter.

Any tags added here will allow dictionary entries with the same tag to behave as a whitelist if there is an EXACT match on the word.

blacklist.disabled [Boolean] Optional defaults to false

This parameter disables the blacklist filter completely. No blacklist matches will be returned and the replacement value will not contain replacements for blacklist matches. When this parameter is set to true all other nested blacklist parameters will be ignored.

blacklist.ignorableCharacters [String] Optional defaults to "qxz" Available since 3.22.0

Set this parameter to a list of characters the filter can skip over to find a match. Only the letters a through z are permitted.

Specifically, this feature will catch any blacklist word even if separated by a single character on this list. Example: SxMxUxRxF Note: only the same letter may be used to separate the characters throughout the word and only one ignored character in a row is permitted.

blacklist.locales [Array<String>] Optional

This parameter specifies the locales that blacklist filter matches must have in order to be included in the response. When this parameter is omitted all matches will be returned regardless of locale. See Locales.

blacklist.minimumSeverity [String] Optional

This parameter specifies the minimum severity that blacklist filter matches must have to be included in the response. When this parameter is omitted all matches will be returned regardless of severity. Possible values:

  • mild

  • medium

  • high

  • severe

blacklist.tags [Array<String>] Optional Available since 3.12.0

This parameter specifies the tags that blacklist filter matches must have to be included in the response.

content [String] Required

The message body to be filtered.

characters [Array<String>] Optional

This parameter specifies the individual characters to find within the content string.


Example Parameter "characters": ["A", "❢", "§"]

contentType [String] Optional defaults to text

This parameter specifies the content type. When this parameter is omitted the API will default to text. Possible values:

  • text

  • bbcode

  • html Available Since 3.19.0

Prior to version 3.19.0, the content type was auto-detected when then content type was not specified.

emails [Object] Optional

Object that defines the email filter options.

emails.disabled [Boolean] Optional defaults to false

This parameter disables the email filter completely. No email matches will be returned and the replacement value will not contain replacements for email matches. When this parameter is set to true all other nested email parameters will be ignored.

emails.domainQuality [Array] Optional

The list of domain quality configurations for the Email filter. Providing domain quality you may override the default behavior. CleanSpeak already adjusts domain scores of domain names that are also dictionary words such as .design and .photo. You may manually provider a lower score for a domain by providing a configuration.


Example Parameter "domainQuality": [{"domain": "chat", "quality": 0.5}]

emails.domainQuality[x].domain [String] Required

This parameter is the name of the domain. For example, for the .chat domain name, you would set this parameter to chat.

emails.domainQuality[x].quality [Double] Required

This parameter sets the initial quality score for the specified domain. This value may be between 0 and 1. See Quality Score.

emails.maximumMatchLength [Integer] Optional defaults to 50

This parameter specifies the maximum length that a match can be in order to be considered an email. If the match length is greater than the maximum match length the match will be ignored.

emails.minimumQuality [Double] Optional

This parameters specifies the minimum quality score that email matches must have to be included in the response and replaced in the replacement value.

emails.spacePenalty [Double] Optional defaults to -0.05

This parameter specifies a penalty applied to the quality score if the match contains any spaces. For example, user@ example.com contains a space so the space penalty value will be added to the quality score. The email space penalty is applied once regardless of the number of spaces found in the match.

phoneNumbers [Object] Optional

Object that defines the phone number filter options.

phoneNumbers.disabled [Boolean] Optional defaults to false

This parameter disables the phone number filter completely. No phone number matches will be returned and the replacement value will not contain replacements for phone number matches. When this parameter is set to true all other nested phoneNumbers parameters will be ignored.

phoneNumbers.maximumMatchLength [Integer] Optional defaults to 20

This parameter specifies the maximum length that a match can be in order to be considered an phone number. If the match length is greater than the maximum match length the match will be ignored.

phoneNumbers.minimumMatchLength [Integer] Optional defaults to 7

This parameter specifies the minimum length that a match can be in order to be considered a phone number. The default value covers most world wide phone number formats.

phoneNumbers.minimumQuality [Double] Optional

This parameters specifies the minimum quality score that phone number matches must have to be included in the response and replaced in the replacement value.

phoneNumbers.separatorPenalty [Double] Optional defaults to -0.02

This parameter specifies a penalty that is applied to the quality score for a match if it contains any type of separator other than a dash or parenthesis. For example, 303;555;1234 contains two penalized separators so the separator penalty will be multiplied by the number of separators and added to the quality score.

phoneNumbers.spacePenalty [Double] Optional defaults to -0.02

This parameter specifies a penalty that is applied to the quality score for a match if it contains one or more spaces. For example, 303 555 1234 contains two spaces so the space penalty will be multiplied by the number of spaces and added to the quality score.

phoneNumbers.wordPenalty [Double] Optional defaults to -0.03

This parameter specifies a penalty that is applied to the quality score for a match if it contains any words rather than digits. For example, three zero three 555 1234 contains three words so the word penalty will be multiplied by the number of words and added to the quality score.

replaceChar [String] Optional defaults to *

The character that is used during a replace operation.

unicode [Object] Optional Available since 3.22.0

Object that defines the unicode filter options.

unicode.disabled [Boolean] Optional defaults to false Available since 3.22.0

This parameter disables the unicode filter completely. No unicode matches will be returned if this is set to true.

unicode.ranges [List<String>] Optional defaults to a provided config Available since 3.22.0

The list of unicode ranges to disallow in content. Each range is a string of two json style unicode escapes separated by a dash. Be sure to escape the slash or else you will be sending a unicode character instead of an escaped unicode character code.


Example Parameter "ranges": ["\\u0000-\\u0001", "\\uFFFF-\\u{FFFFF}"]

usernames [Object] Optional

Object that defines the username filter options.

usernames.disabled [Boolean] Optional defaults to true

This parameter disables the username filter completely. No username matches will be returned and the replacement value will not contain replacements for username matches. When this parameter is set to true all other nested username parameters will be ignored.

usernames.scheme [String] Required

The username filter scheme to use during this filter request. See [Username Filter Schemes].

urls [Object] Optional

Object that defines the url filter options.

urls.disabled [Boolean] Optional defaults to false

This parameter disables the url filter completely. No url matches will be returned and the replacement value will not contain replacements for url matches. When this parameter is set to true all other nested url parameters will be ignored.

urls.domainQuality [Array] Optional

The list of domain quality configurations for the url filter. Providing domain quality you may override the default behavior. CleanSpeak already adjusts domain scores of domain names that are also dictionary words such as .design and .photo. You may manually provider a lower score for a domain by providing a configuration.


Example Parameter "domainQuality": [{"domain": "chat", "quality": 0.5}]

urls.domainQuality[x].domain [String] Required

This parameter is the name of the domain. For example, for the .chat domain name, you would set this parameter to chat.

urls.domainQuality[x].quality [Double] Required

This parameter sets the initial quality score for the specified domain. This value may be between 0 and 1.

urls.maximumMatchLength [Boolean] Optional defaults to 50

This parameter specifies the maximum length that a match can be in order to be considered a url. If the match length is greater than the maximum match length the match will be ignored.

urls.minimumQuality [Double] Optional

This parameters specifies the minimum quality score that url matches must have to be included in the response and replaced in the replacement value.

urls.spacePenalty [Double] Optional defaults to false

This parameter specifies a penalty that is applied to the quality score for a match if it contains one or more spaces. For example, www .ex a m ple .com contains spaces so the space penalty will added to the quality score.

words [Array<String>] Optional

This parameter specifies the individual words to find within the content string. Generally words that should be filtered should be added to your blacklist. This parameter allows you to find matches without modifying your list.
Example Parameter "words": ["Competitor", "badguy", "tuesday"]

whitelist [Boolean] Optional defaults to false

This parameter enables the white list filter. This parameter is unique in that when enabled by setting this parameter to true it implicitly disables all other filters. See [Whitelist Filter].

Example Request JSON
{
  "blacklist": {
    "ignoreCharacters": "qxz",
    "locales": [
      "en"
    ],
    "minimumSeverity": "medium",
    "tags": [
      "Vulgarity",
      "Sexual"
    ]
  },
  "content": "fuck A bill at test.net 332-999 eight767 abcd my address\u0000",
  "characters": [
    "A",
    "3"
  ],
  "contentType": "text",
  "emails": {
    "domainQuality": [
      {
        "domain": "net",
        "quality": "0.8"
      },
      {
        "domain": "xyz",
        "quality": "0.1"
      }
    ],
    "maximumMatchLength": "100",
    "spacePenalty": "-0.2"
  },
  "phoneNumbers": {
    "maximumMatchLength": "20",
    "minimumMatchLength": "3",
    "separatorPenalty": "-0.3",
    "spacePenalty": "-0.1",
    "wordPenalty": "-0.3"
  },
  "replaceChar": "x",
  "unicode": {
    "ranges": [
      "\\u0000-\\u0001"
    ]
  },
  "urls": {
    "domainQuality": [
      {
        "domain": "net",
        "quality": "0.8"
      },
      {
        "domain": "xyz",
        "quality": "0.1"
      }
    ],
    "maximumMatchLength": "50",
    "spacePenalty": "-0.2"
  },
  "words": [
    "abcd",
    "competitor"
  ]
}

4.2. Response

Table 10. Response Codes
Code Description

200

The request was successful. The response will contain a JSON body.

400

The request was invalid and/or malformed. The response will contain an Errors JSON Object with the specific errors.

401

You did not supply a valid Authorization header. The header was omitted or your API key was not valid. The response will be empty. See Authentication.

402

Your license has expired. The response will be empty. Contact sales@inversoft.com for assistance.

500

There was an internal error. A stack trace is provided and logged in the CleanSpeak log files. The response will be empty.

Table 11. Response Body

matches [Array]

The array of matches returned by the filter request.

matches.indices [Array<Integer>] Available since 3.22.0

A list of integer offsets of illegal unicode characters. These characters were defined on input or are part of a default configuration.

This field will only be present on a unicode type match.

matches[x].length [Integer]

The length of the filter match.

matches[x].start [Integer]

The starting index of the match into the original content string. For example, consider the following string You’re a real jerk!. If we match on jerk, the start index of this match is 14.

matches[x].locale [String]

The locale of the match. This value returned will be the ISO 639-1 two letter language code followed by an optional underscore and a ISO 3166-1 alpha-2 country code.

matches[x].matched [String]

If the match is of the type blacklist then this will contain the conjugation or variation that the filter matched on. For example, if smurf is on the blacklist and marked as a verb, and smurfing is in the content, then 'smurfing' would be the matched value.

matches[x].root [String]

If the match is of the type blacklist then this will contain the root word of the match. For example, if smurf is on the blacklist and marked as a verb, and smurfing is in the content, then 'smurf' would be the root value.

matches[x].quality [Double]

The quality score of the match. Blacklist matches will always return with a value of 1.0. Email, phone numbers and URL matches will return with a value between 0.0 - 1.0. See Quality Score.

matches[x].severity [String]

If the match is of the type blacklist then this will contain the severity of the match. Possible values are:

  • none

  • mild

  • medium

  • high

  • severe

matches[x].type [String]

The type of the match. This will correspond to the filter types that were enabled and configured in the request. Possible values are:

  • blacklist

  • characters

  • emails

  • phoneNumbers

  • urls

  • words

  • whitelist

  • unicode Available since 3.22.0

  • username

matches[x].tags [Array<String>]

A list of Blacklist Tags that a match contains.

matches[x].whitelistResult [String]

A whitelist result status.

  • allowed - The input text contains only allowed words and is allowed

  • disallowedWord - The input contains text that is not on the allowed words list.

  • disallowedPhrase - The input contains allowed words arranged in a disallowed way.

matches[x].metaMatches [Array]

The array of meta matches returned by the filter request. Meta matches are returned when the contentType of bbCode or html is filtered and matches are found within the BBCode attributes. Meta match properties are identical to the matches.

Consider the following example content.

{
  "content": "[url=https://www.inversoft.com]Hello[/url]",
  "contentType": "bbcode"
}

Notice this content contains a URL match inside of a BBCode attribute, this match is considered a meta match.

replacement [String]

The original message with all matches replaced by a replacement character. If a replacement character was not specified on the request the default replacement character will be used.


For example, consider the following content. Piss off jerk

Assuming piss and jerk are returned as matches, the following replacement string would be returned *** off ****.

Example Response JSON
{
  "matches":[
    {
      "length":4,
      "locale":"en",
      "matched":"fuck",
      "quality":1.0,
      "root":"fuck",
      "severity":"severe",
      "start":0,
      "tags":[
        "Vulgarity"
      ],
      "type":"blacklist"
    },
    {
      "length":1,
      "quality":1.0,
      "start":5,
      "type":"characters"
    },
    {
      "length":16,
      "quality":0.8,
      "start":7,
      "type":"emails"
    },
    {
      "length":8,
      "quality":1.0,
      "start":15,
      "type":"urls"
    },
    {
      "length":16,
      "quality":0.6,
      "start":24,
      "type":"phoneNumbers"
    },
    {
      "length":1,
      "quality":1.0,
      "start":24,
      "type":"characters"
    },
    {
      "length":1,
      "quality":1.0,
      "start":25,
      "type":"characters"
    },
    {
      "length":4,
      "quality":1.0,
      "start":41,
      "type":"words"
    },
    {
      "length":7,
      "locale":"en",
      "matched":"adress",
      "quality":1.0,
      "root":"address",
      "severity":"medium",
      "start":49,
      "tags":[
        "PII"
      ],
      "type":"blacklist"
    },
    {
      "indices": [
        57
      ],
      "quality": 1.0,
      "type": "unicode"
    }
  ],
  "replacement":"xxxx x xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxx my xxxxxxx"
}

5. Flagging Content

This API is used to flag content that has already been sent into CleanSpeak. Flagged content will be queued for a moderator to review in the Content Alert queue.

For example, this API may be used to allow users to flag a forum post for inappropriate content or to flag reviews as containing irrelevant content.

5.1. Request

URI

POST /content/item/flag/{contentItemId}

Table 12. Request Parameters

contentItemId [UUID] Required

The Id of the User Content Item to be flagged.

Table 13. Request Body

flag [Object] Required

The flag object.

flag.comment [String] Optional

An optional description to provide additional details for the reason the content was flagged.

flag.createInstant [Long] Required

The instants the flag event occurred.

flag.reason [String] Optional

A free-form text field that can be used to indicate the reason the content was flagged.

For example, you may use reasons such as abuse, pornography, bullying, grooming, spam or violence.

flag.reporterId [UUID] Required

The Id of the reporting user.

Example Request JSON
{
  "flag": {
    "comment": "this content is really not appropriate for children",
    "createInstant": 1474496312000,
    "reason": "pornography",
    "reporterId": "91303ce2-ee40-48e7-98dc-354c051d0b78"
  }
}

5.2. Response

Table 14. Response Codes
Code Description

200

The request was successful. The response will be empty.

400

The request was invalid and/or malformed. The response will contain an Errors JSON Object with the specific errors.

401

You did not supply a valid Authorization header. The header was omitted or your API key was not valid. The response will be empty. See Authentication.

402

Your license has expired. The response will be empty. Contact sales@inversoft.com for assistance.

404

The object you requested doesn’t exist. The response will be empty.

500

There was an internal error. A stack trace is provided and logged in the CleanSpeak log files. The response will be empty.

6. Batch Filter Content

Available Since Version 3.6.0

This API is used to send multiple pieces of content to CleanSpeak to be filtered. It primarly uses the same API structure as the Filter Content API except that the content is an array instead of an object.

This API can be called synchronously or asynchronously. If the callbackURL is specified in the request, CleanSpeak will handle the request asynchronously and send the response to this URL. Otherwise, the request is handled synchronously and CleanSpeak will send the response back directly.

6.1. Request

URI

POST /content/item/batch-filter

Table 15. Request Body

blacklist [Object] Optional

Object that defines the blacklist filter options.

blacklist.disabled [Boolean] Optional defaults to false

This parameter disables the blacklist filter completely. No blacklist matches will be returned and the replacement value will not contain replacements for blacklist matches. When this parameter is set to true all other nested blacklist parameters will be ignored.

blacklist.locales [Array<String>] Optional

This parameter specifies the locales that blacklist filter matches must have in order to be included in the response. When this parameter is omitted all matches will be returned regardless of locale. See Locales.

blacklist.minimumSeverity [String] Optional

This parameter specifies the minimum severity that blacklist filter matches must have to be included in the response. When this parameter is omitted all matches will be returned regardless of severity. Possible values:

  • mild

  • medium

  • high

  • severe

blacklist.tags [Array<String>] Optional

This parameter specifies the tags that blacklist filter matches must have to be included in the response.

callbackHeaders [Object] Optional

The key-value pair Object that contains HTTP headers that are included by CleanSpeak when it sends the response to the callbackURL.

callbackURL [String] Optional

Indicates that the batch request should be processed asynchronously and that CleanSpeak should send the response to this URL.

contentItems [Array<String>] Required

The individual pieces of content to be filtered.

characters [Array<String>] Optional

This parameter specifies the individual characters to find within the content string.


Example Parameter "characters": ["A", "❢", "§"]

contentType [String] Optional

This parameter specifies the content type. When this parameter is omitted the API will attempt to identify the content as one of the supported content types. Possible values:

  • text

  • bbcode

  • html Available Since 3.19.0

emails [Object] Optional

Object that defines the email filter options.

emails.disabled [Boolean] Optional defaults to false

This parameter disables the email filter completely. No email matches will be returned and the replacement value will not contain replacements for email matches. When this parameter is set to true all other nested email parameters will be ignored.

emails.domainQuality [Array] Optional

The list of domain quality configurations for the Email filter. Providing domain quality you may override the default behavior. CleanSpeak already adjusts domain scores of domain names that are also dictionary words such as .design and .photo. You may manually provider a lower score for a domain by providing a configuration.


Example Parameter "domainQuality": [{"domain": "chat", "quality": 0.5}]

emails.domainQuality[x].domain [String] Required

This parameter is the name of the domain. For example, for the .chat domain name, you would set this parameter to chat.

emails.domainQuality[x].quality [Double] Required

This parameter sets the initial quality score for the specified domain. This value may be between 0 and 1. See Quality Score.

emails.maximumMatchLength [Integer] Optional defaults to 50

This parameter specifies the maximum length that a match can be in order to be considered an email. If the match length is greater than the maximum match length the match will be ignored.

emails.minimumQuality [Double] Optional

This parameters specifies the minimum quality score that email matches must have to be included in the response and replaced in the replacement value.

emails.spacePenalty [Double] Optional defaults to -0.05

This parameter specifies a penalty applied to the quality score if the match contains any spaces. For example, user@ example.com contains a space so the space penalty value will be added to the quality score. The email space penalty is applied once regardless of the number of spaces found in the match.

phoneNumbers [Object] Optional

Object that defines the phone number filter options.

phoneNumbers.disabled [Boolean] Optional defaults to false

This parameter disables the phone number filter completely. No phone number matches will be returned and the replacement value will not contain replacements for phone number matches. When this parameter is set to true all other nested phoneNumbers parameters will be ignored.

phoneNumbers.maximumMatchLength [Integer] Optional defaults to 20

This parameter specifies the maximum length that a match can be in order to be considered an phone number. If the match length is greater than the maximum match length the match will be ignored.

phoneNumbers.minimumMatchLength [Integer] Optional defaults to 7

This parameter specifies the minimum length that a match can be in order to be considered a phone number. The default value covers most world wide phone number formats.

phoneNumbers.minimumQuality [Double] Optional

This parameters specifies the minimum quality score that phone number matches must have to be included in the response and replaced in the replacement value.

phoneNumbers.separatorPenalty [Double] Optional defaults to -0.02

This parameter specifies a penalty that is applied to the quality score for a match if it contains any type of separator other than a dash or parenthesis. For example, 303;555;1234 contains two penalized separators so the separator penalty will be multiplied by the number of separators and added to the quality score.

phoneNumbers.spacePenalty [Double] Optional defaults to -0.02

This parameter specifies a penalty that is applied to the quality score for a match if it contains one or more spaces. For example, 303 555 1234 contains two spaces so the space penalty will be multiplied by the number of spaces and added to the quality score.

phoneNumbers.wordPenalty [Double] Optional defaults to -0.03

This parameter specifies a penalty that is applied to the quality score for a match if it contains any words rather than digits. For example, three zero three 555 1234 contains three words so the word penalty will be multiplied by the number of words and added to the quality score.

replaceChar [Boolean] Optional defaults to *

The character that is used during a replace operation.

unicode [Object] Optional Available since 3.22.0

Object that defines the unicode filter options.

unicode.disabled [Boolean] Optional defaults to false Available since 3.22.0

This parameter disables the unicode filter completely. No unicode matches will be returned if this is set to true.

unicode.ranges [List<String>] Optional defaults to a provided config Available since 3.22.0

The list of unicode ranges to disallow in content. Each range is a string of two json style unicode escapes separated by a dash. Be sure to escape the slash or else you will be sending a unicode character instead of an escaped unicode character code.


Example Parameter "ranges": ["\\u0000-\\u0001", "\\uFFFF-\\u{FFFFF}"]

usernames [Object] Optional

Object that defines the username filter options.

usernames.disabled [Boolean] Optional defaults to true

This parameter disables the username filter completely. No username matches will be returned and the replacement value will not contain replacements for username matches. When this parameter is set to true all other nested username parameters will be ignored.

usernames.scheme [String] Required

The username filter scheme to use during this filter request. See [Username Filter Schemes].

urls [Object] Optional

Object that defines the url filter options.

urls.disabled [Boolean] Optional defaults to false

This parameter disables the url filter completely. No url matches will be returned and the replacement value will not contain replacements for url matches. When this parameter is set to true all other nested url parameters will be ignored.

urls.domainQuality [Array] Optional

The list of domain quality configurations for the url filter. Providing domain quality you may override the default behavior. CleanSpeak already adjusts domain scores of domain names that are also dictionary words such as .design and .photo. You may manually provider a lower score for a domain by providing a configuration.


Example Parameter "domainQuality": [{"domain": "chat", "quality": 0.5}]

urls.domainQuality[x].domain [String] Required

This parameter is the name of the domain. For example, for the .chat domain name, you would set this parameter to chat.

urls.domainQuality[x].quality [Double] Required

This parameter sets the initial quality score for the specified domain. This value may be between 0 and 1.

urls.maximumMatchLength [Boolean] Optional defaults to 50

This parameter specifies the maximum length that a match can be in order to be considered a url. If the match length is greater than the maximum match length the match will be ignored.

urls.minimumQuality [Double] Optional

This parameters specifies the minimum quality score that url matches must have to be included in the response and replaced in the replacement value.

urls.spacePenalty [Double] Optional defaults to false

This parameter specifies a penalty that is applied to the quality score for a match if it contains one or more spaces. For example, www .ex a m ple .com contains spaces so the space penalty will added to the quality score.

words [Array<String>] Optional

This parameter specifies the individual words to find within the content string. Generally words that should be filtered should be added to your blacklist. This parameter allows you to find matches without modifying your list.
Example Parameter "words": ["Competitor", "badguy", "tuesday"]

whitelist [Boolean] Optional defaults to false

This parameter enables the white list filter. This parameter is unique in that when enabled by setting this parameter to true it implicitly disables all other filters. See [Whitelist Filter].

Example Request JSON
{
  "content": [
    "fuck A bill at test.net 332-999 eight767 abcd my address\u0000",
    "another piece of content",
    "and another piece of content"
  ],
  "characters": [
    "A",
    "3"
  ],
  "contentType": "text",
  "emails": {
    "domainQuality": [
      {
        "domain": "net",
        "quality": "0.8"
      },
      {
        "domain": "xyz",
        "quality": "0.1"
      }
    ],
    "maximumMatchLength": "100",
    "spacePenalty": "-0.2"
  },
  "phoneNumbers": {
    "maximumMatchLength": "20",
    "minimumMatchLength": "3",
    "separatorPenalty": "-0.3",
    "spacePenalty": "-0.1",
    "wordPenalty": "-0.3"
  },
  "replaceChar": "x",
  "unicode": {
    "ranges": [
      "\\u0000-\\u0001"
    ]
  },
  "urls": {
    "domainQuality": [
      {
        "domain": "net",
        "quality": "0.8"
      },
      {
        "domain": "xyz",
        "quality": "0.1"
      }
    ],
    "maximumMatchLength": "50",
    "spacePenalty": "-0.2"
  },
  "words": [
    "abcd",
    "competitor"
  ]
}

6.2. Response

Table 16. Response Codes
Code Description

200

The request was successful. The response will contain a JSON body.

400

The request was invalid and/or malformed. The response will contain an Errors JSON Object with the specific errors.

401

You did not supply a valid Authorization header. The header was omitted or your API key was not valid. The response will be empty. See Authentication.

402

Your license has expired. The response will be empty. Contact sales@inversoft.com for assistance.

500

There was an internal error. A stack trace is provided and logged in the CleanSpeak log files. The response will be empty.

Table 17. Response Body

results [Array]

The array of results, one for each piece of content in the request, ordered.

results[x].matches [Array]

The array of matches returned by the filter request.

results[x].matches.indices [Array<Integer>] Available since 3.22.0

A list of integer offsets of illegal unicode characters. These characters were defined on input or are part of a default configuration.

This field will only be present on a unicode type match.

results[x].matches[x].length [Integer]

The length of the filter match.

results[x].matches[x].start [Integer]

The starting index of the match into the original content string. For example, consider the following string You’re a real jerk!. If we match on jerk, the start index of this match is 14.

results[x].matches[x].locale [String]

The locale of the match. This value returned will be the ISO 639-1 two letter language code followed by an optional underscore and a ISO 3166-1 alpha-2 country code.

results[x].matches[x].matched [String]

If the match is of the type blacklist then this will contain the conjugation or variation that the filter matched on. For example, if smurf is on the blacklist and marked as a verb, and smurfing is in the content, then 'smurfing' would be the matched value.

results[x].matches[x].root [String]

If the match is of the type blacklist then this will contain the root word of the match. For example, if smurf is on the blacklist and marked as a verb, and smurfing is in the content, then 'smurf' would be the root value.

results[x].matches[x].quality [Double]

The quality score of the match. Blacklist matches will always return with a value of 1.0. Email, phone numbers and URL matches will return with a value between 0.0 - 1.0. See Quality Score.

results[x].matches[x].severity [String]

If the match is of the type blacklist then this will contain the severity of the match. Possible values are:

  • none

  • mild

  • medium

  • high

  • severe

results[x].matches[x].type [String]

The type of the match. This will correspond to the filter types that were enabled and configured in the request. Possible values are:

  • blacklist

  • characters

  • emails

  • phoneNumbers

  • urls

  • words

  • whitelist

  • unicode Available since 3.22.0

  • username

results[x].matches[x].tags [Array<String>]

A list of Blacklist Tags that a match contains.

results[x].matches[x].whitelistResult [String]

A whitelist result status.

  • allowed - The input text contains only allowed words and is allowed

  • disallowedWord - The input contains text that is not on the allowed words list.

  • disallowedPhrase - The input contains allowed words arranged in a disallowed way.

results[x].matches[x].metaMatches [Array]

The array of meta matches returned by the filter request. Meta matches are returned when the contentType of bbCode or html is filtered and matches are found within the BBCode attributes. Meta match properties are identical to the matches.

Consider the following example content.

{
  "content": "[url=https://www.inversoft.com]Hello[/url]",
  "contentType": "bbcode"
}

Notice this content contains a URL match inside of a BBCode attribute, this match is considered a meta match.

results[x].replacement [String]

The original message with all matches replaced by a replacement character. If a replacement character was not specified on the request the default replacement character will be used.


For example, consider the following content. Piss off jerk

Assuming piss and jerk are returned as matches, the following replacement string would be returned *** off ****.

Example Response JSON
{
  "results": [
    {
      "matches": [
        {
          "length": 4,
          "locale": "en",
          "matched": "fuck",
          "quality": 1.0,
          "root": "fuck",
          "severity": "severe",
          "start": 0,
          "tags": [
            "Vulgarity"
          ],
          "type": "blacklist"
        },
        {
          "length": 1,
          "quality": 1.0,
          "start": 5,
          "type": "characters"
        },
        {
          "length": 16,
          "quality": 0.8,
          "start": 7,
          "type": "emails"
        },
        {
          "length": 8,
          "quality": 1.0,
          "start": 15,
          "type": "urls"
        },
        {
          "length": 16,
          "quality": 0.6,
          "start": 24,
          "type": "phoneNumbers"
        },
        {
          "length": 1,
          "quality": 1.0,
          "start": 24,
          "type": "characters"
        },
        {
          "length": 1,
          "quality": 1.0,
          "start": 25,
          "type": "characters"
        },
        {
          "length": 4,
          "quality": 1.0,
          "start": 41,
          "type": "words"
        },
        {
          "length": 7,
          "locale": "en",
          "matched": "adress",
          "quality": 1.0,
          "root": "address",
          "severity": "medium",
          "start": 49,
          "tags": [
            "PII"
          ],
          "type": "blacklist"
        },
        {
          "indices": [
            57
          ],
          "quality": 1.0,
          "type": "unicode"
        }
      ],
      "replacement": "xxxx x xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxx my xxxxxxx"
    },
    {
      "replacement": "another piece of content"
    },
    {
      "replacement": "and another piece of content"
    }
  ]
}

7. Batch Moderate Content

Available Since Version 3.6.0

This API is used to send multiple pieces of content to CleanSpeak to be moderated. It primarily uses the same API structure as the Moderate Content and Update Content APIs with a few differences:

  • For persistent content, the id of each piece of content is in the request rather than on the URL

  • For transient content, the results come back in the response in the same as they were passed into the request

  • The moderation parameter in the request is applied to each piece of content

This API can be called synchronously or asynchronously. If the callbackURL is specified in the request, CleanSpeak will handle the request asynchronously and send the response to this URL. Otherwise, the request is handled synchronously and CleanSpeak will send the response back directly.

7.1. Request

For new content, you must use the POST request:

URI

POST /content/item/batch-moderate

For updating content, you must use the PUT request:

URI

PUT /content/item/batch-moderate

Table 18. Request Body

callbackHeaders [Object] Optional

The key-value pair Object that contains HTTP headers that are included by CleanSpeak when it sends the response to the callbackURL.

callbackURL [String] Optional

Indicates that the batch request should be processed asynchronously and that CleanSpeak should send the response to this URL.

contentItems [Array] Required

The list of the content being moderated.

contentItems[x].applicationId [UUID] Required

The Id of the application that corresponds to the content source.

contentItems[x].createInstant [Long] Required

The instant that the content was generated.

contentItems[x].id [UUID] Optional

The Id for the piece of content (only required if the application for this piece of content is configured to moderate persistent content).

contentItems[x].location [String] Optional

Specifies the location within the application that the content was generated. For example, you might use a chat room name, area Id for a game, or a thread Id for a forum. This parameter is used by CleanSpeak to display conversational views of content with the [Context View] feature.

contentItems[x].parts [Array] Required

An array that contains one to many content parts. If your content only has a single part, such as a chat message, the array will only contain a single text entry. The reason you would send in multiple content parts within a single request is to ensure the moderation decision affects each part.

For example, you may send in an image for moderation, the image has a title and a description field. You would send this to CleanSpeak with three content parts, the image and two text parts. If the content of the image title is rejected the entire content needs to be rejected wholesale, the title, description and the image. In this case it would make sense to treat all three parts as an atomic unit of content.

If individual content parts are not related and can be rejected or approved separately then you should send them to CleanSpeak as separate requests.

contentItems[x].parts[x].content [String] Required

The content to be filtered. The content type will indicate what type of content is expected in this parameter.

Content Types

Type Description

text

The content to be filtered.

bbcode

Text content to be filtered that may contain BBCode.

html

Text content to be filtered that may contain HTML. Available Since 3.19.0

attribute

A simple attribute of the content. This is an arbitrary string and will not be filtered.

hyperlink

Fully qualified URL to an external web page.

image

Fully qualified URL of the image to be displayed.

video

Fully qualified URL of the video to be displayed.

audio

Fully qualified URL of the audio file to be moderated.

contentItems[x].parts[x].name [String] Optional

The name of the content part. This value is optional an intended to better identify the context when you have more than one content part. For example this could be Title, Message Body or Image.

contentItems[x].parts[x].type [String] Required

The type of this content part. Possible values:

  • text

  • bbcode

  • html Available Since 3.19.0

  • attribute

  • hyperlink

  • image

  • video

  • audio

contentItems[x].receiverDisplayName [String] Optional

The display name of the user that received the content. This parameter should only be set if this piece of content was a private message between two users.

contentItems[x].receiverId [UUID] Optional

The Id of the user that received of the content. This parameter should only be set if this piece of content was a private message between two users.

contentItems[x].senderDisplayName [String] Optional

The display name (username or whatever is displayed to other users in the game/forum) that generated the content.

contentItems[x].senderId [UUID] Required

The Id of the user that generated the content. This parameter is required so that CleanSpeak can analyze and associate the content with the user that generated it.

moderation [String] Optional

Tells CleanSpeak to forcibly put all the content into a queue (Approval, User Alert or Content Alert). This overrides the configuration you have setup for the Application in the Management Interface.

  • requiresApproval

  • generatesAlert

  • generatesContentAlert

Example Request JSON
{
  "contentItems": [
    {
      "applicationId": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
      "createInstant": 13405983821,
      "location": "threadId_42",
      "parts": [
        {
          "content": "Hi",
          "name": "Body",
          "type": "text"
        }
      ],
      "senderDisplayName": "PapaSmurf",
      "senderId": "f6d3df91-ed4b-48ad-810f-05a367d328c2"
    },
    {
      "applicationId": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
      "createInstant": 13405983823,
      "location": "threadId_42",
      "parts": [
        {
          "content": "Smurf off",
          "name": "Body",
          "type": "text"
        }
      ],
      "senderDisplayName": "PapaSmurf",
      "senderId": "f6d3df91-ed4b-48ad-810f-05a367d328c2"
    }
  ]
}

7.2. Response

Table 19. Response Codes
Code Description

200

The request was successful. The response will contain a JSON body.

400

The request was invalid and/or malformed. The response will contain an Errors JSON Object with the specific errors.

401

You did not supply a valid Authorization header. The header was omitted or your API key was not valid. The response will be empty. See Authentication.

402

Your license has expired. The response will be empty. Contact sales@inversoft.com for assistance.

500

There was an internal error. A stack trace is provided and logged in the CleanSpeak log files. The response will be empty.

Table 20. Response Body

results [Array]

The results for each piece of content that was moderated.

results[x].content.id [UUID]

The id of the piece of content. This might have been passed in on the request or generated by CleanSpeak.

results[x].content.parts [Array]

The list of parts of content.

results[x].content.parts[x].name [String]

The name of the part of the content.

results[x].content.parts[x].replacement [String]

The replacement text generated by CleanSpeak after applying the filter rules to this part.

results[x].contentAction [String]

The action that the client should take with the content. Possible values:

Content Actions

Action Description

allow

The content should be allowed.

authorOnly

The content should be allowed but only the author of the content should be allowed to view the content.

replace

The content should be allowed, but utilize the replacement text provided in the response.

queuedForApproval

The content has been queued for approval and should not be displayed to other users until it has been approved by a moderator.

reject

The content should be rejected.

results[x].moderationAction [String]

The action that was taken on the content. Possible values:

  • requiresApproval

  • generatesAlert

  • generatesContentAlert

results[x].stored [Boolean]

This value indicates if the content was stored by CleanSpeak.

Example Response JSON
{
  "results": [
    {
      "content": {
        "id": "99f2c4e8-961a-4a34-b9b9-43fc3f3b43ec"
      },
      "contentAction": "allow",
      "moderationAction": "generatesAlert",
      "stored": true
    },
    {
      "content": {
        "id": "99f2c4e8-961a-4a34-b9b9-43fc3f3b43ed",
        "parts": [
          {
            "name": "body",
            "replacement": "**** off"
          }
        ]
      },
      "contentAction": "replace",
      "moderationAction": "generatesAlert",
      "stored": true
    }
  ]
}