Feed Specification
Generalities
All strings (names, especially) will be considered to contain arbitrary unicode data unless otherwise specified.
All timestamps will be of format 2014-01-01 22:22:22.123456 and in UTC, unless otherwise specified.
All properties will have a value that is not null unless otherwise specified.
In general, push messages will be of the form::
{
"mode": "push",
"type": <message_type>,
"publish_time": "2014-01-01 22:22:22.123456",
"msg": ...
}publish_time is the time the message was published by the feed.
Market categorization
Once a connection is established, the server will proceed to send a list of the sports, competitions, events, market types, and markets that are available. The type of entity is determined by the "type" attribute. However, each entity has an ID which is globally unique, and is (with the exception of markets, which have no prefix) prefixed with a short code followed by a period in order to make it easy to determine the entity type when only the ID is available. The entity types and associated codes are:
Sport
sp
competition
comp
event
ev
market_type
mt
Note that all entity IDs and names are unicode strings (JSON is encoded using UTF-8).
Sport Message
Here is a sample sport message::
Competition message
Here is a sample competition message::
A competition has a name and may have a start time, but the start time may also be null.
Event Message
Here is a sample message representing an event:
In addition to the id and name, an event may have a competition id (the value will be null in the case where there is no associated competition). An event usually has a start time, but it may be null if it is unknown. It also has a "stage" property, which is "pre_play" before the event starts, "in_play" after it starts, "ended" once finished, and null if it is not known whether the event has started or in the case where the distinction between pre-match and in-running is meaningless.
The meta property contains additional information about the event. For golf, it is a list containing a single object. That object will contain the event_id key, whose value is the IMG DDE ID of the event in question. Note that some other keys of arbitrary JSON-serialisable nature may be added to that object in order to satisfy customers' needs.
DL Offerings for markets
DL1 markets - Full shot by shot data live (full L1 stroke by stroke data for PGA events)
DL2 markets - Most DPWT and for non-domestic PGA events that have shot by shot data (Could be L1.5/1.75)
DL3/4 - For L2 Hole by hole scorecard data tournaments with no stroke data (with the decision between the two to be driven by tournament quality/importance)
DL5 - tournaments with leaderboard level data at high latency (L3). Some may be upgraded to DL4 as necessary
Score update message
Here is a sample message representing a score update::
The score field is arbitrary JSON; its structure depends on the sport. For golf, it is the latest state of the leaderboard as per IMG DDE leaderboard endpoint.
Clients will receive score update if they are subscribed to the corresponding score tags e.g. ev.golf_1345 or sp.golf.
Market Definition Message
Market definitions contain information that rarely or never changes about a market. Market definitions will be sent as a series of push messages containing property type set to market. The following example shows the simplest sort of market definition::
The properties of this object have the following semantics:
id The id is a string, and will never change for a given market. It will also be globally unique -- no two markets will have the same ID, even in different events or sports. This is in the same format as the Mustard id.
arena_id
Value added by IMGA to determine the DL market type names. Added back in June/July 2025. IMGA also added backwards compatibility to id value as described above for those wedded to Mustard ids. Current plan is both id and arena_id will be supported indefinitely.
event_id
The event id of the tournament. These Ids are unique to IMGA all can be obtained ahead of time from the IMGA tournaments Ids if necessary.
arena_event_id
The event id of the tournament. These Ids are unique to IMGA all can be obtained ahead of time from the IMGA tournaments Ids if necessary.
name The market display name.
tags This property represents what sport, competition, event(s), and market type(s) the market is part of. It may (rarely) change due to corrections.
start_time
The start time of the market
stage This field's value will be one of: "pre_play", "in_play", or "ended". The use of the "pre_play" and "in_play" statuses differs between market types -- some markets may not appear in the "pre_play" or "in_play" stages at all, depending on whether they are meaningful to that market type. When a market is in the "ended" stage, trading should stop and the market should be hidden from customers' view. Note that markets may change stages in reverse order -- this is rare, but may happen in the case of a mistake being corrected.
numwinners
The number of winning selections in the market which currently maps to the TopN market. This will always be 1 or more. It will only change in the case of corrections. Please note over/unders will be 1 and of all the selections the user can bet on at a given time, only numwinners will result in a winning bet.
meta Arbitrary extra market information. This may be null.
Every market will have exactly one sport, but will usually also have one competition, one event and one or more market types. These are defined by the "tags" property on a market definition.
If more than one market definition is sent with a given id attribute, the later market definition is considered an update, and should replace the earlier one. This update may change any of the attributes (except id), so the client should re-process the definition and decide whether to update its subscriptions.
Removals
After the market's stage reaches "ended", it may be removed. Note that a market which has been removed may be re-added again later, with the same market id, for example, if the removal was in error. Removal of a market is signaled by the following message (note that a list of ids is provided)::
On receipt of a remove_market message, the client should stop allowing trading (if the market was not already ended) and stop displaying it.
Competitions and events may also be removed. In the case of a competition being removed, a message like this will be sent:
When an event is removed, a message like this will be sent:
Upon competition removal, any event with that competition_id will also be removed; along with any markets with those event_ids. Only the single remove_competitions message will be sent.
The same applies for a remove_events message. All markets under it are removed; only the single remove_events message is sent.
Un-voiding
Below is an example of a selection being voided and a subsequent message of the selection being re-activated.
Selection g:520 gets withdrawn and his stake is returned.:
Selection g:520's status reverts to being active. It should be noted there will be no update to the settlement information (stake + payout), it must inferred from status transitioning from settled → active.:
Re-resulting
In the instances where a market is re-resulted the following pattern can be observed. The market being initially resulted:
The message triggered upon the above market being re-resulted.:
Subscription
Client must first establish a connection and send an init command. However, initialising alone will not start the data flow — data will only begin streaming after a successful subscription.
The full subscription payload (with all possible fields) looks like this:
{ "request": "subscribe","msg": {"market_tags": ["mt.oneball_hole"], "tags": ["mt.oneball_hole"], "score_tags": []} }This means the client subscribes to the mt.oneball_hole market and will receive only messages related to this market.
Now, let's break down each key:
score_tagsis supported for backward compatibility only and its values are ignored. The client can send"score_tags": ["sp.golf", "ev.123"]or an empty array, but it will have no effect.score_tagscan also be omitted completely. Sending{ "request": "subscribe","msg": {"market_tags": ["mt.oneball_hole"], "tags": ["mt.oneball_hole"]} }will behave the same as includingscore_tagswith an empty array.market_tagsandtagsare both used to filter by market, but they are not combined. If both are provided with different values, onlymarket_tagswill be used. It takes precedence over tags.So in practice, to subscribe to a specific market, you should send either
{ "request": "subscribe","msg": {"market_tags": ["mt.oneball_hole"]} }or{ "request": "subscribe","msg": {"tags": ["mt.oneball_hole"]} }Both
market_tagsandtagsaccept multiple values, so you can subscribe to multiple markets by sending"market_tags": ["mt.top_n", "mt.oneball_hole"]To subscribe to all markets without filters, you can either send
"market_tags": []or omitmarket_tagsentirely by just sending{ "request": "subscribe","msg": {} }To stop receiving feeds, please send an unsubscribe command:
{ "request": "unsubscribe", "msg": {} }. Currently, it's not possible to unsubscribe from a specific market - this command removes the entire subscription.Clients will continue subscribing to markets as usual using familiar Mustard market types. Internally, we translate these Mustard market types to their DL Trading equivalents.
If a market type can't be translated, we fall back to exact ID matching.
For example, if a client subscribes with
market_tags: ["SOME_MARKET_ID"]and a feed comes with IDtid:1235|mt:SOME_MARKET_ID|r:2, we extract the market type (SOME_MARKET_ID) and check if it matches any market tag in the subscription.
Snapshot - After a successful subscription the distribution service will return a market update for each of the currently available markets on the feed. Currently (we are working on a fix for this), these include all the markets; regardless of whether or not they fit within the filtering requested in the subscription. This snapshot allows consumers to establish a state at connection time (or re-sync; should there have been a downtime, for example cause by a disconnection)
We now added support to query just market type and tournament specific data. Here is an example command for one tournament and one market
"market_tags":["sp.golf","ev.golf_1180", "mt.top_n"]
Here is multiple tournaments and multiple markets
{"msg":{"market_tags":["ev.golf_1180","ev.golf_1210","mt.forecast","mt.hole_in_one","mt.lowest_18_hole_score","mt.make_cut","mt.matchbet","mt.matchbet_tie","mt.outright","mt.round_leader","mt.round_leader_top_n","mt.round_matchbet_tie","mt.threeball","mt.top_n","mt.topgroup","mt.topgroup_top_n","mt.topregion","mt.topregion_top_n","mt.twoball_tie","mt.winonly","mt.winalternateew","mt.winner_without","mt.winner_without_top_n","mt.winning_margin","mt.winning_score","mt.region_top_n"],"tags":["mt.forecast","mt.hole_in_one","mt.lowest_18_hole_score","mt.make_cut","mt.matchbet","mt.matchbet_tie","mt.outright","mt.round_leader","mt.round_leader_top_n","mt.round_matchbet_tie","mt.threeball","mt.top_n","mt.topgroup","mt.topgroup_top_n","mt.topregion","mt.topregion_top_n","mt.twoball_tie","mt.winonly","mt.winalternateew","mt.winner_without","mt.winner_without_top_n","mt.winning_margin","mt.winning_score","mt.region_top_n"]},"request":"subscribe"}
Market Status Update
Clients will receive market status update messages for markets to which they have subscribed. More than one market may be updated in a single market_update message. Below is an example of a market update message::
The properties of a single market update have the following semantics:
id The id is a string, and will never change for a given market. It will also be globally unique -- no two markets will have the same ID, even in different events or sports. This is in the same format as the Mustard id.
arena_id
Value added by IMGA to determine the DL market type names. Added back in June/July 2025. IMGA also added backwards compatibility to id value as described above for those wedded to Mustard ids. Current plan is both id and arena_id will be supported indefinitely.
status This may be one of "suspended" or "active". Active means betting is allowed, suspended means betting should be prohibited. Upon a selection_update status of settled, the market status should be suspended (bug fix going in for this W/C 18th Aug)
stage This field's value will be one of: "pre_play", "in_play", or "ended". The use of the "pre_play" and "in_play" statuses differs between market types -- some markets may not appear in the "pre_play" or "in_play" stages at all, depending on whether they are meaningful to that market type. When a market is in the "ended" stage, trading should stop and the market should be hidden from customers' view. Note that markets may change stages in reverse order -- this is rare, but may happen in the case of a mistake being corrected.
IMPORTANT - Please note this is a new field added on 21st Aug 2025
display Display recommendation (boolean).
In the case that multiple similar markets exist, we may recommend that one of the sets is displayed, and the others are not. For example, in the event that we provide a number of handicap markets with different handicaps, we may use this field to recommend that the market with the most competitive prices be displayed.
It is safe to display markets that we recommend be hidden, and vice versa.
IMPORTANT - this is currently not working as expected but will be fixed for W/C 8th Sept 2025 by DL. Until then display does not transition from true to false correctly.
meta Arbitrary extra market information. This may be null. For golf, this takes the form:
selection_updates
A list of changes to the market selections.
This field will always be present, though it is empty in the case where no selections have changed.
Every selection has a string property id, which is only guaranteed to be unique within a single market.
The rest of the selection properties will only be present when they need to be updated or the first time the selection is seen. The initial selection update will always contain these properties:
settlement An object containing two float fields, stake_returned and payout_returned.
For example, a bet on the winner of an outright market (with no dead heat) will have settlement stake_returned=0.0, payout_returned=1.0. A void selection (i.e. a non-runner) will have settltment stake_returned=1.0, payout_returned=0.0.
In the case of a re-settlement, a new settlement will be sent for a selection or market, this should override any previous settlements you have previously received.
Settlement market_update messages can contain the resulting of multiple selections. This does not mean however that it contains the results to all the selections of the market, depending on how the results come in from the supplier.
There is, on the message a resulting_complete field, that can be true or false (implied false when absent). When this flag is at true, it means that all the selections known to our systems that have been priced have been resulted.
Whenever the systems receive the settlement completing the resulting of a given market, an extra market_update with all the selections' results is going to be produced. So a market_update with "resulting_complete": true will contain all the results for all the selections, and every market will, eventually, have a settlement message with with this flag being true.
Example with true and false
Disclaimer: resulting_complete being true means all selections known to our systems have a result. This protects edge cases such as early voids on the winner market without ever getting priced and those will not result in the flag being true. There are further edge cases, unlikely in theory, not practical that may end up in this flag being true prematurily.
note A human-readable explanatory string.
meta Arbitrary extra selection information (for example, which golfer does this selection relate to?)
For golf, this takes the form:
If a client sees a selection with an id that it has not seen before, it should add the selection to the market. Once added, a selection will always be listed in the feed, but may be marked as being removed.
ew_terms
This property will only be set for markets which allow each-way betting -- in other cases it will be null. Markets may allow each-way bets at some times but not others. The property will always exist.
The value is an object which contains fraction and places properties. The fractionvalue is a string representing the fraction of the win odds used for the place odds, such as "1/4" to mean that the place odds are 1/4 of the win odds. The places property value is a number representing the number of places for the place part of the bet.
related_place_markets
This property will only be set for markets which allow each-way betting -- in other cases it will be null.
It will be a map from a number of places, represented as a string (e.g. "5"), to the market_id which represents that market.
This will contain all historic each-way related markets, not just the current one, i.e. {"3": "top_3_market", "5": "top_5_market"}.
Last updated
Was this helpful?