🔐 Authentication
All API endpoints require a valid API key for authentication. You will receive your API key from your account manager.
How to Use Your API Key
📌 Two Methods to Send Your API Key:
Method 1: HTTP Header (Recommended)
X-API-Key: your_api_key_here
Example:
fetch('https://bf.softo.io/api/sports', {
headers: {
'X-API-Key': 'your_api_key_here'
}
})
Method 2: Query Parameter
https://bf.softo.io/api/sports?apiKey=your_api_key_here
⚠️ Keep Your API Key Secure:
- Never share your API key publicly
- Don't commit API keys to public repositories
- Store keys securely in environment variables
- Contact support if your key is compromised
Testing Your API Key
async function testApiKey() {
const response = await fetch('https://bf.softo.io/api/sports', {
headers: { 'X-API-Key': 'your_api_key_here' }
});
if (response.ok) {
console.log('✅ API key is valid!');
const data = await response.json();
console.log(data);
} else {
console.log('❌ Invalid API key');
}
}
curl -H "X-API-Key: your_api_key_here" \
https://bf.softo.io/api/sports
📡 API Endpoints
Description: Retrieves list of all available sports.
Request
GET https://bf.softo.io/api/sports
X-API-Key: your_api_key_here
Response
{
"data": [
{
"name": "Cricket",
"sportCode": "4"
},
{
"name": "Football",
"sportCode": "1"
},
{
"name": "Horse Racing",
"sportCode": "HORSE_RACING"
},
{
"name": "Greyhound Racing",
"sportCode": "GREYHOUND_RACING"
}
]
}
Description: Retrieves all matches/events for a specific sport.
Query Parameters
| Parameter |
Type |
Required |
Description |
sportId |
String |
Required |
Sport code from /api/sports (e.g., "4" for Cricket) |
Request
GET https://bf.softo.io/api/matches?sportId=4
X-API-Key: your_api_key_here
Response
{
"data": {
"sportData": [
{
"sportName": "Cricket",
"leagues": [
{
"name": "T20 Championship",
"events": [
{
"id": "35125278",
"name": "Team A v Team B"
}
]
}
]
}
]
}
}
Description: Retrieves all horse racing events with venues and race times.
Response Structure
{
"data": {
"countries": [
{
"name": "GB",
"Venues": [
{
"_id": "689b3b35ea46df8ea51a4893",
"name": "Lingfield",
"events": [
{
"_id": "696b5651ea46dfe08a6025a6",
"markets": [
{
"marketStartTime": "2026-01-17T13:55:00.000Z",
"type": "WIN"
}
]
}
]
}
]
}
]
}
}
Description: Retrieves detailed markets for a specific horse race.
Parameters
| Parameter |
Type |
Required |
Description |
eventId |
String |
Required |
Event _id from /api/horse-events |
venue |
String |
Required |
Venue _id from /api/horse-events |
time |
String |
Required |
Market start time (ISO format, URL encoded) |
Request Example
GET https://bf.softo.io/api/horse-event/696b5651ea46dfe08a6025a6?venue=689b3b35ea46df8ea51a4893&time=2026-01-17T13:55:00.000Z
X-API-Key: your_api_key_here
Description: Retrieves all greyhound racing events.
Response structure is identical to /api/horse-events
Description: Retrieves detailed markets for a specific greyhound race.
Parameters and response structure identical to /api/horse-event
Description: Retrieves detailed information for a regular sport event.
Query Parameters
| Parameter |
Type |
Required |
Description |
sport |
String |
Required |
Sport name (e.g., "Cricket") |
eventCode |
String |
Required |
Event ID from /api/matches |
Description: Retrieves live exchange odds (back/lay prices) for regular sports.
Request Body
Array of market IDs (strings)
["1.123456789", "1.987654321"]
Request Example
POST https://bf.softo.io/api/exchange
Content-Type: application/json
X-API-Key: your_api_key_here
["1.123456789"]
Response
{
"data": [
{
"marketId": "1.123456789",
"runners": [
{
"selectionId": "12345",
"runnerName": "Team A",
"ex": {
"availableToBack": [
{ "price": 1.95, "size": 1500 },
{ "price": 1.94, "size": 800 }
],
"availableToLay": [
{ "price": 1.96, "size": 2000 },
{ "price": 1.97, "size": 1200 }
]
}
}
]
}
]
}
📌 Important - Price Array Ordering:
- availableToBack[0]: Best back price (displayed on the rightmost position, closest to lay prices)
- availableToLay[0]: Best lay price (displayed on the leftmost position, closest to back prices)
- Both [0] indices represent the best prices and are highlighted with a blue outline in the UI
- Always display up to 3 prices for each side (back and lay)
Description: Retrieves live exchange odds for horse/greyhound racing.
⚠️ Important: For horse/greyhound racing, send only ONE market ID at a time.
Request Body
["1.252767771"]
Request Example
POST https://bf.softo.io/api/exchange-horse
Content-Type: application/json
X-API-Key: your_api_key_here
["1.252767771"]
Response structure is identical to /api/exchange
🎨 UI Implementation Guide
Integration Flow
Regular Sports Flow
1. List Sports
GET https://bf.softo.io/api/sports → Display all sports
2. Select Sport
GET https://bf.softo.io/api/matches?sportId={id} → Display matches
3. Select Match
GET https://bf.softo.io/api/event?sport={sport}&eventCode={code} → Display markets
4. Load Live Odds
POST https://bf.softo.io/api/exchange → Display live odds + scorecard widget
Horse/Greyhound Racing Flow
1. List Events
GET https://bf.softo.io/api/horse-events → Display venues and race times
2. Select Race
GET https://bf.softo.io/api/horse-event/{id} → Display available markets
3. Select Market
Display market with runners
4. Load Live Odds
POST https://bf.softo.io/api/exchange-horse with single market ID → Display live odds
Direct API Usage Examples
Loading Sports
const API_KEY = 'your_api_key_here';
async function loadSports() {
try {
const response = await fetch('https://bf.softo.io/api/sports', {
headers: {
'X-API-Key': API_KEY
}
});
const data = await response.json();
data.data.forEach(sport => {
const element = document.createElement('div');
element.textContent = sport.name;
element.onclick = () => {
if (sport.sportCode === 'HORSE_RACING') {
loadHorseRacing();
} else if (sport.sportCode === 'GREYHOUND_RACING') {
loadGreyhoundRacing();
} else {
loadMatches(sport.sportCode);
}
};
container.appendChild(element);
});
} catch (error) {
console.error('Error loading sports:', error);
}
}
Loading Exchange Odds
async function loadOdds(marketId) {
try {
const response = await fetch('https://bf.softo.io/api/exchange', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
},
body: JSON.stringify([marketId])
});
const data = await response.json();
displayOdds(data);
} catch (error) {
console.error('Error loading odds:', error);
}
}
📊 Display Guidelines
How to Display Odds
When you receive odds data from the API, display them to your users following these guidelines:
Color Coding
📌 Use these colors:
- Back Prices: Light blue background (#cfe9f8)
- Lay Prices: Light pink background (#f6c1c1)
- Best Prices: Blue outline (#1976ff) around the best price
Layout Structure
Each runner (team/player/horse) should display:
- Runner Name on the left
- 3 Back Prices in the middle (light blue)
- 3 Lay Prices on the right (light pink)
Price Ordering - VERY IMPORTANT
⚠️ Critical: Back Prices Must Be Reversed!
The API returns prices in an array, but you must display them differently:
Example: Team A
← BACK PRICES (Blue)
1.93
[2]
1.94
[1]
1.95
[0]
BEST
LAY PRICES (Pink) →
1.96
[0]
BEST
1.97
[1]
1.98
[2]
↑ Notice: Both [0] prices meet in the middle with blue outline
Understanding the Array Order
✅ The Rule:
| BACK PRICES - Display in REVERSE: |
| API gives you: |
[1.95, 1.94, 1.93] |
| You display: |
[1.93] [1.94] [1.95] (reversed) |
| Result: |
Best price [0]=1.95 appears on the RIGHT |
| LAY PRICES - Display NORMAL: |
| API gives you: |
[1.96, 1.97, 1.98] |
| You display: |
[1.96] [1.97] [1.98] (as-is) |
| Result: |
Best price [0]=1.96 appears on the LEFT |
Why This Matters
The best back price and best lay price should meet in the middle. This is the standard betting exchange layout that users expect. Both best prices (index [0] from each array) should be highlighted with a blue outline.
Each Price Box Shows
- Price: The odds (e.g., 1.95) - display large and bold
- Size: The stake amount (e.g., 1500) - display smaller below the price
📺 Live Scorecard Widgets
Overview
For regular sports (Cricket, Football, Tennis, etc.), you can display live scorecards using iframe widgets. There are two methods available:
Method 1: Market ID Based (Default)
https://bf3.widgets.softo.io/Common/LiveScoreCard?id={marketId}
Usage:
- Replace
{marketId} with the actual market ID from the API
- Use the first market ID from the event's markets array
- Embed in an iframe with recommended dimensions: width 100%, height 260px
Example
<iframe
src="https://bf3.widgets.softo.io/Common/LiveScoreCard?id=1.123456789"
width="100%"
height="260px"
frameborder="0">
</iframe>
Method 2: Event Code Based
https://bf2.widgets.softo.io/sport-radar-ui?event_id={eventCode}
Usage:
- Replace
{eventCode} with the event ID from the API
- This method uses a different scorecard provider
- Same iframe dimensions recommended
Example
<iframe
src="https://bf2.widgets.softo.io/sport-radar-ui?event_id=35125278"
width="100%"
height="260px"
frameborder="0">
</iframe>
Switching Between Methods
You can implement a toggle button to switch between both scorecard methods for better reliability. If one fails to load, users can try the alternative method.
⚠️ Important Notes:
- Scorecards are only for regular sports (Cricket, Football, Tennis, etc.)
- Do NOT use scorecards for Horse Racing or Greyhound Racing
- Both widgets are live and update in real-time
When to Display Scorecards
- Display: When showing odds for Cricket, Football, Tennis, and other regular sports
- Don't Display: For Horse Racing or Greyhound Racing events