openapi: 3.0.3
info:
  title: Mini Game Arcade API
  description: "A public browser-game arcade with playable mini games, local-only scores, game metadata, API/MCP discovery, RSS, sitemap, and public-safe automation hooks.\n\nPublic-safe reads are open by default. PLATPHORM_API_KEY support is scaffolded for future protected backend actions such as global leaderboard persistence, event ingestion, webhook operations, sync, test-triggering, reporting, and administrative actions."
  version: 2.0.0
  contact:
    name: Michael Barbine
    email: Michael@Barbineworldwide.com
    url: "https://github.com/mbarbine"
servers:
  - url: "https://games.platphormnews.com"
    description: Production
security:
[]
tags:
  - name: System
    description: "Health, docs, and route compliance"
  - name: Games
    description: Canonical game catalog and metadata
  - name: Local Scores
    description: "Browser-local score schema and policy"
  - name: Automation
    description: "Public-safe events and future protected webhooks"
  - name: Discovery
    description: "Network, sitemap, feed, llms, and MCP discovery"
  - name: MCP
    description: "JSON-RPC 2.0 MCP introspection and bounded tools"
paths:
  /api/health:
    get:
      operationId: getHealth
      summary: Health check
      tags:
        - System
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HealthResponse"
  /api/v1/health:
    get:
      operationId: getHealth
      summary: Health check
      tags:
        - System
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HealthResponse"
  /api/docs:
    get:
      operationId: getApiDocs
      summary: OpenAPI JSON document
      tags:
        - Discovery
      responses:
        200:
          description: OpenAPI JSON document
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /openapi.json:
    get:
      operationId: getOpenApiJson
      summary: OpenAPI JSON document
      tags:
        - Discovery
      responses:
        200:
          description: OpenAPI JSON document
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /openapi.yaml:
    get:
      operationId: getOpenApiYaml
      summary: OpenAPI YAML document
      tags:
        - Discovery
      responses:
        200:
          description: OpenAPI YAML document
          content:
            text/yaml:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/games:
    get:
      operationId: listGames
      summary: List games
      description: "Returns 23 canonical public browser games with generated category counts, playable state, instructions, controls, accessibility notes, and local-score metadata."
      tags:
        - Games
      parameters:
        - name: category
          in: query
          schema:
            type: string
            enum:
              - Arcade
              - Puzzle
              - Strategy
              - Action
          description: Filter by category.
        - name: search
          in: query
          schema:
            type: string
          description: "Search title, description, keywords, instructions, and aliases."
        - name: page
          in: query
          schema:
            type: integer
            default: 1
            minimum: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 50
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GamesListResponse"
  /api/v1/games/{slug}:
    get:
      operationId: getGame
      summary: Get game metadata
      tags:
        - Games
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
        404:
          description: Game not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/v1/games/{slug}/metadata:
    get:
      operationId: getGameMetadata
      summary: Get detailed game metadata
      tags:
        - Games
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
        404:
          description: Game not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/v1/games/{slug}/events:
    get:
      operationId: getGameEvents
      summary: "Get public-safe events for a game"
      tags:
        - Automation
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
        404:
          description: Game not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/v1/games/{slug}/scores/local-schema:
    get:
      operationId: getLocalScoreSchema
      summary: Get local browser score schema for a game
      tags:
        - Local Scores
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
        404:
          description: Game not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/v1/categories:
    get:
      operationId: listCategories
      summary: List game categories and counts
      tags:
        - Games
      responses:
        200:
          description: List game categories and counts
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/leaderboard/local-info:
    get:
      operationId: getLocalLeaderboardInfo
      summary: "Explain local-only leaderboard policy"
      tags:
        - Local Scores
      responses:
        200:
          description: "Explain local-only leaderboard policy"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/faq:
    get:
      operationId: listFaq
      summary: List FAQ entries
      tags:
        - Discovery
      responses:
        200:
          description: List FAQ entries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/events:
    get:
      operationId: getEvents
      summary: "List public-safe ephemeral events"
      tags:
        - Automation
      responses:
        200:
          description: "List public-safe ephemeral events"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/events:
    get:
      operationId: getVersionedEvents
      summary: "List public-safe ephemeral events"
      tags:
        - Automation
      responses:
        200:
          description: "List public-safe ephemeral events"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/webhooks:
    post:
      operationId: receiveWebhook
      summary: "Receive public-safe webhook event"
      description: "Phase 1 accepts bounded public-safe webhook payloads into an ephemeral in-memory store unless PLATPHORM_REQUIRE_API_KEY=true. Future protected enforcement uses PLATPHORM_API_KEY."
      tags:
        - Automation
      security:
        - PlatPhormApiKey:
[]
        - PlatPhormBearer:
[]
      parameters:
        - name: "x-webhook-id"
          in: header
          schema:
            type: string
          description: Optional idempotency key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/webhooks:
    post:
      operationId: receiveWebhook
      summary: "Receive public-safe webhook event"
      description: "Phase 1 accepts bounded public-safe webhook payloads into an ephemeral in-memory store unless PLATPHORM_REQUIRE_API_KEY=true. Future protected enforcement uses PLATPHORM_API_KEY."
      tags:
        - Automation
      security:
        - PlatPhormApiKey:
[]
        - PlatPhormBearer:
[]
      parameters:
        - name: "x-webhook-id"
          in: header
          schema:
            type: string
          description: Optional idempotency key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/webhooks/status:
    get:
      operationId: getWebhookStatus
      summary: Webhook/event storage status
      tags:
        - Automation
      responses:
        200:
          description: Webhook/event storage status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /network.json:
    get:
      operationId: getNetworkManifest
      summary: PlatPhorm network manifest
      tags:
        - Discovery
      responses:
        200:
          description: PlatPhorm network manifest
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/network:
    get:
      operationId: getVersionedNetworkManifest
      summary: PlatPhorm network manifest
      tags:
        - Discovery
      responses:
        200:
          description: PlatPhorm network manifest
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/route-compliance:
    get:
      operationId: getRouteCompliance
      summary: Route compliance summary
      tags:
        - System
      responses:
        200:
          description: Route compliance summary
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/v1/discovery-compliance:
    get:
      operationId: getDiscoveryCompliance
      summary: Discovery compliance summary
      tags:
        - Discovery
      responses:
        200:
          description: Discovery compliance summary
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
  /api/mcp:
    get:
      operationId: getMcpMetadata
      summary: MCP metadata and usage
      tags:
        - MCP
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
    post:
      operationId: mcpJsonRpc
      summary: "MCP JSON-RPC 2.0 endpoint"
      description: "Accepts JSON-RPC 2.0 object or batch. Public read-only introspection works without PLATPHORM_API_KEY."
      tags:
        - MCP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        200:
          description: "JSON-RPC response"
          content:
            application/json:
              schema:
                type: object
  /api/cron/refresh:
    get:
      operationId: refreshArcadeMetadata
      summary: Bounded refresh and validation
      description: "Cron-safe refresh scaffold for game metadata, route inventory, sitemap/feed/discovery validation, and health snapshots. Requires PLATPHORM_API_KEY when enforcement is enabled or Vercel cron headers are present."
      tags:
        - System
      security:
        - PlatPhormApiKey:
[]
        - PlatPhormBearer:
[]
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
    post:
      operationId: refreshArcadeMetadata
      summary: Bounded refresh and validation
      description: "Cron-safe refresh scaffold for game metadata, route inventory, sitemap/feed/discovery validation, and health snapshots. Requires PLATPHORM_API_KEY when enforcement is enabled or Vercel cron headers are present."
      tags:
        - System
      security:
        - PlatPhormApiKey:
[]
        - PlatPhormBearer:
[]
      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericObjectResponse"
components:
  securitySchemes:
    PlatPhormApiKey:
      type: apiKey
      in: header
      name: "X-PlatPhorm-API-Key"
      description: "Future protected actions use PLATPHORM_API_KEY. Public-safe Phase 1 reads do not require a key."
    PlatPhormBearer:
      type: http
      scheme: bearer
      description: "Authorization: Bearer $PLATPHORM_API_KEY for future protected backend actions."
  schemas:
    ApiEnvelope:
      type: object
      properties:
        ok:
          type: boolean
        data:

        meta:
          type: object
      required:
        - ok
        - data
    Game:
      type: object
      properties:
        id:
          type: string
        slug:
          type: string
        title:
          type: string
        description:
          type: string
        category:
          type: string
          enum:
            - Arcade
            - Puzzle
            - Strategy
            - Action
        status:
          type: string
          enum:
            - playable
            - degraded
            - unavailable
        route:
          type: string
        instructions:
          type: array
          items:
            type: string
        controls:
          type: array
          items:
            type: object
        accessibilityNotes:
          type: array
          items:
            type: string
        hasScore:
          type: boolean
        localScoreKey:
          type: string
          nullable: true
        metadata:
          type: object
      required:
        - id
        - slug
        - title
        - description
        - category
        - status
        - route
    GamesListResponse:
      allOf:
        - $ref: "#/components/schemas/ApiEnvelope"
      example:
        ok: true
        data:
[]
        meta:
          total: 23
          categories:
            - id: arcade
              name: Arcade
              count: 7
              route: /games/category/arcade
              status: "public-safe"
            - id: puzzle
              name: Puzzle
              count: 5
              route: /games/category/puzzle
              status: "public-safe"
            - id: strategy
              name: Strategy
              count: 4
              route: /games/category/strategy
              status: "public-safe"
            - id: action
              name: Action
              count: 7
              route: /games/category/action
              status: "public-safe"
    HealthResponse:
      allOf:
        - $ref: "#/components/schemas/ApiEnvelope"
      example:
        ok: true
        data:
          status: healthy
          gameCount: 23
          playableCount: 23
    GenericObjectResponse:
      allOf:
        - $ref: "#/components/schemas/ApiEnvelope"
    ErrorResponse:
      type: object
      properties:
        ok:
          type: boolean
          example: false
        data:
          nullable: true
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: object
x-platphorm-auth-policy:
  boundary: "future-protected"
  enforcementEnabled: false
  keyName: PLATPHORM_API_KEY
  acceptedHeaders:
    - "Authorization: Bearer"
    - "X-PlatPhorm-API-Key"
  publicSafeByDefault: true
x-arcade-stats:
  gameCount: 23
  playableCount: 23
  degradedCount: 0
  unavailableCount: 0
  categories:
    - id: arcade
      name: Arcade
      count: 7
      route: /games/category/arcade
      status: "public-safe"
    - id: puzzle
      name: Puzzle
      count: 5
      route: /games/category/puzzle
      status: "public-safe"
    - id: strategy
      name: Strategy
      count: 4
      route: /games/category/strategy
      status: "public-safe"
    - id: action
      name: Action
      count: 7
      route: /games/category/action
      status: "public-safe"
  scoreEnabledCount: 18
  localOnlyScoreCount: 18