All systems normalData updated just nowStatusChangelogSupport
badmintonapi

Responses

Every answer is JSON, sent as application/json; charset=utf-8, and has one of exactly two shapes. When the call works you get data and meta; when it does not you get error. There is no third shape, no XML and no HTML error page, so one small function can read every answer the API gives.

When it works

data is what you asked for: an object for one thing (a player, a match, a tournament) and a list for many (results, a draw, a ranking). meta describes the answer: how many items came back, which page you are on, and notes you should know about.

A list, with meta
{
  "data": [
    { "id": "ev_q63vfven", "status": "finished", "winner": 1,
      "games": [[21, 17], [18, 21], [21, 15]] }
  ],
  "meta": {
    "count": 1, "page": 1, "per_page": 50,
    "total": 1, "total_pages": 1, "next_cursor": null
  }
}

When it does not

A failure has a status code that says what kind, and an error object. code is a single word that never changes, so match on it in your code. message is written for a person and may be reworded, so show it but do not test it. docs links to the page that explains the endpoint. Some errors add more: plan on an upgrade, allowed on an unknown parameter, resets_at when the day's calls are used.

An error
{
  "error": {
    "code": "unknown_parameter",
    "message": "\"yeer\" is not a parameter of this endpoint.",
    "allowed": ["year", "discipline", "page", "per_page", "cursor"],
    "docs": "https://badmintonapi.com/documentation"
  }
}

One function for both

Python
def read(r):
    body = r.json()
    if "error" in body:
        e = body["error"]
        raise RuntimeError(f"{r.status_code} {e['code']}: {e['message']}")
    if body["meta"].get("note"):
        print("note:", body["meta"]["note"])
    return body["data"]
JavaScript
async function read(r) {
  const body = await r.json();
  if (body.error) {
    throw new Error(`${r.status} ${body.error.code}: ${body.error.message}`);
  }
  if (body.meta.note) console.warn(body.meta.note);
  return body.data;
}

Fields you can rely on

Every field an endpoint lists is always present. A value that is not known is null, never left out, so player["hand"] never raises a missing-key error. A field your plan does not include is also null, and meta.note names the plan that has it (see Plans and fields). Times are UTC in ISO 8601 and days are YYYY-MM-DD (see Dates and times). Scores are lists of games, each game a pair of points from side 1's side: [[21, 17], [18, 21]]. Answers are never cached by us between calls, so each one reflects the archive at that moment.

Status codes and browsers

A call that works answers 200, even when the list it asked for is empty: an empty data list with meta.count of 0 means there was nothing to find, not that something went wrong. Every other status is a failure with the error shape above. The API sends the headers browsers need for calls from a web page on another site, so fetch from your own front end works without a proxy, but remember that a key in a public page can be read by anyone who opens it: call from your server when the page is public.