API Documentation

Complete reference โ€” every endpoint, field, and response shape

Authentication

All endpoints except /health require your API key in the X-API-Key header.

curl https://sportsapi.nvsbet.com/api/sports \
  -H "X-API-Key: your_api_key"
๐Ÿ”’ Never expose your API key in client-side/browser code. Make all requests server-side.

Base URL

https://sportsapi.nvsbet.com/api

All responses are JSON. Timestamps are ISO 8601 UTC.

Rate Limits

Plan Requests/day Price
Free 500 Free
Basic 20,000 $19.99/mo
Pro 50,000 $49.99/mo
Enterprise Unlimited $99.99/mo

Public endpoints (no key) are limited to 30 req/min per IP. Rate limit headers are returned on every response: X-RateLimit-Limit, X-RateLimit-Remaining.

Pagination

List endpoints are paginated. Use page to navigate. Some endpoints support per_page โ€” see per-endpoint notes for defaults and maximums.

Depending on the endpoint, pagination appears either at the top level or under data.pagination:

Grouped responses (fixtures, upcoming, results)
{
  "status": "success",
  "data": {
    "grouped": [ ... ],
    "pagination": {
      "total":        584,
      "per_page":     50,
      "current_page": 1,
      "last_page":    12
    }
  }
}
Flat list responses (leagues, teams, players)
{
  "status": "success",
  "data": {
    "total":        237,
    "per_page":     50,
    "current_page": 1,
    "last_page":    5,
    "data": [ ... ]
  }
}

Error Codes

200 OK Request successful
202 Pending Resource exists but data not yet available (e.g. odds not computed yet)
401 Unauthorized Missing or invalid API key
404 Not Found Resource does not exist
422 Validation Error Invalid query parameter โ€” response includes an errors object
429 Too Many Requests Rate limit exceeded
500 Server Error Something went wrong on our end

Error shape

{
  "status":  "error",
  "message": "The given data was invalid.",
  "errors":  { "status": ["The selected status is invalid."] }
}

Health Check

GET /api/health No key required
{
  "status":  "ok",
  "service": "SportsAPI",
  "version": "1.0.0",
  "time":    "2026-05-24T13:50:12Z",
  "stats": {
    "sports":   15,
    "leagues":  949,
    "teams":    9813,
    "players":  55794,
    "fixtures": 6801
  }
}

API Keys

GET /api/keys/usage

Returns usage stats for the authenticated key.

{
  "status": "success",
  "data": {
    "name":            "My Key",
    "plan":            "pro",
    "rate_limit":      10000,
    "requests_today":  412,
    "remaining":       9588,
    "resets_at":       "2026-05-24T23:59:59Z"
  }
}
POST /api/keys/generate No key required
curl -X POST https://sportsapi.nvsbet.com/api/keys/generate \
  -H "Content-Type: application/json" \
  -d '{"name": "My App", "plan": "pro"}'

Sports

GET /api/sports List all sports
GET /api/sports/{slug} Single sport by slug
GET /api/sports/{slug}/leagues All leagues for a sport

Sport slugs

football basketball tennis baseball hockey rugby volleyball handball mma formula-1 afl cricket american-football

Response โ€” /api/sports

{
  "status": "success",
  "total":  15,
  "data": [
    {
      "id":            1,
      "name":          "Football",
      "slug":          "football",
      "icon":          null,
      "category":      "team_sport",
      "has_livescore": true,
      "has_players":   true,
      "has_standings": true,
      "has_lineups":   true,
      "has_stats":     true,
      "has_transfers": true,
      "is_active":     true,
      "leagues_count": 237,
      "teams_count":   2671,
      "players_count": 30588,
      "created_at":    "2026-04-26T13:01:42Z",
      "updated_at":    "2026-04-26T13:01:42Z"
    }
  ]
}

Leagues

GET
/api/leagues
List all leagues (paginated, 50/page)
GET
/api/leagues/{id}
League detail with sport & current season
GET
/api/leagues/{id}/seasons
All seasons for a league
GET
/api/leagues/{id}/teams
Teams in this league
GET
/api/leagues/{id}/standings
Standings table

Filters โ€” /api/leagues

sportFilter by sport slug โ€” e.g. ?sport=football
countryFilter by country name โ€” e.g. ?country=England
pagePage number, default 1. Page size is fixed at 50.

Response โ€” /api/leagues/{id}

