Constellation is a daemon whose purpose is to unite all stateful functions of mixer.com.

One of its main features is liveloading.

Liveloading

Liveloading is an event system on Mixer. When models update, users follow channels, or anything else happens that clients might want to be aware of an event is sent. Users must subscribe to Events to recieve them.

Pro tip: you can view liveloading in-action by viewing your websocket log on mixer.com.

Clients

A number of clients already support Constellation. Try them out for a jump start into Constellation.

Session

Users authenticate to Constellation by sending their existing cookies or authentication details in socket headers. No external API are endpoints needed.

Users remain connected to Constellation throughout their session. During the session, they may subscribe to events happening on the site and get notifications when those events occur.

Protocol

Constellation is based on JSON-RPC with additional support for an event system. Initially a user connects to constellation.mixer.com with a standard WebSocket connection. Aside from standard websocket headers, the following headers may also be passed:

  • cookie: may contain the Mixer session cookie. Its presence will cause Constellation to attempt to authenticate the user.
  • authorization: may contain an OAuth Bearer token to authenticate with for 3rd party apps, rather than using a cookie. This will indicate to Constellation that the user is a bot.
  • x-sec-websocket-protocol: if set to cnstl-gzip, Constellation may choose to send websocket frames down as binary, gzipped JSON rather than plain text. Passing this is generally handled by websocket clients themselves, and are usually configured by specifying a preferred subprotocol.

    The client may detect gzipped frames by the fact that they are binary messages and begin with the magic bytes 0x1f and 0x8b as the first and second payload byte, respectively.

  • x-is-bot: this must be set to true if the client is an automated bot rather than a human user and you are not using an authorization header. Failure to set this may cause the account to be banned.

Packets

There are three packet types: method, reply, and event. These are sent over the websocket as JSON encoded messages. Messages to the client may be gzipped if x-supports-gzip was passed in the headers, messages sent to Constellation are always allowed to be gzipped.

Method

Method packets are sent from the client in a way very similar to JSON-RPC. This is the only packet the client may send to the server. A method may look like the following:

{"type": "method", "method": "divide", "params": {"numerator": 16, "denominator": 4}, "id": 123}
  • type is always set to "method"
  • method should be the name of the method to call
  • params should be an object, not an array, of named arguments to pass into the method.
  • id may be any uint32. It’s included in the reply packet and used to correlate replies from the socket. You should ensure that each request has a unique id within your session.

Reply

Reply packets are sent in response to method packets. Replies are always sent in response to methods unless the socket closes before they may be sent. Some reply packets may look like the following:

{"type": "reply", "result": 4, "error": null, "id": 123}
{"type": "reply", "result": null, "error": {"code": 1000, "message": "Cannot divide by zero"}, "id": 124}
  • type is always set to "reply"
  • id is set to the id passed in the corresponding method packet
  • result is the unstructured result of the method, or null
  • error is an error which occurred, or null. If present it will always contain a "code" and an associated "message"

    Note that if fatal errors occur as a result of a method call, a websocket close frame will be sent instead of a reply. The close frame’s code and associated message will be the same as that which otherwise would have been sent in reply.error.

Event

Event packets are sent when an action occurs which a client as asked to be notified about. Event packets look like the following:

{"type": "event", "event": "math_result", "data": 4}
  • type is always set to "event"
  • event is the string name of the event
  • data is unstructured information associated with the event. Usually this is the same as found within the liveloading/sails event of the same type.

Error Codes

Constellation uses the 4xxx error code range reserved for use by applications in addition to the standard 1xxx codes. The following codes are in use:

  • 1011 - Sent in a close or method reply if an unknown internal error occurs.
  • 1012 - Sent in a close frame when we deploy or restart Constellation; clients should attempt to reconnect.
  • 4006 - Error parsing payload as JSON
  • 4007 - Error decompressing a supposedly-gzipped payload
  • 4008 - Unknown packet type
  • 4009 - Unknown method name call
  • 4010 - Error parsing method arguments (not the right type or structure)
  • 4011 - The user session has expired; if using a cookie, they should log in again, or get a bearer auth token if using an authorization header.
  • 4106 - Unknown event used in a livesubscribe call
  • 4107 - You do not have access to subscribe to that livesubscribe event
  • 4108 - You are already subscribed to that livesubscribe event (during livesubscribe)
  • 4109 - You are not subscribed to that livesubscribe event (in response to a liveunsubscribe method)

