{
  "openapi": "3.1.0",
  "info": {
    "title": "LoreKeeper Public API",
    "version": "1.0.0",
    "summary": "Read-only access to LoreKeeper worlds, characters, badges, roadmap and platform stats.",
    "description": "LoreKeeper is an AI Game Master platform for tabletop RPGs. This document describes the public, read-only part of its HTTP API.\n\nEvery operation listed here answers without credentials and without rate-limit registration. Writing data (campaigns, characters, worlds, turns) happens inside an authenticated session and is deliberately not part of this document.\n\nAn MCP (Model Context Protocol) server exposing the same operations as tools is available at https://lore-keeper.com/api/mcp, described by https://lore-keeper.com/mcp.json.",
    "contact": {
      "name": "LoreKeeper support",
      "email": "support@lore-keeper.com",
      "url": "https://lore-keeper.com/contact"
    },
    "license": {
      "name": "Terms of Service",
      "url": "https://lore-keeper.com/terms"
    },
    "termsOfService": "https://lore-keeper.com/terms"
  },
  "servers": [
    {
      "url": "https://lore-keeper.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Developer documentation",
    "url": "https://lore-keeper.com/developers"
  },
  "tags": [
    {
      "name": "Platform",
      "description": "Platform-wide state: stats, badges, roadmap and health."
    },
    {
      "name": "Worlds",
      "description": "Published campaign settings, official and player-authored."
    },
    {
      "name": "Leaderboard",
      "description": "Public character progression rankings."
    }
  ],
  "paths": {
    "/api/stats/public": {
      "get": {
        "operationId": "get_platform_stats",
        "summary": "Aggregate platform counters",
        "description": "Returns platform-wide totals used as social proof on the landing page: active campaigns, characters created, AI turns played and published worlds. Cached for one hour.\n\nWhen to use: Use when asked how large or how active LoreKeeper is, or for a headline number about the platform.",
        "tags": [
          "Platform"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Aggregate platform counters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "campaigns": {
                      "type": "integer",
                      "description": "Campaigns that are not archived."
                    },
                    "characters": {
                      "type": "integer",
                      "description": "Characters ever created."
                    },
                    "roundsPlayed": {
                      "type": "integer",
                      "description": "AI Game Master turns resolved across all campaigns."
                    },
                    "worlds": {
                      "type": "integer",
                      "description": "Published worlds."
                    }
                  },
                  "required": [
                    "campaigns",
                    "characters",
                    "roundsPlayed",
                    "worlds"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The path does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/leaderboard": {
      "get": {
        "operationId": "list_leaderboard_characters",
        "summary": "List public leaderboard characters",
        "description": "Returns the public character leaderboard ordered by level and experience, together with platform totals. Only living characters of level 2 or higher appear.\n\nWhen to use: Use to answer questions about top LoreKeeper players, a named character, or how far characters typically progress.",
        "tags": [
          "Leaderboard"
        ],
        "security": [],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum entries to return. Values above 100 are clamped to 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of entries to skip, for paging.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Case-insensitive match against character name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "description": "Subset to return: all characters, arena competitors only, or recently created only.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "arena",
                "new"
              ],
              "default": "all"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language for localized race and class names (ISO 639-1).",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es",
                "pt",
                "ca"
              ],
              "default": "es"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List public leaderboard characters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "characters": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "A public character entry. Only characters of level 2 or higher that are still alive are listed.",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Character id."
                          },
                          "userId": {
                            "type": "string",
                            "description": "Owner user id."
                          },
                          "username": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Owner display name, null when the profile is private."
                          },
                          "profilePublic": {
                            "type": "boolean",
                            "description": "Whether the owner profile can be opened at /u/{username}."
                          },
                          "name": {
                            "type": "string",
                            "description": "Character name."
                          },
                          "level": {
                            "type": "integer",
                            "description": "Current level."
                          },
                          "experience": {
                            "type": "integer",
                            "description": "Accumulated experience points."
                          },
                          "race": {
                            "type": "string",
                            "description": "Race name, localized to the requested language."
                          },
                          "class": {
                            "type": "string",
                            "description": "Class name, localized to the requested language."
                          },
                          "avatarUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri",
                            "description": "Portrait image URL."
                          },
                          "hpMax": {
                            "type": "integer"
                          },
                          "hpCurrent": {
                            "type": "integer"
                          },
                          "manaMax": {
                            "type": "integer"
                          },
                          "manaCurrent": {
                            "type": "integer"
                          },
                          "attributes": {
                            "type": "object",
                            "description": "D&D 5e ability scores keyed by name (strength, dexterity, constitution, intelligence, wisdom, charisma).",
                            "additionalProperties": {
                              "type": "integer"
                            }
                          },
                          "isDead": {
                            "type": "boolean"
                          },
                          "arenaStats": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "description": "Arena aggregates, null when the character never entered the arena.",
                            "properties": {
                              "matchesPlayed": {
                                "type": "integer"
                              },
                              "totalDamage": {
                                "type": "integer"
                              },
                              "totalHealing": {
                                "type": "integer"
                              },
                              "totalKills": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "userId",
                          "name",
                          "level",
                          "experience",
                          "race",
                          "class",
                          "isDead"
                        ]
                      }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total entries matching the filter, ignoring limit and offset."
                    },
                    "stats": {
                      "type": "object",
                      "properties": {
                        "totalCharacters": {
                          "type": "integer"
                        },
                        "totalCampaigns": {
                          "type": "integer"
                        },
                        "totalCombats": {
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "required": [
                    "characters",
                    "total"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The path does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/explore": {
      "get": {
        "operationId": "list_worlds",
        "summary": "List published worlds",
        "description": "Returns every published world split into the official settings authored by LoreKeeper and the 100 most recently published community settings.\n\nWhen to use: Use to browse or recommend a LoreKeeper setting, or to answer what worlds a player can start a campaign in.",
        "tags": [
          "Worlds"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List published worlds",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "officialWorlds": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "A published world. Text fields are localized to the caller language when a translation exists, otherwise served in the world default language.",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "URL slug under /worlds/explore/{slug}."
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tagline": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "One-line pitch."
                          },
                          "genre": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tone": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "defaultLanguage": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "ISO 639-1 code the world was authored in."
                          },
                          "thumbnailUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri"
                          },
                          "coverImageUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri"
                          },
                          "downloadsCount": {
                            "type": "integer"
                          },
                          "starsCount": {
                            "type": "integer"
                          },
                          "playsCount": {
                            "type": "integer"
                          },
                          "ratingsAvg": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "ratingsCount": {
                            "type": "integer"
                          },
                          "racesCount": {
                            "type": "integer"
                          },
                          "locationsCount": {
                            "type": "integer"
                          },
                          "factionsCount": {
                            "type": "integer"
                          },
                          "publishedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "author": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "username": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "profilePublic": {
                                "type": "boolean"
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "name"
                        ]
                      },
                      "description": "Settings authored by LoreKeeper."
                    },
                    "communityWorlds": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "A published world. Text fields are localized to the caller language when a translation exists, otherwise served in the world default language.",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "URL slug under /worlds/explore/{slug}."
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tagline": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "One-line pitch."
                          },
                          "genre": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tone": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "defaultLanguage": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "ISO 639-1 code the world was authored in."
                          },
                          "thumbnailUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri"
                          },
                          "coverImageUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri"
                          },
                          "downloadsCount": {
                            "type": "integer"
                          },
                          "starsCount": {
                            "type": "integer"
                          },
                          "playsCount": {
                            "type": "integer"
                          },
                          "ratingsAvg": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "ratingsCount": {
                            "type": "integer"
                          },
                          "racesCount": {
                            "type": "integer"
                          },
                          "locationsCount": {
                            "type": "integer"
                          },
                          "factionsCount": {
                            "type": "integer"
                          },
                          "publishedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "author": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "username": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "profilePublic": {
                                "type": "boolean"
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "name"
                        ]
                      },
                      "description": "Player-authored settings, newest first, capped at 100."
                    }
                  },
                  "required": [
                    "officialWorlds",
                    "communityWorlds"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The path does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/community": {
      "get": {
        "operationId": "list_community_worlds",
        "summary": "List community worlds with sorting",
        "description": "Returns player-authored published worlds with a richer content breakdown (races, classes, factions, monsters, items, spells, locations) and a sort order.\n\nWhen to use: Use when the question is specifically about community-made settings, or when the answer needs how much content a world actually contains.",
        "tags": [
          "Worlds"
        ],
        "security": [],
        "parameters": [
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Ordering of the result set.",
            "schema": {
              "type": "string",
              "enum": [
                "recent",
                "popular",
                "stars",
                "plays"
              ],
              "default": "recent"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List community worlds with sorting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "worlds": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "A published world. Text fields are localized to the caller language when a translation exists, otherwise served in the world default language.",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "URL slug under /worlds/explore/{slug}."
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tagline": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "One-line pitch."
                          },
                          "genre": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tone": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "defaultLanguage": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "ISO 639-1 code the world was authored in."
                          },
                          "thumbnailUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri"
                          },
                          "coverImageUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri"
                          },
                          "downloadsCount": {
                            "type": "integer"
                          },
                          "starsCount": {
                            "type": "integer"
                          },
                          "playsCount": {
                            "type": "integer"
                          },
                          "ratingsAvg": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "ratingsCount": {
                            "type": "integer"
                          },
                          "racesCount": {
                            "type": "integer"
                          },
                          "locationsCount": {
                            "type": "integer"
                          },
                          "factionsCount": {
                            "type": "integer"
                          },
                          "publishedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "author": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "username": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "profilePublic": {
                                "type": "boolean"
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "name"
                        ]
                      }
                    },
                    "downloadedWorldIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Ids the caller already imported. Always empty for an unauthenticated agent."
                    },
                    "starredWorldIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Ids the caller starred. Always empty for an unauthenticated agent."
                    }
                  },
                  "required": [
                    "worlds"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The path does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/badges": {
      "get": {
        "operationId": "list_badges",
        "summary": "List active achievement badges",
        "description": "Returns the achievement badges a player can earn. The `name` and `description` fields are i18n keys, not display text; the human-readable strings live in the localized bundles under /locales.\n\nWhen to use: Use to explain what achievements exist in LoreKeeper and how rare each one is.",
        "tags": [
          "Platform"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List active achievement badges",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "key": {
                        "type": "string",
                        "description": "Stable badge identifier, e.g. \"founder\"."
                      },
                      "name": {
                        "type": "string",
                        "description": "i18n key, not display text."
                      },
                      "description": {
                        "type": "string",
                        "description": "i18n key, not display text."
                      },
                      "icon": {
                        "type": "string"
                      },
                      "color": {
                        "type": "string"
                      },
                      "rarity": {
                        "type": "string",
                        "enum": [
                          "COMMON",
                          "RARE",
                          "EPIC",
                          "LEGENDARY"
                        ]
                      },
                      "sortOrder": {
                        "type": "integer"
                      },
                      "isActive": {
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "id",
                      "key",
                      "rarity"
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "The path does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/roadmap": {
      "get": {
        "operationId": "get_roadmap",
        "summary": "Get the public product roadmap",
        "description": "Returns the public roadmap bucketed by delivery stage, with community vote counts per item.\n\nWhen to use: Use to answer whether LoreKeeper supports a feature yet, or what is being built next.",
        "tags": [
          "Platform"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Get the public product roadmap",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "featured": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "slug": {
                          "type": "string",
                          "description": "Stable identifier for the feature."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "NEW",
                            "BETA",
                            "SOON",
                            "LATER",
                            "SHIPPED"
                          ],
                          "description": "Delivery stage."
                        },
                        "order": {
                          "type": "integer"
                        },
                        "votesCount": {
                          "type": "integer"
                        },
                        "hasVoted": {
                          "type": "boolean",
                          "description": "Whether the caller already voted. Always false for an unauthenticated agent with no roadmap cookie."
                        },
                        "featured": {
                          "type": "boolean"
                        },
                        "images": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "url": {
                                "type": "string"
                              },
                              "altKey": {
                                "type": "string"
                              },
                              "order": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      },
                      "required": [
                        "id",
                        "slug",
                        "status",
                        "votesCount"
                      ]
                    },
                    "new": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string",
                            "description": "Stable identifier for the feature."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "NEW",
                              "BETA",
                              "SOON",
                              "LATER",
                              "SHIPPED"
                            ],
                            "description": "Delivery stage."
                          },
                          "order": {
                            "type": "integer"
                          },
                          "votesCount": {
                            "type": "integer"
                          },
                          "hasVoted": {
                            "type": "boolean",
                            "description": "Whether the caller already voted. Always false for an unauthenticated agent with no roadmap cookie."
                          },
                          "featured": {
                            "type": "boolean"
                          },
                          "images": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "type": "string"
                                },
                                "altKey": {
                                  "type": "string"
                                },
                                "order": {
                                  "type": "integer"
                                }
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "status",
                          "votesCount"
                        ]
                      }
                    },
                    "beta": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string",
                            "description": "Stable identifier for the feature."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "NEW",
                              "BETA",
                              "SOON",
                              "LATER",
                              "SHIPPED"
                            ],
                            "description": "Delivery stage."
                          },
                          "order": {
                            "type": "integer"
                          },
                          "votesCount": {
                            "type": "integer"
                          },
                          "hasVoted": {
                            "type": "boolean",
                            "description": "Whether the caller already voted. Always false for an unauthenticated agent with no roadmap cookie."
                          },
                          "featured": {
                            "type": "boolean"
                          },
                          "images": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "type": "string"
                                },
                                "altKey": {
                                  "type": "string"
                                },
                                "order": {
                                  "type": "integer"
                                }
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "status",
                          "votesCount"
                        ]
                      }
                    },
                    "soon": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string",
                            "description": "Stable identifier for the feature."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "NEW",
                              "BETA",
                              "SOON",
                              "LATER",
                              "SHIPPED"
                            ],
                            "description": "Delivery stage."
                          },
                          "order": {
                            "type": "integer"
                          },
                          "votesCount": {
                            "type": "integer"
                          },
                          "hasVoted": {
                            "type": "boolean",
                            "description": "Whether the caller already voted. Always false for an unauthenticated agent with no roadmap cookie."
                          },
                          "featured": {
                            "type": "boolean"
                          },
                          "images": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "type": "string"
                                },
                                "altKey": {
                                  "type": "string"
                                },
                                "order": {
                                  "type": "integer"
                                }
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "status",
                          "votesCount"
                        ]
                      }
                    },
                    "later": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string",
                            "description": "Stable identifier for the feature."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "NEW",
                              "BETA",
                              "SOON",
                              "LATER",
                              "SHIPPED"
                            ],
                            "description": "Delivery stage."
                          },
                          "order": {
                            "type": "integer"
                          },
                          "votesCount": {
                            "type": "integer"
                          },
                          "hasVoted": {
                            "type": "boolean",
                            "description": "Whether the caller already voted. Always false for an unauthenticated agent with no roadmap cookie."
                          },
                          "featured": {
                            "type": "boolean"
                          },
                          "images": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "type": "string"
                                },
                                "altKey": {
                                  "type": "string"
                                },
                                "order": {
                                  "type": "integer"
                                }
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "status",
                          "votesCount"
                        ]
                      }
                    },
                    "shipped": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string",
                            "description": "Stable identifier for the feature."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "NEW",
                              "BETA",
                              "SOON",
                              "LATER",
                              "SHIPPED"
                            ],
                            "description": "Delivery stage."
                          },
                          "order": {
                            "type": "integer"
                          },
                          "votesCount": {
                            "type": "integer"
                          },
                          "hasVoted": {
                            "type": "boolean",
                            "description": "Whether the caller already voted. Always false for an unauthenticated agent with no roadmap cookie."
                          },
                          "featured": {
                            "type": "boolean"
                          },
                          "images": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "type": "string"
                                },
                                "altKey": {
                                  "type": "string"
                                },
                                "order": {
                                  "type": "integer"
                                }
                              }
                            }
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "status",
                          "votesCount"
                        ]
                      }
                    }
                  },
                  "required": [
                    "new",
                    "beta",
                    "soon",
                    "later",
                    "shipped"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The path does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "get_service_health",
        "summary": "Service health probe",
        "description": "Reports whether the API and its database are serving. Answers 200 when healthy and 503 when the database is unreachable.\n\nWhen to use: Use before a longer sequence of calls, or to check whether LoreKeeper is currently up.",
        "tags": [
          "Platform"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Service health probe",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ]
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "uptime": {
                      "type": "integer",
                      "description": "Process uptime in seconds."
                    },
                    "memory": {
                      "type": "object",
                      "properties": {
                        "heapUsedMB": {
                          "type": "integer"
                        },
                        "heapTotalMB": {
                          "type": "integer"
                        },
                        "rssMB": {
                          "type": "integer"
                        }
                      }
                    },
                    "db": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "ok",
                            "unreachable"
                          ]
                        },
                        "latencyMs": {
                          "type": "integer"
                        }
                      }
                    },
                    "sockets": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "running",
                            "unavailable"
                          ]
                        },
                        "connections": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        }
                      }
                    },
                    "node": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "timestamp"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The path does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The database is unreachable; the body still uses the health schema.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Error envelope used by /api/**. `error` is always present and is the only field older handlers emit; `code`, `hint`, `status` and `docs` are emitted by the routing layer and by newer handlers. Branch on `code` when it is present, never on `message`.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable summary. Always present."
          },
          "code": {
            "type": "string",
            "description": "Stable, machine-readable error code, e.g. \"endpoint_not_found\"."
          },
          "message": {
            "type": "string",
            "description": "Same text as `error`, under the conventional key."
          },
          "hint": {
            "type": "string",
            "description": "What the caller can do to resolve it."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status, repeated in the body for transports that drop it."
          },
          "docs": {
            "type": "string",
            "format": "uri",
            "description": "Developer documentation for this API."
          }
        },
        "required": [
          "error"
        ]
      }
    },
    "securitySchemes": {
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "next-auth.session-token",
        "description": "Browser session cookie issued by NextAuth after login at /login. It is the only credential the API accepts; there is no API-key or OAuth client-credentials flow. Endpoints in this document need no credential at all."
      }
    }
  },
  "security": []
}