DocumentationTeams and players
Volleyball team results API
GET/v1/teams/{id}/matches
A team's matches newest first, under every name it has played as, filtered by status.
Parameters
All optional. 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 team id, in the address. Required. | tm_rk2hqqay |
status | enum | One of scheduled, live, finished, awarded, cancelled. | finished |
page | int | Page number, from 1. Adds totals to meta. | 2 |
per_page | int | Rows a page, 1 to 200. 50 when not sent. | 200 |
cursor | string | The next_cursor from the last answer. Send it alone. |
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.
# A team's matches, newest first curl "https://api.volleyballapi.com/v1/teams/tm_rk2hqqay/matches?status=finished&per_page=2" \ -H "Authorization: Bearer $VBA_KEY"
$q = http_build_query(['status' => 'finished', 'per_page' => '2']); $ch = curl_init('https://api.volleyballapi.com/v1/teams/tm_rk2hqqay/matches?' . $q); 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/teams/tm_rk2hqqay/matches", params={"status": "finished", "per_page": "2"}, headers={"Authorization": f"Bearer {os.environ['VBA_KEY']}"}, ) print(r.json()["data"])
const res = await fetch("https://api.volleyballapi.com/v1/teams/tm_rk2hqqay/matches?status=finished&per_page=2", { headers: { "X-API-Key": process.env.VBA_KEY }, }); const { data, meta } = await res.json();
Response
Every answer is data plus meta. A first call with page adds totals to meta; a call with cursor carries only the next cursor, which is quicker over long ranges. This is a real answer to the request above, counted 2026-10-12, with long lists cut short.
{
"data": [
{
"id": "mt_d5rwebd8",
"discipline": "indoor",
"gender": "women",
"status": "finished",
"current_set": null,
"date": "2026-09-22",
"time_local": "16:00",
"start_utc": "2026-09-22T07:00:00Z",
"competition": {
"id": "cp_ge73273e",
"name": "20th Asian Games Aichi–Nagoya 2026 - Women",
"season": 2026
},
"round": null,
"pool": "Final 3-4",
"team_a": { "id": "tm_rk2hqqay", "name": "Korea" },
"team_b": { "id": "tm_mpgq9dch", "name": "Thailand" },
"score": { "a": 0, "b": 3 },
"winner": "b",
"sets": [
{ "set": 1, "a": 20, "b": 25, "duration_s": 1500 },
{ "set": 2, "a": 19, "b": 25, "duration_s": 1500 },
{ "set": 3, "a": 23, "b": 25, "duration_s": 1920 }
],
"sets_complete": true,
"duration_s": 4920,
"updated_utc": "2026-09-29T12:34:46Z"
},
{
"id": "mt_79bmcnjc",
"discipline": "indoor",
"gender": "women",
"status": "finished",
"current_set": null,
"date": "2026-09-21",
"time_local": "19:20",
"start_utc": "2026-09-21T10:20:00Z",
"competition": {
"id": "cp_ge73273e",
"name": "20th Asian Games Aichi–Nagoya 2026 - Women",
"season": 2026
},
"round": null,
"pool": "Semifinals",
"team_a": { "id": "tm_pse11h74", "name": "Japan" },
"team_b": { "id": "tm_rk2hqqay", "name": "Korea" },
"score": { "a": 3, "b": 0 },
"winner": "a",
"sets": [
{ "set": 1, "a": 25, "b": 20, "duration_s": 1620 },
{ "set": 2, "a": 25, "b": 22, "duration_s": 1920 },
{ "set": 3, "a": 25, "b": 16, "duration_s": 1500 }
],
"sets_complete": true,
"duration_s": 5040,
"updated_utc": "2026-09-29T12:34:46Z"
}
],
"meta": {
"plan": "Complete",
"count": 2,
"next_cursor": "eyJvIjoyLCJwIjoyfQ",
"page": 1,
"per_page": 2,
"total": 522,
"total_pages": 261,
"next_page": 2,
"prev_page": null
}
}Fields
| Field | Type | What it holds |
|---|---|---|
id | string | Stable match id, mt_ |
discipline | enum | indoor or beach |
gender | enum | men, women or mixed |
status | enum | scheduled, live, finished, awarded or cancelled |
current_set | int | The set being played, while live; otherwise null |
date, time_local | date, time | The venue's calendar day and clock |
start_utc | datetime | Scheduled start in UTC, ISO 8601 |
competition | object | id, name and season |
round, pool | string | "Semifinals", "Pool B", or null |
team_a, team_b | object | id and name: a club, a national team or a beach pair |
score | object | Sets won by each side |
winner | enum | a or b, null until finished |
sets | array | Each set: number, points each side, duration in seconds |
sets_complete | bool | false when the source's set scores do not add up to its result, so some sets are missing |
duration_s | int | Match length in seconds |
updated_utc | datetime | When anything in the match last changed |
Errors
Errors come back as {"error": {"code", "message", "docs"}}, with plan and pricing added when a plan would answer. Every error.
| HTTP | Code | When |
|---|---|---|
| 400 | bad_request | A value of the wrong shape, or per_page outside 1 to 200 |
| 401 | unauthorized | No key, or a key that is not known or was revoked |
| 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.