Methods

livesubscribe

A livesubscribe method allows users to subscribe to liveloading events.

{"type": "method", "method": "livesubscribe", "params": {"events": ["user:1:update", "channel:1:followed"]}, "id": 42}
  • events is an array of events to subscribe to. Note that either all events are successfully subscribed to, or a failure occurs and no events are subscribed to. Either do or do not, there is no try.

A livesubscribe reply looks like one of the following:

  • A successful reply:
  • {"type": "reply", "result": null, "error": null, "id": 42}
  • A reply with an invalid event:
  • {"type": "reply", "result": null, "error": {"code": 4106, "message": "Unknown event \"my silly event\" "}, "id": 42}
  • A reply for an event you do not have permission to see:
  • {"type": "reply", "result": null, "error": {"code": 4107, "message": "You do not have permission to subscribe to \"user:1:secrets\""}, "id": 42}
  • A reply for an event you are already subscribed to:
  • {"type": "reply", "result": null, "error": {"code": 4108, "message": "Attempt to duplicate subscription to \"user:1:update\""}, "id": 42}

liveunsubscribe

A liveunsubscribe method can be used to stop listening to previously-subscribed-to events:

{"type": "method", "method": "liveunsubscribe", "params": {"events": ["user:1:update", "channel:1:followed"]}, "id": 42}
  • events is an array of events to unsubscribe from. Note that if you are not subscribed to one or more of the events, no error is returned.

A liveunsubcribe reply looks like the following:

{"type": "reply", "result": null, "error": null, "id": 42}

ping

A ping method should be used in environments where websocket implementations do not natively support pings.

{"id":1,"type":"method","method":"ping","params":null}

A ping reply is a blank reply packet with a matching id.

{"id":1,"type":"reply","result":{},"error":null}

Events

hello

A hello event is sent down to the client when they first connect.

{"type": "event", "event": "hello", "data": {"authenticated": true}}
  • authenticated is true if the session is authenticated as a user.

live

A live event looks like the following. Do note the socket event names are not liveloading events. Events you ask for over liveloading are always "live" events which contain the liveloading information. This separation is added so that other kinds of events can be distinguished from liveloading events.

{"type": "event", "event": "live", "data": {"channel": "user:1:update", "payload": {"sparks": 10000}}}

Live Event Types

The following live events are available to subscribe to.

Event Description
⁠⁠⁠⁠announcement:announce

Sent when there is a site-wide announcement. The message property of the body contains the announcement text. Other fields affect how the announcement is displayed on mixer.com.

Payload: Announcement

The site-wide announcement that has been sent.

View example

channel:{id}:followed

Sent when a user follows or unfollows a channel.

Payload: object
  • following:  boolean

    Whether the user just followed the channel (true if this was a follow and false if this was an unfollow).

  • user:  User

    The user who followed the channel. This also includes the channel object as channel.

View example

channel:{id}:hosted

Sent when another user hosts the channel with the provided id. Note that this event is not subject to the spam prevention that the chat message is.

Payload: object
  • hosterId:  uint

    The channel ID who just hosted the channel.

  • hoster:  Channel

    The channel object who just hosted the channel.

View example

channel:{id}:unhosted

Sent when another user finishes hosting the channel with the provided id. Note that this event is not subject to the spam prevention that the chat message is.

Payload: object
  • hosterId:  uint

    The ID of the user who hosted the channel.

  • hoster:  User

    The user who hosted the channel.

View example

channel:{id}:subscribed

Sent when a user subscribes to the channel.

Payload: object
  • user:  User

    The user who just subscribed to the channel.

View example

channel:{id}:resubscribed

Sent when an automatic resubscription to a channel happens.

