> For the complete documentation index, see [llms.txt](https://docs.ggwp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ggwp.com/api-docs-chat/standard-package/chat-api-batch.md).

# Chat API: Batch

\[ Base URL: `api.ggwp.com`]

`POST` /chat/v2/batch

## **Description**

This API endpoint will process an array of input messages, each with their corresponding session id and user id, along with a list of configurable options on toxicity filtering strengths, and return information at 4 levels:

* **Message Details** - indicators for the presence and severity of toxic content for each input message, as well as different variations of the messages removing toxicity.
* **Player Details** - attributes to describe the behavior of that particular user up until that point in the conversation. This includes the prior list of incident types detected, the player mood, reputation score, and current status.
* **Conversation Summary** - metrics that explain all prior activity per session. These include session duration, volume of messages and participants, conversation mood and total incidents detected, along with the types and severities.
* **Recommendations** - information about the penalties imposed upon that particular user due to a history or recent series of toxic behaviors. This includes the penalty itself, the trigger message and time, and the duration of the penalty. The `recommended_message` field will return an empty string while a penalty is in place. This part of the API output will provide the following penalties:
  * Session-mute: the user will be muted for the remaining duration of the session/match.&#x20;
  * Mute: the user will be muted across all sessions/matches for a specific duration of time.

## **Headers**

Please refer to `Headers` section above for `/chat/v2/message` endpoint

## **Parameters**

`body`: Array of dictionaries, each containing the following fields:\
(*Needs to be in utf-8 encoding)*

* **session\_id:** Unique identifier for the conversation channel. For gameplay messages, this could identify a conversation that unfolds over a single match. On forums or message boards, this could represent a distinct thread or discussion. If your platform contains various channel types (eg: lobby, match, direct message, etc.), we recommend that you include this information in the session\_id to enable further analysis by conversation type. This is the suggested format:

  ```json
    session_id = "channelType_numericID"
  ```
* **message:** Message sent by a user during the conversation. Cannot exceed 1,000 characters.
* **user\_id:** Unique identifier for a player or user who sent the message.
* (OPTIONAL) **username**: String with the friendly display name picked by the user.
* (OPTIONAL) **timestamp**: Time the message took place in YYYY-MM-DD HH:MM:SS.SSS or YYYY-MM-DD HH:MM:SS format, in UTC. If not added, then server side UTC timestamp is added in its place.
* (OPTIONAL) **language**: Language of the message to be processed. If omitted, the API will attempt to detect the language from the message content and prior user history. Accepts standard English language names (eg: `"english"` or `"spanish"`), and ISO 639-1 two-letter language codes (eg:  `"en"` or `"es"`). Full locale tags such as `"en-US"`, `"en-GB"`, `"pt-BR"`, and `"es-MX"` are not currently supported; send `"en"`, `"pt"`, or `"es"` instead.
* (OPTIONAL) **message\_index**: String field to track the message sent. Will be included in the output under `message_details` if passed.
* (OPTIONAL) **message\_url**: String field to track the url tagged to the message. Only http or https schemes are valid. Will be visible in the dashboard if valid and passed.
* (OPTIONAL) **metadata**: Dict field to track any metadata associated with the message. Must be under 5KB.  Only permitted keys and corresponding types are valid. Supported keys:

  * channel (string) - communication space that the message is passed to. E.g. dm, party, guild, local
  * participants (array\<string>) - the user\_ids participating in the channel
  * map (string) - identifier or name of the world, level, or environment where the message originates
  * map\_version (string) - version identifier of the map, used to track changes in layout, etc.
  * zone (string) - subsection or named region within a map used for finer-grained location context
  * coordinates (object) - spatial position within the map or zone
    * x (float) - position along the X-axis
    * y (float) - position along the Y-axis
    * z (float) - position along the Z-axis

  Example:

  ```json
  {
    "metadata": {
      "channel": "dm",
      "participants": ["user989", "user990"],
      "map":"golden_wasteland",
      "map_version":"2026.03.1",
      "zone":"cacti_forest",
      "coordinates":{
         "x":123.45,
         "y":67.89,
         "z":-10.25
      }
    }
  }
  ```

  Note: Additional metadata keys can be supported. Please work with your customer representative to define the specific keys that will be applicable to your platform.

💡 **API Limits: The following limits are in place for this API, whichever is smaller:**

* 200 messages (items in the array)
* 1 MB body payload

A 400 error will be returned if any of these limits are exceeded.

Example:

```json
[
	{
	  "session_id": "match_7765",
	  "message": "fucking retards everywhere",
	  "user_id": "user989",
	  "username": "nlxdz",
	  "timestamp": "2022-06-02 16:49:02"
	},
	{
	  "session_id": "lobby_4953",
	  "message": "hi friends!",
	  "user_id": "user159",
	  "username": "jrd",
	  "timestamp": "2022-06-02 16:49:35"
	}
]
```

Sample call:

```bash
curl --request POST 'https://api.ggwp.com/chat/v2/batch' \
--header 'x-api-key: api_key' \
--header 'Content-Type: application/json' \
--data-raw '[
	{
	  "session_id": "match_7765",
	  "message": "fucking retards everywhere",
	  "user_id": "user989",
	  "username": "nlxdz",
	  "timestamp": "2022-06-02 16:49:02"
	},
	{
	  "session_id": "lobby_4953",
	  "message": "hi friends!",
	  "user_id": "user159",
	  "username": "jrd",
	  "timestamp": "2022-06-02 16:49:35"
	}
]'
```

## **Output**

* 200 response - successful operation

Dictionary containing the following fields:

* **message\_details**: list of dictionaries pertaining to each message passed in the payload
  * message\_details\[n].message\_id: Unique identifier assigned to the message.
  * message\_details\[n].original\_message: The raw message sent by the user.
  * message\_details\[n].flag: Indicates whether the message was flagged.
  * message\_details\[n].severity: Severity of the toxicity (none, low, medium, high).
  * message\_details\[n].filtered\_message: Version of the message with flagged terms filtered.&#x20;
    * For space-delimited languages (e.g., English), entire words are filtered. E.g. `You are a shithead` --> `You are a *****`
    * For languages without explicit word boundaries (e.g., Korean, Japanese, Chinese), only the detected term itself is filtered." E.g. `좆까고 있네`--> `*****고 있네`
  * message\_details\[n].replaced\_message: Safe or humorous alternative generated to replace the original message.
  * message\_details\[n].recommended\_message: Suggested version of the message to be passed to the client. For active users, this value defaults to `filtered_message`. For muted users, the `recommended_message` will be an empty string.
  * message\_details\[n].language: Detected language of the message.
  * message\_details\[n].violence: true if the message contains violence.
  * message\_details\[n].verbal\_abuse: true if the message contains verbal abuse.
  * message\_details\[n].profanity: true if the message contains profanity.
  * message\_details\[n].sexual\_content: true if the message contains sexual content.
  * message\_details\[n].identity\_hate: true if the message contains identity hate.
  * message\_details\[n].drugs: true if the message contains drug references.
  * message\_details\[n].self\_harm: true if the message contains self harm.
  * message\_details\[n].custom: true if the message contains custom blocklist terms.
  * message\_details\[n].spam: true if the message contains spam.
  * message\_details\[n].link: true if the message contains external links.
  * message\_details\[n].pii: true if the message contains personally identifiable information.
* **player\_details**: Dictionary containing details pertaining to each `user_id` of the payload
  * player\_details.\<user\_id>.\<session\_id>.user\_id: Unique identifier for the user.
  * player\_details.\<user\_id>.\<session\_id>.username: Display name of the user.
  * player\_details.\<user\_id>.\<session\_id>.num\_messages: Total number of messages sent.
  * player\_details.\<user\_id>.\<session\_id>.num\_incidents: Number of incidents.
  * player\_details.\<user\_id>.\<session\_id>.cumulative\_mood: Overall sentiment for the user's messages.
  * player\_details.\<user\_id>.\<session\_id>.min\_mood: Lowest sentiment observed for the user’s messages.
  * player\_details.\<user\_id>.\<session\_id>.max\_mood: Highest sentiment observed for the user’s messages.
  * player\_details.\<user\_id>.\<session\_id>.incident\_types\_detected: List of incident types associated with the user.
  * player\_details.\<user\_id>.\<session\_id>.incidents\_by\_severity: Breakdown of incidents grouped by severity level.
  * player\_details.\<user\_id>.\<session\_id>.reputation\_score: Overall user reputation score derived from behavior history.
  * player\_details.\<user\_id>.\<session\_id>.languages: Languages detected from the user’s messages.
  * player\_details.\<user\_id>.\<session\_id>.user\_status: Current moderation state of the user (e.g., active, muted).
  * player\_details.\<user\_id>.\<session\_id>.user\_status.status: Specific moderation action applied (muted, etc.).
  * player\_details.\<user\_id>.\<session\_id>.user\_status.expiry\_at: Time when the moderation action expires.
* **conversation\_summary**: Dictionary containing details pertaining to each `session_id` of the payload
  * conversation\_summary.\<session\_id>.start\_time: Timestamp when the conversation session began.
  * conversation\_summary.\<session\_id>.session\_duration: Total duration of the conversation (in seconds).
  * conversation\_summary.\<session\_id>.num\_messages: Total number of messages in the conversation.
  * conversation\_summary.\<session\_id>.num\_participants: Number of users in the conversation.
  * conversation\_summary.\<session\_id>.num\_incidents: Total count of incidents.
  * conversation\_summary.\<session\_id>.conversation\_mood: Overall sentiment for the entire conversation.
  * conversation\_summary.\<session\_id>.incident\_types\_detected: List of incident types found across the conversation.
  * conversation\_summary.\<session\_id>.incidents\_by\_severity: Breakdown of incidents grouped by severity level.
* **recommendations**: Dictionary containing the recommended action to perform on each `user_id`
  * recommendations.\<user\_id>.\<session\_id>.action: Suggested moderation action (e.g., mute).
  * recommendations.\<user\_id>.\<session\_id>.trigger\_message: Offending message that triggered the recommendation.
  * recommendations.\<user\_id>.\<session\_id>.trigger\_time: Timestamp of the triggering message.
  * recommendations.\<user\_id>.\<session\_id>.duration: Length of time (in seconds) the action should remain in effect.

Sample Output:

```json
{
    "message_details": [
        {
            "message_id": "20220602164902.482311-946bb8a9-0766-4c31-995a-d910da8531e5",
            "original_message": "fucking retards everywhere",
            "flag": true,
            "severity": "medium",
            "filtered_message": "***** ***** everywhere",
            "replaced_message": "Wait... you're supposed to be having fun?",
            "recommended_message": "",
            "language": "english",
            "violence": false,
            "verbal_abuse": true,
            "profanity": true,
            "sexual_content": false,
            "identity_hate": true,
            "drugs": false,
            "self_harm": false,
            "custom": false,
            "spam": false,
            "link": false,
            "pii": false,
            "solicitation": false,
	    "scam": false
        },
        {
            "message_id": "20220602164935.788776-92756195-c059-4e11-81a6-7faef57bd5bc",
            "original_message": "hi friends!",
            "flag": false,
            "severity": "none",
            "filtered_message": "hi friends!",
            "replaced_message": "I just met you but I love you",
            "recommended_message": "hi friends!",
            "language": "english",
            "violence": false,
            "verbal_abuse": false,
            "profanity": false,
            "sexual_content": false,
            "identity_hate": false,
            "drugs": false,
            "self_harm": false,
            "custom": false,
            "spam": false,
            "link": false,
            "pii": false,
            "solicitation": false,
	    "scam": false
        }
    ],
    "player_details": {
        "user989": {
            "match_7765": {
                "user_id": "user989",
                "username": "nlxdz",
                "num_messages": 11,
                "num_incidents": 6,
                "cumulative_mood": 0.748,
                "min_mood": 0.0,
                "max_mood": 0.8615,
                "incident_types_detected": [
                    "verbally_abusive_language",
                    "profanity",
                    "identity_hate_language"
                ],
                "incidents_by_severity": {
                    "high": 2,
                    "medium": 3,
                    "low": 1
                },
                "reputation_score": 245,
                "languages": [
                    "english"
                ],
                "user_status": {
                    "status": "muted",
                    "expiry_at": "2022-06-03 16:49:02"
                }
            }
        },
        "user159": {
            "lobby_4953": {
                "user_id": "user159",
                "username": "jrd",
                "num_messages": 3,
                "num_incidents": 0,
                "cumulative_mood": 0.891,
                "min_mood": 0.5,
                "max_mood": 0.891,
                "incident_types_detected": [],
                "incidents_by_severity": {
                    "high": 0,
                    "medium": 0,
                    "low": 0
                },
                "reputation_score": 745,
                "languages": [
                    "english"
                ],
                "user_status": {
                    "status": "active"
                }
            }
        }
    },
    "conversation_summary": {
        "match_7765": {
            "start_time": "2022-05-27 16:53:03",
            "session_duration": 59,
            "num_messages": 46,
            "num_participants": 3,
            "num_incidents": 16,
            "conversation_mood": 0.9816,
            "incident_types_detected": [
                "verbally_abusive_language",
                "profanity",
                "identity_hate_language",
                "sexual_harassment"
            ],
            "incidents_by_severity": {
                "high": 4,
                "medium": 6,
                "low": 6
            }
        },
        "lobby_4953": {
            "start_time": "2022-06-02 15:25:01",
            "session_duration": 125,
            "num_messages": 33,
            "num_participants": 5,
            "num_incidents": 4,
            "conversation_mood": 0.9577,
            "incident_types_detected": [
                "identity_bias",
                "profanity",
                "drug_reference"
            ],
            "incidents_by_severity": {
                "high": 0,
                "medium": 1,
                "low": 3
            }
        }
    },
    "recommendations": {
        "user989": {
            "match_7765": [
                {
                    "action": "mute",
                    "trigger_message": "dumb ass faggot",
                    "trigger_time": "2022-06-02 16:49:00",
                    "duration": 86400
                }
            ]
        }
    }
}
```

* 400
  * Invalid json input, missing required fields, exceeding message character limit, exceeding API limits, etc.
* 403
  * Invalid or missing API key
