# Volleyball API complete reference

Live scores, results with every set, rally-by-rally points, lineups and player figures for indoor and beach volleyball since 2001, as JSON over HTTPS.

- Base URL: `https://api.volleyballapi.com/v1`
- Authentication: `Authorization: Bearer <key>` or `X-API-Key: <key>`; a key in the address is refused
- Site: https://volleyballapi.com
- Endpoints: 22
- Generated: 2026-11-12 21:25 UTC (from the newest source; a copy with an older date is stale)
- This file: https://volleyballapi.com/documentation/manual.md

## Before anything else

- Factual data only: no predictions, ratings, tips or betting advice on any endpoint.
- Not in the data, on any plan: odds or bookmaker prices, video, in-match commentary, and sports other than volleyball.
- Every answer is `{"data": ..., "meta": {...}}`. `meta` carries the plan, counts, the page and `next_cursor`. Errors are `{"error": {"code", "message", "docs"}}`.
- Times are UTC in ISO 8601. A value we do not have is `null`, never left out.

## Plans

| Plan | Price | Reads | Rate limit | Calls |
|---|---|---|---|---|
| Free key | Free | today and yesterday | 10 a minute | 50 a day |
| Live | $39 a month or $390 a year | the last 30 days | 60 a minute | 50,000 a month |
| Archive | $39 a month or $390 a year | every season since 2001 | 60 a minute | 50,000 a month |
| Complete | $79 a month or $790 a year | every season since 2001 | 120 a minute | 250,000 a month |

Prices and every feature: https://volleyballapi.com/pricing

## Coverage

Competitions, matches and players by year and by competition, counted from the data: https://volleyballapi.com/coverage. Your plan and the first day it reads: `GET /v1/usage`.

## Endpoints

### Account

#### `GET /v1/usage`

Your plan, the calls you have made today and this month, your limits, when the quota resets and the days you can read. Calls to this endpoint are never counted.

##### Parameters

None. Any parameter sent is refused with a 422, so a typo never passes unnoticed.

##### 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.

```
# Your plan, your calls today and this month, your limits and the dates you can read
curl "https://api.volleyballapi.com/v1/usage" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "plan": "Complete",
    "key": "vba_6c1f",
    "calls": { "today": 1240, "this_month": 18604 },
    "limits": {
      "per_minute": 120,
      "quota": 250000,
      "quota_period": "month",
      "quota_resets_utc": "2026-12-01T00:00:00Z"
    },
    "reads_from": null,
    "live": true,
    "points": true,
    "players": true
  },
  "meta": { "plan": "Complete" }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `plan` | string | Your plan |
| `key` | string | The first characters of the key you called with |
| `calls` | object | today and this_month |
| `limits` | object | per_minute, quota, quota_period and quota_resets_utc |
| `reads_from` | date | The first day your plan reads, or null for every season |
| `live, points, players` | bool | Whether your plan includes live scores, rallies and player figures |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 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 |

##### 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.

``

```

```

Page: https://volleyballapi.com/documentation/usage

### Matches

#### `GET /v1/matches/live` (Live, Complete)

Every match being played this minute, indoor and beach, with the running score of each set and the set in play. Scores refresh every 15 seconds; meta says when the data last changed and how many seconds behind it is.

##### Parameters

All optional.

| Name | Type | What it does | Example |
|---|---|---|---|
| `discipline` | enum | One of `indoor`, `beach`. | `indoor` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |

##### 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 match being played now, with the running set scores
curl "https://api.volleyballapi.com/v1/matches/live" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. meta carries `last_change`, `seconds_behind` and `poll_seconds`, so your app can say how fresh the scores are. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "mt_2rh5a86t",
      "discipline": "indoor",
      "gender": "men",
      "status": "live",
      "current_set": 5,
      "date": "2026-11-12",
      "time_local": null,
      "start_utc": "2026-11-12T19:00:00Z",
      "utc_offset": null,
      "timezone": null,
      "competition": { "id": "cp_ap4r8hpb", "name": "Champions League", "season": 2026 },
      "round": "Qualification",
      "pool": null,
      "team_a": { "id": "tm_qvwvvz63", "name": "ACH Ljubljana" },
      "team_b": { "id": "tm_1y2paxm6", "name": "Orion Stars" },
      "score": { "a": 2, "b": 2 },
      "winner": null,
      "sets": [
        { "set": 1, "a": 25, "b": 21, "duration_s": null },
        { "set": 2, "a": 22, "b": 25, "duration_s": null },
        { "set": 3, "a": 25, "b": 20, "duration_s": null },
        { "set": 4, "a": 21, "b": 25, "duration_s": null },
        ...
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-11-12T21:23:53Z"
    },
    {
      "id": "mt_xfbev9h4",
      "discipline": "indoor",
      "gender": "men",
      "status": "live",
      "current_set": 5,
      "date": "2026-11-12",
      "time_local": "20:00",
      "start_utc": "2026-11-12T19:00:00Z",
      "utc_offset": "+01:00",
      "timezone": "Europe/Copenhagen",
      "competition": { "id": "cp_jesvvmhb", "name": "Landspokal Cup", "season": null },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_b54cf21q", "name": "Vestsjaelland" },
      "team_b": { "id": "tm_w2c3yybd", "name": "ASV Elite" },
      "score": { "a": 2, "b": 2 },
      "winner": null,
      "sets": [
        { "set": 1, "a": 25, "b": 21, "duration_s": null },
        { "set": 2, "a": 19, "b": 25, "duration_s": null },
        { "set": 3, "a": 14, "b": 25, "duration_s": null },
        { "set": 4, "a": 25, "b": 18, "duration_s": null },
        ...
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-11-12T21:23:53Z"
    },
    ...
  ],
  "meta": {
    "plan": "Complete",
    "count": 5,
    "last_change": "2026-11-12T21:24:03Z",
    "seconds_behind": 96,
    "poll_seconds": 15
  }
}
```

##### 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 |
| `utc_offset` | string | The venue's offset from UTC at the start, such as +02:00, worked out from the local and UTC starts; null when either is missing |
| `timezone` | string | The venue's time zone (IANA, such as Europe/Rome), where its country and the offset agree; else null |
| `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](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape |
| 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 |
| 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 and Complete plans.

``

```

```

Page: https://volleyballapi.com/documentation/live

#### `GET /v1/results/yesterday`

Every match that finished yesterday, in UTC days, with the set-by-set score and durations. Readable on every plan, including the free key: one call a day keeps a results page or a bot up to date.

##### Parameters

All optional.

| Name | Type | What it does | Example |
|---|---|---|---|
| `discipline` | enum | One of `indoor`, `beach`. | `indoor` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |
| `page` | int | Page number, from 1. Adds totals to meta. | `2` |
| `per_page` | int | Rows a page, 1 to 50. 50 when not sent. | `50` |
| `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.

```
# Yesterday's finished matches
curl "https://api.volleyballapi.com/v1/results/yesterday?per_page=2" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. meta carries the `date` the answer is for. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "mt_mg30j2hm",
      "discipline": "indoor",
      "gender": "women",
      "status": "finished",
      "current_set": null,
      "date": "2026-11-11",
      "time_local": "19:30",
      "start_utc": "2026-11-11T00:00:00Z",
      "utc_offset": null,
      "timezone": null,
      "competition": {
        "id": "cp_ggbn0z8s",
        "name": "NPVA Division #1 2026/27 League Series - Women",
        "season": 2026
      },
      "round": null,
      "pool": "Round Robin",
      "team_a": { "id": "tm_nh6j7egw", "name": "Elite BALLERS" },
      "team_b": { "id": "tm_1he8k05t", "name": "University of the Bahamas MINGOES" },
      "score": { "a": 0, "b": 3 },
      "winner": "b",
      "sets": [
        { "set": 1, "a": 18, "b": 25, "duration_s": 1920 },
        { "set": 2, "a": 25, "b": 27, "duration_s": 1800 },
        { "set": 3, "a": 21, "b": 25, "duration_s": 1500 }
      ],
      "sets_complete": true,
      "duration_s": 5220,
      "updated_utc": "2026-11-12T03:07:07Z"
    },
    {
      "id": "mt_dq82ah5s",
      "discipline": "indoor",
      "gender": "women",
      "status": "finished",
      "current_set": null,
      "date": "2026-11-11",
      "time_local": "11:30",
      "start_utc": "2026-11-11T06:30:00Z",
      "utc_offset": "+05:00",
      "timezone": "Asia/Almaty",
      "competition": {
        "id": "cp_krstt0k2",
        "name": "Women's High League, I Round",
        "season": 2026
      },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_hn4tpx3j", "name": "Zhayik" },
      "team_b": { "id": "tm_pe7gwc22", "name": "Qostanay" },
      "score": { "a": 3, "b": 0 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 25, "b": 16, "duration_s": null },
        { "set": 2, "a": 25, "b": 13, "duration_s": null },
        { "set": 3, "a": 25, "b": 17, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-11-11T08:00:15Z"
    }
  ],
  "meta": {
    "plan": "Complete",
    "date": "2026-11-11",
    "count": 2,
    "next_cursor": "eyJvIjoyLCJwIjoyfQ",
    "page": 1,
    "per_page": 2,
    "total": 99,
    "total_pages": 50,
    "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 |
| `utc_offset` | string | The venue's offset from UTC at the start, such as +02:00, worked out from the local and UTC starts; null when either is missing |
| `timezone` | string | The venue's time zone (IANA, such as Europe/Rome), where its country and the offset agree; else null |
| `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](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape, or a per_page below 1 (over 50 is read as 50) |
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/results-yesterday

#### `GET /v1/matches`

Matches on one day or between two days, indoor and beach, filtered by discipline, gender, status, competition or team. Every match carries the set-by-set score, durations, round and pool, and comes back once even when it was played under two names.

##### Parameters

All optional. Send `date`, or `from` and `to`, not both. With no day, range, competition or team you get today. 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 |
|---|---|---|---|
| `date` | date | One day, in the venue's own calendar. Today when no day, range, competition or team is given. | `2021-09-24` |
| `from` | date | First day of a range. Send with `to`; a range covers 31 days at most. | `2026-11-13` |
| `to` | date | Last day of the range, included. | `2026-11-13` |
| `discipline` | enum | One of `indoor`, `beach`. | `indoor` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |
| `status` | enum | One of `scheduled`, `live`, `finished`, `awarded`, `cancelled`. | `scheduled` |
| `competition` | id | A competition id, `cp_`. |  |
| `team` | id | A team id, `tm_`. Matches under every name the team has played as. |  |
| `page` | int | Page number, from 1. Adds totals to meta. | `2` |
| `per_page` | int | Rows a page, 1 to 50. 50 when not sent. | `50` |
| `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.

```
# Matches on a day or between two days, filtered by discipline, gender, status, competition or team
curl "https://api.volleyballapi.com/v1/matches?date=2021-09-24&gender=men" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### 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-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "mt_00q7zcvb",
      "discipline": "beach",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2021-09-24",
      "time_local": null,
      "start_utc": null,
      "utc_offset": null,
      "timezone": null,
      "competition": { "id": "cp_6xk6ym5q", "name": "Arles", "season": 2021 },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_w5hy299a", "name": "Aye, Q./Di Giantommaso" },
      "team_b": { "id": "tm_x2189dh9", "name": "Wattrelot/Lapinta" },
      "score": { "a": 2, "b": 0 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 21, "b": 14, "duration_s": null },
        { "set": 2, "a": 21, "b": 18, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-10-19T17:11:44Z"
    },
    {
      "id": "mt_cxkr9dvm",
      "discipline": "beach",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2021-09-24",
      "time_local": null,
      "start_utc": null,
      "utc_offset": null,
      "timezone": null,
      "competition": { "id": "cp_6xk6ym5q", "name": "Arles", "season": 2021 },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_fk74c9q7", "name": "Cattet/Lebecq" },
      "team_b": { "id": "tm_2vc3hvsb", "name": "Etourneau/Bourillet" },
      "score": { "a": 2, "b": 1 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 19, "b": 21, "duration_s": null },
        { "set": 2, "a": 23, "b": 21, "duration_s": null },
        { "set": 3, "a": 15, "b": 7, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-10-19T17:11:44Z"
    },
    ...
  ],
  "meta": {
    "plan": "Complete",
    "count": 33,
    "next_cursor": null,
    "page": 1,
    "per_page": 50,
    "total": 33,
    "total_pages": 1,
    "next_page": null,
    "prev_page": null
  }
}
```

##### Fields

The same match object comes back from every list. [GET /v1/matches/{id}](https://volleyballapi.com/documentation/match) adds venue, city, country, spectators, referees and links to the rallies and player figures when they exist.

| 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 |
| `utc_offset` | string | The venue's offset from UTC at the start, such as +02:00, worked out from the local and UTC starts; null when either is missing |
| `timezone` | string | The venue's time zone (IANA, such as Europe/Rome), where its country and the offset agree; else null |
| `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](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | date and from/to sent together, a range over 31 days, to before from, a malformed date or a per_page below 1 (over 50 is read as 50) |
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 403 | `upgrade_required` | A day outside your plan: the free key reads today and yesterday, Live the last 30 days |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/matches

#### `GET /v1/matches/{id}/points` (Live, Archive, Complete)

Every rally of every set in the order it was played: the score after it, the side that won it and the side that served it. Enough to work out side-out and break-point rates, runs, momentum and clutch points.

##### 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_854w9wh4` |

##### 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 rally of every set: the score after it, who won it and who served
curl "https://api.volleyballapi.com/v1/matches/mt_854w9wh4/points" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "match": "mt_854w9wh4",
    "sets": [
      {
        "set": 1,
        "complete": true,
        "rallies": [
          { "a": 0, "b": 1, "won_by": "b", "served_by": "a" },
          { "a": 1, "b": 1, "won_by": "a", "served_by": "b" },
          { "a": 1, "b": 2, "won_by": "b", "served_by": "a" },
          { "a": 2, "b": 2, "won_by": "a", "served_by": "b" },
          ...
        ]
      },
      {
        "set": 2,
        "complete": true,
        "rallies": [
          { "a": 1, "b": 0, "won_by": "a", "served_by": "b" },
          { "a": 1, "b": 1, "won_by": "b", "served_by": "a" },
          { "a": 1, "b": 2, "won_by": "b", "served_by": "b" },
          { "a": 2, "b": 2, "won_by": "a", "served_by": "b" },
          ...
        ]
      },
      {
        "set": 3,
        "complete": true,
        "rallies": [
          { "a": 1, "b": 0, "won_by": "a", "served_by": "a" },
          { "a": 1, "b": 1, "won_by": "b", "served_by": "a" },
          { "a": 2, "b": 1, "won_by": "a", "served_by": "b" },
          { "a": 3, "b": 1, "won_by": "a", "served_by": "a" },
          ...
        ]
      }
    ]
  },
  "meta": { "plan": "Complete", "rallies": 128, "sets_incomplete": 0 }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `match` | string | The match id |
| `sets` | array | One entry a set: set, complete, and rallies in the order played |
| `sets[].complete` | bool | true when the last rally ends on the set's score; false when rallies are missing from the record; null when the set score is not held |
| `rallies[].a, rallies[].b` | int | The score after the rally |
| `rallies[].won_by` | enum | a or b, the side that won it |
| `rallies[].served_by` | enum | a or b, the side that served it |
| `meta.rallies` | int | Rallies in the match |
| `meta.sets_incomplete` | int | Sets whose rallies do not end on the set's score |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| 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 Live, Archive and Complete plans.

``

```

```

Page: https://volleyballapi.com/documentation/match-points

