openapi: 3.1.0
info:
  title: Style Guide Generator API
  version: 1.0.0
  description: "Programmatic access to all style guide generation features. Generate and refine palettes, export tokens, and capture screenshots.\n\n---\n\n## Recommended workflow (read this first)\n\nIf you are an LLM or AI agent calling this API on behalf of a user, the **golden path** is iterative and visual, not blind. The shortcut of \"generate once, export the first variation\" almost always picks the wrong palette. The right loop:\n\n1. **Generate** — `POST /chat/generate { \"prompt\": \"<brand brief>\" }`. Write a brief that names the **product, audience, mood, anti-mood**, and **tagline if any**. Returns 4 palette variations and a `conversationId`. Each variation has a `versionId` (in `message.versionIds[i]`).\n\n2. **Screenshot every variation** — for each `versionId`, GET `/conversations/{conversationId}/screenshot?versionId=<id>&view=components&fullPage=true&width=1024`. Save each PNG. Look at them. Variations differ in **fonts, accent hue, density, and warmth** in ways that the JSON palette data alone hides.\n\n3. **Pick deliberately** — do not default to index 0. Compare typography (Geist vs Inter vs Söhne vs Manrope), accent restraint, and how the buttons + alerts + forms render together. A palette that reads well in JSON can look loud or sterile in a real layout.\n\n4. **Refine if none fit** — `POST /conversations/{id}/refine { \"instruction\": \"...\" }` with a tight instruction (e.g. \"replace green accent with a quieter teal that signals confirmation without celebration\"). Returns 4 new variations. Screenshot and compare again. 1–2 refine cycles is normal; more usually means the brief was unclear.\n\n5. **Select** — `POST /conversations/{id}/select { \"messageId\", \"variationIndex\" }` to mark one variation as the active version.\n\n6. **Export** — `GET /conversations/{id}/export/{format}` for a single format (e.g. `tailwind`, `css`, `json`, `scss`, `ts`) or `/export` for a ZIP of all eight.\n\n### Use cases this loop fits\n\n- **Bootstrapping a new product's frontend**: generate from a one-paragraph product description, screenshot, refine, export Tailwind config + font choice. End result is a `tailwind.config.ts` + a Google Fonts import that drops into a Next.js app.\n- **Rebranding an existing app**: paste the existing CSS and the brand brief; refine until the screenshots match the new direction; export back as the same format you started with.\n- **Generating per-tenant theming**: same brief shape, multiple tenant-specific instructions; one conversation per tenant; persist the conversationId so you can refine later without losing history.\n- **Comparing options for a stakeholder**: generate, screenshot all four, share the four PNGs in a doc, let the human pick the index, then `/select` and export.\n- **Style audits**: feed a screenshot of the current product into the brief (\"here's what we have, generate four directions that fix the cramped contrast\"), then compare against the existing.\n\n### What goes wrong if you skip steps\n\n- **Skipping screenshots → picking ugly palettes.** The colors in the JSON look fine; the rendered layout reveals the typography clash or the over-bright accent.\n- **Skipping refinement → settling for \"close enough\".** One refine pass usually fixes the one thing that's off (e.g. wrong font weight, accent too loud) and leaves the rest intact.\n- **Picking variation 0 every time.** The model deliberately spans the space (warm/cool, mono/sans, bright/muted). Picking index 0 ignores the diversity.\n\n### Tips for the brief\n\n- Lead with the **product positioning and audience**. \"Developer-tool, CLI vibes, calm not flashy\" beats \"modern and clean\".\n- Name the **anti-mood** — what should this NOT look like. \"Not flashy\", \"not playful\", \"not corporate-blue\".\n- Quote the **tagline** if there is one — it shapes typography and accent intensity.\n- Mention **specific reference products** if helpful: \"feels like Linear's density with Stripe's restraint\".\n- Keep it under ~250 words. Longer briefs don't help; they push the model toward bland compromises."
servers:
  - url: "https://styleguide.ideaplaces.com/api/v1"
    description: Production
  - url: "https://styleguide.ideaplaces.dev/api/v1"
    description: Development
  - url: "http://localhost:7392/api/v1"
    description: Local