Payload: object
  • user:  User

    The user who just subscribed to the channel.

  • since:  IsoDate

    The date for when the user first subscribed, from the start of the recurring billing period.

  • until:  IsoDate

    The date for when the subscription expires.

  • totalMonths:  uint

    The number of months the user has been subscribed since the beginning of time.

View example

channel:{id}:resubShared

Sent when a user who has recently resubscribed to the channel chooses to 'share' their resubscription, by clicking the 'Share' button within the site chat. This event is preferred to the channel:{id}:resubscribed event if your integration reacts with some form of celebration, but you should be aware that this event will not fire at all for a resubscription if the user does not choose to share it. The body is identical to that of the channel:{id}:resubscribed event.

Payload: object
  • user:  User

    The user who just subscribed to the channel.

  • since:  IsoDate

    The date for when the user first subscribed, from the start of the recurring billing period.

  • until:  IsoDate

    The date for when the subscription expires.

  • totalMonths:  uint

    The number of months the user has been subscribed since the beginning of time.

View example

channel:{id}:update

Sent when the channel model is changed.

Payload: Channel

Contains changes to the channel model. Please note this event may not necessarily include the entire channel resource. For example, when a channel goes online, an event with the key online going to true is sent.

costream:{id}:update

Sent when a costream model is changed (e.g. when a streamer joins/leaves the costream, or when the costream's settings have been changed).

Payload: Costream

The full costream model after the costream has been changed.

View example

interactive:{id}:connect

Sent when an interactive app connects to this channel.

Payload: string

The address of the interactive server the application has connected to.

View example

interactive:{id}:disconnect

Sent when an interactive app disconnects from this channel.

Payload: string

The address of the interactive server the application has connected to.

View example

team:{id}:deleted

Sent when a team is deleted.

Payload: object
  • team:  Team

    The team's record prior to deletion.

View example

team:{id}:memberAccepted

Sent when an invitee accepts their team invitation.

Payload: User

The user who accepted their invitation.

View example

team:{id}:memberInvited

Sent when a member is invited to a team.

Payload: User

The user who was sent an invitation.

View example

team:{id}:memberRemoved

Sent when a team member leaves or invitee rejects their invite.

Payload: User

The member who left the team.

View example

team:{id}:ownerChanged

Sent when a team's ownership changes.

Payload: User

The new team owner.

View example

user:{id}:achievement

Sent when a user achievement earning is updated.

Payload: AchievementEarning

The updated achievement.

View example

user:{id}:followed

Sent when a user follows or unfollows a channel.

Payload: object
  • following:  boolean

    Whether the user just followed the channel (true if this was a follow and false if this was an unfollow).

  • channel:  Channel

    The channel that the user just followed.

View example

user:{id}:notify

Sent when the user receives a new notification. Notifications of the same type will always follow the same structure. This event requires authentication.

Payload: Notification

The new notification.

View example

user:{id}:subscribed

Sent when the user subscribes to another channel.

Payload: object
  • channel:  uint

    The ID of the channel the user subscribed to.

View example

user:{id}:resubscribed

Sent when an automatic resubscription to a channel happens.

Payload: object
  • channel:  uint

    The ID of the channel the user subscribed to.

  • since:  IsoDate

    The date for when the user first subscribed, from the start of the recurring billing period.

  • until:  IsoDate

    The date for when the subscription expires.

  • totalMonths:  uint

    The number of months the user has been subscribed since the beginning of time.

View example

user:{id}:teamAccepted

Sent when a user accepts their invite to a team.

Payload: Team

The team the user accepted the invitation for.

View example

user:{id}:teamInvited

Sent when a user is invited to a team.

Payload: Team

The team the user was invited to. This includes the team owner's user object as owner.

View example

user:{id}:teamRemoved

Sent when a user leaves a team or rejects its invite.

Payload: Team

The team the user left.

View example

user:{id}:update

Sent when the user model is changed.

Payload: User

Contains changes to the user model. Please note this event may not necessarily include the entire user resource.

Need more help?

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