Sportstalk 247 Documentation
REST API Reference
The REST API is documented with Postman. You can access it here: https://apiref.sportstalk247.com/
Client SDKs
We provide SDKs for the following languages:
The client SDKs are wrappers around the REST API and provide convenience functionality to make development easier. It is always possible to drop back into the REST API directly if you need special functionality.
The iOS and Android SDKs currently contain only chat functionality. The Javascript SDK has clients for chat and comments. In all platforms it’s possible to use the REST API directly.
CHAT CONCEPTS
EVENTS are emitted whenever anythign happens in the room. There are two categories of events:
DISPLAYABLE events are events you can see, such as the user said something, entered the room, left the room, an advertisement
NOTIFICATION events are events that you can’t see, but change the state of the room. For example, if a user says something that will emit a “SPEECH” event. But if a moderator deletes that event, a “REMOVE” event will be emitted with the ID of the speect event. The SDK user will then remove the event from their app.
Chatting happens within rooms. You can configure how each room behaves.
PREMODERATED rooms require all displayable messages to go through moderation before they appear in the chat experience
POSTMODERATED rooms allow messages to show up immediately, but people chatting can flag events, and if that happens, they will be sent to the moderation queue.
Details methods in the API return a single object
List methods in the API return a cursor object
CHAT USER EFFECTS
Various effects can be applied users on either the global level or the individual chat room level. This allows you to have moderators who can restrict a user in one context without barring the user from another context. For example, if you are implementing a club experience, the user could be removed from one club but participate in another club.
ROOM LEVEL EFFECTS
Here are all the user effects that can occur on a room level:
bounced: The user is ejected from the room. The user should not even be allowed to read content. The user does not appear in the participant list and can not interact with the room.
flagged: A user becomes flagged when other users report the user too many times within a time period. A flagged user has the shadowban effect applied.
mute: The user is in a read-only mode. The user can join a chat room and read messages. If the user tries to do so, the user will receive an error message. The user cannot contribute anything to the chat room, such as speech, replies, or reactions. This may be applied forever or for a specified number of seconds. The user does appear in the participant list.
shadowban: The user is in a read-only mode such as with mute, except the user doesn’t know it. The user will receive a success code, but any messages from the user will have the shadowban flag set to true and will be ignored by the SDKs. This may be applied forever or for a specified number of seconds.
GLOBAL LEVEL EFFECTS
The same effects can be applied on a global level, affecting ALL chat rooms:
banned: The user is banned from all talk experiences including chat and comments. The user may read comments but cannot interact with them. The user should not be allowed to read content in chat rooms. The user does not appear in the participant list of a chat room and can not interact with the room.
flagged: A user becomes flagged when other users report the user too many times using the user level report user API. Room level reports do not flag users on the global level. A flagged user has the shadowban effect applied.
mute: The user is in a read-only mode for all chat rooms. The user can join a chat room and read messages. If the user tries to do so, the user will receive an error message. The user cannot contribute anything to the chat room, such as speech, replies, or reactions. This may be applied forever or for a specified number of seconds. The user does appear in the participant list.
shadowban: The user is in a read-only mode such as with mute for all chat rooms, except the user doesn’t know it. The user will receive a success code, but any messages from the user will have the shadowban flag set to true and will be ignored by the SDKs. This may be applied forever or for a specified number of seconds.
CURSORING
The API uses cursoring which is different from pagenation. The idea of the cursor is you can call the list function without a cursor to get an initial result set, and then call it again to read more items from the list. This way, as more data is flowing into the system, you can always continue from where you left of to read the latest data.
All of the list method return a cursor object. The cursor object contains:
A list field that varies by type, can be a list of comments, events, users, rooms, conversations etc.
If you have reached the end of the list you are querying:
“more” field: This will be set to false.
“cursor” field: If the response returns any items, a new cursor string will be returned. If the response returns no items, you will receive back the same cursor you passed in, so you can use it to poll for more data.
If there are more items to read:
“more” field: This will be set to true telling you that you can retrieve more items immediately with another call to the list method.
“cursor” field: A new cursor string will be returned which you pass into the next call to the list method to get the next batch of results.
The first time you invoke a list method you do not pass a value for the cursor field. The list method will return an initial list. Call the list method again to get the next set of results.
Example (JavaScript)
let more = true;
let cursor = "";
while (more) {
let roomCursor = chatClient.listRooms(cursor, 100);
roomCursor.rooms.each(function(room) {
// Do something with the room object
});
more = roomCursor.more;
cursor = roomCursor.cursor;
}
HOW TO IMPLEMENT A CHAT APP
Initialize your SDK. iOS, Android (Kotlin), and JavaScript SDKs are available.
CREATE a room.
You can optionally provide a unique, URL friendly custom ID for your room
JOIN the chat room. The user must “JOIN” the room before the user can interact with the room.
There are two versions of JOIN: Join by RoomID, and Join by CustomID
You can create/update your user with the JOIN command by passing optional parameters
JOIN will return information about the room object
JOIN will return recent events. JOIN will only return DISPLAYABLE EVENTS
You can request JOIN also returns threaded replies to recent messages
CATCH UP your chat room by passing each event returned by JOIN to your event handler.
START LISTENING for updates. This will cause your event handler to be invoked whenever a new event is emitted in your room.
EXECUTE commands in the room. For example the command “Hello, World!” will emit a speech event containing “Hello, World!”
STOP LISTENING for updates. Your app will stop retrieving updates for the room.
EXIT the room. This removes your user from the list of participants.
BEHAVIOR OF JOIN, GET UPDATES, LIST PREVIOUS EVENTS, LIST EVENT HISTORY
The normal use case for a chat application when you open a chat room is you: 1. Join the room 2. Receive previous events (displayable events that were emitted in the room before you joined) so the user has some context of the conversation 3. Subscribe for notifications of new events 4. Scroll back to view message history using listPreviousEvents
JOIN: This method will add a user to a room. You can create or update an existing user with this method. It will also return recent displayable events from before the user joined the room.
Join will include an eventsCursor object with recent events in it. The cursor has the same result as if you called getUpdates with no cursor string.
GET UPDATES:
The purpose of getUpdates is to receive events that update the state of the room as users interact with it.
When called without a cursor string:
This is what join uses internally when returning the eventsCursor.
This will return recent displayable events only (non-displayable event types are not returned)
The ‘more’ property will be true if there are previous displayable events, which indicates scrollback content is available
When a cursor string is provided:
getUpdates will get events emitted that are newer than the cursor value even if they are not displayable (like remove, replace, report, react).
When you call getUpdates, you are moving forward in time, getting events newer than the cursor in the sort order.
You should not try to create your own cursor string, it should only have meaning to the API. It represents a place in a sort order, and how that is calculated could be changed.
The SDK manages this for you, invoking getUpdates and tracking the most recent cursor value
The ‘more’ property will be true if there are newer events in the update stream that you can retrieve
LIST PREVIOUS EVENTS:
This method is used to power a scroll back feature. It allows you to look back in time at previous events. When you first call it, it will start from the most recent event, and move backwards in time each time you pass the cursor string.
This method only returns displayable events.
LIST EVENT HISTORY:
This method is used to download or export events.
The first time you call it without a cursor string it will return the first event in the room and it moves forward in time.
It will return all events, regardless of if they are deleted or moderator rejected, or if the event is not displayable.
INTERPRETING EVENT PROPERTIES
PROPERTY |
MEANING |
id |
The ID for the event assigned by the server |
applicationid |
The ID of the application the event is for |
roomid |
The ID of the room in which the event was emitted |
body |
The body of the event, used by displayable events like “speech” or quoted reply. |
originalbody |
The original body of the event, as sent by the user. This is empty if the body was not modified. The body is modified if censoring is enabled and the body contained profanity, or if a moderator altered the body. |
deleted |
The event is logically deleted, but it has threaded replies that may be displayed |
added |
When the event was emitted. ISO 8601 time format, in UTC time. |
modified |
When the event was lasted modified. ISO 8601 time format, in UTC time. |
ts |
The high resolution timer (ticks) timestamp of when this event was emitted. |
eventtype |
The type of event this is. See event types below. |
userid |
The userid of the user who created this event. |
user |
A copy of the user object of the user who created the event. |
customtype |
Specify a string for your own custom type. |
customid |
Optionally provide a unique key for your event. Must be unique within a room. |
custompayload |
Optionally provide your own JSON or XML object or string. |
customtags |
Optionally provide an array of strings to tag your event with. |
customfield1 |
Optionally store any string in this field. |
customfield2 |
Optionally store any string in this field. |
replyto |
A copy of the object this event is directed at. |
parentid |
If this is a threaded reply this field indicates the parent event. |
hierarchy |
This is an array, in order, of the parent hierarchy of a threaded reply. |
depth |
A numeric value indicationg how deep in a tree this item is. |
editedafterpublish |
True if the user modified her message after it was published. |
editedbymoderator |
True if a moderator changed the contents of the message. |
censored |
True if profanity filter censored the content body. |
isactive |
False if the event should nto be used or displayed, for example if it is in the moderation queue. |
mutedby |
An array of userids of users who have muted the user who sent this event. |
shadowbanned |
True if the user who posted this event is shadowbanned. Only show that user this event. |
hashtags |
A list of hashtags detected in the message. |
likecount |
The number of LIKE reactions on the mesage. |
replycount |
The number of replies on the message. |
reactions |
The reactions by users to the event, grouped by reaction type. |
moderationstate |
Used by moderation queue. |
reports |
Submissions by users indicating this event is abuse. |
EVENT TYPES
EVENT TYPE |
HOW TO REACT TO THIS EVENT TYPE |
DISPLAYABLE |
unknown |
Ignore this event |
NO |
custom |
Indicates this is a custom event. In this case user is providing a custom type value. |
YES |
announcement |
Indicates the message is an announcement |
YES |
speech |
The user said something in chat |
YES |
reply |
The user issued a threaded reply to another event. Display the reply. |
YES |
quote |
The user quoted something someone else said in another event. Display the quoted reply. |
YES |
reaction |
The user reacted to an event previously emitted. Update that event in your UI to display the updated reaction information. |
NO |
replace |
The event is replaced with a new version of the event. The updated copy is in the replyto field. This is only emitted for displayabe event types. |
NO |
remove |
The referenced event (via parentid field) is to be removed from the chat stream UI |
NO |
purge |
Remove all events from the specified user |
NO |
ad |
Display an advertisement |
YES |
enter |
A user entered the chat room |
YES |
exit |
A user exited the chat room |
YES |
roomopened |
The room has been opened. Display a message that the room is now open. |
YES |
roomclosed |
The room is not accepting any more commands. Display a message that the room is closed. |
YES |
action |
User performed an action command. |
YES |
THREADED REPLIES
You can provide the user with the option to post a threaded reply. This would typically be done in a user interface by having a reply button under a mesage, and when the user replies it starts a tree like structure in the user interface, or a side panel for the a “sidebar” style conversation. Up to two levels of depth are allowed. The top level event is considered the “parent” and the replies are considered “children”. * To send a threaded reply, see the SDK documentation.
DELETING EVENTS
LOGICAL DELETE : Since events can have threaded replies, it is possible to delete a parent event and not delete the replies. In this case the event is “logically deleted”. When you logically delete an event, its children are not deleted.
PERMANENT DELETE : If you permanently delete an event it is deleted, and so are any threaded replies to that event, and they cannot be recovered.
You can issue a logical delete command, with the permanentifnoreplies flag set to true, which will cause the API to logically delete the event if there are threaded replies, but permanently delete the event if there are no threaded replies.
If you use the flag *permanentifnoreplies*=true and you delete a reply, if its parent no longer has any replies and is also logically deleted then the parent will also be permanently deleted.
If an event is permanently deleted, a REMOVE event will be raised in the room notifying you to remove the deleted event from your user interface.
If an event is logically deleted, it will be modified, and a REPLACE event will be sent to update it.
Security
You can enable additional security as an Organization setting using the management API. In most cases, the SportsTalk team will enable this for you.
With additional security enabled, Applications will require a signed JWT to be sent in the Authorization header as part of requests. That JWT is signed with a secret you can get from the security settings API.
Sample code to generate a signed JWT:
const jwt = require('jsonwebtoken');
function createUserToken(userid, SHARED_SECRET, durationMinutes, applicationIDs) {
const options = {
algorithm: 'HS256'
}
const payload = {
userid,
exp: Math.floor(Date.now() / 1000) + (60 * (durationMinutes || 60)),
}
// if you specify application IDs, the JWT will be limited to those applications.
if(applicationIDs) {
payload.aud = [].concat(applicationIDs);
}
const user_token = jwt.sign(payload, SHARED_SECRET, options);
return user_token
}