{
  "status": "success",
  "data": {
    "id":          1,
    "sport_id":    1,
    "name":        "Premier League",
    "slug":        "premier-league",
    "country":     "England",
    "country_code":null,
    "logo":        "https://...",
    "flag":        null,
    "type":        "league",
    "source_id":   "682",
    "source":      "sportsapipro",
    "is_active":   true,
    "fixtures_count": 32,
    "seasons_count":  1,
    "sport": { "id":1, "name":"Football", "slug":"football", ... },
    "current_season": {
      "id":                  1,
      "league_id":           1,
      "name":                "2026",
      "year":                "2026",
      "start_date":          null,
      "end_date":            null,
      "is_current":          true,
      "standings_available": false,
      "created_at":          "2026-04-26T13:01:42Z",
      "updated_at":          "2026-05-24T02:00:01Z"
    },
    "created_at": "2026-04-26T13:01:42Z",
    "updated_at": "2026-05-22T00:37:17Z"
  }
}

Response โ€” /api/leagues/{id}/standings

{
  "status": "success",
  "league": "Premier League",
  "season": "2026",
  "data": [
    {
      "id":              11,
      "league_id":       1,
      "season_id":       1,
      "team_id":         9,
      "rank":            1,
      "group":           null,
      "points":          78,
      "played":          37,
      "won":             24,
      "drawn":            6,
      "lost":             7,
      "goals_for":       68,
      "goals_against":   39,
      "goal_difference": 29,
      "form":            null,
      "description":     null,
      "team": {
        "id":         9,
        "name":       "Arsenal",
        "short_name": "ARS",
        "slug":       "arsenal",
        "logo":       "https://..."
      }
    }
  ]
}

Teams

GET
/api/teams
List teams (paginated, 50/page)
GET
/api/teams/{id}
Team profile + sport
GET
/api/teams/{id}/players
Current squad
GET
/api/teams/{id}/fixtures
Team fixtures (paginated, 20/page)
GET
/api/teams/{id}/stats
Season statistics
GET
/api/teams/{id}/injuries
Current injury list

Filters โ€” /api/teams

sportFilter by sport slug
countryFilter by country
searchSearch by team name โ€” e.g. ?search=Arsenal
pagePage number, default 1. Page size fixed at 50.

Filters โ€” /api/teams/{id}/fixtures

statusFilter by fixture status โ€” e.g. ?status=scheduled
pagePage number, default 1. Page size fixed at 20.

Response โ€” /api/teams/{id}

{
  "status": "success",
  "data": {
    "id":            1,
    "sport_id":      1,
    "venue_id":      null,
    "name":          "Arsenal",
    "short_name":    "ARS",
    "slug":          "arsenal",
    "logo":          "https://...",
    "country":       null,
    "country_code":  null,
    "national":      false,
    "founded":       null,
    "source_id":     "359",
    "source":        "football",
    "is_active":     true,
    "players_count": 26,
    "sport":  { "id":1, "name":"Football", "slug":"football", ... },
    "venue":  null,
    "created_at": "2026-04-26T13:01:42Z",
    "updated_at": "2026-04-26T13:01:42Z"
  }
}

Players

GET
/api/players
List players (paginated, 50/page)
GET
/api/players/{id}
Player profile + sport + team
GET
/api/players/{id}/stats
Player statistics
GET
/api/players/{id}/transfers
Transfer history

Filters โ€” /api/players

sportFilter by sport slug
team_idFilter by team ID โ€” e.g. ?team_id=2
positionFilter by position โ€” e.g. ?position=G (G, D, M, F)
nationalityFilter by nationality โ€” e.g. ?nationality=England
searchSearch by player name โ€” e.g. ?search=Saka
statusFilter by status โ€” e.g. ?status=active
pagePage number, default 1. Page size fixed at 50.

Response โ€” /api/players/{id}

{
  "status": "success",
  "data": {
    "id":            1,
    "sport_id":      1,
    "team_id":       13949,
    "name":          "Fraser Forster",
    "firstname":     null,
    "lastname":      null,
    "date_of_birth": "1988-03-17T00:00:00Z",
    "nationality":   "England",
    "country_code":  null,
    "position":      "G",
    "jersey_number": 17,
    "height":        "200.66",
    "weight":        "92.08",
    "photo":         "https://...",
    "status":        "active",
    "source_id":     "93193",
    "source":        "football",
    "sport": { "id":1, "name":"Football", "slug":"football", ... },
    "team":  { "id":13949, "name":"Bournemouth", "slug":"...", ... },
    "created_at": "2026-04-26T13:02:02Z",
    "updated_at": "2026-05-23T14:13:57Z"
  }
}

