{
  "openapi": "3.1.0",
  "info": {
    "title": "Kineticist API",
    "version": "1.0.0",
    "description": "The world's most comprehensive pinball game database. Access game data, manufacturers, design credits, editions, images, and more.\n\nAll requests require a Bearer token. Create a free API key at https://www.kineticist.com/settings\n\nAlso available as a CLI (`npx @kineticist/cli pinball random`) and MCP server for AI agents (`@kineticist/mcp-server`).",
    "contact": {
      "name": "Kineticist API Support",
      "email": "api@kineticist.com",
      "url": "https://www.kineticist.com/docs/api"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://www.kineticist.com/docs/api#terms-of-use--attribution"
    }
  },
  "servers": [
    {
      "url": "https://www.kineticist.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Games",
      "description": "Pinball game data — titles, editions, images, credits, tags"
    },
    {
      "name": "Files",
      "description": "ROM files and other downloadable game files"
    },
    {
      "name": "Meta",
      "description": "Database statistics and API health"
    },
    {
      "name": "Me",
      "description": "Per-user actions scoped to the API key owner — log plays, toggle ownership, wishlists, fun scores"
    }
  ],
  "paths": {
    "/api/v1/games": {
      "get": {
        "operationId": "listGames",
        "tags": [
          "Games"
        ],
        "summary": "List games",
        "description": "List pinball games with filtering, sorting, and pagination. Returns core fields and editions_count. Use this to browse the catalog, search by name, or filter by manufacturer and production status.\n\nx-agent-hint: Use this endpoint to find games by manufacturer, year, production status, or name search. Supports fuzzy manufacturer matching — 'stern' will match 'Stern Pinball Inc.'",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Search by game name (fuzzy, 2+ characters). Natural language works — 'that stern game with the dinosaur' will find Godzilla.",
            "schema": {
              "type": "string",
              "minLength": 2
            }
          },
          {
            "name": "manufacturer",
            "in": "query",
            "description": "Filter by manufacturer slug or name. Fuzzy match — 'stern' matches 'stern-pinball-inc'. Only matches game manufacturers, not mod-only companies.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "in_production",
            "in": "query",
            "description": "Filter by production status.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "year_from",
            "in": "query",
            "description": "Filter by minimum manufacture year.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "year_to",
            "in": "query",
            "description": "Filter by maximum manufacture year.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "game_type",
            "in": "query",
            "description": "Filter by game type (e.g. 'solid_state', 'ss', 'em').",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort field. Prefix with '-' for descending. Default: -first_manufacture_year (newest first).",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "-name",
                "first_manufacture_year",
                "-first_manufacture_year",
                "average_fun_score",
                "-average_fun_score",
                "ratings_count",
                "-ratings_count"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of results to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Comma-separated list of fields for sparse responses (e.g. 'name,slug,average_fun_score').",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of games",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GameListResponse"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "gm_fe8989f4-bf09-5e15-80a0-c6012e74398d",
                      "name": "Godzilla",
                      "slug": "godzilla-2021",
                      "first_manufacture_year": 2021,
                      "in_production": false,
                      "game_type": "ss",
                      "display_type": "lcd",
                      "player_count": 4,
                      "average_fun_score": 87,
                      "ratings_count": 342,
                      "featured_image": "https://media.kineticist.com/games/godzilla-2021/featured/...",
                      "manufacturer": {
                        "id": "mfr_c1aee15e-...",
                        "name": "Stern Pinball Inc.",
                        "slug": "stern-pinball-inc"
                      },
                      "editions_count": 4
                    }
                  ],
                  "pagination": {
                    "total": 247,
                    "limit": 25,
                    "offset": 0,
                    "has_more": true
                  },
                  "links": {
                    "self": "/api/v1/games?limit=25&offset=0",
                    "next": "/api/v1/games?limit=25&offset=25"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/{idOrSlug}": {
      "get": {
        "operationId": "getGame",
        "tags": [
          "Games"
        ],
        "summary": "Get a game",
        "description": "Get full details for a single pinball game. Editions (Pro, Premium, LE variants) and tags are always included. Use ?include=credits to also get the design team.\n\nAccepts multiple identifier formats: slug (godzilla-2021), prefixed ID (gm_xxx), raw UUID, OPDB group ID (weeP), or full OPDB machine ID (GweeP-MW95j — resolves to parent game).\n\nx-agent-hint: Use this to get complete game information. You can pass a slug, Kineticist ID, or OPDB ID. If you have an OPDB machine ID for a specific edition, it will resolve to the parent game.",
        "parameters": [
          {
            "name": "idOrSlug",
            "in": "path",
            "required": true,
            "description": "Game identifier. Accepts: slug (godzilla-2021), prefixed ID (gm_xxx), raw UUID, OPDB group ID (weeP), or OPDB machine ID (GweeP-MW95j).",
            "schema": {
              "type": "string"
            },
            "examples": {
              "slug": {
                "value": "godzilla-2021",
                "summary": "By slug"
              },
              "opdb_group": {
                "value": "weeP",
                "summary": "By OPDB group ID"
              },
              "opdb_machine": {
                "value": "GweeP-MW95j",
                "summary": "By OPDB machine ID (resolves to parent game)"
              }
            }
          },
          {
            "name": "include",
            "in": "query",
            "description": "Comma-separated sub-resources to inline. Currently supports: 'credits' (design team). Editions and tags are always included.",
            "schema": {
              "type": "string",
              "enum": [
                "credits"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Game detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GameDetailResponse"
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/{idOrSlug}/credits": {
      "get": {
        "operationId": "getGameCredits",
        "tags": [
          "Games"
        ],
        "summary": "Get design team credits",
        "description": "Get the design team for a game — designer, artist, programmer, mechanical engineer, sound designer, animator, etc.\n\nx-agent-hint: Use this to find who designed, programmed, or did artwork for a specific game. Each credit includes the person's name, slug, and role.",
        "parameters": [
          {
            "name": "idOrSlug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditListResponse"
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/{idOrSlug}/tags": {
      "get": {
        "operationId": "getGameTags",
        "tags": [
          "Games"
        ],
        "summary": "Get game tags",
        "description": "Get tags/categories for a game (e.g. 'Licensed', 'Monsters', 'Party').",
        "parameters": [
          {
            "name": "idOrSlug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of tags",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagListResponse"
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/{idOrSlug}/trims": {
      "get": {
        "operationId": "getGameTrims",
        "tags": [
          "Games"
        ],
        "summary": "Get game editions/trims",
        "description": "Get all editions (Pro, Premium, LE, etc.) for a game. Each edition has its own MSRP, production run, specs, and OPDB cross-reference ID. Note: editions are also always included on game detail responses.",
        "parameters": [
          {
            "name": "idOrSlug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of editions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrimListResponse"
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/random": {
      "get": {
        "operationId": "getRandomGame",
        "tags": [
          "Games"
        ],
        "summary": "Get a random game",
        "description": "Returns a random game with full detail (same shape as getGame). Different game on every request. Great for 'game of the day' features or exploring the catalog.\n\nx-agent-hint: Use this to discover games or when the user asks for a surprise/recommendation.",
        "responses": {
          "200": {
            "description": "Random game detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GameDetailResponse"
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/batch": {
      "get": {
        "operationId": "getGamesBatch",
        "tags": [
          "Games"
        ],
        "summary": "Get multiple games by ID",
        "description": "Get up to 50 games by ID in a single request. Returns full detail for each game. Accepts prefixed (gm_xxx) or raw UUIDs.\n\nx-agent-hint: Use this when you need details for multiple known games. More efficient than individual requests.",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "description": "Comma-separated game IDs (max 50). Accepts prefixed or raw UUIDs.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of game details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/GameDetailResponse"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/{idOrSlug}/files": {
      "get": {
        "operationId": "listGameFiles",
        "tags": [
          "Files"
        ],
        "summary": "List files for a game",
        "description": "List downloadable files (ROMs, etc.) for a specific game. Returns file metadata — use the download endpoint to get a signed URL.\n\nx-agent-hint: Use this to find ROM files for a game. Each file has an id you can pass to the download endpoint.",
        "parameters": [
          {
            "name": "idOrSlug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Game identifier (slug, prefixed ID, raw UUID, or OPDB ID)."
          },
          {
            "name": "format",
            "in": "query",
            "description": "Filter by file format (e.g. 'zip', 'bin', 'txt').",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "description": "Filter by file type.",
            "schema": {
              "type": "string",
              "enum": [
                "rom",
                "parts_list",
                "manual",
                "schematic",
                "instruction_card"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of files",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileListResponse"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "fil_a1b2c3d4-...",
                      "name": "Revision L-5 Game ROM",
                      "file_type": "rom",
                      "format": "zip",
                      "size_bytes": 199384,
                      "download_count": 42,
                      "created_at": "2026-04-04T10:00:00Z"
                    }
                  ],
                  "pagination": {
                    "total": 3,
                    "limit": 25,
                    "offset": 0,
                    "has_more": false
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/games/{idOrSlug}/files/{fileId}": {
      "get": {
        "operationId": "downloadGameFile",
        "tags": [
          "Files"
        ],
        "summary": "Download a game file",
        "description": "Get a signed download URL for a specific file. The URL expires after 5 minutes. Each call increments the file's download counter. The file must belong to the specified game (ownership check).\n\nPass ?redirect=true to get a 302 redirect to the signed URL instead of JSON.\n\nx-agent-hint: Use the file id from listGameFiles. Returns a temporary URL — download promptly.",
        "parameters": [
          {
            "name": "idOrSlug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Game identifier (slug, prefixed ID, raw UUID, or OPDB ID)."
          },
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "File identifier (prefixed fil_xxx or raw UUID)."
          },
          {
            "name": "redirect",
            "in": "query",
            "description": "If 'true', returns a 302 redirect to the download URL instead of JSON.",
            "schema": {
              "type": "string",
              "enum": [
                "true"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Signed download URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileDownloadResponse"
                },
                "example": {
                  "object": "file_download",
                  "id": "fil_a1b2c3d4-...",
                  "data": {
                    "name": "Revision L-5 Game ROM",
                    "format": "zip",
                    "size_bytes": 199384,
                    "download_url": "https://...",
                    "expires_in": 300
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "302": {
            "description": "Redirect to signed download URL (when ?redirect=true)"
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "503": {
            "description": "Download temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/files": {
      "get": {
        "operationId": "listFiles",
        "tags": [
          "Files"
        ],
        "summary": "Browse all files",
        "description": "Browse downloadable files across all games, sorted by download count (most popular first). Filter by file type, format, game slug, or manufacture year range.\n\nx-agent-hint: Use this to discover popular ROM downloads or parts lists across the catalog, or to find files for a specific game by slug.",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "description": "Filter by file format (e.g. 'zip', 'bin', 'txt').",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "description": "Filter by file type.",
            "schema": {
              "type": "string",
              "enum": [
                "rom",
                "parts_list",
                "manual",
                "schematic",
                "instruction_card"
              ]
            }
          },
          {
            "name": "game",
            "in": "query",
            "description": "Filter by game slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "year_from",
            "in": "query",
            "description": "Filter by minimum manufacture year of the game.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "year_to",
            "in": "query",
            "description": "Filter by maximum manufacture year of the game.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of files with game context",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileBrowseListResponse"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "fil_a1b2c3d4-...",
                      "name": "Revision L-5 Game ROM",
                      "file_type": "rom",
                      "format": "zip",
                      "size_bytes": 199384,
                      "download_count": 42,
                      "created_at": "2026-04-04T10:00:00Z",
                      "game": {
                        "id": "gm_...",
                        "name": "The Addams Family",
                        "slug": "the-addams-family",
                        "year": 1992
                      }
                    }
                  ],
                  "pagination": {
                    "total": 1005,
                    "limit": 25,
                    "offset": 0,
                    "has_more": true
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/stats": {
      "get": {
        "operationId": "getStats",
        "tags": [
          "Meta"
        ],
        "summary": "Get database statistics",
        "description": "Get high-level database stats: total games, games in production, total manufacturers, average fun score, most rated game, and newest game. Cached for 1 hour.\n\nx-agent-hint: Use this to get a quick overview of the database size and highlights.",
        "responses": {
          "200": {
            "description": "Database stats",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatsResponse"
                },
                "example": {
                  "object": "stats",
                  "data": {
                    "total_games": 1711,
                    "games_in_production": 38,
                    "total_manufacturers": 201,
                    "total_people": 566,
                    "average_fun_score": 46.8,
                    "most_rated_game": {
                      "id": "gm_aaf85887-...",
                      "name": "Metallica",
                      "slug": "metallica",
                      "ratings_count": 89
                    },
                    "newest_game": {
                      "id": "gm_67e8140b-...",
                      "name": "Pokemon",
                      "slug": "pokemon-2026",
                      "first_manufacture_year": 2026
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/me/state": {
      "get": {
        "operationId": "getMyGameState",
        "tags": [
          "Me"
        ],
        "summary": "Read your state for a game",
        "description": "Return the API key owner's per-game state: ownership flags, wishlist membership, play count, latest play, fun score, favorite flag. Lets an agent verify mutations it made via /api/v1/me/actions.\n\nx-agent-hint: Use this after a POST to /api/v1/me/actions to confirm the write landed.",
        "parameters": [
          {
            "name": "gameId",
            "in": "query",
            "required": true,
            "description": "Internal game UUID (not the prefixed public id). Strip the 'gm_' prefix when calling this endpoint.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "User's per-game state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MyGameState"
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    },
    "/api/v1/me/actions": {
      "post": {
        "operationId": "postMyAction",
        "tags": [
          "Me"
        ],
        "summary": "Perform an engagement action on your own data",
        "description": "Dispatch one of nine engagement actions scoped to the API key owner: log a play, update or delete a play, toggle ownership, toggle wishlist, update ownership details, set or clear fun score, or undo the last play. All actions are subject to per-user rate limits in addition to the API key tier limits.\n\nx-agent-hint: Body shape is `{ \"handler\": \"<name>\", ...fields }`. See descriptions of each handler below.\n\nHandlers:\n- `logPlay` — fields: `gameId` (uuid, required), `playedAt` (ISO date, required, <= today), `dateKnown` (boolean, default true; set false when the user played but doesn't remember when), `locationId` (uuid), `locationText` (string <= 200), `note` (string <= 500), `score` (integer >= 0), `isReplay` (boolean).\n- `updatePlayLog` — fields: `playLogId` (uuid, required), plus same optional fields as logPlay including `dateKnown`.\n- `deletePlayLog` — fields: `playLogId` (uuid, required).\n- `toggleOwnership` — fields: `gameId` (uuid, required), `action` (`own` | `disown`, required), `removalReason` (`sold`|`traded`|`other`), `removedAt` (ISO date).\n- `toggleWant` — fields: `gameId` (uuid, required), `wantType` (`play` | `own`, required).\n- `updateOwnershipDetails` — fields: `gameId` (uuid, required), `purchasePrice`, `purchaseSource`, `tradeDetail`, `trimId`, `salePrice`.\n- `updateFunScore` — fields: `gameId` (uuid, required), `score` (0-100, required).\n- `undoLastPlay` — fields: `gameId` (uuid, required).\n- `deleteFunScore` — fields: `gameId` (uuid, required).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MyActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Action result. `success: true` means the action landed; some mutations also return a message or updated value (e.g. `score` for updateFunScore).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MyActionResponse"
                }
              }
            },
            "headers": {
              "X-RateLimit-Tier": {
                "$ref": "#/components/headers/RateLimitTier"
              },
              "X-RateLimit-Remaining-Day": {
                "$ref": "#/components/headers/RateLimitRemainingDay"
              },
              "X-RateLimit-Remaining-Minute": {
                "$ref": "#/components/headers/RateLimitRemainingMinute"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from https://www.kineticist.com/settings. Format: ki_live_xxx"
      }
    },
    "schemas": {
      "ManufacturerRef": {
        "type": "object",
        "description": "Manufacturer reference inlined on game responses",
        "properties": {
          "id": {
            "type": "string",
            "description": "Prefixed manufacturer ID",
            "example": "mfr_c1aee15e-b23f-5dac-abae-baabffe0d632"
          },
          "name": {
            "type": "string",
            "example": "Stern Pinball Inc."
          },
          "slug": {
            "type": "string",
            "example": "stern-pinball-inc"
          }
        }
      },
      "TagRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "tag_28c88887-f483-526e-ae15-76f58bf96ede"
          },
          "name": {
            "type": "string",
            "example": "Licensed"
          },
          "slug": {
            "type": "string",
            "example": "licensed"
          }
        }
      },
      "Edition": {
        "type": "object",
        "description": "A game edition/trim (Pro, Premium, LE, etc.) with its own pricing, specs, and OPDB cross-reference",
        "properties": {
          "id": {
            "type": "string",
            "description": "Prefixed edition ID",
            "example": "trm_692760a3-fa3e-47bf-ab87-3858615a3140"
          },
          "opdb_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "OPDB machine ID for cross-referencing with opdb.org. Includes G prefix.",
            "example": "GweeP-MW95j"
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "example": "Godzilla (Pro)"
          },
          "trim_level": {
            "type": [
              "string",
              "null"
            ],
            "description": "Edition level: Pro, Premium, LE, etc.",
            "example": "Pro"
          },
          "game_type": {
            "type": [
              "string",
              "null"
            ],
            "example": "Solid State"
          },
          "display_type": {
            "type": [
              "string",
              "null"
            ],
            "example": "LCD"
          },
          "player_count": {
            "type": [
              "integer",
              "null"
            ],
            "example": 4
          },
          "production_run": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Number of units produced (typically only populated for LEs)",
            "example": 1000
          },
          "msrp": {
            "type": [
              "string",
              "null"
            ],
            "description": "Manufacturer's suggested retail price in USD (no currency symbol)",
            "example": "6899"
          },
          "manufacture_date": {
            "type": [
              "string",
              "null"
            ],
            "description": "Date or date range of manufacture",
            "example": "June, 2020"
          },
          "model_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Manufacturer model number",
            "example": "502-5600-00"
          },
          "mpu": {
            "type": [
              "string",
              "null"
            ],
            "description": "MPU/CPU board type",
            "example": "Stern SPIKE 2"
          }
        }
      },
      "Credit": {
        "type": "object",
        "description": "A design credit linking a person to their role on a game",
        "properties": {
          "role": {
            "type": "string",
            "description": "Role on the design team",
            "enum": [
              "design",
              "art",
              "code",
              "mechanics",
              "animation",
              "sound_music",
              "callouts"
            ],
            "example": "design"
          },
          "person": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "example": "prs_eb53ddfb-420b-59a4-b6d3-8a4fb5a52bf4"
              },
              "name": {
                "type": "string",
                "example": "Keith Elwin"
              },
              "slug": {
                "type": "string",
                "example": "keith-elwin"
              }
            }
          }
        }
      },
      "GameListItem": {
        "type": "object",
        "description": "Game summary for list responses. Use the slug or ID to fetch full details.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Prefixed game ID (gm_ + UUID)",
            "example": "gm_fe8989f4-bf09-5e15-80a0-c6012e74398d"
          },
          "name": {
            "type": "string",
            "example": "Godzilla"
          },
          "slug": {
            "type": "string",
            "example": "godzilla-2021"
          },
          "first_manufacture_year": {
            "type": [
              "integer",
              "null"
            ],
            "example": 2021
          },
          "last_manufacture_year": {
            "type": [
              "integer",
              "null"
            ],
            "example": 2021
          },
          "in_production": {
            "type": [
              "boolean",
              "null"
            ],
            "example": false
          },
          "game_type": {
            "type": [
              "string",
              "null"
            ],
            "example": "ss"
          },
          "display_type": {
            "type": [
              "string",
              "null"
            ],
            "example": "lcd"
          },
          "player_count": {
            "type": [
              "integer",
              "null"
            ],
            "example": 4
          },
          "average_fun_score": {
            "type": [
              "number",
              "null"
            ],
            "description": "Community fun score from 0-100, based on ratings on kineticist.com",
            "example": 87
          },
          "ratings_count": {
            "type": "integer",
            "description": "Number of community ratings",
            "example": 342
          },
          "featured_image": {
            "type": [
              "string",
              "null"
            ],
            "description": "URL to the primary game image on media.kineticist.com",
            "format": "uri"
          },
          "manufacturer": {
            "$ref": "#/components/schemas/ManufacturerRef"
          },
          "editions_count": {
            "type": "integer",
            "description": "Number of editions (Pro, Premium, LE, etc.)",
            "example": 4
          }
        }
      },
      "GameDetail": {
        "type": "object",
        "description": "Full game detail including editions, tags, images, and content",
        "allOf": [
          {
            "$ref": "#/components/schemas/GameListItem"
          },
          {
            "type": "object",
            "properties": {
              "opdb_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "OPDB group ID for cross-referencing with opdb.org",
                "example": "weeP"
              },
              "tags": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TagRef"
                }
              },
              "images": {
                "type": "object",
                "description": "Game image galleries served from media.kineticist.com CDN",
                "properties": {
                  "flyers": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "tutorial": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "other": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "HTML description of the game"
              },
              "full_tutorial_link": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "URL to full tutorial article",
                "format": "uri"
              },
              "game_rules_link": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "URL to rules/rulesheet (typically Tilt Forums)",
                "format": "uri"
              },
              "editions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Edition"
                }
              },
              "credits": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Credit"
                },
                "description": "Only included when ?include=credits is set"
              }
            }
          }
        ]
      },
      "GameListResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GameListItem"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "links": {
            "$ref": "#/components/schemas/PaginationLinks"
          }
        }
      },
      "GameDetailResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "game"
          },
          "id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/GameDetail"
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "trims": {
                "type": "string"
              },
              "credits": {
                "type": "string"
              },
              "tags": {
                "type": "string"
              },
              "web": {
                "type": "string",
                "description": "URL to this game on kineticist.com"
              }
            }
          }
        }
      },
      "CreditListResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Credit"
            }
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "game": {
                "type": "string"
              }
            }
          }
        }
      },
      "TagListResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagRef"
            }
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "game": {
                "type": "string"
              }
            }
          }
        }
      },
      "TrimListResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Edition"
            }
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "game": {
                "type": "string"
              }
            }
          }
        }
      },
      "StatsResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "stats"
          },
          "data": {
            "type": "object",
            "properties": {
              "total_games": {
                "type": "integer"
              },
              "games_in_production": {
                "type": "integer"
              },
              "total_manufacturers": {
                "type": "integer"
              },
              "total_people": {
                "type": "integer"
              },
              "average_fun_score": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "most_rated_game": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "ratings_count": {
                    "type": "integer"
                  }
                }
              },
              "newest_game": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "first_manufacture_year": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      },
      "MyGameState": {
        "type": "object",
        "description": "Per-user state for a single game",
        "properties": {
          "isOwned": {
            "type": "boolean"
          },
          "wasPreviouslyOwned": {
            "type": "boolean"
          },
          "wantToPlay": {
            "type": "boolean"
          },
          "wantToOwn": {
            "type": "boolean"
          },
          "isFavorited": {
            "type": "boolean"
          },
          "playCount": {
            "type": "integer"
          },
          "latestPlayDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "latestPlayLocation": {
            "type": [
              "string",
              "null"
            ]
          },
          "funScore": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "funScoreDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ownershipDetails": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "purchasePrice": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "purchaseSource": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "tradeDetail": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "trimId": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "trimName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "salePrice": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "acquiredAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date"
              },
              "removedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date"
              },
              "removalReason": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  null,
                  "sold",
                  "traded",
                  "other"
                ]
              }
            }
          }
        }
      },
      "MyActionRequest": {
        "type": "object",
        "description": "Engagement action envelope. Required fields vary by handler — see the POST /api/v1/me/actions description.",
        "required": [
          "handler"
        ],
        "properties": {
          "handler": {
            "type": "string",
            "enum": [
              "logPlay",
              "updatePlayLog",
              "deletePlayLog",
              "toggleOwnership",
              "toggleWant",
              "updateOwnershipDetails",
              "updateFunScore",
              "undoLastPlay",
              "deleteFunScore"
            ]
          },
          "gameId": {
            "type": "string",
            "format": "uuid"
          },
          "playLogId": {
            "type": "string",
            "format": "uuid"
          },
          "playedAt": {
            "type": "string",
            "format": "date"
          },
          "dateKnown": {
            "type": "boolean",
            "default": true
          },
          "locationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "locationText": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500
          },
          "score": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "isReplay": {
            "type": "boolean"
          },
          "action": {
            "type": "string",
            "enum": [
              "own",
              "disown"
            ]
          },
          "removalReason": {
            "type": "string",
            "enum": [
              "sold",
              "traded",
              "other"
            ]
          },
          "removedAt": {
            "type": "string",
            "format": "date"
          },
          "wantType": {
            "type": "string",
            "enum": [
              "play",
              "own"
            ]
          },
          "purchasePrice": {
            "type": "number"
          },
          "purchaseSource": {
            "type": "string"
          },
          "tradeDetail": {
            "type": "string"
          },
          "trimId": {
            "type": "string",
            "format": "uuid"
          },
          "salePrice": {
            "type": "number"
          }
        }
      },
      "MyActionResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "score": {
            "type": "integer",
            "description": "Returned by updateFunScore — confirms the persisted score"
          }
        },
        "required": [
          "success"
        ]
      },
      "GameFile": {
        "type": "object",
        "description": "A downloadable file associated with a game",
        "properties": {
          "id": {
            "type": "string",
            "description": "Prefixed file ID",
            "example": "fil_a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "name": {
            "type": "string",
            "example": "Service Manual"
          },
          "file_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "File category",
            "enum": [
              "rom",
              "parts_list",
              "manual",
              "schematic",
              "instruction_card"
            ],
            "example": "manual"
          },
          "format": {
            "type": [
              "string",
              "null"
            ],
            "description": "File format (e.g. 'zip', 'bin', 'pdf')",
            "example": "pdf"
          },
          "size_bytes": {
            "type": [
              "integer",
              "null"
            ],
            "description": "File size in bytes",
            "example": 5971968
          },
          "download_count": {
            "type": "integer",
            "description": "Total downloads",
            "example": 42
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISO 639-1 language code. Null for English.",
            "example": null
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "GameFileWithGame": {
        "allOf": [
          {
            "$ref": "#/components/schemas/GameFile"
          },
          {
            "type": "object",
            "properties": {
              "game": {
                "type": "object",
                "description": "Parent game reference",
                "properties": {
                  "id": {
                    "type": "string",
                    "example": "gm_550e8400-e29b-..."
                  },
                  "name": {
                    "type": "string",
                    "example": "The Addams Family"
                  },
                  "slug": {
                    "type": "string",
                    "example": "the-addams-family"
                  },
                  "year": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "example": 1992
                  }
                }
              }
            }
          }
        ]
      },
      "FileListResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GameFile"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "links": {
            "$ref": "#/components/schemas/PaginationLinks"
          }
        }
      },
      "FileBrowseListResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GameFileWithGame"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "links": {
            "$ref": "#/components/schemas/PaginationLinks"
          }
        }
      },
      "FileDownloadResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "file_download"
          },
          "id": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "format": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "size_bytes": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "download_url": {
                "type": "string",
                "format": "uri",
                "description": "Signed download URL — expires after 5 minutes"
              },
              "expires_in": {
                "type": "integer",
                "description": "URL expiry in seconds",
                "example": 300
              }
            }
          }
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          }
        }
      },
      "PaginationLinks": {
        "type": "object",
        "properties": {
          "self": {
            "type": "string"
          },
          "next": {
            "type": "string"
          }
        }
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "rate_limit_error",
                  "not_found_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Pinball-themed hint for developers"
              },
              "param": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "doc_url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    },
    "responses": {
      "AuthError": {
        "description": "Authentication failed — missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "error": {
                "type": "authentication_error",
                "code": "missing_api_key",
                "message": "Missing API key. Include it as: Authorization: Bearer ki_live_...",
                "hint": "Insert coin to continue.",
                "doc_url": "https://www.kineticist.com/docs/api/errors#missing_api_key"
              }
            }
          }
        }
      },
      "NotFoundError": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "error": {
                "type": "not_found_error",
                "code": "not_found",
                "message": "The requested game was not found.",
                "hint": "Ball drained. That resource doesn't exist.",
                "doc_url": "https://www.kineticist.com/docs/api/errors#not_found"
              }
            }
          }
        }
      },
      "ValidationError": {
        "description": "Invalid request parameters",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "invalid_parameter",
                "message": "The 'limit' parameter must be between 1 and 100.",
                "hint": "Nudge detected. Check your parameters.",
                "param": "limit",
                "doc_url": "https://www.kineticist.com/docs/api/errors#invalid_parameter"
              }
            }
          }
        }
      },
      "RateLimitError": {
        "description": "Rate limit exceeded. Limits vary by tier: free (60/min, 1,000/day), builder (120/min, 5,000/day), partner (200/min, 25,000/day). Check X-RateLimit-Tier and X-RateLimit-Remaining-* response headers.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "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"
              }
            }
          }
        },
        "headers": {
          "X-RateLimit-Tier": {
            "$ref": "#/components/headers/RateLimitTier"
          },
          "X-RateLimit-Remaining-Day": {
            "$ref": "#/components/headers/RateLimitRemainingDay"
          },
          "X-RateLimit-Remaining-Minute": {
            "$ref": "#/components/headers/RateLimitRemainingMinute"
          }
        }
      }
    },
    "headers": {
      "RateLimitTier": {
        "description": "Tier of the API key that authorized this request — 'free', 'builder', or 'partner'. Drives the rate-limit ceiling on X-RateLimit-Remaining-*.",
        "schema": {
          "type": "string",
          "enum": [
            "free",
            "builder",
            "partner"
          ]
        },
        "example": "free"
      },
      "RateLimitRemainingDay": {
        "description": "Remaining requests for the current calendar day at the key's tier. Resets at 00:00 UTC.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 987
      },
      "RateLimitRemainingMinute": {
        "description": "Remaining requests for the current rolling minute window at the key's tier.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 58
      }
    }
  }
}
