Chat

Introduction

Our chat servers use a standard secure websocket protocol wss://. Messages are sent and received in standard JSON.

Connection

To connect to the chat server, you first need to retrieve some connection details from our REST API. You can do this by calling the GET /chats/{channelId} REST endpoint where channelId is the channel id of the channel you wish to join and chat in.

You can find your channel id by going to https://mixer.com/api/v1/channels/username?fields=id in your browser, replacing username with your Mixer username.

If you are authenticated when you make the request, you will receive an authkey in the response for authentication purposes. You may join chat and read messages without being authenticated, but you will not be able to participate in chat.

This is what a typical response from the GET /chats/{channelId} endpoint looks like:

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Date: Sun, 26 Jun 2016 22:50:41 GMT

{
    "authkey": "b41e9ae6b14df18c59f415419b1f827c",
    "endpoints": [
        "wss://chat2-dal.mixer.com:443",
        "wss://chat1-dal.mixer.com:443"
    ],
    "permissions": [
        "chat",
        "connect",
        "poll_vote"
    ]
}

Once you have the details, you'll need to use them to connect to a chat server. The response's endpoints array contains a list of chat servers. You should choose one randomly to connect to. If you lose connection to this address, you should reconnect to a different server (you can choose randomly or use a round-robin strategy of your choosing).

After connecting to a server you must call the auth method.

Packets

There are 3 types of packets sent over the socket: method, reply, and event packets. The former two are typical RPC-style packets; think of sending them as calling a function or method and getting a return value back, but over the network.

We go into more detail below, but a typical exchange between the server and client might look like this:

Client: {"type":"method","method":"auth","arguments":[1,1,"fc3f865c156f32cac0755cde007654a8"],"id":0}
Server: {"type":"reply","error":null,"id":0,"data":{"authenticated":true,"roles":["Owner"]}}
Client: {"type":"method","method":"msg","arguments":["Hello world :)"],"id":2}
Server: {"type":"reply","error":null,"id":2,"data":{"channel":1,"id":"6351f9e0-3bf2-11e6-a3b3-bdc62094c158","user_name":"connor","user_id":1,"user_roles":["Owner"],"message":{"message":[{"type":"text","data":"Hello world ","text":"Hello world!"}],"meta":{}}}}
Server: {"type":"event","event":"ChatMessage","data":{"channel":1,"id":"6351f9e0-3bf2-11e6-a3b3-bdc62094c158","user_name":"connor","user_id":1,"user_roles":["Owner"],"message":{"message":[{"type":"text","data":"Hello world ","text":"Hello world!"}],"meta":{}}}}

Method

A method is sent to the chat server the server will respond with a Reply packet.

type Must be method.
method The method name to execute.
arguments An array of arguments, specific per method type.
id Must be a unique numeric ID. If the method you sent has a reply, the numeric ID will be sent back down in the Reply packet.

Reply

A reply is received from the server in response to a Method packet.

type Must be reply.
error If an error has not occured null, otherwise an error message.
data Associated event data - may be of any type, specific to the event.
id Must be a unique numeric ID. The ID will match the ID sent in the Method packet that this reply is in response to.

Event

An event is received from the chat server when an event occurs in the channel's chat. This includes chat messages themselves, polls, and role changes. The full list can be found in the Events section below.

type Must be event.
event The event name.
data Associated event data - may be of any type, specific to the event.

Methods

auth

Authenticate as an active user in a specified channel. Arguments are channelId, userId, key.

You can connect anonymously by supplying just the channnelId as an argument, but if you do this you will not be able to send messages or participate in chat. This can be useful for creating chat overlays.

Arguments:

  1. The channel ID of the channel you are joining.

  2. The user ID of the user you are connecting as. This can be omitted if you are connecting anonymously.

  3. The authorization key retrieved from a request to our REST API, as explained in the Connection section. This can be omitted if you are connecting anonymously.

Request Response
Authenticating as a User successfully.
{
   "type": "method",
   "method": "auth",
   "arguments": [
      12345,
      54321,
      "key"
   ],
   "id": 0
}
{
   "type": "reply",
   "error": null,
   "id": 0,
   "data": {
      "authenticated": true,
      "roles": [
         "Owner"
      ]
   }
}
Authenticating anonymously
{
   "type": "method",
   "method": "auth",
   "arguments": [
      12345
   ],
   "id": 0
}
{
   "type": "reply",
   "error": null,
   "id": 0,
   "data": {
      "authenticated": false,
      "roles": []
   }
}
An unsuccessful authentication attempt.
{
   "type": "method",
   "method": "auth",
   "arguments": [
      12345,
      12345,
      "Not an AuthKey"
   ],
   "id": 0
}
{
   "type": "reply",
   "error": {
      "code": 1,
      "message": "UNOTFOUND",
      "stacktrace": [],
      "data": {}
   },
   "id": 0
}