Fixtures

GET
/api/fixtures
All fixtures grouped by sport โ†’ league (paginated)
GET
/api/fixtures/today
Today's fixtures grouped by sport โ†’ league
GET
/api/fixtures/live
All currently live fixtures grouped by sport โ†’ league
GET
/api/fixtures/upcoming
Upcoming fixtures grouped by sport โ†’ league (paginated)
GET
/api/fixtures/results
Recent results grouped by sport โ†’ league (paginated)
GET
/api/fixtures/by-league/{id}
All fixtures for one league (flat, paginated)
GET
/api/fixtures/{id}
Full fixture detail
GET
/api/fixtures/{id}/lineups
Match lineups
GET
/api/fixtures/{id}/events
Match events (goals, cards, subs)
GET
/api/fixtures/{id}/stats
Match statistics per team

Filters โ€” /api/fixtures and /results

sportFilter by sport slug โ€” e.g. ?sport=football
league_idFilter by league ID
statusComma-separated statuses โ€” e.g. ?status=live,halftime
dateSingle date โ€” e.g. ?date=2026-05-24
from / toDate range โ€” e.g. ?from=2026-05-01&to=2026-05-31
per_pageItems per page, default 50
pagePage number

Filters โ€” /api/fixtures/upcoming

sportFilter by sport slug
league_idFilter by league ID
daysLook-ahead window in days โ€” default 7, max 30
per_pageItems per page, default 50
pagePage number

Filters โ€” /api/fixtures/today and /live

sportFilter by sport slug
league_idFilter by league ID

Filters โ€” /api/fixtures/by-league/{id}

statusComma-separated statuses โ€” e.g. ?status=scheduled,live
dateSingle date โ€” e.g. ?date=2026-05-24
from / toDate range โ€” e.g. ?from=2026-05-01&to=2026-05-31
per_pageItems per page, default 50
pagePage number

Fixture status values

scheduled confirmed confirmed_scheduled live halftime extra_time penalties confirmed_finished finished full_time_pending postponed suspended cancelled abandoned

Response โ€” Grouped list (today / live / upcoming / results)

{
  "status": "success",
  "data": {
    "date":  "2026-05-24",
    "total": 239,
    "grouped": [
      {
        "sport_id":   1,
        "sport_name": "Football",
        "sport_slug": "football",
        "leagues": [
          {
            "league_id":   1,
            "league_name": "Premier League",
            "country":     "England",
            "logo":        "https://...",
            "fixtures": [
              {
                "id":           308,
                "source_id":    "15635599",
                "kickoff_time": "2026-05-24T15:00:00Z",
                "status":       "live",
                "round":        null,
                "home_team": { "id":2, "name":"Arsenal", "short_name":"ARS", "logo":"https://...", "country":null },
                "away_team": { "id":3, "name":"Chelsea", "short_name":"CHE", "logo":"https://...", "country":null },
                "score": {
                  "home": 2, "away": 1,
                  "halftime":  { "home":1, "away":0 },
                  "extra_time":{ "home":null, "away":null },
                  "penalties": { "home":null, "away":null }
                },
                "lineup_available": true,
                "events_available": true,
                "stats_available":  true
              }
            ]
          }
        ]
      }
    ],
    "pagination": {
      "total": 239, "per_page": 50, "current_page": 1, "last_page": 5
    }
  }
}

Response โ€” /api/fixtures/{id}

{
  "status": "success",
  "data": {
    "id":           308,
    "source_id":    "15635599",
    "source":       "sportsapipro",
    "kickoff_time": "2026-05-24T15:00:00Z",
    "status":       "confirmed_finished",
    "round":        null,
    "home_team": { "id":2, "name":"Arsenal", "short_name":"ARS", "logo":"https://...", "country":null },
    "away_team": { "id":3, "name":"Chelsea", "short_name":"CHE", "logo":"https://...", "country":null },
    "score": {
      "home": 2, "away": 1,
      "halftime":  { "home":1, "away":0 },
      "extra_time":{ "home":null, "away":null },
      "penalties": { "home":null, "away":null }
    },
    "lineup_available": true,
    "events_available": true,
    "stats_available":  true,
    "league": { "id":1, "name":"Premier League", "logo":"https://..." },
    "sport":  { "id":1, "name":"Football", "slug":"football" },
    "venue":   null,
    "referee": null,
    "updated_at": "2026-05-23T09:44:51Z"
  }
}