#### `GET /v1/matches/{id}/players` (Archive, Complete)

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_gb8xfagd` |

##### 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_gb8xfagd/players" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "match": "mt_gb8xfagd",
    "team_a": [
      {
        "player": { "id": "pl_7f67na0t", "name": "Puķīte Elza" },
        "shirt": "2",
        "sets_played": "232--",
        "points": { "total": 6, "break_points": 3, "won_minus_lost": -2 },
        "serve": { "total": 9, "errors": 1, "aces": 2 },
        "reception": { "total": 15, "errors": 5, "positive_pct": 7, "excellent_pct": 7 },
        "attack": {
          "total": 15,
          "errors": 1,
          "blocked": 1,
          "kills": 4,
          "kill_pct": 27
        },
        "block": { "points": 0 }
      },
      {
        "player": { "id": "pl_vw5343qx", "name": "Vikse Marī" },
        "shirt": "4",
        "sets_played": "--5--",
        "points": { "total": 0, "break_points": 0, "won_minus_lost": -4 },
        "serve": { "total": 1, "errors": 0, "aces": 0 },
        "reception": { "total": 6, "errors": 3, "positive_pct": 17, "excellent_pct": 17 },
        "attack": { "total": 2, "errors": 0, "blocked": 1, "kills": 0, "kill_pct": 0 },
        "block": { "points": 0 }
      },
      {
        "player": { "id": "pl_6bnx4vgm", "name": "Arhipova Loreta" },
        "shirt": "5",
        "sets_played": "***--",
        "points": { "total": 0, "break_points": 0, "won_minus_lost": -2 },
        "serve": { "total": 0, "errors": 0, "aces": 0 },
        "reception": {
          "total": 18,
          "errors": 2,
          "positive_pct": 28,
          "excellent_pct": 28
        },
        "attack": {
          "total": 0,
          "errors": 0,
          "blocked": 0,
          "kills": 0,
          "kill_pct": null
        },
        "block": { "points": 0 }
      },
      {
        "player": { "id": "pl_esxmn5a3", "name": "Dēvita Patrīcija" },
        "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 }
      },
      ...
    ],
    "team_b": [
      {
        "player": { "id": "pl_3ke0s8ps", "name": "Krustkalne Katrīna Paula" },
        "shirt": "1",
        "sets_played": "4----",
        "points": { "total": 7, "break_points": 6, "won_minus_lost": 6 },
        "serve": { "total": 9, "errors": 1, "aces": 2 },
        "reception": {
          "total": 0,
          "errors": 0,
          "positive_pct": null,
          "excellent_pct": null
        },
        "attack": {
          "total": 6,
          "errors": 0,
          "blocked": 0,
          "kills": 4,
          "kill_pct": 67
        },
        "block": { "points": 1 }
      },
      {
        "player": { "id": "pl_hms4nn1z", "name": "Linde Rūta" },
        "shirt": "2",
        "sets_played": "--1--",
        "points": { "total": 6, "break_points": 6, "won_minus_lost": 6 },
        "serve": { "total": 12, "errors": 0, "aces": 5 },
        "reception": {
          "total": 0,
          "errors": 0,
          "positive_pct": null,
          "excellent_pct": null
        },
        "attack": { "total": 1, "errors": 0, "blocked": 0, "kills": 0, "kill_pct": 0 },
        "block": { "points": 1 }
      },
      {
        "player": { "id": "pl_ghsrnmf0", "name": "Putene Rūta" },
        "shirt": "5",
        "sets_played": "-2---",
        "points": { "total": 5, "break_points": 5, "won_minus_lost": 3 },
        "serve": { "total": 11, "errors": 0, "aces": 4 },
        "reception": { "total": 6, "errors": 2, "positive_pct": 33, "excellent_pct": 17 },
        "attack": {
          "total": 7,
          "errors": 0,
          "blocked": 0,
          "kills": 1,
          "kill_pct": 14
        },
        "block": { "points": 0 }
      },
      {
        "player": { "id": "pl_f8g19j5x", "name": "Ankevica Agija" },
        "shirt": "7",
        "sets_played": "2----",
        "points": { "total": 4, "break_points": 2, "won_minus_lost": 4 },
        "serve": { "total": 4, "errors": 0, "aces": 2 },
        "reception": { "total": 3, "errors": 0, "positive_pct": 33, "excellent_pct": 0 },
        "attack": {
          "total": 5,
          "errors": 0,
          "blocked": 0,
          "kills": 2,
          "kill_pct": 40
        },
        "block": { "points": 0 }
      },
      ...
    ]
  },
  "meta": { "plan": "Complete", "players": 25 }
}
```

##### 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](https://volleyballapi.com/documentation/errors).

| 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.

``

```

```

Page: https://volleyballapi.com/documentation/match-players

#### `GET /v1/matches/{id}/lineups` (Archive, Complete)

Who started every set and where: the six players in court zones 1 to 6 for each team, the players who came on during the set, liberos marked, and both head coaches. Rotations, substitution patterns and coach records in one call.

##### 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_gb8xfagd` |

##### 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.

```
# Starting six by court zone for every set, the players who came on, and both head coaches
curl "https://api.volleyballapi.com/v1/matches/mt_gb8xfagd/lineups" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "match": "mt_gb8xfagd",
    "coaches": { "team_a": "Ikauniece Inga", "team_b": "Minusa Inguna" },
    "sets": [
      {
        "set": 1,
        "team_a": {
          "starters": [
            {
              "zone": 1,
              "player": { "id": "pl_ajt1sgeb", "name": "Gūtmane Dina" },
              "shirt": "12",
              "libero": false
            },
            {
              "zone": 2,
              "player": { "id": "pl_7f67na0t", "name": "Puķīte Elza" },
              "shirt": "2",
              "libero": false
            },
            {
              "zone": 3,
              "player": { "id": "pl_naqvj04a", "name": "Preikše Karmena Emīlija" },
              "shirt": "18",
              "libero": false
            },
            {
              "zone": 4,
              "player": { "id": "pl_z689vdtk", "name": "Prelgauska Gabriela" },
              "shirt": "10",
              "libero": false
            },
            ...
          ],
          "came_on": [
            {
              "player": { "id": "pl_6bnx4vgm", "name": "Arhipova Loreta" },
              "shirt": "5",
              "libero": true
            },
            {
              "player": { "id": "pl_d0j09t0q", "name": "Kronberga Karlīna" },
              "shirt": "15",
              "libero": true
            }
          ]
        },
        "team_b": {
          "starters": [
            {
              "zone": 1,
              "player": { "id": "pl_cqy54rg9", "name": "Dolotova Elvita" },
              "shirt": "17",
              "libero": false
            },
            {
              "zone": 2,
              "player": { "id": "pl_f8g19j5x", "name": "Ankevica Agija" },
              "shirt": "7",
              "libero": true
            },
            {
              "zone": 3,
              "player": { "id": "pl_gn7m8akh", "name": "Martinsone Loreta" },
              "shirt": "13",
              "libero": false
            },
            {
              "zone": 4,
              "player": { "id": "pl_3ke0s8ps", "name": "Krustkalne Katrīna Paula" },
              "shirt": "1",
              "libero": false
            },
            ...
          ],
          "came_on": [
            {
              "player": { "id": "pl_h21vgb4s", "name": "Kramēna Kristīne" },
              "shirt": "14",
              "libero": true
            },
            {
              "player": { "id": "pl_5w9f90r0", "name": "Grundmane Megija" },
              "shirt": "26",
              "libero": true
            }
          ]
        }
      },
      {
        "set": 2,
        "team_a": {
          "starters": [
            {
              "zone": 1,
              "player": { "id": "pl_tcfrnn8z", "name": "Pavlovska Marta" },
              "shirt": "14",
              "libero": false
            },
            {
              "zone": 2,
              "player": { "id": "pl_ajt1sgeb", "name": "Gūtmane Dina" },
              "shirt": "12",
              "libero": false
            },
            {
              "zone": 3,
              "player": { "id": "pl_7f67na0t", "name": "Puķīte Elza" },
              "shirt": "2",
              "libero": false
            },
            {
              "zone": 4,
              "player": { "id": "pl_naqvj04a", "name": "Preikše Karmena Emīlija" },
              "shirt": "18",
              "libero": false
            },
            ...
          ],
          "came_on": [
            {
              "player": { "id": "pl_6bnx4vgm", "name": "Arhipova Loreta" },
              "shirt": "5",
              "libero": true
            },
            {
              "player": { "id": "pl_d0j09t0q", "name": "Kronberga Karlīna" },
              "shirt": "15",
              "libero": true
            }
          ]
        },
        "team_b": {
          "starters": [
            {
              "zone": 1,
              "player": { "id": "pl_956xwkmr", "name": "Leišavniece Roberta Ginta" },
              "shirt": "15",
              "libero": false
            },
            {
              "zone": 2,
              "player": { "id": "pl_ghsrnmf0", "name": "Putene Rūta" },
              "shirt": "5",
              "libero": false
            },
            {
              "zone": 3,
              "player": { "id": "pl_gn7m8akh", "name": "Martinsone Loreta" },
              "shirt": "13",
              "libero": false
            },
            {
              "zone": 4,
              "player": { "id": "pl_qaqm9j2t", "name": "Ķetlere Katrīna" },
              "shirt": "97",
              "libero": false
            },
            ...
          ],
          "came_on": [
            {
              "player": { "id": "pl_5w9f90r0", "name": "Grundmane Megija" },
              "shirt": "26",
              "libero": true
            }
          ]
        }
      },
      {
        "set": 3,
        "team_a": {
          "starters": [
            {
              "zone": 1,
              "player": { "id": "pl_ajt1sgeb", "name": "Gūtmane Dina" },
              "shirt": "12",
              "libero": false
            },
            {
              "zone": 2,
              "player": { "id": "pl_7f67na0t", "name": "Puķīte Elza" },
              "shirt": "2",
              "libero": false
            },
            {
              "zone": 3,
              "player": { "id": "pl_naqvj04a", "name": "Preikše Karmena Emīlija" },
              "shirt": "18",
              "libero": false
            },
            {
              "zone": 4,
              "player": { "id": "pl_z689vdtk", "name": "Prelgauska Gabriela" },
              "shirt": "10",
              "libero": false
            },
            ...
          ],
          "came_on": [
            {
              "player": { "id": "pl_6bnx4vgm", "name": "Arhipova Loreta" },
              "shirt": "5",
              "libero": true
            },
            {
              "player": { "id": "pl_c2bgjp8c", "name": "Strode Kristena" },
              "shirt": "9",
              "libero": false
            },
            {
              "player": { "id": "pl_5g8scbs7", "name": "Kacēviča Paula" },
              "shirt": "17",
              "libero": false
            }
          ]
        },
        "team_b": {
          "starters": [
            {
              "zone": 1,
              "player": { "id": "pl_hms4nn1z", "name": "Linde Rūta" },
              "shirt": "2",
              "libero": false
            },
            {
              "zone": 2,
              "player": { "id": "pl_8azj5878", "name": "Cepurīte Anna" },
              "shirt": "9",
              "libero": false
            },
            {
              "zone": 3,
              "player": { "id": "pl_gn7m8akh", "name": "Martinsone Loreta" },
              "shirt": "13",
              "libero": false
            },
            {
              "zone": 4,
              "player": { "id": "pl_qaqm9j2t", "name": "Ķetlere Katrīna" },
              "shirt": "97",
              "libero": false
            },
            ...
          ],
          "came_on": [
            {
              "player": { "id": "pl_h21vgb4s", "name": "Kramēna Kristīne" },
              "shirt": "14",
              "libero": true
            }
          ]
        }
      }
    ]
  },
  "meta": { "plan": "Complete", "sets": 3 }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `match` | string | The match id |
| `coaches` | object | team_a and team_b: each head coach's name, or null |
| `sets` | array | One entry a set: set, team_a, team_b |
| `starters` | array | The starting six by court zone 1 to 6 (zone 1 serves first): zone, player, shirt, libero |
| `came_on` | array | Players who came on during the set: player, shirt, libero |
| `meta.sets` | int | Sets with a lineup |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| 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.

``

```

```

Page: https://volleyballapi.com/documentation/match-lineups

#### `GET /v1/matches/{id}`

One match in full: both teams, the result, every set with its duration, the venue, city and country, attendance and referees, and links to its rallies and player figures when they exist.

##### 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_pcbe3hvw` |

##### 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.

```
# One match: teams, result, every set, duration, venue, spectators and referees
curl "https://api.volleyballapi.com/v1/matches/mt_pcbe3hvw" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "id": "mt_pcbe3hvw",
    "discipline": "indoor",
    "gender": "men",
    "status": "finished",
    "current_set": null,
    "date": "2021-09-24",
    "time_local": "13:00",
    "start_utc": "2021-09-24T10:00:00Z",
    "utc_offset": "+03:00",
    "timezone": "Europe/Sofia",
    "competition": {
      "id": "cp_p80k5t4s",
      "name": "FIVB Volleyball Men's U21 World Championship",
      "season": 2021
    },
    "round": "Preliminary Round",
    "pool": "Pool D",
    "team_a": { "id": "tm_7h04r4t8", "name": "Canada" },
    "team_b": { "id": "tm_gq4s1mva", "name": "Brazil" },
    "score": { "a": 0, "b": 3 },
    "winner": "b",
    "sets": [
      { "set": 1, "a": 22, "b": 25, "duration_s": 1740 },
      { "set": 2, "a": 21, "b": 25, "duration_s": 1500 },
      { "set": 3, "a": 18, "b": 25, "duration_s": 1440 }
    ],
    "sets_complete": true,
    "duration_s": 4680,
    "updated_utc": "2026-10-27T02:27:59Z",
    "venue": "Levski Sofia",
    "city": "Sofia",
    "country_code": "BG",
    "spectators": null,
    "referees": ["Guillet Olivier (FRA)", "Vinaliev Aleksandar (BUL)"],
    "officials": [
      { "role": "referee_1", "name": "Guillet Olivier", "country": "FRA" },
      {
        "role": "referee_2",
        "name": "Vinaliev Aleksandar",
        "country": "BUL"
      }
    ],
    "coaches": { "team_a": null, "team_b": null },
    "detail": {
      "points": "https://api.volleyballapi.com/v1/matches/mt_pcbe3hvw/points",
      "players": null,
      "lineups": null
    }
  },
  "meta": { "plan": "Complete" }
}
```

##### 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 |
| `utc_offset` | string | The venue's offset from UTC at the start, such as +02:00, worked out from the local and UTC starts; null when either is missing |
| `timezone` | string | The venue's time zone (IANA, such as Europe/Rome), where its country and the offset agree; else null |
| `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 |
| `venue, city, country_code` | string | Where it was played |
| `spectators` | int | Official attendance |
| `referees` | array | First and second referee |
| `officials` | array | Every official by role: role (referee_1, referee_2, line_judge_1 to line_judge_4, scorer, assistant_scorer), name, country (three-letter code, or null) |
| `coaches` | object | team_a and team_b: each head coach, or null |
| `weather` | object | Beach matches only: at_start (temp_c, humidity_pct, wind_ms, rain_mm in the hour the match started) and day (temp_min_c, temp_max_c, wind_max_ms, rain_mm over its day, UTC); null until the tournament's weather is read, a few days after it ends |
| `detail` | object | Links to the rallies, player figures and lineups, or null when there are none |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 403 | `upgrade_required` | A day outside your plan: the free key reads today and yesterday, Live the last 30 days |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/match

### Bulk export

#### `GET /v1/export/matches` (Complete)

Every match between two days in one call, up to 184 days at a time: the full match record with sets, venue, referees, attendance and coaches. Built for loading a season into your own database without paging.

##### 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 |
|---|---|---|---|
| `from` | date | First day of the range. Send with `to`; a call covers up to 184 days. | `2021-09-24` |
| `to` | date | Last day of the range, included. | `2021-09-24` |
| `discipline` | enum | One of `indoor`, `beach`. | `indoor` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |

##### 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 match between two days in one call, with sets, venue, officials and coaches (up to 184 days)
curl "https://api.volleyballapi.com/v1/export/matches?from=2021-09-24&to=2021-09-24&gender=men" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "mt_00q7zcvb",
      "discipline": "beach",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2021-09-24",
      "time_local": null,
      "start_utc": null,
      "utc_offset": null,
      "timezone": null,
      "competition": { "id": "cp_6xk6ym5q", "name": "Arles", "season": 2021 },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_w5hy299a", "name": "Aye, Q./Di Giantommaso" },
      "team_b": { "id": "tm_x2189dh9", "name": "Wattrelot/Lapinta" },
      "score": { "a": 2, "b": 0 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 21, "b": 14, "duration_s": null },
        { "set": 2, "a": 21, "b": 18, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-10-19T17:11:44Z",
      "venue": null,
      "city": "Arles",
      "country_code": "FR",
      "spectators": null,
      "referees": [],
      "officials": [],
      "weather": {
        "at_start": null,
        "day": {
          "temp_min_c": 17,
          "temp_max_c": 25.8,
          "wind_max_ms": 4.4,
          "rain_mm": 0
        }
      }
    },
    {
      "id": "mt_cxkr9dvm",
      "discipline": "beach",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2021-09-24",
      "time_local": null,
      "start_utc": null,
      "utc_offset": null,
      "timezone": null,
      "competition": { "id": "cp_6xk6ym5q", "name": "Arles", "season": 2021 },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_fk74c9q7", "name": "Cattet/Lebecq" },
      "team_b": { "id": "tm_2vc3hvsb", "name": "Etourneau/Bourillet" },
      "score": { "a": 2, "b": 1 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 19, "b": 21, "duration_s": null },
        { "set": 2, "a": 23, "b": 21, "duration_s": null },
        { "set": 3, "a": 15, "b": 7, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-10-19T17:11:44Z",
      "venue": null,
      "city": "Arles",
      "country_code": "FR",
      "spectators": null,
      "referees": [],
      "officials": [],
      "weather": {
        "at_start": null,
        "day": {
          "temp_min_c": 17,
          "temp_max_c": 25.8,
          "wind_max_ms": 4.4,
          "rain_mm": 0
        }
      }
    }
  ],
  "meta": {
    "plan": "Complete",
    "from": "2021-09-24",
    "to": "2021-09-24",
    "count": 33
  }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `data[]` | array | One full match record per match, as /v1/matches/{id} gives it, in date order |
| `id` | string | Stable match id, `mt_` |
| `discipline` | enum | indoor or beach |
| `gender` | enum | men, women or mixed |
| `meta.from, meta.to, meta.count` | mixed | The range and how many matches it holds |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| 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 |
| 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 Complete plans.

``

```

