Getting Started

Welcome to our Restream API!

This API document is designed for those interested in developing and integrating third party applications with the Restream ecosystem.

Feel free to contact team@restream.io if you have any issues with the API.

Creating an app

You can manage your applications from the Developer Portal

Overview

You will need to perform the following sequence of steps in order to authenticate the user:

  1. Send the user to Restream OAuth2 Login page
  2. Capture the response code on your redirect endpoint via a webhook
  3. Exchange a code for a token pair
  4. Refresh expired access tokens
  5. Revoke tokens

Authorize dialog

Parameters
response_type
This value should always be code
redirect_uri
One of the valid redirect URIs you specified in your Restream API application
client_id
The client id of your Restream API application
state
A random opaque token

In order to obtain an OAuth2 authorization code you should first send the user to the Restream Oauth2 Login page.

Send the user to the following URL with the specified parameters:

https://api.restream.io/login?response_type=code&client_id=[your client id]&redirect_uri=[your 
redirect URI]&state=[random opaque token]

This endpoint will render a view and automatically attempt to authenticate the user if they already have a valid session from Restream.io.

If successful, the user will automatically be presented with the authorization dialog.

Otherwise, they will be presented with a form where the user can login or create a new account. Upon successful login or registration, the user will be presented with the authorization dialog.

If the user denies the dialog, they will be redirected back to the redirect_uri with no parameters.

Info: While it is not implemented yet, in the future if a user only selects a subset of permissions your application has asked for, you must allow the user to continue without enforcing permissions unless it were to affect the functionality of your client app. A scope parameter will be returned in the Capture step.

Note: The state token is used to prevent CSRF attacks and should be generated and saved using web storage when the client presents the user to authenticate with Restream. In the Capture step, the state parameter will be sent back as a query parameter. This value should equal the initial value sent in the original request. If it is not equal, do not issue a request for exchanging the code for a token.

Capture the code

Parameters
code
The short lived code from the authorization grant
scope
A comma-separated string of permissions the user has agreed to allow.
state
The state parameter specified in the original request

After user has granted access for the application, he should be redirected back to the specified redirect uri (valid to the application) with an OAuth2 code, scope, and state appended as get parameters.

https://your-website.com/oauth?code=[code]&scope=[allowed permissions]&state=[original state 
parameter]

Recommended: If a user has declined the application -or- has declined required permissions for your application, you should inform the user with a warning to prompt them to try again with the minimum permissions your application needs to avoid confusion.

Note: It is the client’s responsibility to verify the state parameter received in the webhook is the same as the one sent in the original Authorize dialog request to prevent CSRF attacks.

Code exchange

Parameters
grant_type
For a code exchange, this value should be set to authorization_code
redirect_uri
Redirect URI of your Restream API application
code
Code, received from the previous method: Receiving the code
client_id
Client id of your Restream API application
client_secret
Client secret of your Restream API application

There are two ways to exchange a code for an access / refresh token pair:

  1. Using a Basic Auth header to send the client_id and client_secret
  2. Use the client_id and client_secret as part of the x-www-form-urlencoded body

Recommended: Use the Basic Auth header to prevent passing confidential information as part of a query string that could be logged. For example a web server hosting an Nginx load balancer could log the request with the full query string.

You can exchange the received code for token by sending a POST request to the following URL:

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --user [your client id]:[your 
client secret] --data 
"grant_type=authorization_code&redirect_uri=[your redirect URI]&code=[code]"
 https://api.restream.io/oauth/token

Upon a successful exchange, you will receive a pair of tokens with their expiration times. The expiration time for access tokens is 1 hour and 1 year for refresh tokens from the time of grant.