msg

Send a chat message to the server. The server will reply with data identical to a ChatMessage event.

This method requires the chat:chat permission scope.

Arguments:

  1. The message to send, as a string.

Request Response
{
   "type": "method",
   "method": "msg",
   "arguments": [
      "Hello World!"
   ],
   "id": 2
}
{
   "type": "reply",
   "error": null,
   "id": 2,
   "data": {
      "channel": 12345,
      "id": "06cba8a0-3a4a-11e6-b410-e9a72fcede64",
      "user_name": "username",
      "user_id": 12345,
      "user_roles": [
         "User"
      ],
      "message": {
         "message": [
            {
               "type": "text",
               "data": "Hello World!",
               "text": "Hello World!"
            }
         ],
         "meta": {}
      }
   }
}

whisper

Send a whisper to another user in the chat.

This method requires the chat:whisper permission scope.

Arguments:

  1. The username of the user that the whisper will be sent to.

  2. The whisper's message.

Request Response
{
   "type": "method",
   "method": "whisper",
   "arguments": [
      "targetUsername",
      "message"
   ],
   "id": 5
}
{
   "type": "reply",
   "error": null,
   "id": 5,
   "data": {
      "channel": 12345,
      "id": "077e31c0-3a34-11e6-89dd-6363b2f3be15",
      "user_name": "username",
      "user_id": 12345,
      "user_roles": [
         "User"
      ],
      "message": {
         "message": [
            {
               "type": "text",
               "data": "hi",
               "text": "hi"
            }
         ],
         "meta": {
            "whisper": true
         }
      },
      "target": "username"
   }
}

vote:choose

Cast a vote in the current poll.

This method requires the chat:poll_vote permission scope.

Arguments:

  1. The numerical index of the option that the vote is being cast for.

Request Response
{
   "type": "method",
   "method": "vote:choose",
   "arguments": [
      0
   ],
   "id": 3
}
{
   "type": "reply",
   "error": null,
   "id": 3,
   "data": true
}

vote:start

Start a poll in the channel.

This method requires the chat:poll_start permission scope.

Arguments:

  1. The poll's question.

  2. An array of possible options.

  3. The duration of the poll, in seconds.

Request Response
{
   "type": "method",
   "method": "vote:start",
   "arguments": [
      "Turkey or Ham?",
      [
         "Turkey",
         "Ham"
      ],
      30
   ],
   "id": 3
}
{
   "type": "reply",
   "error": null,
   "id": 3,
   "data": "Poll started."
}

timeout

Time a user out and purge their chat messages. They cannot send messages until the duration is over. The user being timed out must be in the channel.

This method requires the chat:timeout permission scope.

Arguments:

  1. The username of the user who will be timed out.

  2. The duration for which the user will be unable to send messages. A human-readable duration with units can be provided (such as 30s or 1m15s), or providing no unit will result in the value being taken as seconds.

Request Response
{
   "type": "method",
   "method": "timeout",
   "arguments": [
      "username",
      "30s"
   ],
   "id": 4
}
{
   "type": "reply",
   "error": null,
   "id": 4,
   "data": "username has been timed out for 30s."
}

purge

Purge a user's messages from that chat without timing them out.

This method requires the chat:purge permission scope.

Arguments:

  1. The username of the user to purge.

Request Response
{
   "type": "method",
   "method": "purge",
   "arguments": [
      "username"
   ],
   "id": 5
}
{
   "type": "reply",
   "error": null,
   "id": 5
}

deleteMessage

Delete a message from chat.

This method requires the chat:remove_message permission scope.

Arguments:

  1. The id property of the message to delete.

Request Response
{
   "type": "method",
   "method": "deleteMessage",
   "arguments": [
      "8e07a0b0-3a2e-11e6-a9ef-0b7037d1fbdd"
   ],
   "id": 10
}
{
   "type": "reply",
   "error": null,
   "id": 10,
   "data": "Message deleted."
}

clearMessages

Clear all chat messages in the channel.

This method requires the chat:clear_messages permission scope.

Request Response
{
   "type": "method",
   "method": "clearMessages",
   "arguments": [],
   "id": 11
}
{
   "type": "reply",
   "error": null,
   "id": 11,
   "data": "Messages cleared."
}

history

Request previous messages from this chat from before you joined.

Arguments:

  1. The number of messages to request. The maximum value is 100.

Request Response
{
   "type": "method",
   "method": "history",
   "arguments": [
      1
   ],
   "id": 1
}
{
   "type": "reply",
   "error": null,
   "id": 1,
   "data": [
      {
         "channel": 12345,
         "id": "8e07a0b0-3a2e-11e6-a9ef-0b7037d1fbdd",
         "user_name": "username",
         "user_id": 186526,
         "user_roles": [
            "User"
         ],
         "message": {
            "message": [
               {
                  "type": "text",
                  "data": "historic message",
                  "text": "historic message"
               }
            ],
            "meta": {}
         }
      }
   ]
}

