Skip to content

Developer API

Early Access

Kineticist API

REST API, command-line tool, and MCP server for AI agents. 1,700+ games with edition pricing, design team credits, images, OPDB cross-references, and community ratings.

Quick Start

  1. 1. Sign in to your Kineticist account (or create one)
  2. 2. Go to Settings and create an API key
  3. 3. Make your first request:
curl -H "Authorization: Bearer ki_live_YOUR_KEY" \
  https://www.kineticist.com/api/v1/games/random

For interactive try-it-out docs, see the API Reference. Download the OpenAPI spec.


Authentication

All requests require an API key sent as a Bearer token in the Authorization header:

Authorization: Bearer ki_live_Ri5EsH...axTM

Keys are free. You can create up to 3 active keys in Settings.


Tiers & Rate Limits

Every key belongs to one of three tiers. All tiers are free during early access — the tier labels just set the ceiling. New keys start on free.

TierBurst (per second)Per minutePer day
free10601,000
builder201205,000
partner3020025,000

Daily limits reset at midnight UTC. Every response includes rate limit headers: X-RateLimit-Tier, X-RateLimit-Remaining-Day, X-RateLimit-Remaining-Minute, and X-RateLimit-Reset.

Need a higher ceiling? Email colin@kineticist.com with a short note about what you're building. Upgrades are free during early access.


Endpoints

Read endpoints return public game data. Write endpoints act on the API key owner's own library (play logs, ownership, wishlist, fun scores).

Read

GET

/api/v1/games

List games with filtering, sorting, and pagination

GET

/api/v1/games/:id_or_slug

Get a game by slug, UUID, or OPDB ID. Editions always included.

GET

/api/v1/games/:id_or_slug/credits

Design team credits

GET

/api/v1/games/:id_or_slug/tags

Game tags

GET

/api/v1/games/:id_or_slug/trims

Editions/trims (also on detail)

GET

/api/v1/games/random

Random game with full detail

GET

/api/v1/games/batch?ids=...

Up to 50 games by ID

GET

/api/v1/games/:id_or_slug/files

List downloadable files (ROMs) for a game

GET

/api/v1/games/:id_or_slug/files/:file_id/download

Get a signed download URL for a file

GET

/api/v1/files

Browse all files across all games

GET

/api/v1/stats

Database statistics

Your library

GET

/api/v1/me/state?gameId=:uuid

Read your state for one game: ownership, wishlist, plays, fun score, favorite

POST

/api/v1/me/actions

Log plays, toggle ownership, toggle wishlist, set fun score, undo last play, and more — see Your Library below

Full request/response examples for every endpoint in the interactive API reference.

Games & Editions

Pinball games often ship in multiple editions — Pro, Premium, LE, etc. In the Kineticist database, a game is the parent title (e.g. "Godzilla") and editions are the variants (Pro, Premium, LE, 70th Anniversary). Each edition has its own MSRP, production run, and specs.

Editions are always included on game detail responses — no extra request needed. Pricing lives on editions, not on the game itself. List responses include an editions_count field so you can see at a glance which games have multiple variants. Where available, editions also include manufacture_date, model_number, and mpu (CPU board type).

There are no separate pages for editions. If someone searches for "Godzilla Premium", direct them to the parent game (/api/v1/games/godzilla-2021) and find the Premium edition in the editions array.


Filtering & Sorting

The /api/v1/games endpoint supports these query parameters:

ParameterDescription
manufacturerFilter by manufacturer slug or name (fuzzy match, e.g. stern). Only matches game manufacturers, not mod-only companies.
in_productiontrue or false
year_from / year_toFilter by manufacture year range
game_typeFilter by type (e.g. solid_state)
qText search by game name (fuzzy, 2+ characters)
sortSort field. Prefix with - for descending. Options: name, first_manufacture_year, average_fun_score, ratings_count
limitResults per page (1-100, default 25)
offsetSkip N results (max 10,000)
fieldsComma-separated fields for sparse responses (e.g. name,slug,average_fun_score)
includeInline optional sub-resources on detail: credits (editions and tags are always included)

Response Format

Game Detail