security:
  - BearerAuth: []
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key (sg_live_* or sg_test_*)
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
        code:
          type: string
          description: Machine-readable error code (e.g. UNAUTHORIZED, NOT_FOUND, RATE_LIMIT)
        retryAfter:
          type: integer
          description: Seconds until next request allowed (rate limit errors only)
      required:
        - error
        - code
    Palette:
      type: object
      description: Full design system palette with colors, typography, spacing, and style tokens
      required:
        - name
        - description
        - rationale
        - colors
        - typography
        - spacing
        - iconStyle
        - borderRadius
        - shadowStyle
      properties:
        name:
          type: string
          description: "Human-readable palette name (e.g. \"Midnight Developer\")"
        description:
          type: string
          description: Short description of the palette mood and intent
        rationale:
          type: string
          description: Explanation of design decisions and color choices
        colors:
          type: object
          description: "All color tokens as #RRGGBB hex strings"
          required:
            - primary
            - primaryLight
            - primaryDark
            - secondary
            - secondaryLight
            - secondaryDark
            - accent
            - background
            - backgroundAlt
            - surface
            - foreground
            - foregroundMuted
            - border
            - borderLight
            - success
            - warning
            - error
            - info
          properties:
            primary:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Primary brand color
            primaryLight:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Lighter variant of primary
            primaryDark:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Darker variant of primary
            secondary:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Secondary brand color
            secondaryLight:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Lighter variant of secondary
            secondaryDark:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Darker variant of secondary
            accent:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Accent color for highlights and CTAs
            background:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Page background
            backgroundAlt:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Alternate background (sections, stripes)
            surface:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Card and panel surfaces
            foreground:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Primary text color
            foregroundMuted:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Secondary/muted text color
            border:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Default border color
            borderLight:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Subtle border color
            success:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Success state color
            warning:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Warning state color
            error:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Error state color
            info:
              type: string
              pattern: "^#[0-9a-fA-F]{6}$"
              description: Informational state color
        typography:
          type: object
          description: "Typography tokens: font families, weights, line heights, and type scale"
          required:
            - fontFamily
            - fontFamilyHeading
            - fontFamilyMono
            - fontWeightBody
            - fontWeightHeading
            - lineHeightBody
            - lineHeightHeading
            - scale
          properties:
            fontFamily:
              type: string
              description: "Body font stack (e.g. \"Inter, system-ui, sans-serif\")"
            fontFamilyHeading:
              type: string
              description: Heading font stack
            fontFamilyMono:
              type: string
              description: Monospace font stack
            fontWeightBody:
              type: integer
              description: Body font weight (e.g. 400)
            fontWeightHeading:
              type: integer
              description: Heading font weight (e.g. 700)
            lineHeightBody:
              type: number
              description: Body line height (e.g. 1.6)
            lineHeightHeading:
              type: number
              description: Heading line height (e.g. 1.2)
            scale:
              type: array
              items:
                type: number
              description: Type scale in px (e.g. [12, 14, 16, 18, 20, 24, 30, 36, 48, 60])
        spacing:
          type: object
          description: "Spacing tokens: base unit and scale"
          required:
            - baseUnit
            - scale
          properties:
            baseUnit:
              type: integer
              description: Base spacing unit in px (typically 4 or 8)
            scale:
              type: array
              items:
                type: number
              description: Spacing scale in px (e.g. [4, 8, 12, 16, 24, 32, 48, 64, 96])
        iconStyle:
          type: string
          enum:
            - outlined
            - filled
            - rounded
          description: Preferred icon style
        borderRadius:
          type: string
          description: "Default border radius (e.g. \"8px\")"
        shadowStyle:
          type: string
          enum:
            - none
            - subtle
            - medium
            - elevated
            - dramatic
          description: Shadow intensity preset
    ConversationSummary:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        activeVersionId:
          type: string
          nullable: true
        versionCount:
          type: integer
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - title
        - createdAt
        - updatedAt
    Message:
      type: object
      properties:
        id:
          type: string
        role:
          type: string
          enum:
            - user
            - assistant
        type:
          type: string
        content:
          type: string
        variations:
          type: array
          items:
            $ref: "#/components/schemas/Palette"
          nullable: true
        versionIds:
          type: array
          items:
            type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - role
        - type
        - content
    Version:
      type: object
      properties:
        id:
          type: string
        conversationId:
          type: string
        versionNumber:
          type: integer
        palette:
          $ref: "#/components/schemas/Palette"
        changeSummary:
          type: string
          nullable: true
        parentVersionId:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - versionNumber
        - palette
        - createdAt
    ApiKey:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        prefix:
          type: string
          description: First 12 characters (e.g. sg_live_a1b2)
        createdAt:
          type: string
          format: date-time
        lastUsedAt:
          type: string
          format: date-time
          nullable: true
        expiresAt:
          type: string
          format: date-time
          nullable: true
      required:
        - id
        - name
        - prefix
        - createdAt
    TreeNode:
      type: object
      properties:
        id:
          type: string
        versionNumber:
          type: integer
        parentId:
          type: string
          nullable: true
        changeSummary:
          type: string
          nullable: true
        isActive:
          type: boolean
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - versionNumber
        - isActive
        - createdAt
