Server Communication

Often times you may want to send changes the the MEDKit from an external server. Any endpoint that can be used by a broadcaster on Twitch can also be used by a server that has access to the extension’s id and secret.

Sending Data from a Server

As the extension owner, you have access to the Extension ID and Secret Key for the extension. You can use these to sign a JWT that may then be used to authenticate any requests with the MEDKit backend.

There are client libraries for generating / parsing JWTs in most languages available: https://jwt.io/#libraries-io

As well as several command line utilities to manually sign JWTs (e.g. jsonwebtokencli)

JWT Payload

{
  "extension_id": "ka3y28rrgh2f533mxt9ml37fv6zb8k",
  "channel_id": "126955211",
  "role": "viewer",
  "exp": 1497990432,
  "opaque_user_id": "A8943236",
  "allowed_stage": "sandbox"
}

The JWT has a few required fields:

field description
extension_id The unique identifier for this extension
channel_id The Twitch channel id
role The ‘authority’ level of this JWT (i.e. viewer, broadcaster or admin)
exp A Unix epoch timestamp of the expiration of this JWT
opaque_user_id This field mimics the opaque user id from Twitch (including the A or U to designate anonymous users)
allowed_stage The environments for which this JWT is valid (i.e. sandbox or production)

Any other fields you include in the header or claims will be ignored.

Signing the JWT with jsonwebtokencli

You can use jsonwebtokencli to sign the JWT (be sure to decode the extension secret first, as it comes from Twitch base64 encoded):

jwt \
--algorithm HS256 \
--secret "<extension secret>" \
--encode '{
  "extension_id": "ka3y28rrgh2f533mxt9ml37fv6zb8k", "channel_id": "126955211",
  "role": "broadcaster", "exp": 1497990432, "opaque_user_id": "A8943236",
  "allowed_stage": "sandbox"
}'

Outputs

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzkxODk1MzMsImV4cCI6MTQ5Nzk5MDQzMiwiZXh0ZW5zaW9uX2lkIjoia2EzeTI4cnJnaDJmNTMzbXh0OW1sMzdmdjZ6YjhrIiwiY2hhbm5lbF9pZCI6IjEyNjk1NTIxMSIsInJvbGUiOiJicm9hZGNhc3RlciIsIm9wYXF1ZV91c2VyX2lkIjoiQTg5NDMyMzYiLCJhbGxvd2VkX3N0YWdlIjoic2FuZGJveCJ9.nSxDQ4rxz1uy99z_klZgRcNQ7kAWTc371IE2aMAdI0E

Which can then be used in requests.

Using the JWT

Once you have a signed JWT, it can be used along with your extension ID to perform server-initiated requests.

To use it, simply populate the Authorization header with a string containing both values.

Authorization: ExtensionID JWT

For example:

curl -X POST \
 -H "Content-Type: application/json" \
 -H 'Authorization: ka3y28rrgh2f533mxt9ml37fv6zb8k eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzkxODk1MzMsImV4cCI6MTQ5Nzk5MDQzMiwiZXh0ZW5zaW9uX2lkIjoia2EzeTI4cnJnaDJmNTMzbXh0OW1sMzdmdjZ6YjhrIiwiY2hhbm5lbF9pZCI6IjEyNjk1NTIxMSIsInJvbGUiOiJicm9hZGNhc3RlciIsIm9wYXF1ZV91c2VyX2lkIjoiQTg5NDMyMzYiLCJhbGxvd2VkX3N0YWdlIjoic2FuZGJveCJ9.nSxDQ4rxz1uy99z_klZgRcNQ7kAWTc371IE2aMAdI0E' \
 -d '{ "potato": "russet", "awesomeness": 11 }' \
 https://sandbox.api.muxy.io/v1/e/json_store?id=awesome_server_action

Retrieving the Data

The data you POST to this endpoint will be stored indefinitely, keyed on your extension id and provided identifier. The current stored data may be retrieved at any time by calling:

sdk.getJSONStore('awesome_server_action').then((resp) => {
  console.log(resp.awesomeness);
});

The response will be a json object with your values:

{
  "potato": "russet",
  "awesomeness": 11
}

Automatic Updates

To avoid the need to continuously poll the server for data updates, MEDKit will send all viewers currently using your extension when new data is POSTed to the endpoint. You may listen for specific storage events similar to how vote update events are handled:

const opts = new Muxy.DebuggingOptions();
opts.role('viewer');
Muxy.debug(opts);

sdk.listen('json_store_update:awesome_server_action', (data) => {
  console.log(data.value.awesomeness);
});

The response includes the event id and value:

{
  "id": "awesome_server_action",
  "value": {
    "potato": "russet",
    "awesomeness": 11
  }
}

If you are posting json data to several different keys and would like to listen for all JSON store updates, you can use the * character to reference all update events:

const opts = new Muxy.DebuggingOptions();
opts.role('viewer');
Muxy.debug(opts);

sdk.listen('json_store_update:*', (data) => {
  if (data.id === 'awesome_server_action') {
    console.log(data.value.awesomeness);
  }
});

The response is the same as listening to an individual update event:

{
  "id": "awesome_server_action",
  "value": {
    "potato": "russet",
    "awesomeness": 11
  }
}