{
  "object": "game",
  "id": "gm_44587386-0321-5463-89a6-0df400c1c7d4",
  "data": {
    "name": "Godzilla",
    "slug": "godzilla-2021",
    "first_manufacture_year": 2021,
    "in_production": true,
    "average_fun_score": 89,
    "ratings_count": 81,
    "manufacturer": { "id": "mfr_...", "name": "Stern Pinball Inc.", "slug": "stern-pinball-inc" },
    "editions_count": 4,
    "editions": [
      { "id": "trm_...", "name": "Godzilla (Pro)", "trim_level": "Pro", "msrp": "6899", ... }
    ],
    "tags": [ { "id": "tag_...", "name": "Licensed", "slug": "licensed" } ],
    "images": { "flyers": [...], "tutorial": [...], "other": [...] }
  },
  "links": {
    "self": "/api/v1/games/godzilla-2021",
    "credits": "/api/v1/games/godzilla-2021/credits",
    "web": "https://www.kineticist.com/games/pinball/godzilla-2021"
  }
}

List responses return the same fields minus editions, tags, and images, but include editions_count and pagination links.

Errors

{
  "error": {
    "type": "rate_limit_error",
    "code": "daily_limit_exceeded",
    "message": "Daily request limit of 1,000 exceeded. Resets at midnight UTC.",
    "hint": "You're tilting! Step away from the machine and come back tomorrow.",
    "doc_url": "https://www.kineticist.com/docs/api/errors#daily_limit_exceeded"
  }
}

Error types: invalid_request_error, authentication_error, rate_limit_error, not_found_error, api_error


Object IDs

All IDs are type-prefixed UUIDs. You can pass either the prefixed or raw UUID — both work. Responses always include the prefix.

TypePrefixExample
Gamegm_gm_550e8400-e29b-...
Manufacturermfr_mfr_7c9e6679-...
Personprs_prs_a1b2c3d4-...
Tagtag_tag_f2a3b4c5-...
Editiontrm_trm_e0f1a2b3-...
Filefil_fil_d4e5f6a7-...

Example Queries

Stern games currently in production

GET /api/v1/games?manufacturer=stern&in_production=true

Highest rated games of the 90s

GET /api/v1/games?year_from=1990&year_to=1999&sort=-average_fun_score

Search for a game

GET /api/v1/games?q=medieval+madness

Get a random game with full details

GET /api/v1/games/random

Get a game with design credits in one call

GET /api/v1/games/medieval-madness?include=credits

Look up a game by OPDB ID

GET /api/v1/games/GweeP-MW95j

Works with both OPDB group IDs (weeP) and full machine IDs (GweeP-MW95j). Machine IDs resolve to the parent game.


Files

ROMs, service manuals, schematics, parts lists, and instruction cards. List files for a specific game, browse all files across the catalog, or get a signed download URL. Downloads require authentication. Signed URLs expire after 5 minutes.

List files for a game

GET /api/v1/games/the-addams-family/files

Filter by format (zip, bin, pdf, txt) or file_type (rom, parts_list, manual, schematic, instruction_card). Supports standard limit/offset pagination.

Download a file

GET /api/v1/games/the-addams-family/files/fil_xxx/download
{
  "object": "file_download",
  "id": "fil_a1b2c3d4-...",
  "data": {
    "name": "Revision L-5 Game ROM",
    "format": "zip",
    "size_bytes": 199384,
    "download_url": "https://...",
    "expires_in": 300
  }
}

Pass ?redirect=true for a 302 redirect to the download URL instead of JSON — useful for direct browser downloads.

Browse all files

GET /api/v1/files?game=medieval-madness&format=zip

Sorted by download count (most popular first). Each file includes a nested game object with the parent game's name, slug, and year. Filter by game (slug), format, file_type, year_from, and year_to.


Your Library

Read and write the API key owner's own game data — play logs, ownership, wishlist, fun scores, favorites. The CLI and MCP server wrap these same endpoints.

Read your state for a game

GET /api/v1/me/state?gameId=44587386-0321-5463-89a6-0df400c1c7d4
{
  "gameId": "44587386-0321-5463-89a6-0df400c1c7d4",
  "owned": true,
  "wantToPlay": false,
  "wantToOwn": false,
  "favorite": true,
  "playCount": 12,
  "latestPlayAt": "2026-04-12",
  "funScore": 87
}

Pass the raw UUID (without the gm_ prefix). Agents typically call this after a write to verify the mutation landed.

Write actions

All writes go through one endpoint. Pick a handler and send its fields in the same JSON body.

