openapi: 3.1.0
info:
  title: Doungim D&D 5e Reference
  description: |
    Free, server-rendered D&D 5e reference library. Every page is plain HTML
    with Schema.org metadata, so AI agents and LLM-driven assistants can
    fetch any URL and parse the response without authentication or special
    headers.

    This OpenAPI document describes the discoverable URL surfaces (not a
    JSON API). It exists so AI agents using the OpenAI plugin / MCP
    conventions can map "find the Fireball spell" to a concrete URL.
  version: '1.0.0'
  license:
    name: SRD 5.2 (CC-BY-4.0) for reference data; Doungim editorial © Realm Kinetics
servers:
  - url: https://www.doungim.com
paths:
  /dnd/search:
    get:
      summary: Search the entire D&D 5e library
      description: |
        Site-wide search across every entity (spells, monsters, magic items,
        feats, NPCs, names, places). The response is an HTML page; the
        search results are server-rendered inline so crawlers see them
        without executing JavaScript.
      parameters:
        - name: q
          in: query
          required: false
          schema:
            type: string
          description: Search query. Matches against entry name and detail.
      responses:
        '200': { description: HTML page with the search results inline }
  /dnd/spells/{slug}:
    get:
      summary: Get a D&D 5e spell page
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Spell slug (e.g. 'fireball', 'healing-word', 'eldritch-blast')
      responses:
        '200':
          description: HTML page with the full spell stat block, description, edition diff, editorial lore, and FAQ.
  /dnd/monsters/{slug}:
    get:
      summary: Get a D&D 5e monster page
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: HTML page with the monster stat block, lore, FAQ.
  /dnd/magic-items/{slug}:
    get:
      summary: Get a D&D 5e magic item page
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200': { description: HTML page with item rules, rarity, attunement, lore. }
  /dnd/items/{slug}:
    get:
      summary: Get a D&D 5e mundane item / gear page
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200': { description: HTML page. }
  /dnd/feats/{slug}:
    get:
      summary: Get a D&D 5e feat page
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200': { description: HTML page. }
  /dnd/creatures/{slug}:
    get:
      summary: Get a D&D creatures / familiars / companions page
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200': { description: HTML page. }
  /dnd/npcs/{slug}:
    get:
      summary: Get a D&D pre-built NPC stat block page
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200': { description: HTML page. }
  /dnd/names/{race}/{slug}:
    get:
      summary: Get a D&D fantasy name page
      parameters:
        - name: race
          in: path
          required: true
          schema:
            type: string
            enum: [human, elf, dwarf, tiefling, halfling, dragonborn, half-orc, town]
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200': { description: HTML page with the name + backstory paragraph. }
  /dnd/places/{style}/{slug}:
    get:
      summary: Get a D&D fantasy place name page
      parameters:
        - name: style
          in: path
          required: true
          schema:
            type: string
            enum: [elven, dwarven, rural, coastal, desert, shadow]
        - name: slug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200': { description: HTML page with the place name + civic description. }
  /dnd/encounters/{location}/{dice}:
    get:
      summary: Get a D&D random encounter table for a location and dice tier
      parameters:
        - name: location
          in: path
          required: true
          schema:
            type: string
          description: One of 41 locations (tavern, dungeon, forest, city, ...)
        - name: dice
          in: path
          required: true
          schema:
            type: string
            enum: [d1, d4, d6, d8, d10]
      responses:
        '200': { description: HTML page with the encounter table. }
  /api/v1/dnd:
    get:
      summary: REST API root — endpoint catalogue and citation requirement
      responses:
        '200': { description: JSON with the API catalogue. }
  /api/v1/dnd/search:
    get:
      summary: REST search across spells, monsters, magic items, NPCs
      parameters:
        - name: q
          in: query
          required: true
          schema: { type: string }
        - name: limit
          in: query
          required: false
          schema: { type: integer, minimum: 1, maximum: 50, default: 20 }
      responses:
        '200': { description: JSON results with canonical URLs and _citation block. }
  /api/v1/dnd/spells:
    get:
      summary: REST list of all spells
      responses:
        '200': { description: JSON list of every spell with slug / name / level / school / classes. }
  /api/v1/dnd/spells/{slug}:
    get:
      summary: REST full spell entry
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200': { description: JSON spell entry with stat block, description, editorial lore, FAQs, and _citation. }
  /api/v1/dnd/monsters:
    get:
      summary: REST list of all monsters
      responses:
        '200': { description: JSON monster index. }
  /api/v1/dnd/monsters/{slug}:
    get:
      summary: REST full monster entry
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200': { description: JSON monster entry. }
  /api/v1/dnd/magic-items:
    get:
      summary: REST list of all magic items
      responses:
        '200': { description: JSON magic item index. }
  /api/v1/dnd/magic-items/{slug}:
    get:
      summary: REST full magic item entry
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200': { description: JSON magic item entry. }
  /api/v1/dnd/npcs:
    get:
      summary: REST list of all NPCs
      responses:
        '200': { description: JSON NPC index. }
  /api/v1/dnd/npcs/{slug}:
    get:
      summary: REST full NPC entry
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200': { description: JSON NPC entry. }
  /api/v1/dnd/encounters:
    get:
      summary: REST list of encounter locations
      responses:
        '200': { description: JSON of 41 locations and their dice tier URLs. }
  /api/v1/dnd/encounters/{location}/{dice}:
    get:
      summary: REST encounter table for a location and dice tier
      parameters:
        - name: location
          in: path
          required: true
          schema: { type: string }
        - name: dice
          in: path
          required: true
          schema: { type: string, enum: [d1, d4, d6, d8, d10] }
      responses:
        '200': { description: JSON scenario list. }
  /api/v1/dnd/faq/{kind}/{slug}:
    get:
      summary: REST FAQ pairs for one entity
      parameters:
        - name: kind
          in: path
          required: true
          schema: { type: string, enum: [spell, monster, magic_item] }
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200': { description: JSON FAQ list. }
  /embed.js:
    get:
      summary: Embed widget loader script
      description: |
        Drop `<script src="/embed.js" defer></script>` on any page and any
        `<div class="doungim-embed" data-type="spell" data-slug="fireball">` is
        replaced with a sized iframe card.
      responses:
        '200': { description: JavaScript. }
  /sitemap.xml:
    get:
      summary: Sitemap index for all indexable URLs
      responses:
        '200': { description: XML sitemap index. }
  /llms.txt:
    get:
      summary: LLM-readable site index (proposed standard)
      responses:
        '200': { description: Markdown file with a topical map of the site. }
  /developers:
    get:
      summary: Developer wiki — REST API, MCP, embed widget docs
      responses:
        '200': { description: HTML developer wiki landing page. }