```

Page: https://volleyballapi.com/documentation/export-matches

#### `GET /v1/export/lineups` (Complete)

Every lineup between two days in one call, up to 92 days at a time: the starting six by court zone for each set, the players who came on, and both head coaches.

##### 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 |
|---|---|---|---|
| `from` | date | First day of the range. Send with `to`; a call covers up to 92 days. | `2026-11-10` |
| `to` | date | Last day of the range, included. | `2026-11-10` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |

##### 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 lineup between two days in one call: starting six by zone, players who came on, coaches (up to 92 days)
curl "https://api.volleyballapi.com/v1/export/lineups?from=2026-11-10&to=2026-11-10" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "match": "mt_d5m3mya4",
      "date": "2026-11-10",
      "coaches": { "team_a": "FRESCHI MATTEO", "team_b": "Jókay Zoltán" },
      "sets": [
        {
          "set": 1,
          "team_a": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_y5rfxwva", "name": "KISS GRÉTA" },
                "shirt": "14",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_trawvs8d", "name": "ÖHMAN DANIELA MARIA" },
                "shirt": "15",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_p3bcnnrs", "name": "PASSARO VIOLA" },
                "shirt": "6",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_yqkp8z92", "name": "DZAKOVIC DANIJELA" },
                "shirt": "12",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_zc3yrp53", "name": "FÁTH KINGA" },
                "shirt": "1",
                "libero": true
              },
              {
                "player": { "id": "pl_am9nmgm0", "name": "FEKETE RAMÓNA" },
                "shirt": "4",
                "libero": false
              }
            ]
          },
          "team_b": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_1seewavg", "name": "BATHÁZI RÉKA MÁRTA" },
                "shirt": "16",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_kb218bdg", "name": "MÁRKUS NÓRA" },
                "shirt": "1",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_rvaf1n5h", "name": "SZABÓ KRISZTINA IVETTA" },
                "shirt": "14",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_bsgw6tnw", "name": "ERŐSS MIRTILL" },
                "shirt": "17",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_fez6v3ss", "name": "WEIDEMANN LILI" },
                "shirt": "6",
                "libero": true
              },
              {
                "player": { "id": "pl_z84knjn7", "name": "STANKOVICS ALINDA" },
                "shirt": "7",
                "libero": true
              },
              {
                "player": { "id": "pl_6we4t08x", "name": "VÉRTES SZONJA" },
                "shirt": "12",
                "libero": false
              }
            ]
          }
        },
        {
          "set": 2,
          "team_a": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_y5rfxwva", "name": "KISS GRÉTA" },
                "shirt": "14",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_trawvs8d", "name": "ÖHMAN DANIELA MARIA" },
                "shirt": "15",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_p3bcnnrs", "name": "PASSARO VIOLA" },
                "shirt": "6",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_yqkp8z92", "name": "DZAKOVIC DANIJELA" },
                "shirt": "12",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_zc3yrp53", "name": "FÁTH KINGA" },
                "shirt": "1",
                "libero": true
              },
              {
                "player": { "id": "pl_am9nmgm0", "name": "FEKETE RAMÓNA" },
                "shirt": "4",
                "libero": false
              }
            ]
          },
          "team_b": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_kb218bdg", "name": "MÁRKUS NÓRA" },
                "shirt": "1",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_rvaf1n5h", "name": "SZABÓ KRISZTINA IVETTA" },
                "shirt": "14",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_bsgw6tnw", "name": "ERŐSS MIRTILL" },
                "shirt": "17",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_756a740z", "name": "OLCSVÁRY DÓRA" },
                "shirt": "5",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_fez6v3ss", "name": "WEIDEMANN LILI" },
                "shirt": "6",
                "libero": true
              },
              {
                "player": { "id": "pl_z84knjn7", "name": "STANKOVICS ALINDA" },
                "shirt": "7",
                "libero": true
              },
              {
                "player": { "id": "pl_6we4t08x", "name": "VÉRTES SZONJA" },
                "shirt": "12",
                "libero": false
              }
            ]
          }
        },
        {
          "set": 3,
          "team_a": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_y5rfxwva", "name": "KISS GRÉTA" },
                "shirt": "14",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_trawvs8d", "name": "ÖHMAN DANIELA MARIA" },
                "shirt": "15",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_p3bcnnrs", "name": "PASSARO VIOLA" },
                "shirt": "6",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_yqkp8z92", "name": "DZAKOVIC DANIJELA" },
                "shirt": "12",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_zc3yrp53", "name": "FÁTH KINGA" },
                "shirt": "1",
                "libero": true
              },
              {
                "player": { "id": "pl_am9nmgm0", "name": "FEKETE RAMÓNA" },
                "shirt": "4",
                "libero": false
              },
              {
                "player": { "id": "pl_3beydwyq", "name": "KAPRONCZAI BLANKA" },
                "shirt": "7",
                "libero": false
              },
              {
                "player": { "id": "pl_pvk6g7g5", "name": "SCHNEIDER TAMARA" },
                "shirt": "44",
                "libero": true
              }
            ]
          },
          "team_b": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_6we4t08x", "name": "VÉRTES SZONJA" },
                "shirt": "12",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_kb218bdg", "name": "MÁRKUS NÓRA" },
                "shirt": "1",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_rvaf1n5h", "name": "SZABÓ KRISZTINA IVETTA" },
                "shirt": "14",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_bsgw6tnw", "name": "ERŐSS MIRTILL" },
                "shirt": "17",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_fez6v3ss", "name": "WEIDEMANN LILI" },
                "shirt": "6",
                "libero": true
              },
              {
                "player": { "id": "pl_z84knjn7", "name": "STANKOVICS ALINDA" },
                "shirt": "7",
                "libero": true
              },
              {
                "player": { "id": "pl_1seewavg", "name": "BATHÁZI RÉKA MÁRTA" },
                "shirt": "16",
                "libero": false
              }
            ]
          }
        }
      ]
    },
    {
      "match": "mt_f0yy2ep5",
      "date": "2026-11-10",
      "coaches": { "team_a": "SIMAAN Saher", "team_b": "SIMAAN Simaan" },
      "sets": [
        {
          "set": 1,
          "team_a": {
            "starters": [
              {
                "zone": 1,
                "player": {
                  "id": "pl_7fd84h1z",
                  "name": "BORJA VALENCIA Juan Camilo"
                },
                "shirt": "10",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_8h41az6w", "name": "SOIKA Shay" },
                "shirt": "7",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_42jk0bny", "name": "ODEH Moataz" },
                "shirt": "8",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_5artf8e9", "name": "NSEIR George" },
                "shirt": "14",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_694vaedq", "name": "RIBEIRO Renan" },
                "shirt": "12",
                "libero": true
              }
            ]
          },
          "team_b": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_5sjgpk9w", "name": "SIMAAN Julyan" },
                "shirt": "9",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_0hpbyze1", "name": "SULISTA Petr" },
                "shirt": "11",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_3hbhfjge", "name": "AUKBA Abd Al-Kareem" },
                "shirt": "4",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_bhjanfkp", "name": "COSTA Gregore" },
                "shirt": "18",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_6yzw86bx", "name": "DAHER Habeeb" },
                "shirt": "7",
                "libero": true
              }
            ]
          }
        },
        {
          "set": 2,
          "team_a": {
            "starters": [
              {
                "zone": 1,
                "player": {
                  "id": "pl_7fd84h1z",
                  "name": "BORJA VALENCIA Juan Camilo"
                },
                "shirt": "10",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_8h41az6w", "name": "SOIKA Shay" },
                "shirt": "7",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_42jk0bny", "name": "ODEH Moataz" },
                "shirt": "8",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_5artf8e9", "name": "NSEIR George" },
                "shirt": "14",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_tyxz4eba", "name": "KATZ Guy" },
                "shirt": "5",
                "libero": false
              },
              {
                "player": { "id": "pl_694vaedq", "name": "RIBEIRO Renan" },
                "shirt": "12",
                "libero": true
              }
            ]
          },
          "team_b": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_5sjgpk9w", "name": "SIMAAN Julyan" },
                "shirt": "9",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_0hpbyze1", "name": "SULISTA Petr" },
                "shirt": "11",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_3hbhfjge", "name": "AUKBA Abd Al-Kareem" },
                "shirt": "4",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_bhjanfkp", "name": "COSTA Gregore" },
                "shirt": "18",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_6yzw86bx", "name": "DAHER Habeeb" },
                "shirt": "7",
                "libero": true
              }
            ]
          }
        },
        {
          "set": 3,
          "team_a": {
            "starters": [
              {
                "zone": 1,
                "player": {
                  "id": "pl_7fd84h1z",
                  "name": "BORJA VALENCIA Juan Camilo"
                },
                "shirt": "10",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_8h41az6w", "name": "SOIKA Shay" },
                "shirt": "7",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_42jk0bny", "name": "ODEH Moataz" },
                "shirt": "8",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_5artf8e9", "name": "NSEIR George" },
                "shirt": "14",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_694vaedq", "name": "RIBEIRO Renan" },
                "shirt": "12",
                "libero": true
              }
            ]
          },
          "team_b": {
            "starters": [
              {
                "zone": 1,
                "player": { "id": "pl_5sjgpk9w", "name": "SIMAAN Julyan" },
                "shirt": "9",
                "libero": false
              },
              {
                "zone": 2,
                "player": { "id": "pl_0hpbyze1", "name": "SULISTA Petr" },
                "shirt": "11",
                "libero": false
              },
              {
                "zone": 3,
                "player": { "id": "pl_3hbhfjge", "name": "AUKBA Abd Al-Kareem" },
                "shirt": "4",
                "libero": false
              },
              {
                "zone": 4,
                "player": { "id": "pl_bhjanfkp", "name": "COSTA Gregore" },
                "shirt": "18",
                "libero": false
              },
              ...
            ],
            "came_on": [
              {
                "player": { "id": "pl_6yzw86bx", "name": "DAHER Habeeb" },
                "shirt": "7",
                "libero": true
              },
              {
                "player": { "id": "pl_y7g86epd", "name": "HAYEK Micheal" },
                "shirt": "10",
                "libero": false
              }
            ]
          }
        }
      ]
    }
  ],
  "meta": {
    "plan": "Complete",
    "from": "2026-11-10",
    "to": "2026-11-10",
    "count": 5
  }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `data[].match, data[].date` | string | The match id and its day |
| `data[].coaches` | object | team_a and team_b head coaches |
| `data[].sets` | array | As /v1/matches/{id}/lineups: per set, starters by zone and players who came on |
| `meta.count` | int | Matches with a lineup in the range |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| 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 |
| 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 Complete plans.

``

```

```

Page: https://volleyballapi.com/documentation/export-lineups

#### `GET /v1/export/points` (Complete)

Every rally of every match between two days in one call, up to 14 days at a time: the score after each rally, who won it and who served.

##### 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 |
|---|---|---|---|
| `from` | date | First day of the range. Send with `to`; a call covers up to 14 days. | `2026-11-11` |
| `to` | date | Last day of the range, included. | `2026-11-11` |
| `discipline` | enum | One of `indoor`, `beach`. | `indoor` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |

##### 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 rally of every match between two days in one call (up to 14 days)
curl "https://api.volleyballapi.com/v1/export/points?from=2026-11-11&to=2026-11-11" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "match": "mt_xakqv3s2",
      "date": "2026-11-11",
      "sets": [
        {
          "set": 1,
          "rallies": [
            { "a": 0, "b": 1, "won_by": "b", "served_by": "b" },
            { "a": 1, "b": 1, "won_by": "a", "served_by": "b" },
            { "a": 2, "b": 1, "won_by": "a", "served_by": "a" }
          ]
        }
      ]
    }
  ],
  "meta": {
    "plan": "Complete",
    "from": "2026-11-11",
    "to": "2026-11-11",
    "count": 71,
    "rallies": 11016
  }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `data[].match, data[].date` | string | The match id and its day |
| `data[].sets` | array | As /v1/matches/{id}/points: per set, every rally |
| `meta.count, meta.rallies` | int | Matches and rallies in the range |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| 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 |
| 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 Complete plans.

``

```

```

Page: https://volleyballapi.com/documentation/export-points

### Competitions

#### `GET /v1/competitions`

Competitions newest first, from world championships and tours to national leagues and cups, filtered by discipline, gender, season or a word in the name.

##### Parameters

All optional.

| Name | Type | What it does | Example |
|---|---|---|---|
| `discipline` | enum | One of `indoor`, `beach`. | `beach` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |
| `season` | int | The year a season starts in, like `2025`. | `2025` |
| `q` | text | A word in the competition's name, 2 to 80 characters. |  |
| `page` | int | Page number, from 1. Adds totals to meta. | `2` |
| `per_page` | int | Rows a page, 1 to 50. 50 when not sent. | `50` |
| `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.

