Virtual Racing API

SportLogic Virtuals API

The same Kiron virtual racing data that powers retail betting terminals, now as a REST API. Horses, greyhounds, motor racing, harness, speed skating. 8 game types, events every ~10 minutes, 24/7. Schedules, runners with odds, results with settlement. You build the front-end.

Draw 1 Draw 5 Draw 9
Base URL https://virtuals-api.sportlogic.io/api/v1
Auth X-API-Key: sv_YOUR_KEY
Engine Kiron Interactive
Get API Key → Football API Docs

Getting Started

Typical workflow for consuming virtual racing data.

Workflow

  1. List game types - Call GET /v1/game-types to see available racing categories (e.g. Dashing Derby, Platinum Hounds).
  2. List events - Call GET /v1/events filtered by game_type_id and status to find upcoming or recent events.
  3. Get event with runners and odds - Call GET /v1/events/{id} to get the runner list with win/place odds, form, and draw colors.
  4. Get results and settlement - After the event finishes, call GET /v1/events/{id}/results for finishing positions and settlement data (win, place, forecast, tricast).

First request

Replace sv_YOUR_KEY with the API key from your dashboard.

curl -G https://virtuals-api.sportlogic.io/api/v1/events \
  -H "X-API-Key: sv_YOUR_KEY" \
  --data-urlencode "status=scheduled" \
  --data-urlencode "per_page=5"
Tip: All endpoints require the X-API-Key header.

Authentication

Every request requires a valid API key in the X-API-Key header.

Header

HeaderValueDescription
X-API-Keysv_your_key_hereRequired on all endpoints. Keys are prefixed with sv_.

Register

Create a new account and receive an API key via POST /api/v1/register.

Auth error codes

HTTPCodeMeaning
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENKey suspended or insufficient permissions

Rate Limits & Pricing

Limits are counted per API key. Rate limits are enforced per minute.

PlanPriceEvents/dayRate Limit
Free$050010 req/min
Starter$69/mo15,000120 req/min
Pro$129/mo50,000300 req/min
Business$249/mo200,000600 req/min

Response headers

HeaderDescription
X-RateLimit-LimitYour daily request limit
X-RateLimit-RemainingRequests remaining today

On limit exceeded, the API returns HTTP 429 with error code RATE_LIMIT_EXCEEDED.

Business plan includes

  • - Silk asset pack - 40 jockey silks + 8 game type icons (PNG/SVG)
  • - VisionViewer integration - Kiron's 3D race renderer. Racing, Keno, LuckyLoot, Spin and Win.
  • - 1-to-1 integration support
  • - Custom rate limits on request

Business assets and VisionViewer docs are shared directly after subscription. Contact support@sportlogic.io to get started.

Game Types

8 Kiron virtual racing categories. Same game types running on retail betting terminals worldwide. Each has a fixed field size and event cycle.

GET /api/v1/game-types

List all active virtual racing game types.

Available game types

Dashing DerbyDashingDerby · 14 runners · 10 min
Platinum HoundsPlatinumHounds · 8 runners · 10 min
Harness RacingHarnessRacing · 10 runners · 9 min
Motor RacingMotorRacing · 14 runners · 9 min
Horse Racing RouletteHorseRacingRouletteV2 · 8 runners · 9 min
Steeple ChaseSteepleChase · 14 runners · 9 min
Speed SkatingSpeedSkating · 6 runners · 9 min
Single Seater Motor RacingSingleSeaterMotorRacing · 14 runners · 9 min
Kiron Interactive virtual racing engine. Same events, same odds model, same race outcomes served to retail betting shops. We expose the data - you render it however you want.

Response fields

  • idGame type ID - use to filter events
  • codeMachine-readable code (e.g. "DashingDerby")
  • nameDisplay name
  • categoryAlways "racing"
  • runner_countNumber of runners per event
  • cycle_secondsSeconds between events
  • is_activeWhether this game type is currently running
curl https://virtuals-api.sportlogic.io/api/v1/game-types \
  -H "X-API-Key: sv_YOUR_KEY"
const res = await fetch(
  'https://virtuals-api.sportlogic.io/api/v1/game-types',
  { headers: { 'X-API-Key': 'sv_YOUR_KEY' } }
);
const { data } = await res.json();
import requests

r = requests.get(
    "https://virtuals-api.sportlogic.io/api/v1/game-types",
    headers={"X-API-Key": "sv_YOUR_KEY"}
)
game_types = r.json()["data"]

Response
{ "success": true, "data": [ { "id": 1, "code": "DashingDerby", "name": "Dashing Derby", "category": "racing", "runner_count": 14, "cycle_seconds": 600, "is_active": true }, { "id": 2, "code": "PlatinumHounds", "name": "Platinum Hounds", "category": "racing", "runner_count": 8, "cycle_seconds": 600, "is_active": true }, { "id": 3, "code": "HarnessRacing", "name": "Harness Racing", "category": "racing", "runner_count": 10, "cycle_seconds": 558, "is_active": true } ] }
GET /api/v1/game-types/{id}/info

Detailed info for a single game type, including available markets.