Response โ€” /api/fixtures/{id}/lineups

โš ๏ธ Check lineup_available on the fixture before calling this. If false, the response returns available: false with no data array.
// When available: false
{ "status":"success", "fixture":308, "available":false }

// When available: true
{
  "status":   "success",
  "fixture":  308,
  "available": true,
  "data": {
    "home": { "formation":"4-3-3", "starting":[ ... ], "subs":[ ... ] },
    "away": { "formation":"4-2-3-1", "starting":[ ... ], "subs":[ ... ] }
  }
}

Livescores

โšก Updated every 30 seconds. The updated_at field at the root tells you the exact last sync time.
GET
/api/livescores
All live games across all sports
GET
/api/livescores/{sport}
Live games for a sport slug e.g. /livescores/football
GET
/api/livescores/fixture/{id}
Live data for a single fixture

Response โ€” /api/livescores

{
  "status": "success",
  "live_count": 8,
  "ft_count": 4,
  "updated_at": "2026-05-27T20:30:00Z",
  "data": [
    {
      "id": 525,
      "sport": "Football",
      "sport_slug": "football",
      "league": "Premier League",
      "league_id": 1,
      "home_team": {
        "id": 2,
        "name": "Arsenal",
        "logo": "https://...",
        "yellow_cards": 1,
        "red_cards": 0
      },
      "away_team": {
        "id": 3,
        "name": "Chelsea",
        "logo": "https://...",
        "yellow_cards": 2,
        "red_cards": 0
      },
      "home_score": 2,
      "away_score": 1,
      "home_score_ht": 1,
      "away_score_ht": 0,
      "elapsed": 90,
      "status": "FT",
      "status_raw": "finished",
      "kickoff_time": "2026-05-27T15:00:00Z",
      "updated_at": "2026-05-27T16:55:00Z",

      "has_var": true,
      "has_penalty": false,
      "events_count": 24,

      "results": {
        "source": "sportsapipro_websocket",
        "provider_status": "finished",
        "finalized_at": "2026-05-27 16:55:00",
        "elapsed": 90,
        "home_score": 2,
        "away_score": 1,
        "winner": "home",
        "events_summary": {
          "events_count": 24,
          "has_var": true,
          "var_goal_awarded": false,
          "var_goal_not_awarded": true,
          "var_penalty_awarded": false,
          "var_penalty_not_awarded": false,
          "var_card_upgrade": false,
          "has_penalty": false,
          "penalty_scored": false,
          "penalty_missed": false,
          "goals": [
            {
              "time": 34,
              "team": "home",
              "player": "Bukayo Saka",
              "assist": "Martin Odegaard",
              "penalty": false
            }
          ],
          "assists": [
            {
              "time": 34,
              "team": "home",
              "player": "Martin Odegaard"
            }
          ],
          "cards": [
            {
              "time": 55,
              "team": "away",
              "player": "Conor Gallagher",
              "class": "yellow"
            }
          ],
          "substitutions": []
        }
      },

      "events_summary": {
        "events_count": 24,
        "has_var": true,
        "var_goal_not_awarded": true,
        "has_penalty": false,
        "goals": [],
        "assists": [],
        "cards": [],
        "substitutions": []
      },

      "events": [
        {
          "time": 75,
          "incidentType": "varDecision",
          "incidentClass": "goalNotAwarded",
          "confirmed": true,
          "player": { "id": 123, "name": "Player Name" }
        }
      ],

      "stats": []
    }
  ]
}
Status field notes
status โ€” display label e.g. "LIVE", "HT", "FT", "SUSP". Both full_time_pending and confirmed_finished display as "FT"
status_raw โ€” raw DB value e.g. "live", "halftime", "confirmed_finished", "suspended"

Odds

โ„น๏ธ Odds are pre-computed and served from cache. If a fixture has no odds yet the endpoint returns HTTP 202 with status: "pending". Odds values are strings (e.g. "3.080") โ€” parse to float as needed.
GET
/api/odds
Bulk odds for all fixtures โ€” filterable, paginated
GET
/api/odds/today
Today's fixture odds (same as /odds locked to today)
GET
/api/odds/live
Odds for all currently live fixtures
GET
/api/odds/fixture/{id}
Odds for a single fixture โ€” all markets

