# Trovo Chat Service - Read from Websocket

# 1. Introduction

Trovo chat service is for applications built by third-party developers to receive and send chat messages to a channel.

(a) Receives chats by connecting to websocket based chat service and keep the persistent connection.

(n) Sends chats through send chat API. (See send chat APIs in Trovo Chat Service (opens new window))

For OAuth and other Trovo APIs please refer to Trovo APIs Developer Doc: Trovo APIs (opens new window)

# 2. Steps to connect chat service websocket

To receive real time chats, you need to create websockets to receive chat messages from one or more channels.

(a) Get a token for chat service. The token will determine which channel or shard or channels you receive chats from. The token would be invalid in 20 seconds.(See section 4.1)

(b) Connect to chat service: Trovo provides a standard websocket protocol wss:// for the chat service. Service address: wss://open-chat.trovo.live/chat

(c) Send AUTH request: Send AUTH request right after successfully connecting to the chat service. Upon successful, the connection will be kept, otherwise, the chat service will be disconnected. (See section 3.1)

(d) Keep persistent connection: Through ping-pong protocol, send heartbeat to our chat service to keep persistent connection. (See section 3.2)

(e) Receive chats: During valid connection, you will receive chats from chat service. (See section 3.3)

# 3. Message structures

Messages are sent in JSON format through websocket. Here is the JSON structure for the chat message:

{
   "type": "<string>",
   "nonce": "<string>",
   "error": "<string>",
   "data": "<JSON>"
}
1
2
3
4
5
6

Field descriptions:

Field name Description
type Required Type of the message. Value options: AUTH, PING, PONG, RESPONSE, CHAT
nonce Optional Random string. Used to match requests and responses. This field is created by the client and returned in the server response. Required for requests sent from the client.
error Optional Error messages returned from the server.
data Optional Data in for the message. The structure of data varies for different message types.

# 3.1 AUTH message

Upon connecting to the chat service, the client needs to send the request for AUTH immediately, otherwise the client will be disconnected to the chat service.

Request format:

{
    "type": "AUTH",
    "nonce": "< random string >",
    "data": {
        "token": "< token from the chat oauth >"
    }
}
1
2
3
4
5
6
7

Response format:

{
   "type": "RESPONSE",
   "nonce": "<string matching the nounce in the request>"
}
1
2
3
4

# 3.2 PING-PONG message

In order to keep persistent connection to the chat service. You need to send heartbeat to the server. The recommended frequency is every 30 sec.

Request format:

{
    "type": "PING",
    "nonce": "<random_string>"
}
1
2
3
4

Response format:

{
    "type": "PONG",
    "nonce": "<string matching the nounce in the request>",
    "data": {
        "gap": 30
    }
}
1
2
3
4
5
6
7

Notice: Gap is sent from the chat service in the response. It is the recommended time period for the client to send heartbeat. Upon receiving the recommended time period, the client should adjust the frequency for sending heartbeat based on the recommendation.

Default recommendation is to send PING every 30 seconds.

# 3.3 CHAT message

Chat messages are sent from the chat server to the client, and the client does not need to respond back to the chat messages.

Chat message structure:

