DocumentationTeams and players
Volleyball head-to-head API
GET/v1/head-to-head
Every meeting of two teams since 2001 that your plan can read, newest first, with the record between them.
Parameters
Parameters marked required must be sent; the rest are 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 |
|---|---|---|---|
team_a | id | A team id, tm_. Required. | tm_ttx004b7 |
team_b | id | A team id, tm_. Required. | tm_918m51s1 |
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.
# Every meeting of two teams, with the record between them curl "https://api.volleyballapi.com/v1/head-to-head?team_a=tm_ttx004b7&team_b=tm_918m51s1" \ -H "Authorization: Bearer $VBA_KEY"
$q = http_build_query(['team_a' => 'tm_ttx004b7', 'team_b' => 'tm_918m51s1']); $ch = curl_init('https://api.volleyballapi.com/v1/head-to-head?' . $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/head-to-head", params={"team_a": "tm_ttx004b7", "team_b": "tm_918m51s1"}, headers={"Authorization": f"Bearer {os.environ['VBA_KEY']}"}, ) print(r.json()["data"])
const res = await fetch("https://api.volleyballapi.com/v1/head-to-head?team_a=tm_ttx004b7&team_b=tm_918m51s1", { 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-13, with long lists cut short.
{
"data": {
"team_a": {
"id": "tm_ttx004b7",
"name": "Kazakhstan",
"discipline": "indoor",
"gender": "women",
"kind": "national",
"federation": "KAZ",
"country_code": "KZ"
},
"team_b": {
"id": "tm_918m51s1",
"name": "Colombia",
"discipline": "indoor",
"gender": "women",
"kind": "national",
"federation": "COL",
"country_code": "CO"
},
"record": { "team_a_won": 1, "team_b_won": 4, "meetings": 5 },
"matches": [
{
"id": "mt_kj24vsak",
"discipline": "indoor",
"gender": "women",
"status": "finished",
"current_set": null,
"date": "2017-07-23",
"time_local": "16:30",
"start_utc": "2017-07-23T07:30:00Z",
"competition": {
"id": "cp_5xa9c2z0",
"name": "World Grand Prix 2017 - Group 2",
"season": 2017
},
"round": null,
"pool": "Pool H2",
"team_a": { "id": "tm_ttx004b7", "name": "Kazakhstan" },
"team_b": { "id": "tm_918m51s1", "name": "Colombia" },
"score": { "a": 0, "b": 3 },
"winner": "b",
"sets": [
{ "set": 1, "a": 22, "b": 25, "duration_s": 1560 },
{ "set": 2, "a": 19, "b": 25, "duration_s": 1680 },
{ "set": 3, "a": 20, "b": 25, "duration_s": 1500 }
],
"sets_complete": true,
"duration_s": 4740,
"updated_utc": "2026-09-29T12:34:56Z"
},
{
"id": "mt_qt0dsv97",
"discipline": "indoor",
"gender": "women",
"status": "finished",
"current_set": null,
"date": "2017-07-15",
"time_local": "17:10",
"start_utc": "2017-07-15T11:10:00Z",
"competition": {
"id": "cp_5xa9c2z0",
"name": "World Grand Prix 2017 - Group 2",
"season": 2017
},
"round": null,
"pool": "Pool D2",
"team_a": { "id": "tm_ttx004b7", "name": "Kazakhstan" },
"team_b": { "id": "tm_918m51s1", "name": "Colombia" },
"score": { "a": 1, "b": 3 },
"winner": "b",
"sets": [
{ "set": 1, "a": 21, "b": 25, "duration_s": 4920 },
{ "set": 2, "a": 25, "b": 20, "duration_s": 1680 },
{ "set": 3, "a": 25, "b": 27, "duration_s": 1920 },
{ "set": 4, "a": 16, "b": 25, "duration_s": 1500 }
],
"sets_complete": true,
"duration_s": 10020,
"updated_utc": "2026-09-29T12:34:56Z"
},
{
"id": "mt_5nrfe2d9",
"discipline": "indoor",
"gender": "women",
"status": "finished",
"current_set": null,
"date": "2016-06-18",
"time_local": "15:10",
"start_utc": "2016-06-18T09:10:00Z",
"competition": {
"id": "cp_zpr57cfb",
"name": "World Grand Prix 2016 - 3rd group",
"season": 2016
},
"round": null,
"pool": "Semifinals",
"team_a": { "id": "tm_ttx004b7", "name": "Kazakhstan" },
"team_b": { "id": "tm_918m51s1", "name": "Colombia" },
"score": { "a": 3, "b": 2 },
"winner": "a",
"sets": [
{ "set": 1, "a": 25, "b": 20, "duration_s": 1560 },
{ "set": 2, "a": 25, "b": 20, "duration_s": 1680 },
{ "set": 3, "a": 21, "b": 25, "duration_s": 1620 },
{ "set": 4, "a": 18, "b": 25, "duration_s": 1500 },
...
],
"sets_complete": true,
"duration_s": 7320,
"updated_utc": "2026-09-29T12:34:57Z"
},
{
"id": "mt_exaatxd7",
"discipline": "indoor",
"gender": "women",
"status": "finished",
"current_set": null,
"date": "2016-06-12",
"time_local": "18:34",
"start_utc": "2016-06-12T23:30:00Z",
"competition": {
"id": "cp_zpr57cfb",
"name": "World Grand Prix 2016 - 3rd group",
"season": 2016
},
"round": null,
"pool": "Pool C3",
"team_a": { "id": "tm_918m51s1", "name": "Colombia" },
"team_b": { "id": "tm_ttx004b7", "name": "Kazakhstan" },
"score": { "a": 3, "b": 1 },
"winner": "a",
"sets": [
{ "set": 1, "a": 25, "b": 21, "duration_s": 1500 },
{ "set": 2, "a": 22, "b": 25, "duration_s": 1560 },
{ "set": 3, "a": 25, "b": 19, "duration_s": 1560 },
{ "set": 4, "a": 25, "b": 12, "duration_s": 1320 }
],
"sets_complete": true,
"duration_s": 5940,
"updated_utc": "2026-09-29T12:34:57Z"
},
...
]
},
"meta": { "plan": "Complete", "count": 5 }
}Fields
| Field | Type | What it holds |
|---|---|---|
team_a, team_b | object | The two teams, as GET /v1/teams/{id} shows them |
record | object | team_a_won, team_b_won and meetings |
matches | array | Every meeting, newest first, as match objects |
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 a required parameter left out |
| 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 Live, Archive and Complete plans.