giveaway:start

Start a giveaway in the channel. After sending this method, the 'HypeBot' user will publicly announce the winner of the giveaway, who will be randomly selected.

This method requires the chat:giveaway_start permission scope.

Request Response
{
   "type": "method",
   "method": "giveaway:start",
   "arguments": [],
   "id": 11
}
{
   "type": "reply",
   "error": null,
   "id": 11,
   "data": "Starting a giveaway"
}

ping

A ping method. This is used in environments where websocket implementations do not natively support pings.

Request Response
{
   "type": "method",
   "method": "ping",
   "arguments": [],
   "id": 12
}
{
   "type": "reply",
   "error": null,
   "id": 12
}

attachEmotes

Enable an enhancement to the ChatMessage event. This will populate the meta property of the event with a hash containing the emoticon text mapped to the base64 PNG representation.

Request Response
Tells the chat server that you want emotes to be attached to chat messages.
{
   "type": "method",
   "method": "attachEmotes",
   "arguments": [],
   "id": 12
}
{
   "type": "reply",
   "error": null,
   "id": 12
}
The `ChatMessage` event will now look as follows:
{}
{
   "type": "event",
   "event": "ChatMessage",
   "data": {
      "channel": 143,
      "id": "f1e092c0-9c8c-11e6-91dd-55a101b33e4e",
      "user_name": "Jamy",
      "user_id": 162,
      "user_roles": [
         "Owner"
      ],
      "message": {
         "message": [
            {
               "type": "emoticon",
               "source": "builtin",
               "pack": "default",
               "coords": {
                  "x": 96,
                  "y": 0,
                  "width": 24,
                  "height": 24
               },
               "text": ":)"
            }
         ],
         "meta": {
            "emoticons": {
               ":)": "iVBORw0KGgoAAAANSUhE...AAAElFTkSuQmCC"
            }
         }
      }
   }
}

Events

WelcomeEvent

Sent by the server once you're fully connected to chat.

{
   "type": "event",
   "event": "WelcomeEvent",
   "data": {
      "server": "cb4fce87-cd05-44db-830e-cccc53a33fab"
   }
}

ChatMessage

Sent by the server when a client sends a message. It contains multiple message components, such as text, emoticon, link, and tag. The meta property of a message contains various attributes which define additional details about where the message comes from.

Regular Message

A regular channel message seen by all users

{
   "type": "event",
   "event": "ChatMessage",
   "data": {
      "type": "event",
      "event": "ChatMessage",
      "data": {
         "channel": 12345,
         "id": "cfa8a5b0-2ec5-11e6-1234-f3d652ffec28",
         "user_name": "Username",
         "user_id": 12345,
         "user_roles": [
            "User"
         ],
         "message": {
            "message": [
               {
                  "type": "text",
                  "data": "Hello! ",
                  "text": "Hello! "
               },
               {
                  "type": "emoticon",
                  "source": "builtin",
                  "pack": "default",
                  "coords": {
                     "x": 96,
                     "y": 0,
                     "width": 24,
                     "height": 24
                  },
                  "text": ":)"
               },
               {
                  "type": "text",
                  "data": " ",
                  "text": " "
               },
               {
                  "type": "link",
                  "url": "http://mixer.com/mixer",
                  "text": "mixer.com/mixer"
               },
               {
                  "type": "emoticon",
                  "source": "external",
                  "pack": "https://uploads.mixer.com/emoticons/x.png",
                  "coords": {
                     "x": 24,
                     "y": 48,
                     "width": 24,
                     "height": 24
                  },
                  "text": ":coolpartneremote"
               }
            ],
            "meta": {}
         }
      }
   }
}

Whisper

A private whisper from one user to another which is only sent to the recipient. The meta object contains a whisper attribute which is true.

{
   "type": "event",
   "event": "ChatMessage",
   "data": {
      "channel": 12345,
      "id": "eaf6e9b0-3a25-11e6-b410-e9a72fcede64",
      "user_name": "username",
      "user_id": 12345,
      "user_roles": [
         "User"
      ],
      "message": {
         "message": [
            {
               "type": "text",
               "data": "hi",
               "text": "hi"
            }
         ],
         "meta": {
            "whisper": true
         }
      },
      "target": "recipient username"
   }
}

Action

When a user uses /me in chat. The meta object contains a me attribute which is true.

{
   "type": "event",
   "event": "ChatMessage",
   "data": {
      "channel": 12345,
      "id": "c46148d0-3a30-11e6-b368-2953589298fa",
      "user_name": "username",
      "user_id": 12345,
      "user_roles": [
         "User"
      ],
      "message": {
         "message": [
            {
               "type": "text",
               "data": "waves",
               "text": "waves"
            }
         ],
         "meta": {
            "me": true
         }
      }
   }
}

