Skip to content

Be resilient

Calls can fail: you may be calling too fast, the network may drop or Bazoodle may be briefly unavailable. A good tool slows down politely and keeps working. This guide covers retries, listing every game, and a status line.

Status Meaning What to do
200 Success Use the data
400 Your request has a value that is not allowed Fix the request; do not retry unchanged
404 Not found or not public Show “not found”; do not retry
429 Too many requests Wait Retry-After seconds, then try again
5xx or no answer A problem on the way Wait and try again, a little longer each time

A retry helper in Python 3 (standard library only):

import json
import time
import urllib.error
import urllib.request
BASE = "https://bazoodle.com/api/v1"
def get_json(path, tries=4):
delay = 2
for attempt in range(tries):
request = urllib.request.Request(BASE + path, headers={"User-Agent": "MyGameList/1.0 (contact: you@example.com)"})
try:
with urllib.request.urlopen(request, timeout=20) as response:
return json.load(response)
except urllib.error.HTTPError as error:
if error.code in (400, 404):
raise
if error.code == 429:
wait = int(error.headers.get("Retry-After", "60"))
else:
wait = delay
delay *= 2
except urllib.error.URLError:
wait = delay
delay *= 2
if attempt == tries - 1:
raise RuntimeError("giving up after " + str(tries) + " tries")
time.sleep(min(wait, 120))
print(get_json("/catalog/categories")["max_tags_per_game"])

The rules behind it:

  • Obey Retry-After. Retrying sooner only keeps you blocked.
  • Back off. For errors with no Retry-After, wait 2 seconds, then 4, then 8, and give up after a few tries.
  • Never retry a 400 or 404: the answer will not change.
  • Keep what you cached. If the API is not answering, show the last good data instead of nothing.
  • Find out whether it is us. Status says whether Bazoodle has a problem; check it before you tell your users something is broken.

Sometimes you want every game you are allowed to see, for an index or a quiz. This Python loop uses the api helper from the Python guide:

def all_games(**params):
seen = set()
offset = 0
while offset is not None:
page = api("/catalog/browse", limit=50, offset=offset, **params)
for game in page["games"]:
if game["id"] not in seen:
seen.add(game["id"])
yield game
offset = page["next_offset"]
games = list(all_games(sort="new"))
print(len(games), "games")

It asks for 50 games at a time (the largest page), follows next_offset until it is null, and skips a game it has already seen, because lists change while you read them. You can reach at most the first 500 games of a list, so for more use different lists, one for each tag or filter, each with its own first 500:

categories = api("/catalog/categories")
by_tag = {}
for tag in categories["tags"]:
by_tag[tag["id"]] = [g["title"] for g in all_games(tag=tag["id"], sort="top")]
print({tag: len(titles) for tag, titles in by_tag.items()})

A full pass is about ten requests for 500 games, well inside the rate limit. Do it at most a few times a day and save the result, and do not use many addresses to get around the limits.

A small “Bazoodle status” line is easy to build on Status. This JavaScript for Node.js 18 or later turns the answer into one line you can show:

const response = await fetch("https://bazoodle.com/api/v1/status", {
headers: { "User-Agent": "MyGameList/1.0 (contact: you@example.com)" },
});
const status = await response.json();
function describe(s) {
if (s.maintenance.mode !== "off" && s.maintenance.message) {
return `Notice from Bazoodle: ${s.maintenance.message}`;
}
if (s.status === "operational") return "Bazoodle is working normally.";
if (s.status === "maintenance") return "Bazoodle is down for planned work.";
const broken = s.components.filter((c) => c.status !== "ok").map((c) => c.label);
return `Bazoodle is having trouble: ${broken.join(", ")}.`;
}
console.log(describe(status));
console.log("checked", new Date(status.checked_at * 1000).toISOString());

The answer is cached for 30 seconds, so once a minute is plenty for a page; for a plain yes or no from a monitor use /healthz (Small endpoints). Keep the text honest and short, link to https://bazoodle.com/status, and if your own request to the API fails, say “we can’t reach Bazoodle right now” instead of “Bazoodle is down”: the problem may be your network.