Intro to Push
Push API feeds automatically send JSON payloads via a push service, and can dramatically reduce the number of calls you need to make to our RESTful API feeds. The structure of a Push feed is similar to the structure of a corresponding RESTful API feed.
Our Push services are based on a HTTP publish/subscribe model. When making a call to the Push feeds, you "subscribe" to various data feeds provided by our service. Whenever new content is available on a feed, the server pushes it out to your client. When no new information is available on the feed, a heartbeat message is sent every 5 seconds to keep the connection active.
If you want to filter the results of the feeds, there are several optional query string parameters that can be applied to a request. If left unfiltered, all data for the feed is displayed (i.e. all games, events, or statistics).
Technical Requirements
For your applications to accept data from our Push feeds, ensure that your application can:
- Can follow a HTTP redirect or use the location provided in the feeds header within one minute of your initial request.
- Can accept HTTP data transfer encoded as chunked.
Access
Push feeds are an add-on service, and unavailable in the self-issued trial within your account. Reach out to a sales representative for trial access.
Syntax for using our Push feeds and examples of the JSON payloads can be found on each endpoint page.
Don't have a Push trial? Access past games - including Push - with our API Simulations!
Disconnections
Should you stop receiving heartbeat messages, or be disconnected from the Push service for any reason, resume the session with Push Catchup: the stream replays the messages you missed, then continues live. It applies to every Push feed.
1. Keep the session ID from your subscribe redirect. Every subscribe request is answered with a 302 redirect whose Location header carries the stream URL, including a sessionId and a token. Capture sessionId from that header (or from the final URL if your client follows redirects). It is not returned anywhere else.
GET https://api.sportradar.com/ufl/{access_level}/stream/{language_code}/events/subscribe
x-api-key: <key>2. Resume within 10 minutes. Repeat the same subscribe request, with the same feed and filter parameters, and add resumeSessionId:
GET https://api.sportradar.com/ufl/{access_level}/stream/{language_code}/events/subscribe?resumeSessionId=<sessionId>
x-api-key: <key>The service re-checks the API key, league and access level, feed, and filter, then issues a fresh token and redirect. Do not reuse the old token.
3. Expect a replay, then live data.
- Window: 10 minutes from the last message delivered on the session, or from its creation if nothing was delivered yet.
- Replay: up to 5,000 messages or 30 seconds, after which the stream continues live.
- Delivery: at-least-once. A resume can repeat a few messages around the reconnect point and skips none, so de-duplicate on your side.
4. After the window, start over. If the window has passed or any check fails, the request returns no error: it opens a new session with a new sessionId and no replay. Capture the new ID the same way, and use the corresponding RESTful feed to recover anything older than the window.
Samples
Each Push feed page includes code samples in Ruby, Java and Python which provide an example of feed consumption. Using these samples will output the feed content to STDOUT.
For Java, we have also provided a Stream Client to assist your integration.
Note: In the provided Java sample, replace "URL GOES HERE" with the desired Push feed URL.
require 'httpclient'
module Sportradar
module HTTP
module Stream
class Client
attr_reader :url, :logger
def initialize(url, api_key, logger)
@url = url
@logger = logger
@api_key = api_key
@client = ::HTTPClient.new(agent_name: 'SportsData/1.0')
end
def start
@thread ||= Thread.new do
logger.debug "Starting loop"
headers = {
'x-api-key' => @api_key
}
@client.get_content(url, header: headers, follow_redirect: true) do |chunk|
@publisher.publish(::JSON.parse(chunk)) if @publisher
end
logger.debug "finished loop"
end
end
def stop
@thread.terminate if @thread
end
end
end
end
endpackage com.sportradar.http.stream.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class StreamClient {
private Thread streamThread;
private volatile boolean running = false;
private String apiKey;
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public void stream(String serviceUrl, Handler handler) {
running = true;
streamThread = new Thread(() -> {
try {
URL url = new URL(serviceUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", "SportsData/1.0");
if (apiKey != null && !apiKey.isEmpty()) {
connection.setRequestProperty("x-api-key", apiKey);
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while (running && (line = reader.readLine()) != null) {
if (!line.trim().isEmpty()) {
handler.handle(line);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
streamThread.start();
}
public void terminate() {
running = false;
if (streamThread != null) {
streamThread.interrupt();
}
}
}