ParameterTypeRequiredDescription
idintegerrequiredGame type ID (path parameter)
curl https://virtuals-api.sportlogic.io/api/v1/game-types/1/info \
  -H "X-API-Key: sv_YOUR_KEY"

Response
{ "success": true, "data": { "id": 1, "code": "DashingDerby", "name": "Dashing Derby", "category": "racing", "runner_count": 14, "cycle_seconds": 600, "is_active": true } }

Events

Virtual racing events with runners, odds, and results.

GET /api/v1/events

List events with optional filters. Returns cursor-paginated results.

ParameterTypeRequiredDescription
game_type_idintegeroptionalFilter by game type
statusstringoptionalscheduled open closed started finished
per_pageintegeroptional1–100, default 25
cursorstringoptionalPagination cursor from previous response

Response fields

  • idEvent ID
  • game_type_idReferences a game type
  • event_codeShort event code (e.g. "1031")
  • venueVirtual venue name (e.g. "MILNERTON 1000")
  • scheduled_atISO 8601 UTC scheduled start time
  • statusscheduled · open · closed · started · finished
  • game_typeEmbedded game type object
curl -G https://virtuals-api.sportlogic.io/api/v1/events \
  -H "X-API-Key: sv_YOUR_KEY" \
  --data-urlencode "game_type_id=1" \
  --data-urlencode "status=finished" \
  --data-urlencode "per_page=25"
const res = await fetch(
  'https://virtuals-api.sportlogic.io/api/v1/events?game_type_id=1&status=finished',
  { headers: { 'X-API-Key': 'sv_YOUR_KEY' } }
);
const { data, pagination } = await res.json();
import requests

r = requests.get(
    "https://virtuals-api.sportlogic.io/api/v1/events",
    headers={"X-API-Key": "sv_YOUR_KEY"},
    params={"game_type_id": "1", "status": "finished"}
)
events = r.json()["data"]

Response
{ "success": true, "data": [ { "id": 120486, "game_type_id": 1, "event_code": "1031", "venue": "MILNERTON 1000", "scheduled_at": "2026-04-07T04:46:00.000000Z", "status": "finished", "game_type": { "id": 1, "code": "DashingDerby", "name": "Dashing Derby", "category": "racing", "runner_count": 14, "cycle_seconds": 600 } } ], "pagination": { "next_cursor": "eyJzY2hlZ...", "prev_cursor": null, "has_more": true, "per_page": 25 } }
GET /api/v1/events/{id}

Single event with full runner list. Each runner includes draw number, name, color, win/place odds, recent form, and finish position (if finished).

ParameterTypeRequiredDescription
idintegerrequiredEvent ID (path parameter)

Runner fields

  • draw_numberPosition in the draw (1-14 depending on game type)
  • nameRunner name
  • colorHex color for the draw position (e.g. "#e53e3e")
  • odds_winDecimal win odds as string
  • odds_placeDecimal place odds as string
  • formArray of recent finishing positions (most recent first)
  • finish_positionFinal position (null if event not finished)
curl https://virtuals-api.sportlogic.io/api/v1/events/120486 \
  -H "X-API-Key: sv_YOUR_KEY"
const res = await fetch(
  'https://virtuals-api.sportlogic.io/api/v1/events/120486',
  { headers: { 'X-API-Key': 'sv_YOUR_KEY' } }
);
const { data } = await res.json();
console.log(data.runners);
import requests

r = requests.get(
    "https://virtuals-api.sportlogic.io/api/v1/events/120486",
    headers={"X-API-Key": "sv_YOUR_KEY"}
)
runners = r.json()["data"]["runners"]

Response
{ "success": true, "data": { "event": { "id": 120486, "game_type_id": 1, "event_code": "1031", "venue": "MILNERTON 1000", "scheduled_at": "2026-04-07T04:46:00.000000Z", "status": "finished" }, "runners": [ { "draw_number": 1, "name": "Chilly Billy", "color": "#e53e3e", "odds_win": "12.25", "odds_place": "3.02", "form": [7, 2, 3, 2, 3], "finish_position": 3 }, { "draw_number": 2, "name": "Dawn Dragon", "color": "#3182ce", "odds_win": "17.16", "odds_place": "3.45", "form": [1, 0, 0, 0, 2], "finish_position": 2 }, { "draw_number": 3, "name": "Cincinnati Kid", "color": "#38a169", "odds_win": "4.34", "odds_place": "1.98", "form": [1, 1, 4, 1, 1], "finish_position": 1 } ] } }
GET /api/v1/events/{id}/results

Finishing positions and settlement data for a completed event. Filter by draw_number or finish_position to look up a specific runner. Settlement data (win, place, forecast, tricast) is always returned in full regardless of filters - only the positions array is filtered.

ParameterTypeRequiredDescription
idintegerrequiredEvent ID (path parameter)
draw_numberintegeroptionalFilter positions to a specific runner by draw number
finish_positionintegeroptionalFilter positions to a specific finishing position