{
  "access_token": "2a407cfcfdf8920242fd6dc7e5f83c86374ef925",
  "expires": 1520280067,
  "expires_in": 3600,
  "refresh_token": "9ca0e1e99ae3eae136a2bd98fc9c1534ea928ed3",
  "scope": "profile.default.read channels.default.read chat.default.read stream.default.read",
  "token_type": "Bearer",
  "accessToken": "2a407cfcfdf8920242fd6dc7e5f83c86374ef925",
  "accessTokenExpiresIn": 3600,
  "accessTokenExpiresAt": "2018-03-05T20:01:07.215Z",
  "accessTokenExpiresEpoch": 1520280067,
  "refreshToken": "9ca0e1e99ae3eae136a2bd98fc9c1534ea928ed3",
  "refreshTokenExpiresIn": 31536000,
  "refreshTokenExpiresAt": "2019-03-05T19:01:07.215Z",
  "refreshTokenExpiresEpoch": 1551812467,
  "scopeJson": [
    "profile.default.read",
    "channels.default.read",
    "chat.default.read",
    "stream.default.read"
  ],
  "tokenType": "Bearer"
}
{
  "error": {
    "statusCode": 400,
    "status": 400,
    "code": 400,
    "message": "Invalid grant: authorization code is invalid",
    "name": "invalid_grant"
  }
}

Refreshing tokens

Parameters
grant_type
This value should be set to refresh_token
refresh_token
The refresh token received from the code exchange or a previous refresh_token grant
client_id
Client id of your Restream API application
client_secret
Client secret of your Restream API application

There are two ways to refresh tokens:

  1. Using a Basic Auth header to send the client_id and client_secret
  2. Use the client_id and client_secret as part of the x-www-form-urlencoded body

Recommended: Use the Basic Auth header to prevent passing confidential information as part of a query string that could be logged. For example a web server hosting an Nginx load balancer could log the request with the full query string.

You can refresh an access token by sending a POST request to the following URL:

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --user [your client id]:[your 
client secret] --data 
"grant_type=refresh_token&refresh_token=[refresh token]"
 https://api.restream.io/oauth/token

Upon a successful refresh, the previous access & refresh token pair will be invalidated and you will receive a new pair of tokens with new expiration times. The expiration time for access tokens is 1 hour and 1 year for refresh tokens from the time of grant.

Note: Because this endpoint requires the submission of the client_secret, user’s devices should never have or use the secret to make refresh requests directly to Restream. Instead, their device should make a request to a proxy endpoint provided by the client web application. The client should then forward the request with the appropriate credentials to the refresh token route listed above and relay the results back to the user.

{
  "access_token": "7e61c8a5e2f99404730c511de6580412e618da35",
  "expires": 1520280099,
  "expires_in": 3600,
  "refresh_token": "0e633c3343a2df84b1526f4c2e6993ff17e05cab",
  "scope": "profile.default.read channels.default.read chat.default.read stream.default.read",
  "token_type": "Bearer",
  "accessToken": "7e61c8a5e2f99404730c511de6580412e618da35",
  "accessTokenExpiresIn": 3600,
  "accessTokenExpiresAt": "2018-03-05T20:01:38.518Z",
  "accessTokenExpiresEpoch": 1520280099,
  "refreshToken": "0e633c3343a2df84b1526f4c2e6993ff17e05cab",
  "refreshTokenExpiresIn": 31536000,
  "refreshTokenExpiresAt": "2019-03-05T19:01:38.518Z",
  "refreshTokenExpiresEpoch": 1551812499,
  "scopeJson": [
    "profile.default.read",
    "channels.default.read",
    "chat.default.read",
    "stream.default.read"
  ],
  "tokenType": "Bearer"
}
{
  "error": {
    "statusCode": 400,
    "status": 400,
    "code": 400,
    "message": "Invalid grant: refresh token is invalid",
    "name": "invalid_grant"
  }
}

Revoking tokens

Parameters
token
This parameter should contain the token string to be revoked
token_type_hint
Optional for performance - this can be either one of access_token or refresh_token.

Revoking a token should be done when a user wishes to logout of the client integration.

The response is always returned with an empty body and a 200 http status code regardless if a token was revoked or not.

