nvl.sportangle.co.uk

nvl_league_data_api

Season

NVL League Data API

Public JSON API for National Volleyball League standings, fixtures, and head-to-head records across all NVL divisions.

Base URL

https://nvl.sportangle.co.uk/api/v1

Authentication

None required — this is a public, read-only API. API keys may be introduced in future.

Quick start

curl "https://nvl.sportangle.co.uk/api/v1/standings?category=men&division=division-2-north"

Endpoints

GET /api/v1/divisions

Returns all available divisions.

Parameters: None

Example request:

curl "https://nvl.sportangle.co.uk/api/v1/divisions"

Example response:

[
  {
    "category": "Men",
    "division": "DYNAMIK Men's Super League",
    "slug": "dynamik-super-league",
    "tier": "Super League",
    "region": null
  },
  {
    "category": "Women",
    "division": "MAAREE Women's Super League",
    "slug": "maaree-super-league",
    "tier": "Super League",
    "region": null
  },
  {
    "category": "Men",
    "division": "Division 1 North",
    "slug": "division-1-north",
    "tier": "1",
    "region": "North"
  }
]

GET /api/v1/seasons

Returns the seasons addressable by the API. currentSeason is the default when season is omitted from another endpoint.

Parameters: None

Example request:

curl "https://nvl.sportangle.co.uk/api/v1/seasons"

Example response:

{
  "availableSeasons": [],
  "currentSeason": null
}

Migrated sites return their addressable season values in YYYY-YYYY form, for example 2025-2026 and 2024-2025. An unmigrated site returns no addressable seasons while still serving its current fixtures when season is omitted.


GET /api/v1/fixtures

Returns fixtures for a given division. Results are sorted newest first.

Parameters:

Name Type Required Description
category string Yes men or women
division string Yes Division slug (e.g. division-2-north) — see /divisions for valid slugs
status string No Filter by played or scheduled
limit integer No Maximum number of fixtures to return
season string No Season in YYYY-YYYY form. Defaults to currentSeason; see /seasons.

Example request:

curl "https://nvl.sportangle.co.uk/api/v1/fixtures?category=men&division=division-2-north&status=played&limit=2"

Example response:

[
  {
    "fixtureId": "men-division-2-north.json-0",
    "date": "2026-03-14",
    "time": null,
    "category": "Men",
    "division": "Division 2 North",
    "round": "",
    "venue": "",
    "homeTeam": "Moss Side",
    "awayTeam": "Tameside",
    "homeSets": 3,
    "awaySets": 1,
    "setScores": [
      { "home": 25, "away": 20 },
      { "home": 23, "away": 25 },
      { "home": 25, "away": 18 },
      { "home": 25, "away": 15 }
    ],
    "status": "played"
  }
  ...
]

GET /api/v1/standings

Returns computed league standings for a division, sorted by points then set quotient.

Parameters:

Name Type Required Description
category string Yes men or women
division string Yes Division slug
date string No ISO 8601 date — only count fixtures on or before this date
detail string No Set to true to include scoreBreakdown and form fields
season string No Season in YYYY-YYYY form. Defaults to currentSeason; finalized past seasons use their stored table. See /seasons.

Example request:

curl "https://nvl.sportangle.co.uk/api/v1/standings?category=men&division=division-2-north&detail=true"

Example response:

[
  {
    "position": 1,
    "team": "Moss Side",
    "played": 12,
    "won": 10,
    "lost": 2,
    "setsWon": 33,
    "setsLost": 12,
    "setQuotient": 2.75,
    "pointsWon": 920,
    "pointsLost": 780,
    "pointQuotient": 1.179,
    "points": 28,
    "scoreBreakdown": {
      "w30": 5,
      "w31": 3,
      "w32": 2,
      "l23": 1,
      "l13": 1,
      "l03": 0
    },
    "form": ["W", "W", "L", "W", "W", "W", "L", "W", "W", "W", "W", "W"]
  }
  ...
]

GET /api/v1/h2h

Returns head-to-head records for a team against all opponents (or a specific opponent) in a division.

Parameters:

Name Type Required Description
category string Yes men or women
division string Yes Division slug
team string Yes Exact team name (case-sensitive)
opponent string No Filter to a single opponent
season string No Season in YYYY-YYYY form. Defaults to currentSeason; see /seasons.

Example request:

curl "https://nvl.sportangle.co.uk/api/v1/h2h?category=men&division=division-2-north&team=Moss+Side"

Example response:

{
  "team": "Moss Side",
  "opponents": {
    "Tameside": {
      "played": 2,
      "won": 2,
      "lost": 0,
      "setsWon": 6,
      "setsLost": 2,
      "fixtures": [
        {
          "date": "2026-03-14",
          "home": "Moss Side",
          "away": "Tameside",
          "homeSets": 3,
          "awaySets": 1
        },
        {
          "date": "2025-11-09",
          "home": "Tameside",
          "away": "Moss Side",
          "homeSets": 1,
          "awaySets": 3
        }
      ]
    }
    ...
  }
}

Field reference

Standings fields

Field Description
position League position (1-indexed)
played Total matches played
won / lost Matches won / lost
setsWon / setsLost Total sets won / lost across all matches
setQuotient setsWon / setsLost (3 decimal places). null if no sets lost.
pointsWon / pointsLost Total rally points won / lost (from set scores)
pointQuotient pointsWon / pointsLost (3 decimal places). null if no points lost.
points League points: 3 for a 3-0/3-1 win, 2 for a 3-2 win, 1 for a 2-3 loss, 0 otherwise

Score breakdown (detail mode)

Key Meaning
w30 Wins 3-0
w31 Wins 3-1
w32 Wins 3-2
l23 Losses 2-3
l13 Losses 1-3
l03 Losses 0-3

Form (detail mode)

An array of "W" and "L" values in chronological order (oldest first), one entry per played fixture. Unplayed fixtures are null.

Fixture fields

Field Description
fixtureId Unique identifier for the fixture
date ISO 8601 date string
time Match time or null
category "Men" or "Women"
division Full division name
round Round name/number (may be empty)
venue Venue name (may be empty)
homeTeam / awayTeam Team names
homeSets / awaySets Sets won by each team (null if unplayed)
setScores Array of { home, away } point scores per set
status "played" or "scheduled"

Errors

All errors return a JSON object with an error field.

Status Cause
400 Missing required parameters
404 Division not found, or no matching fixtures/team

Example:

{ "error": "category and division are required" }

Rate limits

No rate limits are currently enforced. Please be reasonable with request volume — this may change.


Usage examples

JavaScript (fetch)

const res = await fetch(
  'https://nvl.sportangle.co.uk/api/v1/standings?category=men&division=division-2-north'
)
const standings = await res.json()
console.log(standings[0].team, standings[0].points)

Python (requests)

import requests

r = requests.get('https://nvl.sportangle.co.uk/api/v1/standings', params={
    'category': 'men',
    'division': 'division-2-north'
})
standings = r.json()
print(standings[0]['team'], standings[0]['points'])

curl (all scheduled fixtures)

curl "https://nvl.sportangle.co.uk/api/v1/fixtures?category=women&division=division-1-north&status=scheduled"

CORS

The API supports cross-origin requests from any origin — you can call it directly from browser-based applications.

Site HTML, sitemaps, and robots files are produced by the frontend production build (scripts/prerender.js, scripts/generate-seo-files.js). They are not served by these API routes.

    Run a volleyball league? I can build your results site too.

    Get in touch