Filters โ€” /api/odds and /api/odds/today

sportFilter by sport slug โ€” e.g. ?sport=football
league_idFilter by league ID
dateDate to fetch โ€” e.g. ?date=2026-05-24 (defaults to today)
statusprematch | live | all (default: all)
marketReturn only one market โ€” e.g. ?market=1x2
per_pageItems per page, default 25, max 100
pagePage number

Filters โ€” /api/odds/live

sportFilter by sport slug
marketReturn only one market

Filters โ€” /api/odds/fixture/{id}

marketReturn only one market โ€” e.g. ?market=btts

Available Markets

Football

1x2 match_winner double_chance draw_no_bet btts btts_result correct_score over_under_0.5 over_under_1.5 over_under_2.5 over_under_3.5 over_under_4.5 asian_handicap european_handicap half_time ht_ft sh_result sh_over_under_05 sh_over_under_15 sh_over_under_25 sh_over_under_35 sh_correct_score which_half_more_goals penalty_in_match_special number_of_penalties var_goal_disallowed woodwork_hit_home woodwork_hit_away both_teams_woodwork offside_in_match offsides_over_25 offsides_over_35 offsides_over_45 anytime_goalscorer first_goalscorer last_goalscorer player_brace player_hattrick clean_sheet win_to_nil to_score total_goals_exact

Basketball

match_winner moneyline match_winner_incl_ot match_winner_reg_only draw_no_bet will_overtime spread total_145_5 total_150_5 total_153_5 total_155_5 total_157_5 total_159_5 total_160_5 total_161_5 total_162_5 total_164_5 total_166_5 total_169_5 total_172_5 total_175_5 home_total_points away_total_points ht_total_points sh_total_points ht_winner sh_winner ht_result ht_ft q1_winner q2_winner q3_winner q4_winner q1_result q2_result q3_result q4_result q1_total q2_total q3_total q4_total q1_handicap q2_handicap q3_handicap q4_handicap race_to_10 race_to_20 race_to_30 winning_margin winner_margin_combo winner_and_total winner_and_overtime technical_foul ejection player_points_10_5 player_points_15_5 player_points_20_5 player_points_25_5 player_points_30_5 player_rebounds_3_5 player_rebounds_5_5 player_rebounds_7_5 player_assists_2_5 player_assists_4_5 player_assists_6_5

AFL

match_winner match_result double_chance line winning_margin draw_yes_no total_110_5 total_120_5 total_130_5 total_140_5 total_150_5 total_160_5 total_170_5 total_180_5 total_190_5 total_200_5 home_total away_total odd_even both_50plus both_60plus both_70plus both_80plus q1_winner q1_line q1_total q2_winner q2_line q2_total q3_winner q3_line q3_total q4_winner q4_line q4_total ht_result ht_ft ht_line most_quarters_won home_all_quarters away_all_quarters highest_scoring_q total_goals_10_5 total_goals_12_5 total_goals_14_5 total_goals_16_5 total_goals_18_5 total_goals_20_5 total_goals_22_5 home_goals away_goals total_behinds first_score_type first_scoring_team last_scoring_team team_100plus team_120plus player_disposals_155 player_disposals_205 player_disposals_255 player_disposals_305 player_goals_05 player_goals_15 player_goals_25 player_goals_35 player_marks_35 player_marks_55 player_tackles_25 player_tackles_35 player_first_goal player_anytime_goal player_3plus_goals player_4plus_goals player_5plus_goals margin_at_ht any_player_5goals total_behinds_combined live_winner live_line live_total live_next_score live_quarter_winner live_remaining_score

Baseball

match_winner moneyline draw_no_bet run_line_n15 run_line_p15 run_line_n25 run_line_p25 first_5_winner first_5_run_line total_runs_6_5 total_runs_7_5 total_runs_8_5 total_runs_9_5 total_runs_10_5 total_runs_11_5 total_runs_12_5 home_runs_total away_runs_total odd_even_runs f5_total both_3plus both_4plus both_5plus first_inning_score first_inning_winner first_inning_ou extra_innings first_team_score last_team_score highest_scoring_inning inning1_winner inning1_total inning2_winner inning2_total inning3_winner inning3_total inning4_winner inning4_total inning5_winner inning5_total inning6_winner inning6_total inning7_winner inning7_total inning8_winner inning8_total inning9_winner inning9_total home_hits away_hits total_hits total_errors total_walks total_k total_hr_0_5 total_hr_1_5 total_hr_2_5 no_hitter perfect_game grand_slam hit_by_pitch double_play triple_in_match player_hits_05 player_hits_15 player_runs_05 player_rbi_05 player_hr_05 player_strikeouts_35 player_strikeouts_55 player_bases_15 live_moneyline live_total_runs live_run_line live_next_run live_next_inning