You can revoke an access or refresh token by sending a POST request to the following URL:

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data
"token=[access or refresh token]&token_type_hint=['access_token' or 'refresh_token']"
 https://api.restream.io/oauth/revoke

Upon a successful revocation, any access or refresh tokens which were associated with each other will be permanently invalidated. Ex: A revocation request for an access token will also revoke the corresponding refresh token and vice versa.

<Empty body>
<Empty body>

Ingests

List all Restream's ingest points

Note: This is a public method, authentication is not required

List all Restream’s ingest servers. Ingests are public servers where users can connect for publishing RTMP content.

curl -X GET https://api.restream.io/v2/server/all
[
  {
    "id": 1,
    "name": "EU-West (London, GB)",
    "url": "eu-london.restream.io",
    "rtmpUrl": "rtmp://eu-london.restream.io/live"
  },
  {
    "id": 2,
    "name": "EU-West (Amsterdam, NL)",
    "url": "eu-ams.restream.io",
    "rtmpUrl": "rtmp://eu-ams.restream.io/live"
  },
  {
    "id": 3,
    "name": "EU-Central (Frankfurt, DE)",
    "url": "eu-central.restream.io",
    "rtmpUrl": "rtmp://eu-central.restream.io/live"
  },
  ...
]

Platforms

List all Restream's supported platforms

Note: This is a public method, authentication is not required

List all Restream’s supported platforms. Platforms are the destinations where users can send their streams.

curl -X GET https://api.restream.io/v2/platform/all
[
    {
        "id": 1,
        "name": "Twitch",
        "url": "http://twitch.tv",
        "image": {
            "png": "https://restream.io/img/api/platforms/platform-1.png",
            "svg": "https://restream.io/img/api/platforms/platform-1.svg"
        }
    },
    {
        "id": 2,
        "name": "Cybergame",
        "url": "http://cybergame.tv",
        "image": {
            "png": "https://restream.io/img/api/platforms/platform-2.png",
            "svg": "https://restream.io/img/api/platforms/platform-2.svg"
        }
    },
    {
        "id": 3,
        "name": "Goodgame",
        "url": "http://goodgame.ru",
        "image": {
            "png": "https://restream.io/img/api/platforms/platform-3.png",
            "svg": "https://restream.io/img/api/platforms/platform-3.svg"
        }
    },
  ...
]

Profile

List user's profile details

Note: This method requires authentication

Retrieve a user’s profile information.

