Volleyball API
DocumentationLiveCoveragePricingMCPStatusSign inGet a free key

DocumentationMatches

Volleyball point-by-point API

GET/v1/matches/{id}/points

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.

PlansFree keyLiveArchiveComplete
Base URLhttps://api.volleyballapi.com
Answerone object

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.

NameTypeWhat it doesExample
idpathThe match id, in the address. Required.mt_jg5ktpky

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_jg5ktpky/points" \
  -H "Authorization: Bearer $VBA_KEY"

Response

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

200 application/json
{
  "data": {
    "match": "mt_jg5ktpky",
    "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": 1, "b": 2, "won_by": "b", "served_by": "a" },
          { "a": 2, "b": 2, "won_by": "a", "served_by": "b" },
          ...
        ]
      },
      {
        "set": 2,
        "rallies": [
          { "a": 1, "b": 0, "won_by": "a", "served_by": "a" },
          { "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,
        "rallies": [
          { "a": 0, "b": 1, "won_by": "b", "served_by": "b" },
          { "a": 0, "b": 2, "won_by": "b", "served_by": "b" },
          { "a": 1, "b": 2, "won_by": "a", "served_by": "b" },
          { "a": 2, "b": 2, "won_by": "a", "served_by": "a" },
          ...
        ]
      },
      {
        "set": 4,
        "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": 213 }
}

Fields

FieldTypeWhat it holds
matchstringThe match id
setsarrayOne entry a set: set, and rallies in the order played
rallies[].a, rallies[].bintThe score after the rally
rallies[].won_byenuma or b, the side that won it
rallies[].served_byenuma or b, the side that served it
meta.ralliesintRallies in the match

Errors

Errors come back as {"error": {"code", "message", "docs"}}, with plan and pricing added when a plan would answer. Every error.

HTTPCodeWhen
401unauthorizedNo key, or a key that is not known or was revoked
403upgrade_requiredYour plan does not include this endpoint; the answer names the plans that do
404not_foundAn id that does not exist
422unknown_parameterA parameter this endpoint does not take; the answer lists the ones it does
429rate_limitedToo many calls this minute; Retry-After says when to try again
429quota_exceededThe 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.