DocumentationMatches
Volleyball player statistics API
GET/v1/matches/{id}/players
Each player's figures for the match, both teams: points, break points, serve, reception, attack and block, as the official match sheet records them.
Parameters
Days you can read depend on your plan: the free key reads today and yesterday, Live the last 30 days, Archive and Complete every season since 2001.
| Name | Type | What it does | Example |
|---|---|---|---|
id | path | The match id, in the address. Required. | mt_y6t4v607 |
Request
Send your key in the Authorization header as a Bearer token, or in X-API-Key. A key in the address is refused, so it never ends up in a log.
# Per-player figures for the match: points, serve, reception, attack and block curl "https://api.volleyballapi.com/v1/matches/mt_y6t4v607/players" \ -H "Authorization: Bearer $VBA_KEY"
$ch = curl_init('https://api.volleyballapi.com/v1/matches/mt_y6t4v607/players'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('VBA_KEY')], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true); print_r($res['data']);
import os, requests r = requests.get( "https://api.volleyballapi.com/v1/matches/mt_y6t4v607/players", headers={"Authorization": f"Bearer {os.environ['VBA_KEY']}"}, ) print(r.json()["data"])
const res = await fetch("https://api.volleyballapi.com/v1/matches/mt_y6t4v607/players", { headers: { "X-API-Key": process.env.VBA_KEY }, }); const { data, meta } = await res.json();
Response
Every answer is data plus meta. This is a real answer to the request above, counted 2026-10-12, with long lists cut short.
{
"data": {
"match": "mt_y6t4v607",
"team_a": [
{
"player": { "id": "pl_mpe1paze", "name": "Ringqvist Joacim" },
"shirt": "2",
"sets_played": "--*--",
"points": { "total": null, "break_points": null, "won_minus_lost": null },
"serve": { "total": 1, "errors": null, "aces": null },
"reception": {
"total": null,
"errors": null,
"positive_pct": null,
"excellent_pct": null
},
"attack": {
"total": null,
"errors": null,
"blocked": null,
"kills": null,
"kill_pct": null
},
"block": { "points": null }
},
{
"player": { "id": "pl_ggzpcn7v", "name": "Rune Andreas" },
"shirt": "3",
"sets_played": "--*--",
"points": { "total": 2, "break_points": 1, "won_minus_lost": 2 },
"serve": { "total": 1, "errors": null, "aces": null },
"reception": {
"total": 1,
"errors": null,
"positive_pct": 0,
"excellent_pct": 0
},
"attack": {
"total": 1,
"errors": null,
"blocked": null,
"kills": 1,
"kill_pct": 100
},
"block": { "points": 1 }
},
{
"player": { "id": "pl_jh8c4yts", "name": "Bogdanovitj Dimitri" },
"shirt": "4",
"sets_played": "555--",
"points": { "total": 4, "break_points": 2, "won_minus_lost": -2 },
"serve": { "total": 8, "errors": 2, "aces": 1 },
"reception": {
"total": 22,
"errors": null,
"positive_pct": 55,
"excellent_pct": 32
},
"attack": {
"total": 15,
"errors": 2,
"blocked": 2,
"kills": 3,
"kill_pct": 20
},
"block": { "points": null }
},
{
"player": { "id": "pl_b2fbxw8g", "name": "Larsson Martin" },
"shirt": "6",
"sets_played": "--*--",
"points": { "total": 4, "break_points": 2, "won_minus_lost": 4 },
"serve": { "total": 3, "errors": null, "aces": 1 },
"reception": {
"total": 3,
"errors": null,
"positive_pct": 67,
"excellent_pct": 0
},
"attack": {
"total": 3,
"errors": null,
"blocked": null,
"kills": 3,
"kill_pct": 100
},
"block": { "points": null }
},
...
],
"team_b": [
{
"player": { "id": "pl_ratj3gmc", "name": "Kronstrand Noa" },
"shirt": "1",
"sets_played": "-*---",
"points": { "total": null, "break_points": null, "won_minus_lost": -1 },
"serve": { "total": 2, "errors": null, "aces": null },
"reception": {
"total": 5,
"errors": null,
"positive_pct": 40,
"excellent_pct": 20
},
"attack": {
"total": 2,
"errors": 1,
"blocked": null,
"kills": null,
"kill_pct": 0
},
"block": { "points": null }
},
{
"player": { "id": "pl_gw5df6z1", "name": "VAGULS Gvido" },
"shirt": "3",
"sets_played": "444--",
"points": { "total": 13, "break_points": 2, "won_minus_lost": 2 },
"serve": { "total": 7, "errors": 3, "aces": null },
"reception": {
"total": null,
"errors": null,
"positive_pct": null,
"excellent_pct": null
},
"attack": {
"total": 28,
"errors": 6,
"blocked": 2,
"kills": 12,
"kill_pct": 43
},
"block": { "points": 1 }
},
{
"player": { "id": "pl_he2gtvy4", "name": "Gustafsson Viktor" },
"shirt": "5",
"sets_played": "333--",
"points": { "total": 2, "break_points": 1, "won_minus_lost": -5 },
"serve": { "total": 11, "errors": 4, "aces": null },
"reception": {
"total": null,
"errors": null,
"positive_pct": null,
"excellent_pct": null
},
"attack": {
"total": 9,
"errors": 2,
"blocked": 1,
"kills": 1,
"kill_pct": 11
},
"block": { "points": 1 }
},
{
"player": { "id": "pl_qg2kqmzj", "name": "Hedberg Ville" },
"shirt": "6",
"sets_played": "-----",
"points": { "total": null, "break_points": null, "won_minus_lost": null },
"serve": { "total": null, "errors": null, "aces": null },
"reception": {
"total": null,
"errors": null,
"positive_pct": null,
"excellent_pct": null
},
"attack": {
"total": null,
"errors": null,
"blocked": null,
"kills": null,
"kill_pct": null
},
"block": { "points": null }
},
...
]
},
"meta": { "plan": "Complete", "players": 21 }
}Fields
| Field | Type | What it holds |
|---|---|---|
match | string | The match id |
team_a, team_b | array | One entry a player, by shirt number |
player | object | id and name |
shirt, sets_played | string | Shirt number and the sets the player was on court |
points | object | total, break_points, won_minus_lost |
serve | object | total, errors, aces |
reception | object | total, errors, positive_pct, excellent_pct |
attack | object | total, errors, blocked, kills, kill_pct |
block | object | points |
Errors
Errors come back as {"error": {"code", "message", "docs"}}, with plan and pricing added when a plan would answer. Every error.
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | No key, or a key that is not known or was revoked |
| 403 | upgrade_required | Your plan does not include this endpoint; the answer names the plans that do |
| 404 | not_found | An id that does not exist |
| 422 | unknown_parameter | A parameter this endpoint does not take; the answer lists the ones it does |
| 429 | rate_limited | Too many calls this minute; Retry-After says when to try again |
| 429 | quota_exceeded | The day's or month's allowance is used; the answer says when it resets |
Try it
Fill in what you need; the request is built as you type. Paste your key to run it here, straight against the API. This endpoint answers on the Archive and Complete plans.