The bowling ball catalog,
as an API.
The same normalized catalog behind BowlerDepot Learn: every ball's specs per weight, cover and core, ball motion plotter position and similar-ball suggestions, kept in sync with a cursor-based change feed. Read-only, JSON over HTTPS, built for platforms that need ball data they don't have to maintain.
$ curl -s -H "Authorization: Bearer $BOWLERIQ_KEY" \ https://api.bowleriq.io/partner/v1/balls/ff32beb3-… { "name": "PHAZE II", "brand": { "name": "Storm" }, "coverstock": { "name": "TX-16 Solid", "type": "solid" }, "core": { "name": "Velocity", "type": "symmetric" }, "weights": [ { "weight_lbs": 16, "rg": 2.48, "differential": 0.051 }, … ], "plotter": { "oil": 9.1, "motion": 14.4, "source": "estimated" }, … }
One record per colorway, one shape for every brand.
Twelve manufacturers publish specs twelve different ways. The API gives you one schema, with units and vocabularies normalized, and nulls where a manufacturer hasn't published something.
Identity
Stable UUIDs you can key on. Each colorway is its own ball. status is
current or retired, and retired balls stay in the catalog.
Specs per weight
RG and differential in inches for every weight the manufacturer lists, heaviest first.
mass_bias (intermediate differential) for asymmetric cores.
Cover & core
Material is reactive_resin, urethane or polyester_plastic;
type is solid, pearl or hybrid; cores are symmetric or asymmetric.
Finish
The manufacturer's own finish text, plus a normalized category:
polished, satin or dull.
Ball motion
Where the ball sits on a 16 × 18 oil-versus-motion chart, to 0.1, and whether that came from a manufacturer chart, our model, or a staff correction.
Links & media
A CDN-hosted product photo, the manufacturer's page, and BowlerDepot's review and product pages when they exist.
Five endpoints. That's the whole surface.
Every response is JSON with "api_version": "1". Lists page with
limit (default 200, max 500) and an opaque next_cursor.
| Endpoint | Returns |
|---|---|
| GET/v1/changes | The sync feed. Balls created, changed or unpublished since your last cursor, as upsert or remove. |
| GET/v1/balls | Every published ball, current and retired, paged by id. For a one-time full load. |
| GET/v1/balls/{id} | One ball by id; 404 if it doesn't exist or isn't published. |
| GET/v1/brands | Brands with at least one published ball. |
| GET/v1/plotter | Every current ball's plotter position, plus similar balls from other brands and the nearest step toward more oil, less oil, more angular and smoother. |
Store a cursor. Ask what changed.
You don't re-download the catalog. Call /v1/changes with the cursor you saved last
time, apply each upsert or remove by id, save the new cursor, and repeat
until has_more is false. The first call with no cursor returns everything.
Changes appear about 60 seconds after they happen. A ball counts as changed when its fields, any weight's specs, its images or its review link change, not on every routine refresh. Each page carries a ball once, in its latest state, and re-applying a page is safe.
Every 15–60 minutes is plenty for most platforms.
cursor = load_cursor() # None on the first run while True: page = get("/v1/changes", cursor=cursor) for change in page["items"]: if change["change"] == "upsert": save(change["ball"]) # create or replace by id else: delete(change["id"]) # no longer published cursor = page["next_cursor"] save_cursor(cursor) # after applying the page if not page["has_more"]: break
Every current ball on one comparable chart.
Manufacturers publish motion charts on their own scales, if at all. We place every current ball on a single chart: oil from 1.0 (light) to 16.0 (heavy) and motion from 1.0 (smooth) to 18.0 (angular), to a tenth.
Positions read from a manufacturer's published chart are marked chart; the rest come from
our model of the cover, finish, core and price (estimated), and staff corrections are
manual. /v1/plotter adds the closest equivalents from other brands and the
nearest ball in each direction, which is what powers "what should I try next?" features.
Boring, on purpose.
One key per platform, sent as a bearer token. Keys are issued by us, attributable per partner, and revocable individually. Keep yours server-side.
v1 only grows. We may add optional fields and endpoints, so ignore what you don't
recognise. We will never rename, remove or retype a field, or change its units or meaning, inside
v1. Anything breaking ships as /v2, and v1 keeps running while you migrate. The v1
contract is locked by automated tests.
Platforms that need ball data they don't want to maintain.
Drilling & layout software
RG, differential and mass bias per weight, core type and cover for every ball in a customer's bag.
Pro shops & retail
A clean, current catalog with photos and specs, including the retired balls customers still bring in.
Coaching & arsenal apps
Plotter positions and directional steps to explain gaps in an arsenal and what to try next.
Comparison tools
One normalized schema across twelve brands, so a cross-brand comparison is a query, not a project.
From email to first sync.
Talk to us
Access is by arrangement. Partner keys are issued by BowlerIQ to platforms we work with directly.
Get your key
We issue a key for your platform. Paste it into the reference's Try it to make real calls in the browser.
Load, then sync
Call /v1/changes once to load everything, then on a schedule with your saved cursor.
Everything else is in the reference.
Every endpoint, field and error, with examples in curl, Python, JavaScript and more, generated from the API itself so it's always current.