```
# Competitions, newest first, filtered by discipline, gender, season or name
curl "https://api.volleyballapi.com/v1/competitions?discipline=beach&per_page=2" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### 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-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "cp_8mz4q89a",
      "name": "KEN NT - Kwale",
      "discipline": "beach",
      "gender": "women",
      "season": 2027,
      "start_date": "2027-09-18",
      "end_date": "2027-09-19",
      "country_code": "KE"
    },
    {
      "id": "cp_kgxvga2q",
      "name": "KEN NT - Kwale",
      "discipline": "beach",
      "gender": "men",
      "season": 2027,
      "start_date": "2027-09-18",
      "end_date": "2027-09-19",
      "country_code": "KE"
    }
  ],
  "meta": {
    "plan": "Complete",
    "count": 2,
    "next_cursor": "eyJvIjoyLCJwIjoyfQ",
    "page": 1,
    "per_page": 2,
    "total": 9315,
    "total_pages": 4658,
    "next_page": 2,
    "prev_page": null
  }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `id` | string | Stable competition id, `cp_` |
| `name` | string | The competition's name |
| `discipline` | enum | indoor or beach |
| `gender` | enum | men, women or mixed |
| `season` | int | The year the season starts in |
| `start_date, end_date` | date | First and last day, where known |
| `country_code` | string | Two-letter country of a national competition |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape, or a per_page below 1 (over 50 is read as 50) |
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/competitions

#### `GET /v1/competitions/{id}/matches`

A competition's matches, every round and pool, filtered by status. Use it for a fixture list, a results page or a whole tournament at once.

##### 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 competition id, in the address. Required. | `cp_p80k5t4s` |
| `status` | enum | One of `scheduled`, `live`, `finished`, `awarded`, `cancelled`. | `scheduled` |
| `page` | int | Page number, from 1. Adds totals to meta. | `2` |
| `per_page` | int | Rows a page, 1 to 50. 50 when not sent. | `50` |
| `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 competition's matches
curl "https://api.volleyballapi.com/v1/competitions/cp_p80k5t4s/matches?per_page=2" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### 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-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "mt_rt4f5rnn",
      "discipline": "indoor",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2021-09-23",
      "time_local": "10:00",
      "start_utc": "2021-09-23T07:00:00Z",
      "utc_offset": "+03:00",
      "timezone": "Europe/Sofia",
      "competition": {
        "id": "cp_p80k5t4s",
        "name": "FIVB Volleyball Men's U21 World Championship",
        "season": 2021
      },
      "round": "Preliminary Round",
      "pool": "Pool D",
      "team_a": { "id": "tm_eksjkvqt", "name": "Cameroon" },
      "team_b": { "id": "tm_7h04r4t8", "name": "Canada" },
      "score": { "a": 0, "b": 3 },
      "winner": "b",
      "sets": [
        { "set": 1, "a": 0, "b": 25, "duration_s": null },
        { "set": 2, "a": 0, "b": 25, "duration_s": null },
        { "set": 3, "a": 0, "b": 25, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-10-27T02:27:59Z"
    },
    {
      "id": "mt_7hpakhya",
      "discipline": "indoor",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2021-09-23",
      "time_local": "13:00",
      "start_utc": "2021-09-23T10:00:00Z",
      "utc_offset": "+03:00",
      "timezone": "Europe/Sofia",
      "competition": {
        "id": "cp_p80k5t4s",
        "name": "FIVB Volleyball Men's U21 World Championship",
        "season": 2021
      },
      "round": "Preliminary Round",
      "pool": "Pool B",
      "team_a": { "id": "tm_1qrdqvza", "name": "Cuba" },
      "team_b": { "id": "tm_da2hmtp1", "name": "Poland" },
      "score": { "a": 1, "b": 3 },
      "winner": "b",
      "sets": [
        { "set": 1, "a": 16, "b": 25, "duration_s": 1260 },
        { "set": 2, "a": 19, "b": 25, "duration_s": 1500 },
        { "set": 3, "a": 25, "b": 18, "duration_s": 1500 },
        { "set": 4, "a": 19, "b": 25, "duration_s": 1860 }
      ],
      "sets_complete": true,
      "duration_s": 6120,
      "updated_utc": "2026-10-27T02:27:59Z"
    }
  ],
  "meta": {
    "plan": "Complete",
    "count": 2,
    "next_cursor": "eyJvIjoyLCJwIjoyfQ",
    "page": 1,
    "per_page": 2,
    "total": 64,
    "total_pages": 32,
    "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 |
| `utc_offset` | string | The venue's offset from UTC at the start, such as +02:00, worked out from the local and UTC starts; null when either is missing |
| `timezone` | string | The venue's time zone (IANA, such as Europe/Rome), where its country and the offset agree; else null |
| `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](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape, or a per_page below 1 (over 50 is read as 50) |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/competition-matches

#### `GET /v1/competitions/{id}/standings`

The table for every pool or league phase of a competition, worked out from its finished matches, one for each stage and pool: played, won, lost, league points, sets and points for and against, and the last five results. Indoor tables give 3 points for a 3-0 or 3-1 win, 2 for a 3-2 win and 1 for a 3-2 loss, and rank by points, then wins, set ratio and point ratio. Beach pools give 2 for a win and 1 for a loss and rank by wins. Knockout rounds are left out unless you ask for them.

##### 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 competition id, in the address. Required. | `cp_x2e5f59m` |
| `stage` | enum | `table` (the default) counts league and pool matches only; `all` counts every finished match, knockout rounds included. | `table` |
| `pool` | text | Only the tables whose pool or stage name contains this, like `Pool B` or `Winners`. |  |

##### 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.

```
# League tables for a competition, one per pool, worked out from its results
curl "https://api.volleyballapi.com/v1/competitions/cp_x2e5f59m/standings" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "competition": {
      "id": "cp_x2e5f59m",
      "name": "Superleague",
      "discipline": "indoor",
      "gender": "men",
      "season": 2026
    },
    "tables": [
      {
        "stage": null,
        "pool": null,
        "rows": [
          {
            "rank": 1,
            "team": { "id": "tm_by47tw97", "name": "Zenit Kazan" },
            "played": 7,
            "won": 5,
            "lost": 2,
            "points": 16,
            "sets_won": 18,
            "sets_lost": 6,
            "set_ratio": 3,
            "points_won": 576,
            "points_lost": 524,
            "point_ratio": 1.099,
            "form": "LWWLW"
          },
          {
            "rank": 2,
            "team": { "id": "tm_x4mcnhzq", "name": "Novosibirsk" },
            "played": 6,
            "won": 5,
            "lost": 1,
            "points": 15,
            "sets_won": 15,
            "sets_lost": 6,
            "set_ratio": 2.5,
            "points_won": 517,
            "points_lost": 454,
            "point_ratio": 1.139,
            "form": "LWWWW"
          },
          {
            "rank": 3,
            "team": { "id": "tm_ba5z2q78", "name": "Din. Moscow" },
            "played": 6,
            "won": 5,
            "lost": 1,
            "points": 14,
            "sets_won": 16,
            "sets_lost": 6,
            "set_ratio": 2.667,
            "points_won": 530,
            "points_lost": 477,
            "point_ratio": 1.111,
            "form": "WLWWW"
          },
          {
            "rank": 4,
            "team": { "id": "tm_1m47bqjn", "name": "Zenit St. Petersburg" },
            "played": 6,
            "won": 5,
            "lost": 1,
            "points": 13,
            "sets_won": 16,
            "sets_lost": 7,
            "set_ratio": 2.286,
            "points_won": 538,
            "points_lost": 466,
            "point_ratio": 1.155,
            "form": "LWWWW"
          },
          ...
        ]
      }
    ]
  },
  "meta": { "plan": "Complete", "matches": 48, "pending": 6, "tables": 1 }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `competition` | object | id, name, discipline, gender and season |
| `tables` | array | One entry a table: stage and pool (null where the competition has none) and rows |
| `rows[].rank` | int | Place in the table |
| `rows[].team` | object | id and name |
| `rows[].played, won, lost` | int | Matches counted |
| `rows[].points` | int | League points |
| `rows[].sets_won, sets_lost, set_ratio` | mixed | Sets for and against |
| `rows[].points_won, points_lost, point_ratio` | mixed | Rally points for and against, where every set is known |
| `rows[].form` | string | Last five results, newest last: W or L |
| `meta.matches` | int | Finished matches counted |
| `meta.pending` | int | Matches in the table still to be played |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/competition-standings

#### `GET /v1/competitions/{id}/rosters`

The players each team registered for a competition, team by team in shirt order: shirt number, captain, libero, position where given, nationality, birth date and height. International indoor competitions from 2018 on, read from the official registrations, so a squad is there before its first match.

##### 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 competition id, in the address. Required. | `cp_kxgcx249` |

##### 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.

```
# The players each team registered for a competition: shirt, captain, libero, birth date and height
curl "https://api.volleyballapi.com/v1/competitions/cp_kxgcx249/rosters" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "competition": {
      "id": "cp_kxgcx249",
      "name": "XXI Central American VB U-21 Women - Honduras 2026",
      "discipline": "indoor",
      "gender": "women",
      "season": 2026
    },
    "teams": [
      {
        "team": { "id": "tm_tzkxkfja", "name": "Belize" },
        "players": [
          {
            "player": { "id": "pl_xj4xz9td", "name": "Emaun Marin" },
            "shirt": "1",
            "captain": false,
            "libero": false,
            "position": "2",
            "nationality": "BIZ",
            "birth_date": "2010-03-11",
            "height_cm": 179
          },
          {
            "player": { "id": "pl_196h5txb", "name": "Nathalie Popper" },
            "shirt": "2",
            "captain": false,
            "libero": false,
            "position": "3",
            "nationality": "BIZ",
            "birth_date": "2011-02-03",
            "height_cm": 182
          },
          {
            "player": { "id": "pl_4y3s7692", "name": "Chloe Bowman" },
            "shirt": "3",
            "captain": false,
            "libero": false,
            "position": "2",
            "nationality": "BIZ",
            "birth_date": "2011-12-20",
            "height_cm": 169
          },
          {
            "player": { "id": "pl_k55q520n", "name": "Sara Safa" },
            "shirt": "4",
            "captain": true,
            "libero": false,
            "position": "1",
            "nationality": "BIZ",
            "birth_date": "2009-10-29",
            "height_cm": 168
          },
          ...
        ]
      },
      {
        "team": { "id": "tm_0s20hcq1", "name": "Costa Rica" },
        "players": [
          {
            "player": { "id": "pl_qjdgzcef", "name": "Esmeralda Ugalde Hernandez" },
            "shirt": "2",
            "captain": false,
            "libero": false,
            "position": "2",
            "nationality": "CRC",
            "birth_date": "2010-02-16",
            "height_cm": 175
          },
          {
            "player": { "id": "pl_6nb4s7n9", "name": "Nathalia Zavaleta Méndez" },
            "shirt": "6",
            "captain": false,
            "libero": false,
            "position": "6",
            "nationality": "CRC",
            "birth_date": "2008-04-20",
            "height_cm": 176
          },
          {
            "player": { "id": "pl_ytbnr1v7", "name": "Kristina Vargas Mbeki" },
            "shirt": "8",
            "captain": false,
            "libero": false,
            "position": "1",
            "nationality": "CRC",
            "birth_date": "2008-10-21",
            "height_cm": 172
          },
          {
            "player": { "id": "pl_pcxt3nge", "name": "Nadia Lucía Granados Salazar" },
            "shirt": "9",
            "captain": false,
            "libero": false,
            "position": "1",
            "nationality": "CRC",
            "birth_date": "2008-09-06",
            "height_cm": 168
          },
          ...
        ]
      },
      {
        "team": { "id": "tm_7bvptfb9", "name": "El Salvador" },
        "players": [
          {
            "player": {
              "id": "pl_qc68pd0d",
              "name": "Fiorella Abigail Apontes Di Majo"
            },
            "shirt": "1",
            "captain": false,
            "libero": true,
            "position": "4",
            "nationality": "ESA",
            "birth_date": "2008-09-22",
            "height_cm": 153
          },
          {
            "player": {
              "id": "pl_pnypmj29",
              "name": "Galilea Fernanda Guardado Batres"
            },
            "shirt": "2",
            "captain": false,
            "libero": false,
            "position": "6",
            "nationality": "ESA",
            "birth_date": "2009-06-30",
            "height_cm": 170
          },
          {
            "player": {
              "id": "pl_9z3argd2",
              "name": "Larissa Milagros Rodriguez Diaz"
            },
            "shirt": "3",
            "captain": false,
            "libero": false,
            "position": "1",
            "nationality": "ESA",
            "birth_date": "2010-11-11",
            "height_cm": 175
          },
          {
            "player": {
              "id": "pl_ahwgdmdg",
              "name": "Tatiana Valeria Gomez Alvarado"
            },
            "shirt": "4",
            "captain": false,
            "libero": false,
            "position": "2",
            "nationality": "ESA",
            "birth_date": "2010-05-13",
            "height_cm": 162
          },
          ...
        ]
      },
      {
        "team": { "id": "tm_vfhtv517", "name": "Guatemala" },
        "players": [
          {
            "player": {
              "id": "pl_8mdf4r34",
              "name": "Appril Larissa García García"
            },
            "shirt": null,
            "captain": false,
            "libero": false,
            "position": "2",
            "nationality": "GUA",
            "birth_date": "2012-03-03",
            "height_cm": 168
          },
          {
            "player": { "id": "pl_gmtsfhcx", "name": "Isabel Herrera García" },
            "shirt": "1",
            "captain": false,
            "libero": false,
            "position": "2",
            "nationality": "GUA",
            "birth_date": "2012-04-09",
            "height_cm": 170
          },
          {
            "player": {
              "id": "pl_96vb4n3k",
              "name": "Melissa Daniela Guerra Morataya"
            },
            "shirt": "2",
            "captain": true,
            "libero": false,
            "position": "6",
            "nationality": "GUA",
            "birth_date": "2009-02-23",
            "height_cm": 171
          },
          {
            "player": { "id": "pl_aepf86s8", "name": "Daniela Falla Hegel" },
            "shirt": "3",
            "captain": false,
            "libero": false,
            "position": "3",
            "nationality": "GUA",
            "birth_date": "2012-04-25",
            "height_cm": 174
          },
          ...
        ]
      },
      ...
    ]
  },
  "meta": { "plan": "Complete", "teams": 7, "players": 152 }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `competition` | object | id, name, discipline, gender and season |
| `teams` | array | One entry a team: team (id and name) and players |
| `players[].player` | object | id and name |
| `players[].shirt` | string | Shirt number |
| `players[].captain, players[].libero` | bool | Captain and libero |
| `players[].position` | string | Position where the registration gives one, else null |
| `players[].nationality` | string | Three-letter federation code |
| `players[].birth_date, players[].height_cm` | date, int | Where known |
| `meta.teams, meta.players` | int | Teams and players in the answer |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/competition-rosters

#### `GET /v1/competitions/{id}`

One competition with its discipline, gender, season and dates, the number of matches you can read in it and the first and last of them.

##### Parameters

This endpoint takes the parameters below.

| Name | Type | What it does | Example |
|---|---|---|---|
| `id` | path | The competition id, in the address. Required. | `cp_p80k5t4s` |

##### 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.

```
# One competition, with its dates and match count
curl "https://api.volleyballapi.com/v1/competitions/cp_p80k5t4s" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "id": "cp_p80k5t4s",
    "name": "FIVB Volleyball Men's U21 World Championship",
    "discipline": "indoor",
    "gender": "men",
    "season": 2021,
    "start_date": "2021-09-23",
    "end_date": "2021-10-03",
    "country_code": null,
    "matches": 64,
    "first_match": "2021-09-23",
    "last_match": "2021-10-03"
  },
  "meta": { "plan": "Complete" }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `id` | string | Stable competition id, `cp_` |
| `name` | string | The competition's name |
| `discipline` | enum | indoor or beach |
| `gender` | enum | men, women or mixed |
| `season` | int | The year the season starts in |
| `start_date, end_date` | date | First and last day, where known |
| `country_code` | string | Two-letter country of a national competition |
| `matches` | int | Matches in it your plan can read |
| `first_match, last_match` | date | The first and last of them |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/competition

### Teams and players

#### `GET /v1/teams`

Clubs, national teams and beach pairs found by name, including the other names a team has played under. Each comes back once, under one id.

##### Parameters

Parameters marked required must be sent; the rest are optional.

| Name | Type | What it does | Example |
|---|---|---|---|
| `q` | text | Part of the name, 2 to 80 characters. Required. | `Canada` |
| `discipline` | enum | One of `indoor`, `beach`. | `indoor` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |
| `country` | text | A two-letter country code, like `IT`: teams that play for that country. |  |
| `page` | int | Page number, from 1. Adds totals to meta. | `2` |
| `per_page` | int | Rows a page, 1 to 50. 50 when not sent. | `50` |
| `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.

```
# Teams and beach pairs, found by name
curl "https://api.volleyballapi.com/v1/teams?q=Canada" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### 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-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "tm_7h04r4t8",
      "name": "Canada",
      "discipline": "indoor",
      "gender": "men",
      "kind": "national",
      "federation": "CAN",
      "country_code": "CA"
    },
    {
      "id": "tm_vryjkgbs",
      "name": "Canada",
      "discipline": "indoor",
      "gender": "women",
      "kind": "national",
      "federation": "CAN",
      "country_code": "CA"
    },
    ...
  ],
  "meta": {
    "plan": "Complete",
    "count": 6,
    "next_cursor": null,
    "page": 1,
    "per_page": 50,
    "total": 6,
    "total_pages": 1,
    "next_page": null,
    "prev_page": null
  }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `id` | string | Stable team id, `tm_` |
| `name` | string | The name it plays under |
| `discipline` | enum | indoor or beach |
| `gender` | enum | men, women or mixed |
| `kind` | enum | club, national or pair |
| `federation` | string | Three-letter federation code, for national teams and pairs |
| `country_code` | string | Two-letter country the team plays for, or null where it is not certain |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape, or a per_page below 1 (over 50 is read as 50), or a required parameter left out |
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/teams