Tag

When a user tags another user with @ e.g. @username

{
   "channel": 12345,
   "id": "c46148d0-3a30-11e6-b368-2953589298fa",
   "user_name": "username",
   "user_id": 12345,
   "user_roles": [
      "User"
   ],
   "message": {
      "message": [
         {
            "text": "@username",
            "type": "tag",
            "username": "username",
            "id": 12345
         }
      ],
      "meta": {}
   }
}

UserJoin

Sent when a user joins the chat. This is not emitted for unauthenticated users.

{
   "originatingChannel": 1,
   "username": "USERNAME",
   "roles": [
      "User"
   ],
   "id": 12345
}

UserLeave

Sent when a user leaves the chat. This is not emitted for unauthenticated users.

{
   "originatingChannel": 1,
   "username": "USERNAME",
   "id": 12345
}

PollStart

Initially sent when a new poll is started. Then, over the course of a poll, it is re-sent with information about the poll's progress.

{
   "originatingChannel": 1,
   "q": "How's the weather?",
   "answers": [
      "Good.",
      "Bad."
   ],
   "author": {
      "user_name": "USERNAME",
      "user_id": 12345,
      "user_roles": [
         "Mod"
      ]
   },
   "duration": 29996,
   "endsAt": 1465533783407,
   "voters": 0,
   "responses": {
      "Good.": 0,
      "Bad.": 0
   }
}

PollEnd

Sent when a poll has ended.

{
   "originatingChannel": 1,
   "q": "How's the weather?",
   "answers": [
      "Good.",
      "Bad."
   ],
   "author": {
      "user_name": "USERNAME",
      "user_id": 12345,
      "user_roles": [
         "Mod"
      ]
   },
   "duration": 29996,
   "endsAt": 1465533783407,
   "voters": 5,
   "responses": {
      "Good.": 2,
      "Bad.": 3
   }
}

DeleteMessage

Sent when a message has been deleted from chat.

{
   "type": "event",
   "event": "DeleteMessage",
   "data": {
      "moderator": {
         "user_name": "USERNAME",
         "user_id": 12345,
         "user_roles": [
            "Mod",
            "User"
         ],
         "user_level": 12
      },
      "id": "b6661250-3a31-11e6-830a-a1d867c5621f"
   }
}

PurgeMessage

Sent when a user's messages are purged. Note: The moderator object is only set when a user is purged from in chat. The ban event triggers a purge but the object is not defined.

{
   "type": "event",
   "event": "PurgeMessage",
   "data": {
      "moderator": {
         "user_name": "USERNAME",
         "user_id": 12345,
         "user_roles": [
            "Mod",
            "User"
         ],
         "user_level": 12
      },
      "user_id": 12345
   }
}

ClearMessages

Sent when the server clears all messages in chat.

{
   "type": "event",
   "event": "ClearMessages",
   "data": {
      "clearer": {
         "user_name": "USERNAME",
         "user_id": 12345,
         "user_roles": [
            "Mod",
            "User"
         ],
         "user_level": 12
      }
   }
}

UserUpdate

Sent when a user is updated, usually on status change. E.g. Modding, Subscribing, Banning.

{
   "type": "event",
   "event": "UserUpdate",
   "data": {
      "user": 12345,
      "roles": [
         "Banned",
         "Pro",
         "User"
      ],
      "permissions": [],
      "username": "username"
   }
}

UserTimeout

Sent only to a user when they are timed out.

{
   "type": "event",
   "event": "UserTimeout",
   "data": {
      "user": {
         "user_name": "username",
         "user_id": 102534,
         "user_roles": [
            "Pro",
            "User"
         ]
      },
      "duration": 59998
   }
}

Costreaming

In costreaming, multiple channels' chats are merged into one. All packets are identical, and the various Channel properties in methods and events include the channel each action was triggered from.

Troubleshooting

Getting UNOTFOUND a lot?

This error means that the chat server you're connecting to can't find a record of you when you try to authenticate. This can be caused by a number of reasons so make sure to check the following things.

  • That you're not confusing channelIds and userIds. These are two different numbers.
  • That the channel you're trying to connect to is valid.
  • That you've retrieved an authentication key from the GET /chats/{channelId} endpoint recently. Authentication keys expire after a short period.
  • That you're calling the auth method with 3 arguments that are not null in the following order:
    1. The channel id of the channel you wish to chat in encoded as a Number.
    2. The user id of the user you wish to chat as encoded as a Number.
    3. An authentication key retrieved from GET /chats/{channelId}, where channelId matches the first argument. It should be encoded as a String.

Need more help?

If you're still not sure, or would like some help, hit us up on Gitter!