{
    "type": "CHAT",
    "channel_info": {
        "channel_id": "<channel_id>"
    },
    "data": {
        "eid": "<eid>",
        "chats": [
            {
                "type": <message_type_id>,
                "content": "<message_txt>",
                "nick_name": "<display_name>",
                "avatar": "<profile_picture>",
                "sub_lv": "<subscription_level>",
                "sub_tier": "<subscription_tier>",
                "medals": <array_of_badges>,
                "decos": <array_of_profile_pic_decors>,
                "roles": <array_of_roles>,
                "message_id": "<message_id>",
                "sender_id": <sender_user_id>,
                "send_time":<send_time>,
                "uid":<sender_user_id>,
                "user_name": "<sender_user_name>",
                "content_data":<extra_info_for_message>
            }
        ]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

Field descriptions:

Field name Type Description
eid string Message container ID. This is different from message ID. One message container may contain one or multiple messages.
chats Array of chat objects A list of chats. One chat message may contain multiple chats.
type int Type of chat message. For detailed message types and examples, see section below.
content string Content of the message. Now gift message add new fields, including gift_id, gift_value(unit price of a gift) and value_type(currency type, like Elixir, Mana and so on).
nick_name string Display name of the sender.
avatar string URL of the sender’s profile picture.
sub_lv string The subscription level of the user in the channel. “sub_L1” for level 1 subscriber.
sub_tier string Subscription tier
medals string[] The list of badge names of the sender.
decos string[] The list of decoration names of sender.
roles string[] The list of roles of the message sender. One user can have multiple roles, for example: “roles”:[“mod”, “follower”]
message_id string ID of the message.
sender_id int User ID of the sender.
send_time string send time of the message.
uid int User ID of the sender.
user_name string User name of the sender.
content_data map Extra info of chat, The content_data is different in different chat.(See the table below for the meaning of the content_data fields)
custom_role string The list of role of the message sender which is a json string. Different from "roles", "custom_role" contains more information. However, if you just need the role names, use "roles" instead.

content_data field descriptions:

Field name Type Description
custom_emote_enabled Array of custom emotes objects List of custom emotes.
normal_emote_enabled Array of normal emotes objects List of normal emotes.
gift_display_name string Display name of gift.
gift_id int Id of gift
gift_num int Number of gifts.
specialEffectID int Id of luxury gift special effect.
magicChatGiftID int Id of Special effects barrage gift.
rich string Rich text.
chatShowAuth string The identity of the user.
chatViewerThreshold string Chat viewer threshold.
viewers int The number of people watching.
NickName string The nickname of the anchor of the gift sub to live broadcast room.
UserID string The user id of the anchor of the gift sub to live broadcast room
isReSub int Distinguish between first-time subscription and re-subscription. 0 - first-time subscription, 1 - re-subscription.
{
    "type": "CHAT",
    "channel_info": {
        "channel_id": "100000021"
    },
    "data": {
        "eid": "1610095026714481_100000021_2886926419_1",
        "chats": [
            {
                "type": 0,
                "content": "Good game!",
                "nick_name": "leaf",
                "avatar": "exq7kbiaaaaaafch2bzqsjakcy.jpeg?t=3",
                "sub_lv": "L1",
                "sub_tier": "1",
                "medals": [
                    "sub_L1"
                ],
                "roles": [
                    "subscriber",
                    "follower"
                ],
                "message_id": "1610095026391919299_100000021_100000037_2886927498_1",
                "sender_id": 100000037,
                "send_time": 1612335774,
                "uid": 100000037,
                "user_name": "leaf",
                "content_data":<extra_info_for_message>,
                "custom_role":"[{\"roleName\":\"subscriber\",\"roleType\":100004},{\"roleName\":\"follower\",\"roleType\":100006}]"
            }
        ]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 3.4 Chat Message Types and Samples

Type ID Description Sample chat
0 Normal chat messages. { "type": 0, "content": "text", "nick_name": "ohhh", "avatar": "xxx.png?t=0", "sub_lv": "L3","sub_tier": "1", "medals": ["sub_L3"], "roles": [ "subscriber", "follower" ]}
5 Spells, including: mana spells, elixir spells { "type": 5, "content": "{"gift":"Winner", "num":1}", "nick_name": "wangna", "avatar": "xxx.jpeg?t=8", "sub_lv": "L2", "sub_tier": "1", "medals": [ "creator", "sub_L2"], "roles": ["streamer","subscriber" ]}
6 Magic chat - super cap chat { "type": 6, "content": "super cap.", "nick_name": "ohhh", "avatar": "xxx.png?t=0", "sub_lv": "L3","sub_tier": "1", "medals": ["sub_L3"], "roles": [ "subscriber", "follower" ]}
7 Magic chat - colorful chat { "type": 7, "content": "colorful chat", "nick_name": "ohhh", "avatar": "xxx.png?t=0", "sub_lv": "L3","sub_tier": "1", "medals": ["sub_L3"], "roles": [ "subscriber", "follower" ]}
8 Magic chat - spell chat { "type": 8, "content": "This is a spell chat.", "nick_name": "ohhh", "avatar": "xxx.png?t=0", "sub_lv": "L3","sub_tier": "1", "medals": ["sub_L3"], "roles": [ "subscriber", "follower" ]}
9 Magic chat - bullet screen chat { "type": 9, "content": "bullet screen", "nick_name": "wangna", "avatar": "xxx.jpeg?t=8", "sub_lv": "L2","sub_tier": "1", "medals": [ "creator", "sub_L2"], "roles": ["streamer","subscriber" ]}
5001 Subscription message. Shows when someone subscribes to the channel. { "type": 5001, "content": "has subscribed to the channel!", "nick_name": "mynameislong", "avatar": "xxx.jpeg?t=1", "sub_lv": "L3","sub_tier": "1", "medals": [ "sub_L3" ], "roles": [ "subscriber", "follower" ]}
5002 System message. TBD
5003 Follow message. Shows when someone follows the channel. { "type": 5003, "content": "just followed channel!", "nick_name": "ohhh", "avatar": "xxx.png?t=0", "sub_lv": "L3","sub_tier": "1", "medals": ["sub_L3"], "roles": [ "subscriber", "follower" ]}
5004 Welcome message when viewer joins the channel. { "type": 5004, "content": "just joined channel!", "nick_name": "ohhh", "avatar": "xxx.png?t=0", "sub_lv": "L3","sub_tier": "1", "medals": ["sub_L3"], "roles": [ "subscriber", "follower" ]}
5005 Gift sub message. When a user randomly sends gift subscriptions to one or more users in the channel. { "type": 5005, "content": "2", "nick_name": "flower", "avatar": "5.png", "sub_lv": "L1","sub_tier": "1", "medals": [ "sub_L1" ], "roles": ["subscriber"]}// User “flower” send 2 gift subscriptions randomly to viewers
5006 Gift sub message. The detailed messages when a user sends a gift subscription to another user. { "type": 5006, "content": "100000252,CatKing", "nick_name": "flower", "avatar": "5.png", "sub_lv": "L1","sub_tier": "1", "medals": ["sub_L1"], "roles": [ "subscriber" ]}// User “flower” send a gift subscription to user “CatKing”
5007 Activity / events message. For platform level events. { "type": 5007, "content": "{name} just stepped up to LEVEL {level} ! The Top 3 Spell Point Contributors are: \n#1 {e} #2 {1} #3 {2} ", "nick_name": ""}
5008 Welcome message when users join the channel from raid. { "type": 5008, "content": "{nickname} is carrying {raiderNum} raiders to this channel. Welcome!", "nick_name": "leaf", "avatar": "xxx.jpeg?t=1", "sub_lv": "L3","sub_tier": "1", "medals": ["moderator", "sub_L3"], "roles": [ "mod", "follower" ]}
5009 Custom Spells { "type": 5009, "content": "{"gift":"GiftName", "num":1, "sid":1000001}", "nick_name": "wangna", "avatar": "xxx.jpeg?t=8", "sub_lv": "L2","sub_tier": "1", "medals": [ "creator", "sub_L2"], "roles": ["streamer","subscriber" ]}
5012 Stream on/off messages, invisible to the viewers { "type": 5012, "content": "stream_on", "nick_name": "wangna", "avatar": "xxx.jpeg?t=8", "medals": [ "creator"], "roles": ["streamer","subscriber" ]}
5013 Unfollow message. Shows when someone unfollows the channel. { "type": 5013, "content": "{"name":"unfollow","context":"just unfollowed channel."}", "nick_name": "ohhh", "avatar": "xxx.png?t=0", "sub_lv": "L3","sub_tier": "1", "medals": ["sub_L3"], "roles": ["subscriber", "follower" ]}

# 3.5 User Roles

Type ID Roles Description
100000 streamer Streamer of the current channel
100001 mod Moderator of the current channel
100002 editor Editor of the current channel
100004 subscriber User who subscribed the current channel
100005 supermod Super moderator of the current channel
100006 follower User who followed of the current channel
200000 custom role User who have a role customized by the streamer of the current channel
500000 admin Admin of Trovo platform, across all channels.
500001 warden Warden of Trovo platform, across all channels, who helps to maintain the platform order.
300000 ace Primary tier of Trovo membership
300001 ace+ Premium tier of Trovo membership

# 4. Get Chat Token API

OAuth process is required for all APIs and connections of the chat services. Trovo is using OAuth 2.0 for users to grant access to third-party applications. For the more about the OAuth process, please refer to this page. Trovo APIs (opens new window)

# 4.1 Get Chat Token - read chats from my channel only

Gets the token for Trovo chat service. This token allows you to read from the channel of the user that you passed the access token in.

Requested scope: chat_connect

Request access token: Yes

HTTP request type:GET

Request:

curl \
-H 'Accept: application/json' \
-H 'Client-ID: <your_client_id>' \
-H 'Authorization: OAuth <access_token>' \
-X GET 'https://open-api.trovo.live/openplatform/chat/token'
1
2
3
4
5

Sample Response:

{ "token": "xxxxxxxxxxxxxxx="}
1

# 4.2 Get Chat Channel Token - from any selected channel

Gets the token for Trovo chat service. This allows you to pass in the channel ID and read chats from this specific channel. No scope or access token required.

Requested scope: None.

Request access token: No.

Request URL Params:

Param Description
Channel ID required ID of the target channel.

Request Format:

curl \
-H 'Accept: application/json' \
-H 'Client-ID: < your_client_id >' \
-X GET 'https://open-api.trovo.live/openplatform/chat/channel-token/{channelID}'
1
2
3
4

Request Sample:

curl \
-H 'Accept: application/json' \
-H 'Client-ID: <your_client_id>' \
-X GET 'https://open-api.trovo.live/openplatform/chat/channel-token/100000021'
1
2
3
4

Sample Response:

{ "token": "xxxxxxxxxxxxxxx="}
1

# 4.3 Get Chat Shard Token - read from multiple channels

Gets the token of the shard that is used for reading chat messages from multiple channels. (For how sharding works, please read section 5).

Requested scope: None

Request access token: No

Request Params:

Param Type Description
total_shard int Total number of shards. total_shard > 0.
current_shard int The shard_id of the current shard you want to read. 0 <= current_shard < total_shard

Request Format:

curl \
-H 'Accept: application/json' \
-H 'Client-ID: <client_id>’ \
-X GET 'https://open-api.trovo.live/openplatform/chat/shard-token?current_shard={current_shard}&total_shard={total_shard}'
1
2
3
4

Request Sample:

curl \
-H 'Accept: application/json' \
-H 'Client-ID: <your_client_id>’ \
-X GET 'https://open-api.trovo.live/openplatform/chat/shard-token?current_shard=1&total_shard=3'
1
2
3
4

Response Sample - Success, get token:

{"token":"xxxxxxxxxxx"}
1

Response Sample - Failed, invalid shard value:

{
    "status": 11708,
    "error": "Internal Server Error",
    "message": "Invalid shard value (Please make sure total_shard > 0 and 0 <= current_shard < total_shard)"
}
1
2
3
4
5

# 5. Sharding - Read chats from multiple channels

You may read chat messages from multiple channels through one websocket. Here we use sharding, a simple way to divide channels into shards and each websockets will be sending all the chats from channels in this current shard.

Sharding Formula:

shard_id = channel_id % total_shard

Param Type Description
total_shard int Total number of shards. total_shard > 0.
current_shard int The shard_id of the current shard you want to read. 0 <= current_shard < total_shard
channel_id int The id of the channel, also the user id of the streamer.

For example if you set total_shard to 3, then all the channels will be divided into 3 shards, shard_id 0, 1 and 2. Shard 0 will contain all channels with channel id % 3 = 0. Shard 1 contains all channels with channel id % 3 = 1. And channel 2 contains all channels with channel id % 3 = 2. Larger total_shard means less channels in one shard.