#### `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_7h04r4t8` |
| `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 50. 50 when not sent. | `50` |
| `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_7h04r4t8/matches?status=finished&per_page=2" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### 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-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "mt_c1gwjwbw",
      "discipline": "indoor",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2026-09-19",
      "time_local": "19:00",
      "start_utc": "2026-09-19T22:00:00Z",
      "utc_offset": "-03:00",
      "timezone": "America/Halifax",
      "competition": {
        "id": "cp_c2hxn1cw",
        "name": "NORCECA Men Continental Championship 2026",
        "season": 2026
      },
      "round": "Final Round",
      "pool": "Final 1-2 QF",
      "team_a": { "id": "tm_1qrdqvza", "name": "Cuba" },
      "team_b": { "id": "tm_7h04r4t8", "name": "Canada" },
      "score": { "a": 3, "b": 1 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 25, "b": 21, "duration_s": 1620 },
        { "set": 2, "a": 25, "b": 23, "duration_s": 1560 },
        { "set": 3, "a": 23, "b": 25, "duration_s": 1740 },
        { "set": 4, "a": 25, "b": 22, "duration_s": 1680 }
      ],
      "sets_complete": true,
      "duration_s": 6600,
      "updated_utc": "2026-10-27T02:15:19Z"
    },
    {
      "id": "mt_z7r01wss",
      "discipline": "indoor",
      "gender": "men",
      "status": "finished",
      "current_set": null,
      "date": "2026-09-18",
      "time_local": "16:30",
      "start_utc": "2026-09-18T19:30:00Z",
      "utc_offset": "-03:00",
      "timezone": "America/Halifax",
      "competition": {
        "id": "cp_c2hxn1cw",
        "name": "NORCECA Men Continental Championship 2026",
        "season": 2026
      },
      "round": "Final Round",
      "pool": "Semifinals QF",
      "team_a": { "id": "tm_7h04r4t8", "name": "Canada" },
      "team_b": { "id": "tm_na5bk84w", "name": "Mexico" },
      "score": { "a": 3, "b": 0 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 25, "b": 21, "duration_s": 1500 },
        { "set": 2, "a": 25, "b": 18, "duration_s": 1800 },
        { "set": 3, "a": 25, "b": 13, "duration_s": 1140 }
      ],
      "sets_complete": true,
      "duration_s": 4440,
      "updated_utc": "2026-10-27T02:15:19Z"
    }
  ],
  "meta": {
    "plan": "Complete",
    "count": 2,
    "next_cursor": "eyJvIjoyLCJwIjoyfQ",
    "page": 1,
    "per_page": 2,
    "total": 686,
    "total_pages": 343,
    "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 |
| `utc_offset` | string | The venue's offset from UTC at the start, such as +02:00, worked out from the local and UTC starts; null when either is missing |
| `timezone` | string | The venue's time zone (IANA, such as Europe/Rome), where its country and the offset agree; else null |
| `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](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape, or a per_page below 1 (over 50 is read as 50) |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/team-matches

#### `GET /v1/teams/{id}`

One team with its kind, discipline, gender and federation, and the players it has fielded.

##### Parameters

This endpoint takes the parameters below.

| Name | Type | What it does | Example |
|---|---|---|---|
| `id` | path | The team id, in the address. Required. | `tm_7h04r4t8` |

##### 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.

```
# One team: its name, kind, federation and players
curl "https://api.volleyballapi.com/v1/teams/tm_7h04r4t8" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "id": "tm_7h04r4t8",
    "name": "Canada",
    "discipline": "indoor",
    "gender": "men",
    "kind": "national",
    "federation": "CAN",
    "country_code": "CA",
    "players": [
      { "id": "pl_5q7syzr0", "name": "Landon Currie" },
      { "id": "pl_bc0tead1", "name": "Danny Demyanenko" },
      { "id": "pl_ykqs7jpr", "name": "Max Elgert" },
      { "id": "pl_e3vkwp8z", "name": "Daenan Gyimah" },
      ...
    ]
  },
  "meta": { "plan": "Complete" }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `id` | string | Stable team id, `tm_` |
| `name` | string | The name it plays under |
| `discipline` | enum | indoor or beach |
| `gender` | enum | men, women or mixed |
| `kind` | enum | club, national or pair |
| `federation` | string | Three-letter federation code, for national teams and pairs |
| `country_code` | string | Two-letter country the team plays for, or null where it is not certain |
| `players` | array | id and name of each player the team has fielded |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/team

#### `GET /v1/players`

Players found by name, with gender and federation.

##### Parameters

Parameters marked required must be sent; the rest are optional.

| Name | Type | What it does | Example |
|---|---|---|---|
| `q` | text | Part of the name, 2 to 80 characters. Required. | `Paegle` |
| `gender` | enum | One of `men`, `women`, `mixed`. | `men` |
| `page` | int | Page number, from 1. Adds totals to meta. | `2` |
| `per_page` | int | Rows a page, 1 to 50. 50 when not sent. | `50` |
| `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.

```
# Players, found by name
curl "https://api.volleyballapi.com/v1/players?q=Paegle&per_page=3" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### 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-11-12, with long lists cut short.

200 application/json

```
{
  "data": [
    {
      "id": "pl_6jfm7336",
      "name": "Krista Paegle",
      "gender": "women",
      "federation": "LAT"
    },
    {
      "id": "pl_b4yqer2h",
      "name": "Paegle Krista",
      "gender": "men",
      "federation": null
    }
  ],
  "meta": {
    "plan": "Complete",
    "count": 2,
    "next_cursor": null,
    "page": 1,
    "per_page": 3,
    "total": 2,
    "total_pages": 1,
    "next_page": null,
    "prev_page": null
  }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `id` | string | Stable player id, `pl_` |
| `name` | string | Full name |
| `gender` | enum | men or women |
| `federation` | string | Three-letter federation code |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape, or a per_page below 1 (over 50 is read as 50), or a required parameter left out |
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/players

#### `GET /v1/players/{id}`

One player: name, nationality, date of birth, height, weight, position and hand where known, every team they have played for, and their career competition by competition: matches, wins, points, kills, aces and blocks.

##### Parameters

This endpoint takes the parameters below.

| Name | Type | What it does | Example |
|---|---|---|---|
| `id` | path | The player id, in the address. Required. | `pl_b4yqer2h` |

##### 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.

```
# One player, the teams they have played for and their career, competition by competition
curl "https://api.volleyballapi.com/v1/players/pl_b4yqer2h" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "id": "pl_b4yqer2h",
    "name": "Paegle Krista",
    "first_name": "Krista",
    "last_name": "Paegle",
    "gender": "men",
    "federation": null,
    "nationality": "LV",
    "birth_date": "2002-03-20",
    "birth_year": 2002,
    "height_cm": 175,
    "weight_kg": 70,
    "spike_cm": null,
    "block_cm": null,
    "position": "outside",
    "hand": null,
    "teams": [
      {
        "id": "tm_x8kkwhzy",
        "name": "Jelgavas novads / Evopipes",
        "discipline": "indoor",
        "gender": "men",
        "kind": "club",
        "federation": null,
        "country_code": "LV"
      },
      {
        "id": "tm_3n8x042s",
        "name": "RSU 2",
        "discipline": "indoor",
        "gender": "women",
        "kind": "club",
        "federation": null,
        "country_code": "LV"
      },
      {
        "id": "tm_8jcj6kxw",
        "name": "VK Jelgava",
        "discipline": "indoor",
        "gender": "women",
        "kind": "club",
        "federation": null,
        "country_code": "LV"
      }
    ],
    "career": [
      {
        "season": 2026,
        "discipline": "indoor",
        "competition": {
          "id": "cp_vwfnrrc3",
          "name": "Latvijas čempionāts sievietēm 2026/2027, LČ Pamatturnīrs 2026/2027"
        },
        "team": { "id": "tm_3n8x042s", "name": "RSU" },
        "first_match": "2026-11-10",
        "last_match": "2026-11-10",
        "matches": 1,
        "won": 1,
        "points": 9,
        "kills": 7,
        "aces": 2,
        "blocks": 0,
        "counted_from": "match_sheets"
      },
      {
        "season": 2021,
        "discipline": "indoor",
        "competition": {
          "id": "cp_caj45zk5",
          "name": "Optibet Latvijas Čempionāts sievietēm 21/22, Optibet Latvijas čempionāts sievietēm Play off"
        },
        "team": { "id": "tm_8jcj6kxw", "name": "Jelgava" },
        "first_match": "2022-02-10",
        "last_match": "2022-04-03",
        "matches": 7,
        "won": 6,
        "points": 44,
        "kills": 32,
        "aces": 6,
        "blocks": 6,
        "counted_from": "match_sheets"
      },
      {
        "season": 2021,
        "discipline": "indoor",
        "competition": { "id": "cp_an4p8pbf", "name": "Cewood Latvijas Kauss 2021" },
        "team": { "id": "tm_x8kkwhzy", "name": "VK Jelgava" },
        "first_match": "2021-12-09",
        "last_match": "2021-12-19",
        "matches": 3,
        "won": 3,
        "points": 7,
        "kills": 6,
        "aces": 0,
        "blocks": 1,
        "counted_from": "match_sheets"
      }
    ],
    "career_totals": {
      "indoor": {
        "competitions": 3,
        "seasons": 2,
        "teams": 3,
        "first_season": 2021,
        "last_season": 2026,
        "first_match": "2021-12-09",
        "last_match": "2026-11-10",
        "matches": 11,
        "won": 10,
        "win_pct": 90.9,
        "matches_from_sheets": 11,
        "points": 60,
        "kills": 45,
        "aces": 8,
        "blocks": 7
      }
    }
  },
  "meta": { "plan": "Complete" }
}
```

##### Fields

| Field | Type | What it holds |
|---|---|---|
| `id` | string | Stable player id, `pl_` |
| `name, first_name, last_name` | string | The player's names |
| `gender` | enum | men or women |
| `federation` | string | Three-letter federation code |
| `nationality` | string | Two-letter country code |
| `birth_date` | date | Date of birth |
| `birth_year` | int | Year of birth, also where only the year is known |
| `height_cm, weight_kg` | int | Height and weight |
| `spike_cm, block_cm` | int | Spike and block reach |
| `position` | string | setter, outside, middle, opposite, libero or universal |
| `hand` | enum | left, right or both |
| `teams` | array | Every team they have played for |
| `career` | array | Newest first, one entry per competition and team: season, discipline, competition, team, first_match, last_match, matches, won, and points, kills, aces and blocks where the match sheets have them |

##### Errors

Errors come back as `{"error": {"code", "message", "docs"}}`, with `plan` and `pricing` added when a plan would answer. [Every error](https://volleyballapi.com/documentation/errors).

| HTTP | Code | When |
|---|---|---|
| 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.

``

```

```

Page: https://volleyballapi.com/documentation/player

#### `GET /v1/head-to-head` (Live, Archive, Complete)

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_7h04r4t8` |
| `team_b` | id | A team id, `tm_`. Required. | `tm_gq4s1mva` |

##### 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_7h04r4t8&team_b=tm_gq4s1mva" \
  -H "Authorization: Bearer $VBA_KEY"
```

##### Response

Every answer is `data` plus `meta`. This is a real answer to the request above, counted 2026-11-12, with long lists cut short.

200 application/json

```
{
  "data": {
    "team_a": {
      "id": "tm_7h04r4t8",
      "name": "Canada",
      "discipline": "indoor",
      "gender": "men",
      "kind": "national",
      "federation": "CAN",
      "country_code": "CA"
    },
    "team_b": {
      "id": "tm_gq4s1mva",
      "name": "Brazil",
      "discipline": "indoor",
      "gender": "men",
      "kind": "national",
      "federation": "BRA",
      "country_code": "BR"
    },
    "record": { "team_a_won": 6, "team_b_won": 32, "meetings": 38 },
    "matches": [
      {
        "id": "mt_n8ccvabj",
        "discipline": "indoor",
        "gender": "men",
        "status": "finished",
        "current_set": null,
        "date": "2026-06-28",
        "time_local": "16:30",
        "start_utc": "2026-06-28T14:30:00Z",
        "utc_offset": "+02:00",
        "timezone": "Europe/Ljubljana",
        "competition": {
          "id": "cp_qhjtyyrf",
          "name": "Men's Volleyball Nations League 2026",
          "season": 2026
        },
        "round": "Week 2",
        "pool": "Pool 6 - Preliminary Phase",
        "team_a": { "id": "tm_7h04r4t8", "name": "Canada" },
        "team_b": { "id": "tm_gq4s1mva", "name": "Brazil" },
        "score": { "a": 2, "b": 3 },
        "winner": "b",
        "sets": [
          { "set": 1, "a": 17, "b": 25, "duration_s": 1440 },
          { "set": 2, "a": 25, "b": 23, "duration_s": 1740 },
          { "set": 3, "a": 26, "b": 28, "duration_s": 2880 },
          { "set": 4, "a": 25, "b": 22, "duration_s": 1860 },
          ...
        ],
        "sets_complete": true,
        "duration_s": 9300,
        "updated_utc": "2026-10-27T02:16:24Z"
      },
      {
        "id": "mt_6m63fdgm",
        "discipline": "indoor",
        "gender": "men",
        "status": "finished",
        "current_set": null,
        "date": "2025-08-30",
        "time_local": "20:00",
        "start_utc": "2025-08-30T12:00:00Z",
        "utc_offset": "+08:00",
        "timezone": "Asia/Shanghai",
        "competition": {
          "id": "cp_txmf6c26",
          "name": "FIVB Volleyball Men's U21 World Championship 2025",
          "season": 2025
        },
        "round": "Final Round",
        "pool": "Final 17-18",
        "team_a": { "id": "tm_7h04r4t8", "name": "Canada " },
        "team_b": { "id": "tm_gq4s1mva", "name": "Brazil " },
        "score": { "a": 3, "b": 2 },
        "winner": "a",
        "sets": [
          { "set": 1, "a": 23, "b": 25, "duration_s": 1680 },
          { "set": 2, "a": 25, "b": 20, "duration_s": 1440 },
          { "set": 3, "a": 26, "b": 28, "duration_s": 1860 },
          { "set": 4, "a": 25, "b": 20, "duration_s": 1440 },
          ...
        ],
        "sets_complete": true,
        "duration_s": 7620,
        "updated_utc": "2026-10-27T02:20:56Z"
      },
      {
        "id": "mt_rcc5d331",
        "discipline": "indoor",
        "gender": "men",
        "status": "finished",
        "current_set": null,
        "date": "2025-06-25",
        "time_local": "16:00",
        "start_utc": "2025-06-25T21:00:00Z",
        "utc_offset": "-05:00",
        "timezone": "America/Chicago",
        "competition": {
          "id": "cp_8f6zjr46",
          "name": "Men's Volleyball Nations League 2025",
          "season": 2025
        },
        "round": "Week 2",
        "pool": "Pool 5 - Preliminary Phase",
        "team_a": { "id": "tm_7h04r4t8", "name": "Canada" },
        "team_b": { "id": "tm_gq4s1mva", "name": "Brazil" },
        "score": { "a": 0, "b": 3 },
        "winner": "b",
        "sets": [
          { "set": 1, "a": 22, "b": 25, "duration_s": 1800 },
          { "set": 2, "a": 17, "b": 25, "duration_s": 1140 },
          { "set": 3, "a": 17, "b": 25, "duration_s": 1140 }
        ],
        "sets_complete": true,
        "duration_s": 4080,
        "updated_utc": "2026-10-27T02:20:52Z"
      },
      {
        "id": "mt_yp9j9wtw",
        "discipline": "indoor",
        "gender": "men",
        "status": "finished",
        "current_set": null,
        "date": "2024-06-21",
        "time_local": "15:00",
        "start_utc": "2024-06-21T07:00:00Z",
        "utc_offset": "+08:00",
        "timezone": "Asia/Manila",
        "competition": {
          "id": "cp_54e5j37n",
          "name": "Men's Volleyball Nations League 2024",
          "season": 2024
        },
        "round": "Week 3",
        "pool": "Pool 6 - Preliminary Phase",
        "team_a": { "id": "tm_7h04r4t8", "name": "Canada" },
        "team_b": { "id": "tm_gq4s1mva", "name": "Brazil" },
        "score": { "a": 3, "b": 0 },
        "winner": "a",
        "sets": [
          { "set": 1, "a": 26, "b": 24, "duration_s": 1560 },
          { "set": 2, "a": 25, "b": 19, "duration_s": 1440 },
          { "set": 3, "a": 26, "b": 24, "duration_s": 1620 }
        ],
        "sets_complete": true,
        "duration_s": 4620,
        "updated_utc": "2026-10-27T02:23:42Z"
      },
      ...
    ]
  },
  "meta": { "plan": "Complete", "count": 38 }
}
```

##### 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](https://volleyballapi.com/documentation/errors).

| 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.

``

```

```

Page: https://volleyballapi.com/documentation/head-to-head

## Guides

### Introduction

The Volleyball API holds 526,062 matches: world championships, the Nations League and the beach tours, down to 316 national leagues and cups. Indoor goes back to 2001 and the sand to 2005, with every set score, and 13.1M rallies told point by point.

Live scores refresh every 12 to 15 seconds while anything is being played. Finished matches carry the venue, attendance, referees, both lineups by court zone and each player's serve, reception, attack and block figures. Beach matches carry the weather at the venue, hour by hour.

It is built for live score apps and widgets, prediction and betting models, fantasy and scouting tools, club and federation sites, and AI assistants that answer volleyball questions with real figures.

**526,062**matches**13.1M**rallies point by point**2001**first indoor season**22**endpoints, one key

#### Start here

Three steps from nothing to real data. The free key needs no card and gives 50 calls a day.

1

##### Get a free key

Sign in with Google and your key is made on the spot, and kept here for Try it on every page.

[Get a free key](https://volleyballapi.com/signup)2

##### Make your first call

Ask for yesterday's results, from the box below or with the code in your own language.

[Quick start](https://volleyballapi.com/documentation/quick-start)3

##### Read the answer

Every answer is data and meta; errors are words that say what to change.

[Responses](https://volleyballapi.com/documentation/errors)``

```