Settlement fields

  • positions[]Ordered finishing positions with draw number, name, color, and odds
  • settlement.winWinner details (draw_number, name, odds_win)
  • settlement.placeArray of placed runners with odds_place
  • settlement.forecastFirst and second draw numbers
  • settlement.tricastFirst, second, and third draw numbers
  • settlement.place_termsPlace terms description (e.g. "1-3 of 9 runners")
Returns EVENT_NOT_FINISHED if the event hasn't completed yet.

curl https://virtuals-api.sportlogic.io/api/v1/events/120486/results \
  -H "X-API-Key: sv_YOUR_KEY"


curl "https://virtuals-api.sportlogic.io/api/v1/events/120486/results?draw_number=3" \
  -H "X-API-Key: sv_YOUR_KEY"
const res = await fetch(
  'https://virtuals-api.sportlogic.io/api/v1/events/120486/results',
  { headers: { 'X-API-Key': 'sv_YOUR_KEY' } }
);
const { data } = await res.json();
console.log(data.settlement.win);
import requests

r = requests.get(
    "https://virtuals-api.sportlogic.io/api/v1/events/120486/results",
    headers={"X-API-Key": "sv_YOUR_KEY"}
)
results = r.json()["data"]
print(results["settlement"]["win"])

Response
{ "success": true, "data": { "event_id": 120486, "status": "finished", "positions": [ { "finish_position": 1, "draw_number": 3, "name": "Cincinnati Kid", "color": "#38a169", "odds_win": "4.34", "odds_place": "1.98" }, { "finish_position": 2, "draw_number": 2, "name": "Dawn Dragon", "color": "#3182ce", "odds_win": "17.16", "odds_place": "3.45" }, { "finish_position": 3, "draw_number": 1, "name": "Chilly Billy", "color": "#e53e3e", "odds_win": "12.25", "odds_place": "3.02" } ], "settlement": { "win": { "draw_number": 3, "name": "Cincinnati Kid", "odds_win": "4.34" }, "place": [ { "finish_position": 1, "draw_number": 3, "name": "Cincinnati Kid", "odds_place": "1.98" }, { "finish_position": 2, "draw_number": 2, "name": "Dawn Dragon", "odds_place": "3.45" }, { "finish_position": 3, "draw_number": 1, "name": "Chilly Billy", "odds_place": "3.02" } ], "forecast": { "first": 3, "second": 2 }, "tricast": { "first": 3, "second": 2, "third": 1 }, "place_terms": "1-3 of 9 runners" } } }

Markets

Betting market types available for virtual racing events.

GET /api/v1/markets

List all market types. Markets vary by game type.

Available markets

CodeNameDescription
WINWinRunner to finish first
PLACEPlaceRunner to finish in place positions
SHOWShowRunner to finish in top 3
EXACTAExactaFirst and second in exact order
QUINELLAQuinellaFirst and second in any order
TRIFECTATrifectaFirst, second, and third in exact order
HEAD_TO_HEADHead to HeadWhich of two runners finishes ahead
ODD_EVENOdd/EvenWinner's draw number is odd or even
HIGH_LOWHigh/LowWinner's draw number is high or low

Response fields

  • idMarket ID
  • game_type_idWhich game type this market belongs to
  • codeMachine-readable market code (e.g. "WIN")
  • nameDisplay name
  • tabUI grouping tab (MAIN or ALT)
  • sort_orderDisplay order within the tab
curl https://virtuals-api.sportlogic.io/api/v1/markets \
  -H "X-API-Key: sv_YOUR_KEY"

Response
{ "success": true, "data": [ { "id": 1, "game_type_id": 1, "code": "WIN", "name": "Win", "tab": "MAIN", "sort_order": 1 }, { "id": 2, "game_type_id": 1, "code": "PLACE", "name": "Place", "tab": "MAIN", "sort_order": 2 }, { "id": 4, "game_type_id": 1, "code": "EXACTA", "name": "Exacta", "tab": "ALT", "sort_order": 1 } ], "pagination": { "next_cursor": "eyJpZCI6...", "prev_cursor": null, "has_more": true, "per_page": 25 } }

Runner Colors

Each draw position has a fixed color. The color field on runners uses these hex values.

DrawColorHex
1Red#e53e3e
2Blue#3182ce
3Green#38a169
4Yellow#d69e2e
5Orange#dd6b20
6Purple#805ad5
7White#e2e8f0
8Pink#ed64a6
9Brown#8b6914
10Grey#718096
11Teal#319795
12Maroon#9b2c2c
Not all game types use all 12 colors. For example, Speed Skating has 6 runners and only uses draw positions 1–6.

Errors

All error responses follow a consistent envelope with machine-readable codes.

Error envelope

{
  "success": false,
  "error": {
    "code": "MACHINE_READABLE_CODE",
    "message": "Human-readable description"
  }
}

Error codes

HTTPCodeDescription
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENKey suspended or insufficient permissions
404NOT_FOUNDRequested resource doesn't exist
400VALIDATION_ERRORInvalid query parameters
429RATE_LIMIT_EXCEEDEDDaily or per-minute limit reached
400EVENT_NOT_FINISHEDResults requested for an event that hasn't completed