The Stream API provides a stream of live match data as JSON over a WebSocket connection. Please see the below for how to connect to the stream endpoint.
The process for connecting to the stream endpoints and receiving data is always the same:
● Connect to the SSL websocket address
● Send JSON packet containing API token
Format to send API token:
{"authToken": "authentication token"}
● Receive response indicating that the connection is authorised (or else a response
indicating why the connection cannot be made)
● Receive heartbeat packets every 10 seconds to verify that the connection is live
● Receive data packets
Once you have sent the API token, any further data that you send over the connection will be ignored.
Security protocol:
Please note that we currently we do not support SSL. We only support the use of TLS Version 1.2+.
The code below shows how to make the connection using Java. It uses the following dependencies but you can use any libraries you wish:
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;
import org.glassfish.tyrus.client.ClientManager;
import javax.websocket.*;
@ClientEndpoint
public class WSClient {
private static final String HOST = "???";
private static final String EVENT_ID = "???";
private static final String WS_ENDPOINT =
"wss://"+HOST+"/events/"+EVENT_ID+"/stream";
private static final String TOKEN = "???";
private Logger logger = Logger.getLogger(this.getClass().getName());
private static CountDownLatch latch;
@OnOpen
public void onOpen(Session session) {
logger.info("Connected ... " + session.getId());
try {
session.getBasicRemote().sendText("{\"authToken\": \"" + TOKEN + "\"}");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@OnMessage
public void onMessage(String message, Session session) {
logger.info(message);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
logger.info(String.format("Session %s close because of %s", session.getId(),
closeReason));
latch.countDown();
}
public static void main(String[] args) {
latch = new CountDownLatch(1);
ClientManager client = ClientManager.createClient();
try {
client.connectToServer(WSClient.class, new URI(WS_ENDPOINT));
latch.await();
} catch (DeploymentException | URISyntaxException | InterruptedException e) {
throw new RuntimeException(e);
} }
}
In Java, to send a Web request via a SSL-based protocol (i.e. HTTPS or WSS) one has to add the signed certificate to the keystroke ‘ jssecacerts’ for the specific domain as alias. For that the utility Java program ‘ InstallCert.java’ is used:
Java
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. *
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
*% java InstallCert ecc.fedora.redhat.com
*/
import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* Class used to add the server's certificate to the KeyStore
* with your trusted certificates.
*/
public class InstallCert {
public static void main(String[] args) throws Exception {
String host;
int port;
char[] passphrase;
if ((args.length == 1) || (args.length == 2)) {
String[] c = args[0].split(":");
host = c[0];
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
String p = (args.length == 1) ? "changeit" : args[1];
passphrase = p.toCharArray();
} else {
System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
return;
}
File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager =
(X509TrustManager) tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory factory = context.getSocketFactory();
System.out.println("Opening connection to " + host + ":" + port + "...");
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
return; }
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println();
System.out.println("Server sent " + chain.length + " certificate(s):");
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
}
X509Certificate cert = chain[i];
System.out.println
md5.update(cert.getEncoded());
System.out.println(" md5
System.out.println();
(" " + (i + 1) + " Subject " + cert.getSubjectDN());
System.out.println(" Issuer " + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println(" sha1
System.out.println("Enter certificate to add to trusted keystore or 'q' to
quit: [1]");
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
} catch (NumberFormatException e) {
System.out.println("KeyStore not changed");
return;
}
X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);
OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();
System.out.println();
" + toHexString(sha1.digest()));
" + toHexString(md5.digest()));
System.out.println(cert);
System.out.println();
System.out.println
("Added certificate to keystore 'jssecacerts' using alias '"
+ alias + "'");
}
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
} }
}
When it asks for the input, press ‘ 1 ’. After this step, the informed domain will be added as a trusted keystore, and a file called “ jssecacerts“ will be generated.
The code below shows how to make the connection using Javascript. It assumes you already
have a variable named token holding your API token:
Java
var ws = new WebSocket('wss://{host}:{port}/events/{eventId}/stream');
ws.onmessage = function(message) {
//Listen here to every message coming from the stream
};
// Send the API token as first step
ws.send(JSON.stringify({ authToken: token }));
We can provide code samples in other languages on request.
A Test Server for event streams is also available for testing purpose. To be able to consume events coming from the Test Server one can connect via WebSocket following the steps above and point to the endpoint containing the matchId as “2 015-999-XX999”:
Java
var ws = new WebSocket('wss://{host}:{port}/events/2015-999-XX999/stream');
ws.onmessage = function(message) {
//Listen here to every message coming from the stream
};
// Send the API token as first step
ws.send(JSON.stringify({ authToken: token }));
The test feed will play a real historical match (with the names of the players modified). The match events are sent in an interval of 5 secs with heartbeats messages every 10 secs.
"startPosition" parameter
Note that you can pass the "startPosition=*" parameter in the websocket, where "*" refers to the sequence number the connection should start from.
i,e: wss://dde-streams.data.imgarena.com/tennis/events/2023-XXXX-MSXXX/stream?startPosition=100
The websocket feed will start the at sequence number 100 instead of 0.