Rugby

match_winner match_result draw_no_bet double_chance winning_margin handicap_-20_5 handicap_-15_5 handicap_-12_5 handicap_-10_5 handicap_-7_5 handicap_-5_5 handicap_-3_5 handicap_p3_5 handicap_p5_5 handicap_p7_5 handicap_p10_5 handicap_p12_5 handicap_p15_5 handicap_p20_5 total_30_5 total_33_5 total_36_5 total_39_5 total_42_5 total_45_5 total_48_5 total_51_5 total_54_5 total_57_5 total_60_5 home_total away_total odd_even ht_result sh_result ht_ft total_tries_2_5 total_tries_3_5 total_tries_4_5 total_tries_5_5 total_tries_6_5 total_tries_7_5 total_tries_8_5 home_tries away_tries first_try last_try first_scoring_team next_scoring_team race_to_10 race_to_20 race_to_30 yellow_card red_card sin_bin player_anytime_try player_first_try player_2plus_tries player_3plus_tries live_winner live_handicap live_total live_next_score_type live_next_scoring_team live_next_try live_next_7pts

Hockey

moneyline puck_line three_way draw_no_bet will_overtime btts odd_even_goals over_under_4_5 over_under_5_5 over_under_6_5 over_under_7_5 home_goals_over_15 away_goals_over_15 first_goal period_1 period_2 period_3 period_1_total_05 period_2_total_05 period_3_total_05

American Football (NFL)

moneyline spread first_half sh_winner sh_total home_total away_total odd_even over_under_33_5 over_under_36_5 over_under_39_5 over_under_42_5 over_under_45_5 over_under_48_5 over_under_51_5 over_under_54_5 over_under_57_5 quarter_1_winner quarter_2_winner quarter_3_winner quarter_4_winner quarter_1_total quarter_2_total quarter_3_total quarter_4_total first_team_score last_team_score will_overtime both_teams_td

MMA

fight_winner method_of_victory goes_to_decision fight_distance draw_nc ko_in_fight sub_in_fight total_rounds_1_5 total_rounds_2_5 total_rounds_3_5 total_rounds_4_5 fight_ends_r1 fight_ends_r2 fight_ends_r3 fa_ko_r1 fa_ko_r2 fa_ko_r3 fa_sub_r1 fa_sub_r2 fa_sub_r3 fb_ko_r1 fb_ko_r2 fb_ko_r3 fb_sub_r1 fb_sub_r2 fb_sub_r3

Handball

match_result draw_no_bet double_chance hdp_n6 hdp_n5 hdp_n4 hdp_n3 hdp_n2 hdp_n1 hdp_p1 hdp_p2 hdp_p3 hdp_p4 hdp_p5 hdp_p6 total_40_5 total_42_5 total_44_5 total_46_5 total_48_5 total_50_5 total_52_5 total_54_5 total_56_5 total_58_5 total_60_5 home_over_18_5 home_over_20_5 home_over_22_5 home_over_24_5 home_over_26_5 home_over_28_5 away_over_18_5 away_over_20_5 away_over_22_5 away_over_24_5 away_over_26_5 away_over_28_5 odd_even both_over_20 both_over_22 both_over_24 ht_result sh_result which_half_more ht_handicap sh_handicap ht_total_18_5 ht_total_20_5 ht_total_22_5 ht_total_24_5 ht_total_26_5 ht_total_28_5

Response โ€” /api/odds (bulk)

{
  "status":       "success",
  "date":         "2026-05-24",
  "filters":      { "sport":"football", "league_id":null, "status":"all", "market":null },
  "total":        213,
  "per_page":     25,
  "current_page": 1,
  "last_page":    9,
  "data": [
    {
      "fixture_id": 60,
      "home_team":  "Arsenal",
      "away_team":  "Chelsea",
      "kickoff":    "2026-05-24T15:00:00Z",
      "sport":      "Football",
      "league":     "Premier League",
      "status":     "live",
      "is_live":    true,
      "markets": {
        "1x2": {
          "name":    "1x2",
          "options": { "Home":"1.850", "Draw":"3.500", "Away":"4.200" }
        },
        "btts": {
          "name":    "Btts",
          "options": { "Yes":"1.560", "No":"2.600" }
        }
      }
    }
  ]
}