curl -H "Authorization: Bearer [access token]" https://api.restream.io/v2/user/profile
{
  "id": 000,
  "username": "xxx",
  "email": "xxx"
}
{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Selected ingest

Get user's selected ingest id

Note: This method requires authentication

Retrieves a user’s selected ingest id.

curl -H "Authorization: Bearer [access token]" https://api.restream.io/v2/user/ingest
{
  "ingestId": 8
}
{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Stream

Get a user's live stream information

Note: This method requires authentication

Retrieve a user’s live stream status and outgoing information.

The endpoint will only return useful information when the user is actively streaming. Otherwise, the response will contain live: false and channels: [].

After a user begins to stream, the information takes a few seconds to process. In such cases you may see live: true, but have an empty array channels: []. After a few seconds, the information will become available.

The channels array will contain list of outgoing streams the user has enabled in his or her dashboard. Not all outgoing platforms support the setting of a title nor a gameTitle in which case the data returned could be an empty string ''.

curl -H "Authorization: Bearer [access token]" https://api.restream.io/v2/user/stream
{
    "live": true,
    "channels": [
        {
            "id": 1234567,
            "streamingPlatformId": 1,
            "channelIdentifier": "xxx" || '',
            "eventIdentifier": "yyy" || '',
            "viewers": 63,
            "followers": 2983,
            "title": "Watch me play!" || '',
            "gameTitle": "PLAYERUNKNOWN'S BATTLEGROUNDS" || ''
        }
    ]
}
{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Stream key

Get a user's stream key

Note: This method requires authentication

Retrieve a user’s stream key.

curl -H "Authorization: Bearer [access token]" https://api.restream.io/v2/user/streamKey
{
  "streamKey": "re_xxx_xxx"
}
{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Channels

List user's channels

Note: This method requires authentication

Retrieve a list of the user’s channels.

curl -H "Authorization: Bearer [access token]" https://api.restream.io/v2/user/channel/all
[
  {
      "id": 000,
      "streamingPlatformId": 000,
      "embedUrl": "https://beam.pro/embed/player/xxx",
      "url": "https://beam.pro/xxx",
      "identifier": "xxx",
      "displayName": "xxx",
      "enabled": true
  },
  {
      "id": 111,
      "streamingPlatformId": 111,
      "embedUrl": "http://www.twitch.tv/xxx/embed",
      "url": "http://twitch.tv/xxx",
      "identifier": "xxx",
      "displayName": "xxx",
      "enabled": false
  },
  ...
]

{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Channel Enable

Enable a user's channel

Note: This method requires authentication

Enable a user’s channel in their Restream Dashboard.

curl -X POST -H "Authorization: Bearer [access token]" -H "Content-Type: application/json" -d '{ "channelId": 123456 }' https://api.restream.io/v2/user/channel/enable

 {
   "channelId": 123456
 }


 {
   "id": 123456,
   "streamingPlatformId": 123,
   "embedUrl": "https://beam.pro/embed/player/xxxxxxx",
   "url": "https://beam.pro/xxxxxxx",
   "identifier": "xxxxxxx",
   "displayName": "My Mixer Channel",
   "enabled": true
 }

{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Channel Disable

Disable a user's channel

Note: This method requires authentication

Disable a user’s channel in their Restream Dashboard.

curl -X POST -H "Authorization: Bearer [access token]" -H "Content-Type: application/json" -d '{ "channelId": 123456 }' https://api.restream.io/v2/user/channel/disable

 {
   "channelId": 123456
 }


 {
   "id": 123456,
   "streamingPlatformId": 123,
   "embedUrl": "https://beam.pro/embed/player/xxxxxxx",
   "url": "https://beam.pro/xxxxxxx",
   "identifier": "xxxxxxx",
   "displayName": "My Mixer Channel",
   "enabled": false
 }

{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Webchat URL

Get a user's webchat URL

Note: This method requires authentication

Retrieve a user’s webchat URL.

curl -H "Authorization: Bearer [access token]" https://api.restream.io/v2/user/webchat/url

Note: The URL returned has the default parameters set. You can modify these values as needed.

{
  "webchatUrl": "https://restream.io/chat-application/embed?theme=default&alignment=bottom&msgOpacity=100&chatOpacity=100&scale=100&timeout=2&hideMessages=false&userId=xxx&token=xxx"
}
{
  "error": {
    "statusCode": 401,
    "status": 401,
    "code": 401,
    "message": "Invalid token: access token is invalid",
    "name": "invalid_token"
  }
}

Events

Subscribe or unsubscribe to events

Note: This method requires authentication

'use strict';

const WebSocketClient = require('websocket').client;

// create WebSocket client
const client = new WebSocketClient();

// handle failed connection errors
client.on('connectFailed', (error) => {
    console.log('Connect Error: ' + error.toString());
});

// handler for established connection
client.on('connect', (connection) => {
    console.log('WebSocket Client Connected');

    // handle new messages
    connection.on('message', (message) => {
        console.log('Recieved message', message);
    });

    // handle errors
    connection.on('error', (error) => {
        console.error('Connection Error: ' + error.toString());
    });

    // handle connection close
    connection.on('close', () => {
        console.log('Connection Closed');
    });

    const subscriptions = [
        'user/stream', // receive messages with streaming status changes
        'user/chat' // receive messages from chat
    ];
    // subscribe to events
    connection.send(JSON.stringify({
        action: 'subscribe',
        token: '[access token]', // OAuth `bearer` token
        subscriptions: subscriptions
    }));
    // unsubscribe from user stream status updates
    connection.send(JSON.stringify({
        action: 'unsubscribe',
        userId: '12345',
        subscriptions: ['user/stream']
    }));
});

// connect to API server
client.connect('wss://api.restream.io/v2/ws');

At this time, the only subscriptions that are allowed are:

This page will be updated as more functionality is created.

{
    "success": {
        "action": "subscribe" || "unsubscribe"
        "userId": 12345,
        "subscriptions": ["user/stream", "user/chat"]
    }
}
{
    "error": {
        "code": 400,
        "description": "bad message" || "bad unsubscribe message"
    }
}

Stream status

Listen for stream status change events

Subscribe to events with user/stream subscription type to receive message with stream status changes. Check events for more information about subscription.

Immediately after subscribing, a payload will be emitted. In the event where the subscription occurred before the user has started streaming, you may receive a response similar to live: false and channels: []. You may see similar results when a user has stopped streaming.

After the initial subscription, events are emitted only when there is a change in value. It is possible to see live: true, but have an empty array channels: [] when a user has begun to stream, but further data is calculating. After a few seconds, the information should become available and another event will be emitted.

The channels array will contain list of outgoing streams the user has enabled in his or her dashboard. Not all outgoing platforms support the setting of a title nor a gameTitle in which case the data returned could be an empty string ''.

Initial Data (before streaming has started):

{
  "subscription": "user/stream",
  "payload": {
      "channels": [],
      "live": false,
      "userId": 12345
  }
}

Stream is detected as live (awaiting further data):

{
  "subscription": "user/stream",
  "payload": {
      "channels": [],
      "live": true,
      "userId": 12345
  }
}

Change in data (received change in viewers, followers, live status, etc):

{
    "subscription": "user/stream",
    "payload": {
        "channels": [
            {
                "id": 1234567,
                "streamingPlatformId": 1,
                "channelIdentifier": "xxx" || "",
                "eventIdentifier": "yyy" || "",
                "viewers": 63 || null,
                "followers": 2983 || null,
                "title": "Watch me play!" || "",
                "gameTitle": "PLAYERUNKNOWN'S BATTLEGROUNDS" || ""
            }
        ],
        "live": true,
        "userId": 12345
    }
}

NOTE: viewers and followers can be null when data are not available.

Chat messages

Listen for chat messages

Subscribe to events with user/chat subscription type to receive chat messages. Check events for more information about this subscription.

Events are emitted each time a new message appears on channels which are enabled in user dashboard. Event-based platforms, such as YouTube Events or Periscope, requires stream to be active for the chat to receive messages.

Payload fields

userId
id of chat owner.
channelId
id of channel from which this message was received. More information about channel can be retrieved using Channels method.
platformId
id of the streaming platform from which this message was received. More information about platform can be retrieved using Platforms method.
author
display name of message author.
contents
array which consists of chat message parts. Message exploded into parts by whitespace.
timestamp
date and time when the message was received.
own
shows if chat owner themselves sent the message.
  {
      "subscription": "user/chat",
      "payload": {
          "userId": 123456,
          "channelId": 123456,
          "platformId": 1,
          "author": "user display name",  
          "contents": [
              {
                  "type": "text",
                  "subtype": "normalText",
                  "content": "Hello",
                  "color": null
              },
              {
                  "type": "link",
                  "url": "linkUrl",
                  "content": "linkText"
              },
              {
                  "type": "img",
                  "subtype": "link",
                  "content": "imageUrl"
              },
              {
                  "type": "img",
                  "subtype": "sprite",
                  "link": "imageUrl",
                  "objectPosition": "0px 0px",
                  "height": "24px",
                  "width": "24px"
              }
          ],
          "timestamp": "2029-01-19T12:14:14.664Z",
          "own": false
      }
  }