POST /api/v1/me/actions
{
  "handler": "logPlay",
  "gameId": "44587386-0321-5463-89a6-0df400c1c7d4",
  "playedAt": "2026-04-17",
  "locationText": "Pin Museum",
  "note": "cleared wizard mode",
  "score": 2350000
}
HandlerFields
logPlaygameId, playedAt (ISO date), dateKnown (false if you played but don't remember when), locationId, locationText, note, score, isReplay
updatePlayLogplayLogId, plus the same optional fields as logPlay
deletePlayLogplayLogId
undoLastPlaygameId — removes your most recent play for that game
toggleOwnershipgameId, action (own | disown), removalReason, removedAt
updateOwnershipDetailsgameId, purchasePrice, purchaseSource, tradeDetail, trimId, salePrice
toggleWantgameId, wantType (play | own)
updateFunScoregameId, score (0–100)
deleteFunScoregameId

Writes are available on every tier. They count against the same daily quota as reads, so heavy batch imports will burn through a free key quickly — email colin@kineticist.com if you need a higher ceiling.


CLI

Query the Kineticist database and track your own games from your terminal. Zero dependencies.

$ export KINETICIST_API_KEY=ki_live_...

# read
$ pinball random
$ pinball search "medieval madness"
$ pinball get godzilla-2021
$ pinball list -m stern -p
$ pinball credits godzilla-2021
$ pinball stats

# track your games
$ pinball play godzilla-2021 --location "Pin Museum"
$ pinball own godzilla-2021
$ pinball want godzilla-2021 play
$ pinball rate godzilla-2021 87
$ pinball state godzilla-2021
$ pinball undo godzilla-2021

Read commands

CommandDescription
randomRandom game with full details and credits
get <slug|opdb_id>Full game details by slug or OPDB ID
search <query>Search for games by name
list [options]List with filters: -m manufacturer, -p in production, --from/--to year, -s sort
credits <slug>Design team credits
statsDatabase statistics

Track your games

CommandDescription
play <slug> [flags]Log a play. Flags: --date YYYY-MM-DD, --unknown, --location, --note, --score, --replay
own <slug> [--remove]Mark as owned or no longer owned. With --remove: --reason sold|traded|other, --removed-at
want <slug> play|ownToggle want-to-play or want-to-own
rate <slug> <1-100>Set your fun score
undo <slug>Remove your most recent play
state <slug>Show your state for a game (ownership, wishlist, plays, fun score)

Install globally:

npm install -g @kineticist/cli

MCP Server (AI Agents)

Connect the Kineticist database to AI agents like Claude, ChatGPT, Cursor, and other tools that support the Model Context Protocol. The MCP server exposes 11 tools — 5 for reading the public database and 6 for acting on the key owner's own library.

Read tools

ToolDescription
search_pinball_gamesSearch and filter games with natural language
get_game_detailsFull game info with editions, images, and description
get_game_creditsDesign team for a game
get_random_gameRandom game for discovery
get_pinball_statsDatabase statistics

Your library tools

ToolDescription
kineticist_get_my_stateRead your state for a game: ownership, wishlist, plays, fun score, favorite
kineticist_log_playLog a play with optional date, location, note, score, replay flag
kineticist_toggle_ownershipMark as owned or no longer owned
kineticist_toggle_wantToggle want-to-play or want-to-own
kineticist_set_fun_scoreSet the key owner's fun score (0–100)
kineticist_undo_last_playRemove the most recent play for a game

Add to Claude Code / Cursor

// claude_desktop_config.json or .cursor/mcp.json { "mcpServers": { "kineticist": { "command": "npx", "args": ["@kineticist/mcp-server"], "env": { "KINETICIST_API_KEY": "ki_live_YOUR_KEY" } } } }

Once configured, your AI agent can answer questions like "What Stern games are in production?" or "Who designed Medieval Madness?" using live Kineticist data.


Images

Image URLs returned by the API (e.g. image_url, editions[].image_url) point directly to media.kineticist.com and can be hotlinked, embedded, or displayed in your application.

For heavy usage, we recommend caching images locally or behind your own CDN to keep your app fast and avoid unnecessary bandwidth on both sides.


Terms of Use & Attribution

By using the Kineticist API you agree to the following:

Attribution Required

Any application, website, or service that displays Kineticist data to end users must include visible attribution with a link back to kineticist.com. Use one of these formats:

Data provided by Kineticist
Powered by the Kineticist API

Attribution must be visible on every page or screen that displays Kineticist data. Footer placement is fine. Hidden or invisible attribution does not count.

Permitted Uses

  • - Building apps, tools, or websites that reference pinball game data
  • - Tournament software, collection trackers, and community tools
  • - Editorial and journalistic use with attribution
  • - Academic research and personal projects

Don't scrape the full database to build a competing product or strip the attribution link. We reserve the right to revoke keys that violate these terms.


Free during early access.

Get Your API Key

Feedback? Let Colin know.