Response โ€” /api/odds/fixture/{id} (full)

{
  "fixture_id": 308,
  "home_team": "Monza",
  "away_team": "Catanzaro",
  "kickoff": "2026-05-29T18:00:00Z",
  "sport": "Football",
  "league": "Serie B, Relegation Playoffs",
  "is_live": false,
  "markets": {
    "1x2": {
      "name": "Match Result",
      "options": {
        "Home": "1.73",
        "Draw": "4.06",
        "Away": "4.94"
      }
    },

    "sh_result": {
      "name": "Second Half Result",
      "options": {
        "Home": "2.64",
        "Draw": "2.57",
        "Away": "3.85"
      }
    },

    "sh_over_under_15": {
      "name": "Second Half Over/Under 1.5",
      "options": {
        "Over 1.5": "2.37",
        "Under 1.5": "1.65"
      }
    },

    "penalty_in_match_special": {
      "name": "Penalty in Match",
      "options": {
        "Yes": "4.06",
        "No": "1.28"
      }
    },

    "var_goal_disallowed": {
      "name": "Goal Disallowed by VAR",
      "options": {
        "Yes": "5.41",
        "No": "1.19"
      }
    },

    "woodwork_hit_home": {
      "name": "Home Team to Hit Woodwork",
      "options": {
        "Yes": "5.41",
        "No": "1.19"
      }
    },

    "woodwork_hit_away": {
      "name": "Away Team to Hit Woodwork",
      "options": {
        "Yes": "5.72",
        "No": "1.17"
      }
    },

    "offsides_over_25": {
      "name": "Total Offsides Over/Under 2.5",
      "options": {
        "Over 2.5": "1.51",
        "Under 2.5": "2.74"
      }
    },

    "anytime_goalscorer": {
      "name": "Anytime Goalscorer",
      "options": {
        "Player Name": "4.90"
      }
    },

    "first_goalscorer": {
      "name": "First Goalscorer",
      "options": {
        "Player Name": "14.41"
      }
    }
  }
}

// No odds yet โ†’ HTTP 202
{ "status":"pending", "message":"Odds not available yet for this fixture." }

Webhooks

Push notifications when game events happen โ€” no polling needed.

GET
/api/webhooks
List your webhooks
POST
/api/webhooks
Register a webhook
GET
/api/webhooks/{id}
Get webhook detail
PUT
/api/webhooks/{id}
Update a webhook
DELETE
/api/webhooks/{id}
Delete a webhook
POST
/api/webhooks/{id}/test
Send a test event
GET
/api/webhooks/{id}/logs
View delivery logs
POST
/api/webhooks/{id}/regenerate-secret
Rotate signing secret

Register a webhook

curl -X POST https://sportsapi.nvsbet.com/api/webhooks \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name":   "My App",
    "url":    "https://yourapp.com/webhook",
    "events": ["fixture.finished", "fixture.live", "fixture.goal"],
    "sports": [1]
  }'

Events

fixture.live Game has kicked off
fixture.goal Goal scored โ€” includes scorer, minute, score
fixture.halftime Half-time reached
fixture.finished Full time confirmed
fixture.cancelled Game cancelled
fixture.postponed Game postponed
* All events

Webhook payload

{
  "event":     "fixture.finished",
  "timestamp": "2026-05-24T20:45:00Z",
  "data": {
    "fixture_id": 308,
    "sport":      "Football",
    "league":     "Premier League",
    "home_team":  "Arsenal",
    "away_team":  "Chelsea",
    "home_score": 2,
    "away_score": 1,
    "status":     "confirmed_finished"
  }
}

Verifying signatures

Every delivery includes X-SportsAPI-Signature. Always verify before processing.

PHP
$payload   = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SPORTSAPI_SIGNATURE'];
$secret    = 'your_webhook_secret';

$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

$data = json_decode($payload, true);
Node.js
const crypto = require('crypto');

const payload   = req.rawBody;
const signature = req.headers['x-sportsapi-signature'];
const secret    = 'your_webhook_secret';

const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

if (signature !== expected) {
    return res.status(401).end();
}