paths:
  /auth/register:
    post:
      summary: Auto-register (no auth required)
      tags:
        - Authentication
      security: []
      description: Creates a free-tier account and returns an API key in one step. No password or email verification required.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: User name. Defaults to Anonymous
                email:
                  type: string
                  format: email
                  description: Optional. If already registered, returns 409
                context:
                  type: string
                  description: What the user is building. Used for key naming
      responses:
        201:
          description: Account created with API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  apiKey:
                    type: string
                    description: "Full API key. Use in Authorization: Bearer header"
                  userId:
                    type: string
                  name:
                    type: string
                  plan:
                    type: string
                    enum:
                      - free
                  message:
                    type: string
                required:
                  - apiKey
                  - userId
                  - name
                  - plan
        409:
          description: Email already registered
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Too many registrations from this IP
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /api-keys:
    get:
      summary: List API keys
      tags:
        - API Keys
      responses:
        200:
          description: List of API keys (prefix only, full key is never returned)
          content:
            application/json:
              schema:
                type: object
                properties:
                  keys:
                    type: array
                    items:
                      $ref: "#/components/schemas/ApiKey"
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      summary: Create API key
      tags:
        - API Keys
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                expiresAt:
                  type: string
                  format: date-time
                  nullable: true
              required:
                - name
      responses:
        201:
          description: API key created (full key returned once)
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  key:
                    type: string
                    description: Full API key — only returned at creation
                  prefix:
                    type: string
                  createdAt:
                    type: string
                    format: date-time
                  lastUsedAt:
                    type: string
                    nullable: true
                  expiresAt:
                    type: string
                    nullable: true
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /api-keys/{keyId}:
    delete:
      summary: Revoke API key
      tags:
        - API Keys
      parameters:
        - name: keyId
          in: path
          required: true
          schema:
            type: string
      responses:
        204:
          description: Key revoked
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Key not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations:
    get:
      summary: List conversations
      tags:
        - Conversations
      responses:
        200:
          description: List of conversations
          content:
            application/json:
              schema:
                type: object
                properties:
                  conversations:
                    type: array
                    items:
                      $ref: "#/components/schemas/ConversationSummary"
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /chat/generate:
    post:
      summary: Generate style guide
      tags:
        - Generation
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                prompt:
                  type: string
              required:
                - prompt
      responses:
        201:
          description: 4 palette variations generated
          content:
            application/json:
              schema:
                type: object
                properties:
                  conversationId:
                    type: string
                  message:
                    $ref: "#/components/schemas/Message"
                  versions:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        versionNumber:
                          type: integer
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        403:
          description: Plan limit reached
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}:
    get:
      summary: Get conversation with messages
      tags:
        - Conversations
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Full conversation with messages
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  title:
                    type: string
                  activeVersionId:
                    type: string
                    nullable: true
                  activePalette:
                    $ref: "#/components/schemas/Palette"
                  messages:
                    type: array
                    items:
                      $ref: "#/components/schemas/Message"
                  createdAt:
                    type: string
                    format: date-time
                  updatedAt:
                    type: string
                    format: date-time
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      summary: Delete conversation
      tags:
        - Conversations
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      responses:
        204:
          description: Conversation deleted
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/select:
    post:
      summary: Select variation
      tags:
        - Generation
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                variationIndex:
                  type: integer
                  minimum: 0
                  maximum: 3
                messageId:
                  type: string
              required:
                - variationIndex
      responses:
        200:
          description: Variation selected, new active version created
          content:
            application/json:
              schema:
                type: object
                properties:
                  version:
                    type: object
                    properties:
                      id:
                        type: string
                      versionNumber:
                        type: integer
                      palette:
                        $ref: "#/components/schemas/Palette"
                      changeSummary:
                        type: string
                        nullable: true
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/refine:
    post:
      summary: Refine palette
      tags:
        - Generation
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                instruction:
                  type: string
              required:
                - instruction
      responses:
        201:
          description: 4 refined variations
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    $ref: "#/components/schemas/Message"
                  versions:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        versionNumber:
                          type: integer
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/rollback:
    post:
      summary: Rollback to version
      tags:
        - Generation
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                targetVersionId:
                  type: string
              required:
                - targetVersionId
      responses:
        200:
          description: Rolled back to target version
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: object
                    properties:
                      id:
                        type: string
                      role:
                        type: string
                      type:
                        type: string
                      content:
                        type: string
                  version:
                    type: object
                    properties:
                      id:
                        type: string
                      versionNumber:
                        type: integer
                      palette:
                        $ref: "#/components/schemas/Palette"
                      changeSummary:
                        type: string
                        nullable: true
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation or version not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/palette:
    get:
      summary: Get active palette
      tags:
        - Conversations
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Active palette with version info
          content:
            application/json:
              schema:
                type: object
                properties:
                  conversationId:
                    type: string
                  versionId:
                    type: string
                  versionNumber:
                    type: integer
                  palette:
                    $ref: "#/components/schemas/Palette"
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found or no version exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/versions:
    get:
      summary: List versions
      tags:
        - Versions
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: All versions for conversation
          content:
            application/json:
              schema:
                type: object
                properties:
                  versions:
                    type: array
                    items:
                      $ref: "#/components/schemas/Version"
                  activeVersionId:
                    type: string
                    nullable: true
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/tree:
    get:
      summary: Get version tree
      tags:
        - Versions
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Version tree for visualization
          content:
            application/json:
              schema:
                type: object
                properties:
                  nodes:
                    type: array
                    items:
                      $ref: "#/components/schemas/TreeNode"
                  activeVersionId:
                    type: string
                    nullable: true
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/export/{format}:
    get:
      summary: Export tokens (single format)
      tags:
        - Export
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
        - name: format
          in: path
          required: true
          schema:
            type: string
            enum:
              - css
              - scss
              - tailwind
              - typescript
              - swift
              - android
              - tokens
        - name: versionId
          in: query
          schema:
            type: string
      responses:
        200:
          description: Exported tokens as file download (Content-Type varies by format)
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation or version not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/export:
    get:
      summary: Export all formats (ZIP)
      tags:
        - Export
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
        - name: versionId
          in: query
          schema:
            type: string
      responses:
        200:
          description: ZIP file containing all export formats
          content:
            application/zip: {}
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation or version not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/screenshot:
    get:
      summary: Screenshot style guide
      tags:
        - Screenshots
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
        - name: view
          in: query
          schema:
            type: string
            enum:
              - styleguide
              - components
              - screens
            default: components
        - name: platform
          in: query
          schema:
            type: string
            enum:
              - web
              - ios
              - android
            default: web
        - name: width
          in: query
          schema:
            type: integer
            default: 1440
            minimum: 320
            maximum: 2560
        - name: fullPage
          in: query
          schema:
            type: boolean
            default: false
        - name: versionId
          in: query
          schema:
            type: string
      responses:
        200:
          description: PNG screenshot with dimensions in headers (X-Screenshot-Width, X-Screenshot-Height)
          content:
            image/png: {}
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /conversations/{conversationId}/prompts:
    get:
      summary: Get conversation prompts
      tags:
        - Prompts
      parameters:
        - name: conversationId
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Full prompt chain with LLM messages
          content:
            application/json:
              schema:
                type: object
                properties:
                  conversationId:
                    type: string
                  initialPrompt:
                    type: string
                  refinements:
                    type: array
                    items:
                      type: object
                      properties:
                        instruction:
                          type: string
                        createdAt:
                          type: string
                          format: date-time
                  llmMessages:
                    type: array
                    items:
                      type: object
                      properties:
                        step:
                          type: string
                        messages:
                          type: array
                          items:
                            type: object
                            properties:
                              role:
                                type: string
                              content:
                                type: string
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /prompts:
    get:
      summary: Get system prompt and templates
      tags:
        - Prompts
      responses:
        200:
          description: System prompt, generation/refinement templates, and JSON schema
          content:
            application/json:
              schema:
                type: object
                properties:
                  version:
                    type: string
                  systemPrompt:
                    type: string
                  generateTemplate:
                    type: string
                  refineTemplate:
                    type: string
                  schema:
                    type: object
                    description: JSON Schema for the palette array output
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /versions/{versionId}:
    get:
      summary: Get single version
      tags:
        - Versions
      parameters:
        - name: versionId
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Version details with palette
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Version"
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        404:
          description: Version not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        429:
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
tags:
  - name: Authentication
    description: Register and authenticate (public endpoints)
  - name: API Keys
    description: Manage API keys
  - name: Conversations
    description: Conversation management
  - name: Generation
    description: Generate, select, refine, rollback palettes
  - name: Versions
    description: Version history and tree
  - name: Export
    description: Export tokens in various formats
  - name: Screenshots
    description: Capture visual screenshots
  - name: Prompts
    description: LLM prompt inspection