PubSub Guide
Introduction
PubSub enables you to subscribe to a topic, for updates (e.g. when a user cheers in a channel).
The Twitch PubSub system allows back-end services to broadcast realtime messages to clients. Example applications include:
- An instant messaging service sending instant messages between friends.
- A back-end video system pushing real-time viewer count updates to video players.
- A presence system broadcasting users’ online status to all their friends.
These example applications share a common pattern: on application load, the application fetches a complete snapshot of its state and uses a persistent connection through PubSub to receive updates to this state. The updates act as “diffs” to the initial state.
Clients establish a WebSocket connection to our server, listen on topics they care about, and get messages on those topics in real time. Each command or message sent between the client and server is a JSON string encapsulated in one WebSocket frame.
WebSocket is a communications protocol, providing full-duplex communication channels over a single TCP connection. For more information, see the WebSocket Wikipedia entry.
The JSON messages differ, depending on the type of message or command, but typically they have this form:
{
"type": "<type string>",
"data": "<JSON blob>"
}
A code sample is available for JavaScript.
Terminology
Term | Definition |
---|---|
Client | An end-user session of the Twitch application or a third-party application’s integration point. |
Command | An action that a client issues to the server, which modifies the state of the client connection. |
Message | A piece of data which back-end services broadcast to interested clients via PubSub. PubSub never inspects or mutates messages. |
Server | A Twitch machine that clients connect to for PubSub service. |
Topic | Aka event. A logical partition of messages that clients may subscribe to, to get messages. |
Connection Management
Clients establish a secure WebSocket connection to:
wss://pubsub-edge.twitch.tv
To keep the server from closing the connection, clients must send a PING
command at least once every 5 minutes. If a client does not receive a PONG
message within 10 seconds of issuing a PING
command, it should reconnect to the server. See details in Handling Connection Failures.
Clients must LISTEN
on at least one topic within 15 seconds of establishing the connection, or they will be disconnected by the server.
Clients may receive a RECONNECT
message at any time. This indicates that the server is about to restart (typically for maintenance) and will disconnect the client within 30 seconds. During this time, we recommend that clients reconnect to the server; otherwise, the client will be forcibly disconnected.
Example: PING Connection Message
// Sent from client to server
{
"type": "PING"
}
Example: PONG Connection Message
// Sent from server to client in response to a PING
{
"type": "PONG"
}
Example: RECONNECT Connection Message
// Sent from server to client
{
"type": "RECONNECT"
}
Handling Connection Failures
When a client encounters a situation where it must reconnect to the server, it should first establish a new successful WebSocket connection and then issue a LISTEN
command that contains the set of topics that the application expects to receive messages on.
If a client fails to connect to the server or is disconnected from the server, it should reconnect to the server using an exponential backoff. Our official client implementation initially waits one second (plus a small random jitter: see the next paragraph) to retry a failed connection and doubles the backoff period on subsequent failures, up to a maximum backoff threshold of 2 minutes. This prevents some “stampeding herd” situations where many clients simultaneously connect to the server.
If a client uses timers to issue PING
commands, it should add a small random jitter to the timer. This prevents some situations where many clients issue PING
commands simultaneously.
After a client reconnects to the server, some applications should fetch fresh state, to compensate for any missed messages while the connection was broken. For instance, our Chat application fetches the Bits leaderboard on reconnect (as it does on initial page load), in case the leaderboard received an update while the connection was down.
Authorization Revoked
An authorization can be revoked at any time for a number of reasons, such a user disconnecting from an app through https://www.twitch.tv/settings/connections. Topics associated with the authorization will be unlistened to, and clients will receive an AUTH_REVOKED
message.
Example: AUTH_REVOKED Connection Message
// Sent from server to client
{
"type": "AUTH_REVOKED",
"data": {
"topics": ["channel-bits-events-v1.44322889"]
}
}
API Limits
- Clients can listen on up to 50 topics per connection. Trying to listen on more topics will result in an error message.
- We recommend that a single client IP address establishes no more than 10 simultaneous connections.
The two limits above are likely to be relaxed for approved third-party applications, as we start to better understand third-party requirements.
- Malicious or careless applications that result in abnormally high server load may be denylisted from establishing connections.
- If clients are slow to read messages from their connection and the server is simultaneous buffering more than 30 messages to an individual client, the client will be disconnected.
Topics
Once a client establishes a connection, it can LISTEN
on topics it cares about. Clients can LISTEN
on many topics at once and add new topics at any time by issuing new LISTEN
commands.
Once a client no longer cares about a particular set of topics, it should issue UNLISTEN
commands to stop receiving messages on those topics.
Authentication
All topics require an OAuth token, but only some topics have a specific required scope (noted in the table below).
Available Topics
All topics require an OAuth token, but only some topics have a specific required scope (noted in the table).
Feature | Topic and Example | Required Scope | You are notified when… |
---|---|---|---|
Bits | channel-bits-events-v1.<channel_id> Example: channel-bits-events-v1.44322889 |
bits:read |
Anyone cheers in a specified channel. |
Bits | channel-bits-events-v2.<channel_id> Example: channel-bits-events-v2.4602499 |
bits:read |
Anyone cheers in a specified channel. |
Bits Badge Notification | channel-bits-badge-unlocks.<channel_id> Example: channel-bits-badge-unlocks.44322889 |
bits:read |
Message sent when a user earns a new Bits badge in a particular channel, and chooses to share the notification with chat. |
Channel Points | channel-points-channel-v1.<channel_id> Example: channel-points-channel-v1.44322889 |
channel:read:redemptions |
A custom reward is redeemed in a channel. |
Channel Subscriptions | channel-subscribe-events-v1.<channel_id> Example: channel-subscribe-events-v1.44322889 |
channel:read:subscriptions |
Anyone subscribes (first month), resubscribes (subsequent months), or gifts a subscription to a channel. Subgift subscription messages contain recipient information. |
Chat | automod-queue.<moderator_id>.<channel_id> Example: automod-queue.46024993.44322889 |
channel:moderate |
AutoMod flags a message as potentially inappropriate, and when a moderator takes action on a message. |
Chat | chat_moderator_actions.<user_id>.<channel_id> Example: chat_moderator_actions.46024993.44322889 |
channel:moderate |
Supports moderators listening to the topic, as well as users listening to the topic to receive their own events. Examples of moderator actions are bans, unbans, timeouts, deleting messages, changing chat mode (followers-only, subs-only), changing AutoMod levels, and adding a mod. |
Chat | low-trust-users.<channel_id>.<suspicious_user_id> Example: low-trust-users.12826.141981764 |
channel:moderate |
The broadcaster or a moderator updates the low trust status of a user, or a new message has been sent in chat by a potential ban evader or a bans shared user. |
Chat | user-moderation-notifications.<current_user_id>.<channel_id> Example: user-moderation-notifications.46024993.44322889 |
chat:read |
A user’s message held by AutoMod has been approved or denied. |
Whispers | whispers.<user_id> Example: whispers.44322889 |
whispers:read |
Anyone whispers the specified user. |
Where:
<channel ID>
or<user ID>
is theid
field returned by the Twitch API Get Users endpoint for the respective user(s)
Note: channel-bitsevents
is deprecated. For Bits events, use channel-bits-events-v2
instead.
Note: channel-commerce-events-v1.<channel id>
is deprecated.
Requests
This is an example request for Bits events. It listens to Bits events on channel 44322889. The authorization scope is specified when you generate the OAuth token using our authorization flow; see the Apps & Authentication Guide.
// Request from client to server
{
"type": "LISTEN",
"nonce": "44h1k13746815ab1r2",
"data": {
"topics": ["channel-bits-events-v1.44322889"],
"auth_token": "cfabdegwdoklmawdzdo98xt2fo512y"
}
}
Request Parameter | Type | Description |
type |
string | Valid values: LISTEN , UNLISTEN . |
nonce |
string | (Optional) Random string to identify the response associated with this request. |
data |
JSON | Wraps the topics and auth_token fields. |
topics |
array of strings | List of topics to listen on. Valid values are any of the topics listed in Available Topics. |
auth_token |
string | OAuth token required to listen on some topics. The token is linked to either the specified <channel user ID> (for Bits events) or the specified <user ID> (for whispers events). |
Responses
Here is a sample response:
// Response from server to client
{
"type": "RESPONSE",
"nonce": "44h1k13746815ab1r2",
"error": ""
}
Field | Type | Description |
---|---|---|
type |
string | Valid value: RESPONSE . |
nonce |
string | The nonce that was passed in the request, if one was provided there. |
error |
string | The error message associated with the request, or an empty string if there is no error. For Bits and whispers events requests, error responses can be: ERR_BADMESSAGE , ERR_BADAUTH , ERR_SERVER , ERR_BADTOPIC . |
Receiving Messages
When a message for your subscription is published, you will receive a message containing the applicable data.
Message Parameters: All Messages
Parameter | Type | Description |
type |
string | Valid value: MESSAGE |
data |
JSON | Wraps the topics and message fields. |
topic |
string | The topic that the message pertains to. |
message |
string | The body of the message. Depending on the type of message, the message body contains different fields; see below. |
Example: Bits Event v2 Message
{
"type": "MESSAGE",
"data": {
"topic": "channel-bits-events-v2.46024993",
"message": "{\"data\":{\"user_name\":\"jwp\",\"channel_name\":\"bontakun\",\"user_id\":\"95546976\",\"channel_id\":\"46024993\",\"time\":\"2017-02-09T13:23:58.168Z\",\"chat_message\":\"cheer10000 New badge hype!\",\"bits_used\":10000,\"total_bits_used\":25000,\"context\":\"cheer\",\"badge_entitlement\":{\"new_version\":25000,\"previous_version\":10000}},\"version\":\"1.0\",\"message_type\":\"bits_event\",\"message_id\":\"8145728a4-35f0-4cf7-9dc0-f2ef24de1eb6\",\"is_anonymous\":true}"
}
}
Field | Type | Description |
badge_entitlement (optional) |
object | Information about a user’s new badge level, if the cheer was not anonymous and the user reached a new badge level with this cheer. Otherwise, null. |
bits_used |
integer | Number of bits used. |
channel_id |
string | ID of the channel in which Bits were used. |
chat_message |
string | Chat message sent with the cheer. |
context |
string | Event type associated with this use of Bits. |
is_anonymous |
Boolean | Whether or not the event was anonymous. |
message_id |
string | Message ID. |
message_type |
string | The type of object contained in the data field. |
time |
string | Time when the Bits were used. RFC 3339 format. |
total_bits_used |
integer | All time total number of Bits used in the channel by a specified user. |
user_id (optional) |
string | User ID of the person who used the Bits - if the cheer was not anonymous. Null if anonymous. |
user_name (optional) |
string | Login name of the person who used the Bits - if the cheer was not anonymous. Null if anonymous |
version |
string | Message version |
Example: Bits Event v1 Message
{
"type": "MESSAGE",
"data": {
"topic": "channel-bits-events-v1.44322889",
"message": "{\"data\":{\"user_name\":\"dallasnchains\",\"channel_name\":\"dallas\",\"user_id\":\"129454141\",\"channel_id\":\"44322889\",\"time\":\"2017-02-09T13:23:58.168Z\",\"chat_message\":\"cheer10000 New badge hype!\",\"bits_used\":10000,\"total_bits_used\":25000,\"context\":\"cheer\",\"badge_entitlement\":{\"new_version\":25000,\"previous_version\":10000}},\"version\":\"1.0\",\"message_type\":\"bits_event\",\"message_id\":\"8145728a4-35f0-4cf7-9dc0-f2ef24de1eb6\"}"
}
}
Field | Type | Description |
badge_entitlement |
object | Information about the user’s new badge level, if the user reached a new badge level with this cheer; otherwise. null. |
bits_used |
integer | Number of Bits used. |
channel_id |
string | User ID of the channel on which Bits were used. |
channel_name |
string | Name of the channel on which Bits were used. |
chat_message |
string | Chat message sent with the cheer. |
context |
string | Event type associated with this use of Bits (for example, cheer ). |
message_id |
string | Message ID |
message_type |
string | Message type (that is, the type of object contained in the data field) |
time |
string | Time when the Bits were used. RFC 3339 format. |
total_bits_used |
integer | All-time total number of Bits used on this channel by the specified user. |
user_id |
string | User ID of the person who used the Bits. |
user_name |
string | Login name of the person who used the Bits. |
version |
string | Message version |
Example: Bits Badge Notification Message
{
"type":"MESSAGE","data":{"topic":"channel-bits-badge-unlocks.401394874","message":"
{
\"user_id\":\"232889822\",\"user_name\":\"willowolf\",\"channel_id\":\"401394874\",\"channel_name\":\"fun_test12345\",\"badge_tier\":1000,\"chat_message\":\"this should be received by the public pubsub listener\",\"time\":\"2020-12-06T00:01:43.71253159Z\"}"
}
}
Field | Type | Description |
user_id |
string | ID of user who earned the new Bits badge |
user_name |
string | Login of user who earned the new Bits badge |
channel_id |
string | ID of channel where user earned the new Bits badge |
channel_name |
string | Login of channel where user earned the new Bits badge |
badge_tier |
integer | Value of Bits badge tier that was earned (1000, 10000, etc.) |
chat_message |
string | [Optional] Custom message included with share |
time |
string | Time when the new Bits badge was earned. RFC 3339 format. |
Example: Channel Points Event Message
{
"type": "reward-redeemed",
"data": {
"timestamp": "2019-11-12T01:29:34.98329743Z",
"redemption": {
"id": "9203c6f0-51b6-4d1d-a9ae-8eafdb0d6d47",
"user": {
"id": "30515034",
"login": "davethecust",
"display_name": "davethecust"
},
"channel_id": "30515034",
"redeemed_at": "2019-12-11T18:52:53.128421623Z",
"reward": {
"id": "6ef17bb2-e5ae-432e-8b3f-5ac4dd774668",
"channel_id": "30515034",
"title": "hit a gleesh walk on stream",
"prompt": "cleanside's finest \n",
"cost": 10,
"is_user_input_required": true,
"is_sub_only": false,
"image": {
"url_1x": "https://static-cdn.jtvnw.net/custom-reward-images/30515034/6ef17bb2-e5ae-432e-8b3f-5ac4dd774668/7bcd9ca8-da17-42c9-800a-2f08832e5d4b/custom-1.png",
"url_2x": "https://static-cdn.jtvnw.net/custom-reward-images/30515034/6ef17bb2-e5ae-432e-8b3f-5ac4dd774668/7bcd9ca8-da17-42c9-800a-2f08832e5d4b/custom-2.png",
"url_4x": "https://static-cdn.jtvnw.net/custom-reward-images/30515034/6ef17bb2-e5ae-432e-8b3f-5ac4dd774668/7bcd9ca8-da17-42c9-800a-2f08832e5d4b/custom-4.png"
},
"default_image": {
"url_1x": "https://static-cdn.jtvnw.net/custom-reward-images/default-1.png",
"url_2x": "https://static-cdn.jtvnw.net/custom-reward-images/default-2.png",
"url_4x": "https://static-cdn.jtvnw.net/custom-reward-images/default-4.png"
},
"background_color": "#00C7AC",
"is_enabled": true,
"is_paused": false,
"is_in_stock": true,
"max_per_stream": { "is_enabled": false, "max_per_stream": 0 },
"should_redemptions_skip_request_queue": true
},
"user_input": "yeooo",
"status": "FULFILLED"
}
}
}
Field | Type | Description |
timestamp |
string | Time the pubsub message was sent |
redemption |
object | Data about the redemption, includes unique id and user that redeemed it |
channel_id |
string | ID of the channel in which the reward was redeemed. |
redeemed_at |
string | Timestamp in which a reward was redeemed |
reward |
object | Data about the reward that was redeemed |
user_input (optional) |
string | A string that the user entered if the reward requires input |
status |
string | reward redemption status, will be FULFULLED if a user skips the reward queue, UNFULFILLED otherwise |
Example: Channel Subscriptions Event Message
The data
field is a JSON object that contains topic
and message
fields. Typically, message
is a JSON object that has been escaped (see “Example: Bits Event Message”) and cast into a string.
Note: The months
field is deprecated. We now have fields for cumulative-months
and streak-months
.
Following is an example of a sub/resub message:
{
"type": "MESSAGE",
"data": {
"topic": "channel-subscribe-events-v1.44322889",
"message": {
"user_name": "tww2",
"display_name": "TWW2",
"channel_name": "mr_woodchuck",
"user_id": "13405587",
"channel_id": "89614178",
"time": "2015-12-19T16:39:57-08:00",
"sub_plan": "1000",
"sub_plan_name": "Channel Subscription (mr_woodchuck)",
"cumulative_months": 9,
"streak_months": 3,
"context": "resub",
"is_gift": false,
"sub_message": {
"message": "A Twitch baby is born! KappaHD",
"emotes": [
{
"start": 23,
"end": 7,
"id": 2867
}
]
}
}
}
}
Here is an example of a subgift message, which contains recipient information.
{
"type": "MESSAGE",
"data": {
"topic": "channel-subscribe-events-v1.44322889",
"message": {
"user_name": "tww2",
"display_name": "TWW2",
"channel_name": "mr_woodchuck",
"user_id": "13405587",
"channel_id": "89614178",
"time": "2015-12-19T16:39:57-08:00",
"sub_plan": "1000",
"sub_plan_name": "Channel Subscription (mr_woodchuck)",
"months": 9,
"context": "subgift",
"is_gift": true,
"sub_message": {
"message": "",
"emotes": null
},
"recipient_id": "19571752",
"recipient_user_name": "forstycup",
"recipient_display_name": "forstycup"
}
}
}
Here is an example of a multi-month subgift message, which contains recipient information as well as the number of months gifted.
{
"type": "MESSAGE",
"data": {
"topic": "channel-subscribe-events-v1.44322889",
"message": {
"user_name": "tww2",
"display_name": "TWW2",
"channel_name": "mr_woodchuck",
"user_id": "13405587",
"channel_id": "89614178",
"time": "2015-12-19T16:39:57-08:00",
"sub_plan": "1000",
"sub_plan_name": "Channel Subscription (mr_woodchuck)",
"months": 9,
"context": "subgift",
"is_gift": true,
"sub_message": {
"message": "",
"emotes": null
},
"recipient_id": "19571752",
"recipient_user_name": "forstycup",
"recipient_display_name": "forstycup",
"multi_month_duration": 6
}
}
}
Here is an example of an anonsubgift message. This is like subgift but contains no sender information, since the gifter is anonymous.
{
"type": "MESSAGE",
"data": {
"topic": "channel-subscribe-events-v1.44322889",
"message": {
"channel_name": "mr_woodchuck",
"channel_id": "89614178",
"time": "2015-12-19T16:39:57-08:00",
"sub_plan": "1000",
"sub_plan_name": "Channel Subscription (mr_woodchuck)",
"months": 9,
"context": "anonsubgift",
"is_gift": true,
"sub_message": {
"message": "",
"emotes": null
},
"recipient_id": "13405587",
"recipient_user_name": "tww2",
"recipient_display_name": "TWW2"
}
}
}
Field | Type | Description |
channel_id |
string | ID of the channel that has been subscribed or subgifted |
channel_name |
string | Name of the channel that has been subscribed or subgifted |
context |
string | Event type associated with the subscription product, values: sub , resub , subgift , anonsubgift , resubgift , anonresubgift |
data |
JSON | Wraps the topics and message fields |
user_id |
string | User ID of the person who subscribed or sent a gift subscription |
user_name |
string | Login name of the person who subscribed or sent a gift subscription |
display_name |
string | Display name of the person who subscribed or sent a gift subscription |
message |
string | The body of the user-entered resub message. Depending on the type of message, the message body contains different fields |
months |
int | Cumulative number of months the gifter has giften in the channel (Deprecated) |
recipient_id |
string | User ID of the subscription gift recipient |
recipient_user_name |
string | Login name of the subscription gift recipient |
recipient_display_name |
string | Display name of the person who received the subscription gift |
sub_plan |
string | Subscription Plan ID, values: Prime , 1000 , 2000 , 3000 |
sub_plan_name |
string | Channel Specific Subscription Plan Name |
time |
string | Time when the subscription or gift was completed. RFC 3339 format |
topic |
string | The topic that the message pertains to |
type |
string | Valid value: MESSAGE |
cumulative_months |
string | Cumulative number of tenure months of the subscription |
streak_months |
string | Denotes the user’s most recent (and contiguous) subscription tenure streak in the channel |
is_gift |
bool | If this sub message was caused by a gift subscription |
multi_month_duration |
int | Number of months gifted as part of a single, multi-month gift OR number of months purchased as part of a multi-month subscription |
Example: Multi-month Subscription Message
Here is an example of a multi-month subscription message. This message is published upon purchase, auto-renewal, or re-subscription for a multi-month, recurring subscription
{
"type": "MESSAGE",
"data": {
"topic": "channel-subscribe-events-v1.44322889",
"message": {
"user_name": "tww2",
"display_name": "TWW2",
"channel_name": "mr_woodchuck",
"user_id": "13405587",
"channel_id": "89614178",
"time": "2015-12-19T16:39:57-08:00",
"sub_plan": "1000",
"sub_plan_name": "Channel Subscription (mr_woodchuck)",
"months": 4,
"context": "sub",
"is_gift": false,
"sub_message": {
"message": "",
"emotes": null
},
"recipient_id": "19571752",
"recipient_user_name": "forstycup",
"recipient_display_name": "forstycup",
"multi_month_duration": 6
}
}
}
Example: AutoMod Queue Message
{
"type": "MESSAGE",
"data": {
"topic": "automod-queue.46024993.44322889",
"message": {
"type": "automod_caught_message",
"data": {
"message": {
"id": "some-automod-caught-message-id",
"content": {
"text": "a bad word",
"fragments": [
{
"text": "a bad word",
"automod": {
"topics": {
"swearing": 6
}
}
}
]
},
"sender": {
"user_id": "559969259",
"login": "msongvo222",
"display_name": "msongvo222",
"chat_color": "#8A2BE2"
},
"sent_at": "2021-05-24T18:46:20.964Z"
},
"content_classification": {
"category": "swearing",
"level": 2
},
"status": "PENDING",
"reason_code": "",
"resolver_id": "",
"resolver_login": ""
}
}
}
}
Field | Type | Description |
id |
string | Identifier of the message |
content |
object | Object containing details about the message |
text |
string | The text of the message |
fragments |
object | Object defining the potentially inappropriate content of the message |
sender |
object | Object representing the sender of the message |
user_id |
integer | User ID of the sender |
login |
string | User login on the sender |
display_name |
string | User display name of the sender |
chat_color |
string | Chat color of the sender |
sent_at |
string | Timestamp the message was sent in RFC3339 format. |
content_classification |
object | Object defining the category and level that the content was classified as |
category |
string | Category that the message was classified as |
level |
number | The level that the message was classified as. |
status |
string | Current status of the message, can be “PENDING”, “ALLOWED”, “DENIED”, or “EXPIRED”. |
reason_code |
string | Reserved for internal use |
resolver_id |
string | User ID of the moderator that resolved this message |
resolver_login |
string | User login of the moderator that resolved this message |
Example: Low Trust User Treatment Message
{
"low_trust_id": "12826.141981764",
"channel_id": "12826",
"updated_by": {
"id": "12826",
"login": "twitch",
"display_name": "Twitch"
},
"updated_at": "2023-02-03T21:36:12Z",
"target_user_id": "141981764",
"target_user": "twitchdev",
"treatment": "RESTRICTED",
"types": [
"MANUALLY_ADDED"
],
"ban_evasion_evaluation": "",
"evaluated_at": "2023-01-26T20:56:24Z"
}
Field | Type | Description |
---|---|---|
low_trust_id |
string | An ID for the suspicious user entry, which is a combination of the channel ID where the treatment was updated and the user ID of the suspicious user. |
channel_id |
string | ID of the channel where the suspicious user was present. |
updated_by |
object | Information about the moderator who made any update for the suspicious user. |
id |
string | User ID of the moderator. |
login |
string | Login of the moderator. |
display_name |
string | Display name of the moderator. |
updated_at |
string | RFC3339 timestamp of when the treatment was updated for the suspicious user. |
target_user_id |
string | User ID of the suspicious user. |
target_user |
string | Login of the suspicious user. |
treatment |
string | The treatment set for the suspicious user, can be “NO_TREATMENT”, “ACTIVE_MONITORING”, or “RESTRICTED” |
types |
array of strings | User types (if any) that apply to the suspicious user, can be “UNKNOWN_TYPE”, “MANUALLY_ADDED”, “DETECTED_BAN_EVADER”, or “BANNED_IN_SHARED_CHANNEL” |
ban_evasion_evaluation |
string | A ban evasion likelihood value (if any) that as been applied to the user automatically by Twitch, can be “UNKNOWN_EVADER”, “UNLIKELY_EVADER”, “LIKELY_EVADER”, or “POSSIBLE_EVADER” |
evaluated_at |
string | If applicable, an RFC3339 timestamp for the first time the suspicious user was automatically evaluated by Twitch. |
Example: Low Trust User Chat Message
{
"low_trust_user": {
"id": "141981764",
"low_trust_id": "NDU3NTcxMjM0LjgyNjA2NzQyNg",
"channel_id": "12826",
"sender": {
"user_id": "141981764",
"login": "twitchdev",
"display_name": "TwitchDev"
},
"evaluated_at": "2023-01-26T20:56:24Z",
"updated_at": "2023-02-03T21:36:12Z",
"ban_evasion_evaluation": "UNKNOWN_EVADER",
"treatment": "RESTRICTED",
"updated_by": {
"id": "12826",
"login": "twitch",
"display_name": "Twitch"
},
"shared_ban_channel_ids": null,
"types": [
"MANUALLY_ADDED"
]
},
"message_content": {
"text": "hola HeyGuys",
"fragments": [
{
"text": "hola "
},
{
"text": "HeyGuys",
"emoticon": {
"emoticonID": "30259",
"emoticonSetID": "0"
}
}
]
},
"message_id": "853093ce-17c5-4daa-b500-d1ce03115812",
"sent_at": "2023-02-03T21:36:06Z"
}
Field | Type | Description |
---|---|---|
low_trust_user |
object | Information about the low trust message and suspicious user. |
id |
string | The user ID of the suspicious user. |
low_trust_id |
string | Unique ID for this low trust chat message. |
channel_id |
string | ID of the channel where the suspicious user was present. |
sender |
object | Information about the suspicious user. |
user_id |
string | The user ID of the suspicious user. |
login |
string | The login of the suspicious user. |
display_name |
string | The display name of the suspicious user. |
evaluated_at |
string | If applicable, an RFC3339 timestamp for the first time the suspicious user was automatically evaluated by Twitch. |
updated_at |
string | RFC3339 timestamp of when the treatment was updated for the suspicious user. |
ban_evasion_evaluation |
string | A ban evasion likelihood value (if any) that as been applied to the user automatically by Twitch, can be “UNKNOWN_EVADER”, “UNLIKELY_EVADER”, “LIKELY_EVADER”, or “POSSIBLE_EVADER” |
treatment |
string | The treatment set for the suspicious user, can be “NO_TREATMENT”, “ACTIVE_MONITORING”, or “RESTRICTED” |
updated_by |
object | Information about the moderator who made any update for the suspicious user. |
id |
string | The user ID of the moderator who made any update for the suspicious user. |
login |
string | The login of the moderator who made any update for the suspicious user. |
display_name |
string | The display name of the moderator who made any update for the suspicious user. |
shared_ban_channel_ids |
array of strings | A list of channel IDs where the suspicious user is also banned. |
types |
array of strings | User types (if any) that apply to the suspicious user, can be “UNKNOWN_TYPE”, “MANUALLY_ADDED”, “DETECTED_BAN_EVADER”, or “BANNED_IN_SHARED_CHANNEL” |
message_content |
object | The chat message text and fragments sent by the suspicious user. |
text |
string | Plain text of the message sent. |
fragments |
array | Fragments contained in the message, including emotes. |
text |
string | Plain text fragment of the message sent. |
emoticon |
object | Information about an emote if present in the message. |
emoticonID |
string | An ID that identifies this emote. |
emoticonSetID |
string | An ID that identifies the emote set that the emote belongs to. |
message_id |
string | ID of the chat message. |
sent_at |
string | RFC3339 timestamp of when the chat message was sent. |
Example: User Moderation Notification Message
{
"type": "MESSAGE",
"data": {
"topic": "user-moderation-notifications.46024993.44322889",
"message": {
"type": "automod_caught_message",
"data": {
"message_id": "some-automod-caught-message-id",
"status": "DENIED"
}
}
}
}
Field | Type | Description |
id |
string | Identifier of the message |
status |
string | Current status of the message, can be “PENDING”, “ALLOWED”, “DENIED”, or “EXPIRED”. |
Example: Whispers Event Message
The data
field is a JSON object that contains topic
and message
fields. Typically, message
is a JSON object that has been escaped (see “Example: Bits Event Message” above) and cast into a string.
{
"type":"MESSAGE",
"data":{
"topic":"whispers.44322889",
"message":{
"type":"whisper_received",
"data":{
"id":41
},
"thread_id":"129454141_44322889",
"body":"hello",
"sent_ts":1479160009,
"from_id":39141793,
"tags":{
"login":"dallas",
"display_name":"dallas",
"color":"#8A2BE2",
"emotes":[
],
"badges":[
{
"id":"staff",
"version":"1"
}
]
},
"recipient":{
"id":129454141,
"username":"dallasnchains",
"display_name":"dallasnchains",
"color":"",
"badges":[]
},
"nonce":"6GVBTfBXNj7d71BULYKjpiKapegDI1"
},
"data_object":{
"id":41,
"thread_id":"129454141_44322889",
"body":"hello",
"sent_ts":1479160009,
"from_id":44322889,
"tags":{
"login":"dallas",
"display_name":"dallas",
"color":"#8A2BE2",
"emotes":[],
"badges":[
{
"id":"staff",
"version":"1"
}
]
},
"recipient":{
"id":129454141,
"username":"dallasnchains",
"display_name":"dallasnchains",
"color":"",
"badges":[]
},
"nonce":"6GVBTfBXNj7d71BULYKjpiKapegDI1"
}
}
}
The fields in this message are similar to IRC fields. See the Chatbots and IRC documentation.