```

What it gives, from today's data:

200 application/json

```
{
  "data": [
    {
      "id": "mt_mg30j2hm",
      "discipline": "indoor",
      "gender": "women",
      "status": "finished",
      "current_set": null,
      "date": "2026-11-11",
      "time_local": "19:30",
      "start_utc": "2026-11-11T00:00:00Z",
      "utc_offset": null,
      "timezone": null,
      "competition": {
        "id": "cp_ggbn0z8s",
        "name": "NPVA Division #1 2026/27 League Series - Women",
        "season": 2026
      },
      "round": null,
      "pool": "Round Robin",
      "team_a": { "id": "tm_nh6j7egw", "name": "Elite BALLERS" },
      "team_b": { "id": "tm_1he8k05t", "name": "University of the Bahamas MINGOES" },
      "score": { "a": 0, "b": 3 },
      "winner": "b",
      "sets": [
        { "set": 1, "a": 18, "b": 25, "duration_s": 1920 },
        { "set": 2, "a": 25, "b": 27, "duration_s": 1800 },
        { "set": 3, "a": 21, "b": 25, "duration_s": 1500 }
      ],
      "sets_complete": true,
      "duration_s": 5220,
      "updated_utc": "2026-11-12T03:07:07Z"
    },
    {
      "id": "mt_dq82ah5s",
      "discipline": "indoor",
      "gender": "women",
      "status": "finished",
      "current_set": null,
      "date": "2026-11-11",
      "time_local": "11:30",
      "start_utc": "2026-11-11T06:30:00Z",
      "utc_offset": "+05:00",
      "timezone": "Asia/Almaty",
      "competition": {
        "id": "cp_krstt0k2",
        "name": "Women's High League, I Round",
        "season": 2026
      },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_hn4tpx3j", "name": "Zhayik" },
      "team_b": { "id": "tm_pe7gwc22", "name": "Qostanay" },
      "score": { "a": 3, "b": 0 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 25, "b": 16, "duration_s": null },
        { "set": 2, "a": 25, "b": 13, "duration_s": null },
        { "set": 3, "a": 25, "b": 17, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-11-11T08:00:15Z"
    }
  ],
  "meta": {
    "plan": "Complete",
    "date": "2026-11-11",
    "count": 2,
    "next_cursor": "eyJvIjoyLCJwIjoyfQ",
    "page": 1,
    "per_page": 2,
    "total": 99,
    "total_pages": 50,
    "next_page": 2,
    "prev_page": null
  }
}
```

#### Every subject

A guide for each part of the data: what it covers, how the records link, and the calls for the common jobs.

##### Live scores

Every match being played this minute, indoor and beach, with the running score of each set. Polled every 12 to 15 seconds while anything is live; each answer says how far behind it is.

- [GET /v1/matches/live](https://volleyballapi.com/documentation/live)
- [GET /v1/matches/{id}](https://volleyballapi.com/documentation/match)
- [GET /v1/matches/{id}/points](https://volleyballapi.com/documentation/match-points)
[Read the guide](https://volleyballapi.com/documentation/live-scores)

##### Results and sets

Finished matches with every set score and its duration, the venue, town, attendance and referees. One call a day keeps a results page up to date; any day since the first season is a date away.

- [GET /v1/results/yesterday](https://volleyballapi.com/documentation/results-yesterday)
- [GET /v1/matches](https://volleyballapi.com/documentation/matches)
- [GET /v1/matches/{id}](https://volleyballapi.com/documentation/match)
[Read the guide](https://volleyballapi.com/documentation/results-and-sets)

##### Point by point

Every rally of every set in the order played: the score after it, who won it and who served. Enough for side-out and break-point rates, runs and clutch points.

- [GET /v1/matches/{id}/points](https://volleyballapi.com/documentation/match-points)
- [GET /v1/export/points](https://volleyballapi.com/documentation/export-points)
[Read the guide](https://volleyballapi.com/documentation/point-by-point)

##### Lineups and player figures

The starting six by court zone for every set, who came on, both head coaches, and each player's points, serve, reception, attack and block.

- [GET /v1/matches/{id}/lineups](https://volleyballapi.com/documentation/match-lineups)
- [GET /v1/matches/{id}/players](https://volleyballapi.com/documentation/match-players)
- [GET /v1/export/lineups](https://volleyballapi.com/documentation/export-lineups)
[Read the guide](https://volleyballapi.com/documentation/lineups-and-player-figures)

##### Competitions and standings

World championships and tours down to national leagues and cups, each with its matches and a table for every stage and pool, worked out from the results.

- [GET /v1/competitions](https://volleyballapi.com/documentation/competitions)
- [GET /v1/competitions/{id}](https://volleyballapi.com/documentation/competition)
- [GET /v1/competitions/{id}/matches](https://volleyballapi.com/documentation/competition-matches)
- [GET /v1/competitions/{id}/standings](https://volleyballapi.com/documentation/competition-standings)
- [GET /v1/competitions/{id}/rosters](https://volleyballapi.com/documentation/competition-rosters)
[Read the guide](https://volleyballapi.com/documentation/competitions-and-standings)

##### Teams, players and careers

Clubs, national teams and beach pairs under one id whatever name they played as, their players, each player's career competition by competition, and head-to-head records.

- [GET /v1/teams](https://volleyballapi.com/documentation/teams)
- [GET /v1/teams/{id}](https://volleyballapi.com/documentation/team)
- [GET /v1/teams/{id}/matches](https://volleyballapi.com/documentation/team-matches)
- [GET /v1/players](https://volleyballapi.com/documentation/players)
- [GET /v1/players/{id}](https://volleyballapi.com/documentation/player)
- [GET /v1/head-to-head](https://volleyballapi.com/documentation/head-to-head)
[Read the guide](https://volleyballapi.com/documentation/teams-and-players)

##### Bulk export

Whole ranges in one call for loading your own database: up to 184 days of matches, 92 of lineups or 14 of rallies at a time.

- [GET /v1/export/matches](https://volleyballapi.com/documentation/export-matches)
- [GET /v1/export/lineups](https://volleyballapi.com/documentation/export-lineups)
- [GET /v1/export/points](https://volleyballapi.com/documentation/export-points)
[Read the guide](https://volleyballapi.com/documentation/bulk-export)

#### Every endpoint

Base URL `https://api.volleyballapi.com`. The `/v1` may be left out. The dot says which plans answer.

Every planEvery paid planLive and CompleteArchive and CompleteComplete

##### Matches

Scores, results and everything inside one match.

| Endpoint | What it returns |
|---|---|
| [GET /v1/matches/live](https://volleyballapi.com/documentation/live) | Every match being played now, with the running set scores |
| [GET /v1/results/yesterday](https://volleyballapi.com/documentation/results-yesterday) | Yesterday's finished matches |
| [GET /v1/matches](https://volleyballapi.com/documentation/matches) | Matches on a day or between two days, filtered by discipline, gender, status, competition or team |
| [GET /v1/matches/{id}](https://volleyballapi.com/documentation/match) | One match: teams, result, every set, duration, venue, spectators and referees |
| [GET /v1/matches/{id}/points](https://volleyballapi.com/documentation/match-points) | Every rally of every set: the score after it, who won it and who served |
| [GET /v1/matches/{id}/players](https://volleyballapi.com/documentation/match-players) | Per-player figures for the match: points, serve, reception, attack and block |
| [GET /v1/matches/{id}/lineups](https://volleyballapi.com/documentation/match-lineups) | Starting six by court zone for every set, the players who came on, and both head coaches |

##### Bulk export

Long ranges in one call, on Complete.

| Endpoint | What it returns |
|---|---|
| [GET /v1/export/matches](https://volleyballapi.com/documentation/export-matches) | Every match between two days in one call, with sets, venue, officials and coaches (up to 184 days) |
| [GET /v1/export/lineups](https://volleyballapi.com/documentation/export-lineups) | Every lineup between two days in one call: starting six by zone, players who came on, coaches (up to 92 days) |
| [GET /v1/export/points](https://volleyballapi.com/documentation/export-points) | Every rally of every match between two days in one call (up to 14 days) |

##### Competitions

Tournaments, leagues and their tables.

| Endpoint | What it returns |
|---|---|
| [GET /v1/competitions](https://volleyballapi.com/documentation/competitions) | Competitions, newest first, filtered by discipline, gender, season or name |
| [GET /v1/competitions/{id}](https://volleyballapi.com/documentation/competition) | One competition, with its dates and match count |
| [GET /v1/competitions/{id}/matches](https://volleyballapi.com/documentation/competition-matches) | A competition's matches |
| [GET /v1/competitions/{id}/standings](https://volleyballapi.com/documentation/competition-standings) | League tables for a competition, one per pool, worked out from its results |
| [GET /v1/competitions/{id}/rosters](https://volleyballapi.com/documentation/competition-rosters) | The players each team registered for a competition: shirt, captain, libero, birth date and height |

##### Teams and players

Who played, for whom, and how often they met.

| Endpoint | What it returns |
|---|---|
| [GET /v1/teams](https://volleyballapi.com/documentation/teams) | Teams and beach pairs, found by name |
| [GET /v1/teams/{id}](https://volleyballapi.com/documentation/team) | One team: its name, kind, federation and players |
| [GET /v1/teams/{id}/matches](https://volleyballapi.com/documentation/team-matches) | A team's matches, newest first |
| [GET /v1/players](https://volleyballapi.com/documentation/players) | Players, found by name |
| [GET /v1/players/{id}](https://volleyballapi.com/documentation/player) | One player, the teams they have played for and their career, competition by competition |
| [GET /v1/head-to-head](https://volleyballapi.com/documentation/head-to-head) | Every meeting of two teams, with the record between them |

##### Account

Your plan and what is left.

| Endpoint | What it returns |
|---|---|
| [GET /v1/usage](https://volleyballapi.com/documentation/usage) | Your plan, your calls today and this month, your limits and the dates you can read |

#### Popular calls

What people call most, with a real call to copy.

[GET /v1/competitions/cp_p80k5t4s/matches?per_page=2A competition's matches](https://volleyballapi.com/documentation/competition-matches)[GET /v1/matches/mt_854w9wh4/pointsPoint by point](https://volleyballapi.com/documentation/match-points)[GET /v1/matches/liveLive matches](https://volleyballapi.com/documentation/live)[GET /v1/matches?date=2021-09-24&gender=menMatches by day](https://volleyballapi.com/documentation/matches)[GET /v1/competitions?discipline=beach&per_page=2Competitions](https://volleyballapi.com/documentation/competitions)

#### For assistants and agents

The same API made for AI: a server an assistant can call, a skill that teaches it, and the manual in one file.

##### MCP server

Add it to Claude, ChatGPT, Cursor or Claude Code and the assistant makes the calls itself, with your key.

`https://api.volleyballapi.com/mcp`

##### MCP tools

Every tool, what it returns, its parameters and the plan it needs.

`https://volleyballapi.com/documentation/mcp-tools`

##### Agent skill

Teaches an agent the API: getting a key, the common calls, the limits and the errors.

`https://volleyballapi.com/skill.md`

##### The manual and llms.txt

The whole API in one file, for an agent to read before it starts. llms.txt is the short index.

`https://volleyballapi.com/documentation/manual.md`

#### Plans in short

Every plan uses the same API; what changes is how far back it reads, how many calls it makes and what it includes. [Prices and every feature](https://volleyballapi.com/pricing).

|  | Free key | Live | Archive | Complete |
|---|---|---|---|---|
| Price | Free | $39 a month | $39 a month | $79 a month |
| Reads | today and yesterday | last 30 days | since 2001 | since 2001 |
| Calls | 50 a day | 50,000 a month | 50,000 a month | 250,000 a month |
| Live scores | - | Yes | - | Yes |
| Point by point | - | Yes | Yes | Yes |
| Lineups and player figures | - | - | Yes | Yes |

#### What is new

[2026-11-11Pages hold up to 50 rows: a larger per_page is read as 50, never refused; follow next_cursor for more](https://volleyballapi.com/documentation/pagination)[2026-10-27Rosters: /v1/competitions/{id}/rosters gives the players each team registered for an international competition, with shirt, captain, libero, birth date and height](https://volleyballapi.com/documentation/competition-rosters)[2026-10-27Rounds: international indoor matches carry their round (Preliminary Round, Final Round...) as well as their pool, and standings leave knockout rounds out of the tables](https://volleyballapi.com/documentation/competitions-and-standings)[2026-10-27Officials: a new officials field lists each match's officials by role, with their country; referees for over 11,000 international matches, line judges and scorers where they are published](https://volleyballapi.com/documentation/match)[2026-10-23Time zones: every match gains utc_offset and timezone, and league matches now give their real local day and time (they gave the UTC clock before)](https://volleyballapi.com/documentation/results-and-sets)

[The whole changelog](https://volleyballapi.com/documentation/changelog)

#### Everything else

[AuthenticationYour key in X-API-Key or Authorization: Bearer, never in the address.](https://volleyballapi.com/documentation/authentication)[ErrorsEvery code, what it means and what to do.](https://volleyballapi.com/documentation/errors)[PaginationPages of up to 50 rows, or a cursor for long pulls.](https://volleyballapi.com/documentation/pagination)[Plans and rate limitsCalls a minute, the quota and the headers on every answer.](https://volleyballapi.com/documentation/plans)[StatusUptime of the site, the API and the MCP server.](https://volleyballapi.com/status)[SupportA question, a bug or a missing match: every ticket is answered.](https://volleyballapi.com/support)

#### Questions people ask

Is the free key real data?

Yes. It reads the same data the paid plans read, for today and yesterday, 50 calls a day. Paid fields come back as null with a note naming the plan that has them, so code written on the free key keeps working after an upgrade. [Plans and limits](https://volleyballapi.com/documentation/plans).

How fast are live scores?

While a match is being played the scores are read every 12 to 15 seconds. Every live answer says in meta how many seconds behind it is. [Live scores](https://volleyballapi.com/documentation/live-scores).

How far back does it go?

Indoor from 2001 and beach from 2005, with every set score. Rallies, lineups and player figures cover the seasons each competition published them. [Coverage](https://volleyballapi.com/coverage).

Do ids ever change?

No. Every match, competition, team and player has one id for good, even when a match reached us twice or a team changed its name. [Ids](https://volleyballapi.com/documentation/ids).

Can I use it from an AI assistant?

Yes: add the MCP server with your key and the assistant calls the API itself, within your plan. [MCP for AI agents](https://volleyballapi.com/documentation/mcp).

What happens when I go over my limit?

A 429 that says whether it was the minute or the quota, and when to try again. Nothing is ever charged for going over. [Plans and limits](https://volleyballapi.com/documentation/plans).

Page: https://volleyballapi.com/documentation

### Quick start

From nothing to real volleyball data in three steps. The free key needs no card.

#### 1. Get a key

Sign in with Google at [volleyballapi.com/signup](https://volleyballapi.com/signup). Your free key is made on the spot and shown once; it starts with `vba_`. It is kept in this browser too, so Try it on every page here already has it.

#### 2. Make the first call

Yesterday's finished matches answer on every plan. Send the key in a header.

```
# Yesterday's results
curl "https://api.volleyballapi.com/v1/results/yesterday?per_page=2" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### 3. Read the answer

`data` holds the matches, `meta` your plan, the count and the next cursor. Every match has an id that never changes, the score in sets and every set's points.

200 application/json

```
{
  "data": [
    {
      "id": "mt_mg30j2hm",
      "discipline": "indoor",
      "gender": "women",
      "status": "finished",
      "current_set": null,
      "date": "2026-11-11",
      "time_local": "19:30",
      "start_utc": "2026-11-11T00:00:00Z",
      "utc_offset": null,
      "timezone": null,
      "competition": {
        "id": "cp_ggbn0z8s",
        "name": "NPVA Division #1 2026/27 League Series - Women",
        "season": 2026
      },
      "round": null,
      "pool": "Round Robin",
      "team_a": { "id": "tm_nh6j7egw", "name": "Elite BALLERS" },
      "team_b": { "id": "tm_1he8k05t", "name": "University of the Bahamas MINGOES" },
      "score": { "a": 0, "b": 3 },
      "winner": "b",
      "sets": [
        { "set": 1, "a": 18, "b": 25, "duration_s": 1920 },
        { "set": 2, "a": 25, "b": 27, "duration_s": 1800 },
        { "set": 3, "a": 21, "b": 25, "duration_s": 1500 }
      ],
      "sets_complete": true,
      "duration_s": 5220,
      "updated_utc": "2026-11-12T03:07:07Z"
    },
    {
      "id": "mt_dq82ah5s",
      "discipline": "indoor",
      "gender": "women",
      "status": "finished",
      "current_set": null,
      "date": "2026-11-11",
      "time_local": "11:30",
      "start_utc": "2026-11-11T06:30:00Z",
      "utc_offset": "+05:00",
      "timezone": "Asia/Almaty",
      "competition": {
        "id": "cp_krstt0k2",
        "name": "Women's High League, I Round",
        "season": 2026
      },
      "round": null,
      "pool": null,
      "team_a": { "id": "tm_hn4tpx3j", "name": "Zhayik" },
      "team_b": { "id": "tm_pe7gwc22", "name": "Qostanay" },
      "score": { "a": 3, "b": 0 },
      "winner": "a",
      "sets": [
        { "set": 1, "a": 25, "b": 16, "duration_s": null },
        { "set": 2, "a": 25, "b": 13, "duration_s": null },
        { "set": 3, "a": 25, "b": 17, "duration_s": null }
      ],
      "sets_complete": true,
      "duration_s": null,
      "updated_utc": "2026-11-11T08:00:15Z"
    }
  ],
  "meta": {
    "plan": "Complete",
    "date": "2026-11-11",
    "count": 2,
    "next_cursor": "eyJvIjoyLCJwIjoyfQ",
    "page": 1,
    "per_page": 2,
    "total": 99,
    "total_pages": 50,
    "next_page": 2,
    "prev_page": null
  }
}
```

#### Then

[Live scoresScores while the match is on.](https://volleyballapi.com/documentation/live-scores)[Results and setsAny day since 2001.](https://volleyballapi.com/documentation/results-and-sets)[StandingsEvery league and pool table.](https://volleyballapi.com/documentation/competitions-and-standings)

Page: https://volleyballapi.com/documentation/quick-start

### Authentication

Every call carries your key in a header. Keys are made in your account, shown once, and can be rotated or revoked at any time.

#### Getting a key

Sign in with Google at [volleyballapi.com/signup](https://volleyballapi.com/signup). Your first key is made on the spot on the free plan; it starts with `vba_` and is 40 characters long. It is shown once, so keep it somewhere safe. From your [account](https://volleyballapi.com/account) you can make more keys, rotate one, or revoke it.

#### Sending it

Use either header. Both work on every endpoint.

| Header | Example |
|---|---|
| `Authorization` | `Bearer vba_6c1f...e9` |
| `X-API-Key` | `vba_6c1f...e9` |

```
# Check your key and your plan
curl "https://api.volleyballapi.com/v1/usage" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Never in the address

A key sent as `?key=` or `?api_key=` is refused with a 400 before anything else happens. Addresses end up in logs, browser history and proxies; headers do not.

#### From a browser

The API answers from any origin (CORS), so a key works from a page. Anyone can read a key in a page's code, though: for a public site, call the API from your server, or use a key you are ready to rotate.

#### When it goes wrong

| HTTP | Code | When |
|---|---|---|
| 401 | `unauthorized` | No key, or a key that is not known or was revoked |
| 400 | `bad_request` | A key sent in the address |

Page: https://volleyballapi.com/documentation/authentication

### Responses and errors

Every answer is JSON in one of two shapes: data and meta when it worked, an error object when it did not. Error codes are words, and every error links to the page that explains it.

#### When it works

`data` holds what you asked for: a list, or one object. `meta` holds your plan, counts, pages and the next cursor.

200 application/json

```
{
  "data": [
    {
      "id": "cp_8mz4q89a",
      "name": "KEN NT - Kwale",
      "discipline": "beach",
      "gender": "women",
      "season": 2027,
      "start_date": "2027-09-18",
      "end_date": "2027-09-19",
      "country_code": "KE"
    },
    {
      "id": "cp_kgxvga2q",
      "name": "KEN NT - Kwale",
      "discipline": "beach",
      "gender": "men",
      "season": 2027,
      "start_date": "2027-09-18",
      "end_date": "2027-09-19",
      "country_code": "KE"
    }
  ],
  "meta": {
    "plan": "Complete",
    "count": 2,
    "next_cursor": "eyJvIjoyLCJwIjoyfQ",
    "page": 1,
    "per_page": 2,
    "total": 9315,
    "total_pages": 4658,
    "next_page": 2,
    "prev_page": null
  }
}
```

#### When it does not

`code` is a word you can switch on, `message` says what to change, `docs` links here. When another plan would answer, `plan` and `pricing` say which.

403 application/json

```
{
  "error": {
    "code": "upgrade_required",
    "message": "/v1/matches/live is on the Live and Complete plans.",
    "plan": "Live",
    "pricing": "https://volleyballapi.com/pricing",
    "docs": "https://volleyballapi.com/documentation/live"
  }
}
```

#### Every error

| HTTP | Code | When |
|---|---|---|
| 400 | `bad_request` | A value of the wrong shape, a key sent in the address, 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 or this day; the answer names the plans that do |
| 404 | `not_found` | No endpoint at that address, or no match, competition, team or player with that id |
| 405 | `bad_request` | A method other than GET |
| 422 | `unknown_parameter` | A parameter the 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 |
| 500 | `server_error` | Our fault; it is logged and looked at |

#### Values

Times are UTC in ISO 8601 with a `Z`. `date` and `time_local` are the venue's own calendar day and clock. A value we do not have is `null`, never left out, so every object of a kind has the same keys.

Page: https://volleyballapi.com/documentation/errors

### Pagination

Every list answers 50 rows a page, up to 50 with per_page. Use page numbers when you want totals, or the cursor when you are pulling everything.

#### Pages

Send `page` (from 1) and `per_page`. The first call of a list counts its total, so meta carries the page you are on, the total and the pages either side.

200 application/json

```
{
  "meta": {
    "plan": "Archive",
    "count": 200,
    "next_cursor": "eyJvIjoyMDAsInAiOjIwMH0",
    "page": 1,
    "per_page": 200,
    "total": 1312,
    "total_pages": 7,
    "next_page": 2,
    "prev_page": null
  }
}
```

#### Cursor

Every list answer carries `next_cursor`, or null on the last page. Send it alone as `cursor` for the next page; it keeps your page size and skips the count, so it is the quicker way through a long range.

```
# A whole month, 200 matches a page
curl "https://api.volleyballapi.com/v1/matches?from=2026-10-01&to=2026-10-31&per_page=200" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Calls

Each page is one call, whatever its size, so `per_page=200` is the cheapest way to pull a lot.

Page: https://volleyballapi.com/documentation/pagination

### Plans and limits

Every plan uses the same API. What changes is how many calls you can make, how far back you can read, and whether live scores, rallies and player figures are included.

#### The plans

|  | Free key | Live | Archive | Complete |
|---|---|---|---|---|
| Price | Free | $39 a month | $39 a month | $79 a month |
| Calls a minute | 10 | 60 | 60 | 120 |
| Calls included | 50 a day | 50,000 a month | 50,000 a month | 250,000 a month |
| Days you can read | today and yesterday | last 30 days | since 2001 | since 2001 |
| Live scores | - | Yes | - | Yes |
| Point by point | - | Yes | Yes | Yes |
| Player figures | - | - | Yes | Yes |

[Prices and every feature](https://volleyballapi.com/pricing)

#### Headers on every answer

| Header | What it says |
|---|---|
| `X-RateLimit-Limit` | Calls a minute on your plan |
| `X-RateLimit-Remaining` | Calls left this minute |
| `X-RateLimit-Reset` | Seconds until the minute resets |
| `X-Quota-Limit` | Calls in your day or month |
| `X-Quota-Remaining` | Calls left in it |
| `X-Quota-Reset` | When it resets, UTC |
| `Retry-After` | On a 429: seconds to wait |

#### Going over

Too many calls in a minute gets a 429 `rate_limited` with Retry-After; a used-up day or month gets a 429 `quota_exceeded` with the reset time. Nothing is ever charged for going over. Calls to [/v1/usage](https://volleyballapi.com/documentation/usage) are never counted, and neither are 429s or answers we fail to give.

Page: https://volleyballapi.com/documentation/plans

### Ids that never change

Every match, competition, team and player has one id that never changes. Store it, link to it, and it will answer the same way next season.

#### Four kinds

| Prefix | For | Example |
|---|---|---|
| `mt_` | a match | `mt_0psf8rp2` |
| `cp_` | a competition | `cp_wqxyp8gn` |
| `tm_` | a team or beach pair | `tm_drr98vzn` |
| `pl_` | a player |  |

#### One match, one id

When a match reaches us twice, it is joined and served once, under one id, with the detail of both. A team that has played under several names, or with a sponsor in its name, comes back as one team; its matches under every name are in [its matches](https://volleyballapi.com/documentation/team-matches).

#### An id that does not exist

Any id we did not give out answers 404 `not_found`.

Page: https://volleyballapi.com/documentation/ids

### Live scores

Every match being played this minute, indoor and beach, with the running score of each set. Polled every 12 to 15 seconds while anything is live; each answer says how far behind it is.

#### What it covers

Every indoor and beach match being played anywhere we follow: the set in play, every set score so far and the match score. While anything is live the scores are read every 12 to 15 seconds, and every answer carries `meta.seconds_behind`, so you always know how fresh a score is. Live scores are on the Live and Complete plans.

#### The endpoints

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Endpoint | What it returns |
|---|---|
| [GET /v1/matches/live](https://volleyballapi.com/documentation/live) | Every match being played now, with the running set scores |
| [GET /v1/matches/{id}](https://volleyballapi.com/documentation/match) | One match: teams, result, every set, duration, venue, spectators and referees |
| [GET /v1/matches/{id}/points](https://volleyballapi.com/documentation/match-points) | Every rally of every set: the score after it, who won it and who served |

#### How the records link

A live match has the same id it had when it was scheduled and keeps it once finished, so a live widget can link straight to [the full match](https://volleyballapi.com/documentation/match) and, as the sets go by, to [every rally](https://volleyballapi.com/documentation/match-points).

#### A live scores widget

Ask for everything live, every 15 seconds. Filter by discipline or gender to keep the list short. An empty list is a 200 with `meta.count` 0, not an error.

```
# A live scores widget
curl "https://api.volleyballapi.com/v1/matches/live?discipline=indoor" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Follow one match

Ask for the match by its id; while it is live, `current_set` says which set is being played.

```
# Follow one match
curl "https://api.volleyballapi.com/v1/matches/mt_pcbe3hvw" \
  -H "Authorization: Bearer $VBA_KEY"
```

Page: https://volleyballapi.com/documentation/live-scores

### Results and sets

Finished matches with every set score and its duration, the venue, town, attendance and referees. One call a day keeps a results page up to date; any day since the first season is a date away.

#### What it covers

Every finished match since 2001 with the score in sets, every set's points and duration, and where it was played: hall, town and country where the source gives them, with attendance and both referees. A match whose source left sets out says so with `sets_complete` false, never with made-up numbers.

#### The endpoints

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Endpoint | What it returns |
|---|---|
| [GET /v1/results/yesterday](https://volleyballapi.com/documentation/results-yesterday) | Yesterday's finished matches |
| [GET /v1/matches](https://volleyballapi.com/documentation/matches) | Matches on a day or between two days, filtered by discipline, gender, status, competition or team |
| [GET /v1/matches/{id}](https://volleyballapi.com/documentation/match) | One match: teams, result, every set, duration, venue, spectators and referees |

#### How the records link

Each match names its [competition](https://volleyballapi.com/documentation/competition) and both [teams](https://volleyballapi.com/documentation/team) by id, with the round and pool. A match that reached us twice is served once under one id.

#### Yesterday's results

Answers on every plan, the free key included: one call a day keeps a results page current.

```
# Yesterday's results
curl "https://api.volleyballapi.com/v1/results/yesterday?per_page=50" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### One day, or a range

Up to 31 days a call, filtered by discipline, gender, status, competition or team.

```
# One day, or a range
curl "https://api.volleyballapi.com/v1/matches?date=2021-09-24&gender=men" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### One match in full

Venue, town, attendance, referees and coaches, with links to its rallies and lineups where they exist.

```
# One match in full
curl "https://api.volleyballapi.com/v1/matches/mt_pcbe3hvw" \
  -H "Authorization: Bearer $VBA_KEY"
```

Page: https://volleyballapi.com/documentation/results-and-sets

### Point by point

Every rally of every set in the order played: the score after it, who won it and who served. Enough for side-out and break-point rates, runs and clutch points.

#### What it covers

For each set, every rally in the order it was played: the score after it, the side that won it and the side that served it. From that come side-out and break-point rates, runs, momentum swings and clutch points. Rallies are on every paid plan.

#### The endpoints

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Endpoint | What it returns |
|---|---|
| [GET /v1/matches/{id}/points](https://volleyballapi.com/documentation/match-points) | Every rally of every set: the score after it, who won it and who served |
| [GET /v1/export/points](https://volleyballapi.com/documentation/export-points) | Every rally of every match between two days in one call (up to 14 days) |

#### How the records link

Rallies hang off [a match](https://volleyballapi.com/documentation/match) by its id; `detail` on the match says whether it has them. Sets are numbered as in `sets` on the match.

#### Every rally of a match

One call per match, all sets at once.

```
# Every rally of a match
curl "https://api.volleyballapi.com/v1/matches/mt_854w9wh4/points" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Many matches at once

On Complete, every rally of every match between two days, up to 14 days a call.

```
# Many matches at once
curl "https://api.volleyballapi.com/v1/export/points?from=2026-11-11&to=2026-11-11" \
  -H "Authorization: Bearer $VBA_KEY"
```

Page: https://volleyballapi.com/documentation/point-by-point

### Lineups and player figures

The starting six by court zone for every set, who came on, both head coaches, and each player's points, serve, reception, attack and block.

#### What it covers

For the national leagues whose match sheets carry them: the starting six of each set by court zone (zone 1 serves first), liberos marked, the players who came on, both head coaches, and each player's figures for the match. A player who was on court and did none of something shows 0; a player who never came on shows null. On the Archive and Complete plans.

#### The endpoints

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Endpoint | What it returns |
|---|---|
| [GET /v1/matches/{id}/lineups](https://volleyballapi.com/documentation/match-lineups) | Starting six by court zone for every set, the players who came on, and both head coaches |
| [GET /v1/matches/{id}/players](https://volleyballapi.com/documentation/match-players) | Per-player figures for the match: points, serve, reception, attack and block |
| [GET /v1/export/lineups](https://volleyballapi.com/documentation/export-lineups) | Every lineup between two days in one call: starting six by zone, players who came on, coaches (up to 92 days) |

#### How the records link

Players are linked by id to [their own record](https://volleyballapi.com/documentation/player) and career, and to the [team](https://volleyballapi.com/documentation/team) they played for in that match.

#### Who started, and where

Starters by zone for every set, the players who came on and both coaches.

```
# Who started, and where
curl "https://api.volleyballapi.com/v1/matches/mt_gb8xfagd/lineups" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Every player's figures

Points, break points, serve, reception, attack and block, both teams.

```
# Every player's figures
curl "https://api.volleyballapi.com/v1/matches/mt_gb8xfagd/players" \
  -H "Authorization: Bearer $VBA_KEY"
```

Page: https://volleyballapi.com/documentation/lineups-and-player-figures

### Competitions and standings

World championships and tours down to national leagues and cups, each with its matches and a table for every stage and pool, worked out from the results.

#### What it covers

World championships, the Nations League, the beach tours, and national leagues and cups, each with its season, dates and matches. Standings are worked out from the results: a table for every stage and pool, with played, won, lost, league points, sets and rally points for and against, and the last five results.

#### The endpoints

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Endpoint | What it returns |
|---|---|
| [GET /v1/competitions](https://volleyballapi.com/documentation/competitions) | Competitions, newest first, filtered by discipline, gender, season or name |
| [GET /v1/competitions/{id}](https://volleyballapi.com/documentation/competition) | One competition, with its dates and match count |
| [GET /v1/competitions/{id}/matches](https://volleyballapi.com/documentation/competition-matches) | A competition's matches |
| [GET /v1/competitions/{id}/standings](https://volleyballapi.com/documentation/competition-standings) | League tables for a competition, one per pool, worked out from its results |
| [GET /v1/competitions/{id}/rosters](https://volleyballapi.com/documentation/competition-rosters) | The players each team registered for a competition: shirt, captain, libero, birth date and height |

#### How the records link

Every [match](https://volleyballapi.com/documentation/match) names its competition by id. Teams in a table are linked by id, so a table row leads to [that team's matches](https://volleyballapi.com/documentation/team-matches).

#### Find a competition

By discipline, gender, season or a word in its name.

```
# Find a competition
curl "https://api.volleyballapi.com/v1/competitions?discipline=beach&per_page=5" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### The table

Indoor gives 3 points for a 3-0 or 3-1 win, 2 for a 3-2 win and 1 for a 2-3 loss; beach pools 2 for a win and 1 for a loss. Knockout rounds are left out unless you send `stage=all`.

```
# The table
curl "https://api.volleyballapi.com/v1/competitions/cp_x2e5f59m/standings" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Every match in it

Fixtures and results, every round and pool.

```
# Every match in it
curl "https://api.volleyballapi.com/v1/competitions/cp_p80k5t4s/matches?per_page=2" \
  -H "Authorization: Bearer $VBA_KEY"
```

Page: https://volleyballapi.com/documentation/competitions-and-standings

### Teams, players and careers

Clubs, national teams and beach pairs under one id whatever name they played as, their players, each player's career competition by competition, and head-to-head records.

#### What it covers

Clubs, national teams and beach pairs, each under one id whatever name or sponsor it played under, with the players it fielded. Each player has a nationality, date of birth, height and position where known, every team they played for, and a career competition by competition: matches, wins, points, kills, aces and blocks.

#### The endpoints

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Endpoint | What it returns |
|---|---|
| [GET /v1/teams](https://volleyballapi.com/documentation/teams) | Teams and beach pairs, found by name |
| [GET /v1/teams/{id}](https://volleyballapi.com/documentation/team) | One team: its name, kind, federation and players |
| [GET /v1/teams/{id}/matches](https://volleyballapi.com/documentation/team-matches) | A team's matches, newest first |
| [GET /v1/players](https://volleyballapi.com/documentation/players) | Players, found by name |
| [GET /v1/players/{id}](https://volleyballapi.com/documentation/player) | One player, the teams they have played for and their career, competition by competition |
| [GET /v1/head-to-head](https://volleyballapi.com/documentation/head-to-head) | Every meeting of two teams, with the record between them |

#### How the records link

A team leads to [its matches](https://volleyballapi.com/documentation/team-matches) and its players; a player to their teams and career; two teams to [every meeting between them](https://volleyballapi.com/documentation/head-to-head).

#### Find a team

By part of its name, under any name it has played as.

```
# Find a team
curl "https://api.volleyballapi.com/v1/teams?q=Canada" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### A player and their career

Teams and a career entry per competition, newest first.

```
# A player and their career
curl "https://api.volleyballapi.com/v1/players/pl_b4yqer2h" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Two teams' record

Every meeting, newest first, with who won how many. On every paid plan.

```
# Two teams' record
curl "https://api.volleyballapi.com/v1/head-to-head?team_a=tm_7h04r4t8&team_b=tm_gq4s1mva" \
  -H "Authorization: Bearer $VBA_KEY"
```

Page: https://volleyballapi.com/documentation/teams-and-players

### Bulk export

Whole ranges in one call for loading your own database: up to 184 days of matches, 92 of lineups or 14 of rallies at a time.

#### What it covers

For loading a season or a history into your own database without paging: every match between two days with its full record, every lineup, or every rally. One call is one call against your quota, whatever its size. On the Complete plan.

#### The endpoints

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Endpoint | What it returns |
|---|---|
| [GET /v1/export/matches](https://volleyballapi.com/documentation/export-matches) | Every match between two days in one call, with sets, venue, officials and coaches (up to 184 days) |
| [GET /v1/export/lineups](https://volleyballapi.com/documentation/export-lineups) | Every lineup between two days in one call: starting six by zone, players who came on, coaches (up to 92 days) |
| [GET /v1/export/points](https://volleyballapi.com/documentation/export-points) | Every rally of every match between two days in one call (up to 14 days) |

#### How the records link

Exports carry the same ids as every other endpoint, so a match from an export, a page or a live call is the same match.

#### A month of matches

The full match record, sets, venue, referees and coaches, up to 184 days a call.

```
# A month of matches
curl "https://api.volleyballapi.com/v1/export/matches?from=2021-09-24&to=2021-09-24&gender=men" \
  -H "Authorization: Bearer $VBA_KEY"
```

#### Lineups for a range

Up to 92 days a call.

```
# Lineups for a range
curl "https://api.volleyballapi.com/v1/export/lineups?from=2026-11-10&to=2026-11-10" \
  -H "Authorization: Bearer $VBA_KEY"
```

Page: https://volleyballapi.com/documentation/bulk-export

### MCP for AI agents

An MCP server at https://api.volleyballapi.com/mcp. Every endpoint is a tool with the same parameters, plans and limits, so an AI agent can look up scores, rallies, lineups and players in plain conversation.

#### Connecting

The server speaks MCP over HTTP: JSON-RPC messages sent with POST to `https://api.volleyballapi.com/mcp`, each answered on the same request. Send your API key the way the API takes it, in `Authorization: Bearer` or `X-API-Key`. Listing the tools needs no key; calling one does.

```
# Claude Code
claude mcp add --transport http volleyball https://api.volleyballapi.com/mcp \
  --header "Authorization: Bearer vba_your_key"
```

```
# the tools, without a key
curl https://api.volleyballapi.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

```
# one tool, with your key
curl https://api.volleyballapi.com/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $VBA_KEY" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"results_yesterday","arguments":{"per_page":2}}}'
```

#### The tools

22 tools, one an endpoint, named after its page here. Each takes the endpoint's parameters as arguments, and ids in the same `mt_`, `cp_`, `tm_` and `pl_` form.

| Tool | What it returns | Plans |
|---|---|---|
| [usage](https://volleyballapi.com/documentation/usage) | Your plan, your calls today and this month, your limits and the dates you can read | Every plan |
| [live](https://volleyballapi.com/documentation/live) | Every match being played now, with the running set scores | Live and Complete |
| [results_yesterday](https://volleyballapi.com/documentation/results-yesterday) | Yesterday's finished matches | Every plan |
| [matches](https://volleyballapi.com/documentation/matches) | Matches on a day or between two days, filtered by discipline, gender, status, competition or team | Every plan |
| [match_points](https://volleyballapi.com/documentation/match-points) | Every rally of every set: the score after it, who won it and who served | Live, Archive and Complete |
| [match_players](https://volleyballapi.com/documentation/match-players) | Per-player figures for the match: points, serve, reception, attack and block | Archive and Complete |
| [match_lineups](https://volleyballapi.com/documentation/match-lineups) | Starting six by court zone for every set, the players who came on, and both head coaches | Archive and Complete |
| [export_matches](https://volleyballapi.com/documentation/export-matches) | Every match between two days in one call, with sets, venue, officials and coaches (up to 184 days) | Complete |
| [export_lineups](https://volleyballapi.com/documentation/export-lineups) | Every lineup between two days in one call: starting six by zone, players who came on, coaches (up to 92 days) | Complete |
| [export_points](https://volleyballapi.com/documentation/export-points) | Every rally of every match between two days in one call (up to 14 days) | Complete |
| [match](https://volleyballapi.com/documentation/match) | One match: teams, result, every set, duration, venue, spectators and referees | Every plan |
| [competitions](https://volleyballapi.com/documentation/competitions) | Competitions, newest first, filtered by discipline, gender, season or name | Every plan |
| [competition_matches](https://volleyballapi.com/documentation/competition-matches) | A competition's matches | Every plan |
| [competition_standings](https://volleyballapi.com/documentation/competition-standings) | League tables for a competition, one per pool, worked out from its results | Every plan |
| [competition_rosters](https://volleyballapi.com/documentation/competition-rosters) | The players each team registered for a competition: shirt, captain, libero, birth date and height | Every plan |
| [competition](https://volleyballapi.com/documentation/competition) | One competition, with its dates and match count | Every plan |
| [teams](https://volleyballapi.com/documentation/teams) | Teams and beach pairs, found by name | Every plan |
| [team_matches](https://volleyballapi.com/documentation/team-matches) | A team's matches, newest first | Every plan |
| [team](https://volleyballapi.com/documentation/team) | One team: its name, kind, federation and players | Every plan |
| [players](https://volleyballapi.com/documentation/players) | Players, found by name | Every plan |
| [player](https://volleyballapi.com/documentation/player) | One player, the teams they have played for and their career, competition by competition | Every plan |
| [head_to_head](https://volleyballapi.com/documentation/head-to-head) | Every meeting of two teams, with the record between them | Live, Archive and Complete |

#### Answers and limits

A tool answers with the same JSON the endpoint gives, as text. An error from the API comes back as a tool error carrying the API's error object, so the agent can read what to change. Every tool call is one API call: it counts against your plan, its rate limit and its quota exactly as the REST call does.

#### Use with Claude and agents

The agent skill teaches Claude, Cursor and other agents how to use the Volleyball API: getting a key, the calls that answer common questions, the limits and the errors. Pair it with the [MCP server](https://volleyballapi.com/documentation/mcp) so the agent can make the calls itself.

[Download SKILL.md](https://volleyballapi.com/skill.md)

Save it as `~/.claude/skills/volleyballapi/SKILL.md`, or upload it as a skill in Claude's settings. Agents also find it at `/.well-known/agent-skills/index.json`.

Page: https://volleyballapi.com/documentation/mcp

### MCP tools

The MCP server at https://api.volleyballapi.com/mcp has one tool for each endpoint, with the same parameters, plans and limits. A call to a tool is a call to the API.

#### Every tool

22 tools. The dot says which plans answer; the tool answers with the same JSON as the endpoint. How to connect an assistant: [MCP for AI agents](https://volleyballapi.com/documentation/mcp).

Every planEvery paid planLive and CompleteArchive and CompleteComplete

| Tool | What it returns | Arguments | Endpoint |
|---|---|---|---|
| `usage` | Your plan, your calls today and this month, your limits and the dates you can read | - | [GET /v1/usage](https://volleyballapi.com/documentation/usage) |
| `live` | Every match being played now, with the running set scores | `discipline` `gender` | [GET /v1/matches/live](https://volleyballapi.com/documentation/live) |
| `results_yesterday` | Yesterday's finished matches | `discipline` `gender` | [GET /v1/results/yesterday](https://volleyballapi.com/documentation/results-yesterday) |
| `matches` | Matches on a day or between two days, filtered by discipline, gender, status, competition or team | `date` `from` `to` `discipline` `gender` `status` `competition` `team` | [GET /v1/matches](https://volleyballapi.com/documentation/matches) |
| `match_points` | Every rally of every set: the score after it, who won it and who served | `id` | [GET /v1/matches/{id}/points](https://volleyballapi.com/documentation/match-points) |
| `match_players` | Per-player figures for the match: points, serve, reception, attack and block | `id` | [GET /v1/matches/{id}/players](https://volleyballapi.com/documentation/match-players) |
| `match_lineups` | Starting six by court zone for every set, the players who came on, and both head coaches | `id` | [GET /v1/matches/{id}/lineups](https://volleyballapi.com/documentation/match-lineups) |
| `export_matches` | Every match between two days in one call, with sets, venue, officials and coaches (up to 184 days) | `from` `to` `discipline` `gender` | [GET /v1/export/matches](https://volleyballapi.com/documentation/export-matches) |
| `export_lineups` | Every lineup between two days in one call: starting six by zone, players who came on, coaches (up to 92 days) | `from` `to` `gender` | [GET /v1/export/lineups](https://volleyballapi.com/documentation/export-lineups) |
| `export_points` | Every rally of every match between two days in one call (up to 14 days) | `from` `to` `discipline` `gender` | [GET /v1/export/points](https://volleyballapi.com/documentation/export-points) |
| `match` | One match: teams, result, every set, duration, venue, spectators and referees | `id` | [GET /v1/matches/{id}](https://volleyballapi.com/documentation/match) |
| `competitions` | Competitions, newest first, filtered by discipline, gender, season or name | `discipline` `gender` `season` `q` | [GET /v1/competitions](https://volleyballapi.com/documentation/competitions) |
| `competition_matches` | A competition's matches | `id` `status` | [GET /v1/competitions/{id}/matches](https://volleyballapi.com/documentation/competition-matches) |
| `competition_standings` | League tables for a competition, one per pool, worked out from its results | `id` `stage` `pool` | [GET /v1/competitions/{id}/standings](https://volleyballapi.com/documentation/competition-standings) |
| `competition_rosters` | The players each team registered for a competition: shirt, captain, libero, birth date and height | `id` | [GET /v1/competitions/{id}/rosters](https://volleyballapi.com/documentation/competition-rosters) |
| `competition` | One competition, with its dates and match count | `id` | [GET /v1/competitions/{id}](https://volleyballapi.com/documentation/competition) |
| `teams` | Teams and beach pairs, found by name | `q` `discipline` `gender` `country` | [GET /v1/teams](https://volleyballapi.com/documentation/teams) |
| `team_matches` | A team's matches, newest first | `id` `status` | [GET /v1/teams/{id}/matches](https://volleyballapi.com/documentation/team-matches) |
| `team` | One team: its name, kind, federation and players | `id` | [GET /v1/teams/{id}](https://volleyballapi.com/documentation/team) |
| `players` | Players, found by name | `q` `gender` | [GET /v1/players](https://volleyballapi.com/documentation/players) |
| `player` | One player, the teams they have played for and their career, competition by competition | `id` | [GET /v1/players/{id}](https://volleyballapi.com/documentation/player) |
| `head_to_head` | Every meeting of two teams, with the record between them | `team_a` `team_b` | [GET /v1/head-to-head](https://volleyballapi.com/documentation/head-to-head) |

Page: https://volleyballapi.com/documentation/mcp-tools

### Agent skill

A skill is one markdown file an agent reads before it starts. Ours teaches it the Volleyball API: getting a key, the calls that answer common questions, the limits and the errors.

#### Get it

[Download SKILL.md](https://volleyballapi.com/skill.md)

It is always current: it is built from the same list of endpoints as these pages. Agents also find it on their own at `/.well-known/agent-skills/index.json`.

#### Add it

| Agent | Where it goes |
|---|---|
| Claude Code | `~/.claude/skills/volleyballapi/SKILL.md` |
| Claude apps | Settings, then Skills: upload the file |
| Other agents | Wherever the agent reads its skills or instructions from |

#### Pair it with MCP

The skill tells the agent what to ask; the [MCP server](https://volleyballapi.com/documentation/mcp) lets it ask. Both use your key and your plan. The whole API in one file is at [/documentation/manual.md](https://volleyballapi.com/documentation/manual.md).

Page: https://volleyballapi.com/documentation/skill

### Changelog

New endpoints, new data and changes, newest first. Version 1 only ever gains fields: nothing is renamed or removed.

#### Changes

[2026-11-11Pages hold up to 50 rows: a larger per_page is read as 50, never refused; follow next_cursor for more](https://volleyballapi.com/documentation/pagination)[2026-10-27Rosters: /v1/competitions/{id}/rosters gives the players each team registered for an international competition, with shirt, captain, libero, birth date and height](https://volleyballapi.com/documentation/competition-rosters)[2026-10-27Rounds: international indoor matches carry their round (Preliminary Round, Final Round...) as well as their pool, and standings leave knockout rounds out of the tables](https://volleyballapi.com/documentation/competitions-and-standings)[2026-10-27Officials: a new officials field lists each match's officials by role, with their country; referees for over 11,000 international matches, line judges and scorers where they are published](https://volleyballapi.com/documentation/match)[2026-10-23Time zones: every match gains utc_offset and timezone, and league matches now give their real local day and time (they gave the UTC clock before)](https://volleyballapi.com/documentation/results-and-sets)[2026-10-23Rallies: each set says whether its rallies end on the set's score (sets[].complete), and a set recorded with the previous set's running score now starts from 0-0](https://volleyballapi.com/documentation/match-points)[2026-10-23Rally-by-rally data from May 2019, two months earlier: most of the 2019 Nations League](https://volleyballapi.com/documentation/point-by-point)[2026-10-20National league competitions are named after their league, with its season ("Mestaruusliiga 25/26 Naiset, Runkosarja"), and women's leagues read as men's are put right](https://volleyballapi.com/documentation/competitions-and-standings)[2026-10-20Beach matches carry the town they were played in](https://volleyballapi.com/documentation/results-and-sets)[2026-10-19Documentation in two columns, and your key kept from page to page and filled in after sign-up](https://volleyballapi.com/documentation/authentication)[2026-10-19Guides for every part of the data, a quick start, the MCP tools page and this changelog](https://volleyballapi.com/documentation)[2026-10-12Player careers on /v1/players/{id}: matches, wins, points, kills, aces and blocks per competition and team](https://volleyballapi.com/documentation/player)[2026-10-12Standings: /v1/competitions/{id}/standings gives a table for every stage and pool, worked out from the results](https://volleyballapi.com/documentation/competition-standings)[2026-10-12Halls and towns on national league matches](https://volleyballapi.com/documentation/match)[2026-10-12Player figures: a player who was on court and has an empty cell now shows 0, not null](https://volleyballapi.com/documentation/match-players)[2026-10-12The 2004 Olympics and more early internationals, and set scores for early matches that had none](https://volleyballapi.com/documentation/results-and-sets)

Page: https://volleyballapi.com/documentation/changelog

## Errors

`{"error": {"code": "...", "message": "...", "docs": "..."}}`. Every code and when it happens: https://volleyballapi.com/documentation/errors

## About this document

Generated from the endpoint registry, the documentation pages and the plans, never written by hand. The date at the top is the newest of those sources, so a copy with an older date is stale. Machine-readable alternatives: https://volleyballapi.com/openapi.json, the MCP server at https://api.volleyballapi.com/mcp, and the agent skill at https://volleyballapi.com/skill.md.
