openapi: 3.1.0
info:
  title: AeThex KAEL API
  version: "4.0"
  description: |
    Public contract for the AeThex API and KAEL runtime at api.aethex.tech.

    This contract documents public and user-facing routes. Owner-only deployment,
    world-model mutation, operator administration, and other privileged operations
    are intentionally excluded.
  contact:
    name: AeThex Support
    url: https://aethex.support
  license:
    name: Documentation terms
    url: https://docs.aethex.support/Policies
servers:
  - url: https://api.aethex.tech
    description: Production
security: []
tags:
  - name: Health
  - name: Chat
  - name: Authentication
  - name: History
  - name: Memory
  - name: Identity
  - name: Documents
  - name: Feed
  - name: Integrations
paths:
  /health:
    get:
      tags: [Health]
      summary: Get runtime health
      operationId: getHealth
      responses:
        "200":
          description: Runtime health and enabled model classes
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Health"
  /ping:
    get:
      tags: [Health]
      summary: Check basic reachability
      operationId: getPing
      responses:
        "200":
          description: API is reachable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Ok"
    post:
      tags: [Health]
      summary: Register an active visitor heartbeat
      operationId: postPing
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
      responses:
        "200":
          description: Current active visitor count
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActiveCount"
  /active:
    get:
      tags: [Health]
      summary: Get active visitor count
      operationId: getActive
      responses:
        "200":
          description: Current active visitor count
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActiveCount"
  /welcome:
    post:
      tags: [Chat]
      summary: Get a randomized welcome message
      operationId: getWelcome
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                returning:
                  type: boolean
                  default: false
      responses:
        "200":
          description: Welcome message
          content:
            application/json:
              schema:
                type: object
                required: [message]
                properties:
                  message:
                    type: string
  /chat:
    post:
      tags: [Chat]
      summary: Send a legacy non-streaming chat request
      operationId: postChat
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BasicChatRequest"
      responses:
        "200":
          description: Generated response
          content:
            application/json:
              schema:
                type: object
                required: [response]
                properties:
                  response:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
  /kael:
    post:
      tags: [Chat]
      summary: Send a legacy non-streaming KAEL request
      operationId: postKael
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/KaelRequest"
      responses:
        "200":
          description: KAEL reply
          content:
            application/json:
              schema:
                type: object
                required: [reply]
                properties:
                  reply:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
  /kael/models:
    get:
      tags: [Chat]
      summary: List client-selectable KAEL models
      operationId: listKaelModels
      responses:
        "200":
          description: Stable model keys and access tiers
          content:
            application/json:
              schema:
                type: object
                required: [models]
                properties:
                  models:
                    type: array
                    items:
                      $ref: "#/components/schemas/Model"
  /kael/stream:
    post:
      tags: [Chat]
      summary: Stream a KAEL response using Server-Sent Events
      description: |
        Emits model metadata, JSON token or error events, and a final `data: [DONE]`.
        Some rate-limit and generation failures are represented inside the event
        stream after the HTTP response has started.
      operationId: streamKael
      security:
        - {}
        - kaelSession: []
        - tenantKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/StreamRequest"
      responses:
        "200":
          description: Server-Sent Events stream
          content:
            text/event-stream:
              schema:
                type: string
                examples:
                  - 'data: {"type":"model","model":"KAEL Standard","id":"...","tenant":null}'
                  - 'data: {"token":"Hello"}'
                  - "data: [DONE]"
        "400":
          $ref: "#/components/responses/BadRequest"
  /auth/me:
    get:
      tags: [Authentication]
      summary: Get the current KAEL session identity
      operationId: getCurrentUser
      security:
        - kaelSession: []
      responses:
        "200":
          description: Current user or null
          content:
            application/json:
              schema:
                type: object
                properties:
                  user:
                    oneOf:
                      - $ref: "#/components/schemas/User"
                      - type: "null"
  /auth/login:
    get:
      tags: [Authentication]
      summary: Begin the configured AeThex sign-in flow
      operationId: beginLogin
      parameters:
        - $ref: "#/components/parameters/Redirect"
      responses:
        "302":
          description: Redirect to the identity provider or requested return URL
  /auth/logout:
    get:
      tags: [Authentication]
      summary: Clear the KAEL session
      operationId: logout
      parameters:
        - $ref: "#/components/parameters/Redirect"
      responses:
        "302":
          description: Session cookie cleared and browser redirected
  /auth/email:
    post:
      tags: [Authentication]
      summary: Request an email sign-in code
      operationId: requestEmailCode
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email:
                  type: string
                  format: email
      responses:
        "200":
          description: Code request accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkMessage"
        "400":
          $ref: "#/components/responses/BadRequest"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /auth/verify:
    post:
      tags: [Authentication]
      summary: Verify an email sign-in code
      operationId: verifyEmailCode
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, otp]
              properties:
                email:
                  type: string
                  format: email
                otp:
                  type: string
                  pattern: '^[0-9]{6}$'
      responses:
        "200":
          description: Session established
          headers:
            Set-Cookie:
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                required: [ok, email]
                properties:
                  ok:
                    type: boolean
                  email:
                    type: string
                    format: email
                  username:
                    type: [string, "null"]
                  arm_tier:
                    type: [string, "null"]
        "401":
          $ref: "#/components/responses/Unauthorized"
  /kael/history/save:
    post:
      tags: [History]
      summary: Save a conversation
      operationId: saveHistory
      security:
        - {}
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [sessionId, messages]
              properties:
                sessionId:
                  type: string
                messages:
                  type: array
                  items:
                    $ref: "#/components/schemas/ChatMessage"
      responses:
        "200":
          $ref: "#/components/responses/OkResponse"
  /kael/history/list:
    post:
      tags: [History]
      summary: List conversation sessions
      operationId: listHistory
      security:
        - {}
        - kaelSession: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SessionRequest"
      responses:
        "200":
          description: Conversation summaries
          content:
            application/json:
              schema:
                type: object
                required: [sessions]
                properties:
                  sessions:
                    type: array
                    items:
                      $ref: "#/components/schemas/HistorySummary"
  /kael/history/load:
    post:
      tags: [History]
      summary: Load a conversation
      operationId: loadHistory
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdRequest"
      responses:
        "200":
          description: Conversation messages and title
          content:
            application/json:
              schema:
                type: object
                required: [messages]
                properties:
                  messages:
                    type: array
                    items:
                      $ref: "#/components/schemas/ChatMessage"
                  title:
                    type: string
  /kael/history/delete:
    post:
      tags: [History]
      summary: Delete a signed-in user conversation
      operationId: deleteHistory
      security:
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdRequest"
      responses:
        "200":
          $ref: "#/components/responses/OkResponse"
  /kael/memory/list:
    post:
      tags: [Memory]
      summary: List memory for the current identity or visitor session
      operationId: listMemory
      security:
        - {}
        - kaelSession: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SessionRequest"
      responses:
        "200":
          description: Stored memory entries
          content:
            application/json:
              schema:
                type: object
                required: [memories]
                properties:
                  memories:
                    type: array
                    items:
                      $ref: "#/components/schemas/Memory"
  /kael/memory/save:
    post:
      tags: [Memory]
      summary: Save or update a memory key
      operationId: saveMemory
      security:
        - {}
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [key, value]
              properties:
                sessionId:
                  type: string
                key:
                  type: string
                value: {}
      responses:
        "200":
          $ref: "#/components/responses/OkResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
  /kael/memory/delete:
    post:
      tags: [Memory]
      summary: Delete one memory key
      operationId: deleteMemory
      security:
        - {}
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [key]
              properties:
                sessionId:
                  type: string
                key:
                  type: string
      responses:
        "200":
          $ref: "#/components/responses/OkResponse"
  /kael/memory/clear:
    post:
      tags: [Memory]
      summary: Clear memory for the current identity or visitor session
      operationId: clearMemory
      security:
        - {}
        - kaelSession: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SessionRequest"
      responses:
        "200":
          $ref: "#/components/responses/OkResponse"
  /kael/rate:
    post:
      tags: [Feed]
      summary: Submit feedback on a KAEL response
      operationId: rateResponse
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [sessionId, rating]
              properties:
                sessionId:
                  type: string
                rating:
                  type: integer
                preview:
                  type: string
                  maxLength: 120
      responses:
        "200":
          $ref: "#/components/responses/OkResponse"
  /kael/feed:
    get:
      tags: [Feed]
      summary: Get featured items and response highlights
      operationId: getFeed
      responses:
        "200":
          description: Feed content
          content:
            application/json:
              schema:
                type: object
                required: [featured, highlights]
                properties:
                  featured:
                    type: array
                    items: {}
                  highlights:
                    type: array
                    items: {}
  /kael/featured:
    get:
      tags: [Feed]
      summary: Get featured KAEL conversations
      operationId: getFeatured
      responses:
        "200":
          description: Featured items
          content:
            application/json:
              schema:
                type: object
                required: [featured]
                properties:
                  featured:
                    type: array
                    items: {}
  /kael/profile/stats:
    post:
      tags: [Identity]
      summary: Get usage and identity summary for the current session
      operationId: getProfileStats
      security:
        - {}
        - kaelSession: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SessionRequest"
      responses:
        "200":
          description: Profile statistics
          content:
            application/json:
              schema:
                type: object
                required: [stats]
                properties:
                  stats:
                    type: object
                    additionalProperties: true
  /kael/identity:
    get:
      tags: [Identity]
      summary: Get linked KAEL identity state
      operationId: getKaelIdentity
      security:
        - {}
        - kaelSession: []
      responses:
        "200":
          description: Linked identity state
          content:
            application/json:
              schema:
                type: object
                required: [linked]
                properties:
                  linked:
                    type: boolean
                  user:
                    $ref: "#/components/schemas/User"
                  history_count:
                    type: integer
                  memory_count:
                    type: integer
  /kael/live:
    get:
      tags: [Health]
      summary: Get KAEL active visitor count
      operationId: getKaelLive
      responses:
        "200":
          description: Active visitor count
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActiveCount"
  /kael/docs/generate:
    post:
      tags: [Documents]
      summary: Generate a document with KAEL
      operationId: generateDocument
      security:
        - {}
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [topic]
              properties:
                topic:
                  type: string
                format:
                  type: string
                  default: markdown
      responses:
        "200":
          description: Generated document
          content:
            application/json:
              schema:
                type: object
                required: [document, title]
                properties:
                  document:
                    type: string
                  title:
                    type: string
        "429":
          $ref: "#/components/responses/RateLimited"
  /kael/docs/save:
    post:
      tags: [Documents]
      summary: Save a generated document
      operationId: saveDocument
      security:
        - {}
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [content]
              properties:
                title:
                  type: string
                topic:
                  type: string
                content:
                  type: string
                sessionId:
                  type: string
      responses:
        "200":
          description: Save result
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  id:
                    type: string
  /kael/docs/list:
    post:
      tags: [Documents]
      summary: List the signed-in user’s generated documents
      operationId: listDocuments
      security:
        - kaelSession: []
      responses:
        "200":
          description: Document summaries
          content:
            application/json:
              schema:
                type: object
                required: [docs]
                properties:
                  docs:
                    type: array
                    items: {}
  /kael/docs/load:
    post:
      tags: [Documents]
      summary: Load a generated document
      operationId: loadDocument
      security:
        - {}
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdRequest"
      responses:
        "200":
          description: Stored document
          content:
            application/json:
              schema:
                type: object
                properties:
                  doc: {}
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /kael/docs/delete:
    post:
      tags: [Documents]
      summary: Delete a signed-in user’s generated document
      operationId: deleteDocument
      security:
        - kaelSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdRequest"
      responses:
        "200":
          $ref: "#/components/responses/OkResponse"
        "403":
          $ref: "#/components/responses/Forbidden"
  /proxy/leaderboard/{game}:
    get:
      tags: [Integrations]
      summary: Proxy an AeThex Arcade leaderboard
      operationId: getLeaderboard
      parameters:
        - name: game
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Leaderboard entries or an empty list
          content:
            application/json:
              schema:
                type: array
                items: {}
components:
  securitySchemes:
    kaelSession:
      type: apiKey
      in: cookie
      name: kael_auth
      description: Secure HttpOnly KAEL session cookie.
    tenantKey:
      type: apiKey
      in: header
      name: x-tenant-key
      description: Server-side tenant integration key. Do not embed in public browser code.
  parameters:
    Redirect:
      name: redirect
      in: query
      required: false
      description: Allowed post-authentication return URL.
      schema:
        type: string
        format: uri
  responses:
    OkResponse:
      description: Operation result
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Ok"
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Unauthorized:
      description: Authentication failed
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Forbidden:
      description: Insufficient authorization
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    RateLimited:
      description: Daily or tenant rate limit reached
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    ServiceUnavailable:
      description: Required provider is not configured
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
  schemas:
    Ok:
      type: object
      required: [ok]
      properties:
        ok:
          type: boolean
    OkMessage:
      allOf:
        - $ref: "#/components/schemas/Ok"
        - type: object
          properties:
            message:
              type: string
    Error:
      type: object
      required: [error]
      properties:
        error:
          type: string
        detail:
          type: string
    Health:
      type: object
      required: [status, service, version, uptime, kb_entries, models, timestamp]
      properties:
        status:
          type: string
          example: online
        service:
          type: string
          example: aethex-api
        version:
          type: string
          example: "4.0"
        uptime:
          type: string
        kb_entries:
          type: integer
        models:
          type: object
          additionalProperties:
            type: [string, "null"]
        timestamp:
          type: string
          format: date-time
    ActiveCount:
      type: object
      required: [active]
      properties:
        active:
          type: integer
          minimum: 0
    BasicChatRequest:
      type: object
      required: [message]
      properties:
        message:
          type: string
        sessionId:
          type: string
        userId:
          type: string
    KaelRequest:
      allOf:
        - $ref: "#/components/schemas/BasicChatRequest"
        - type: object
          properties:
            source:
              type: string
            context: {}
    StreamRequest:
      type: object
      properties:
        message:
          type: string
        sessionId:
          type: string
        visitorId:
          type: string
        source:
          type: string
        context: {}
        model:
          type: string
          description: Client model key returned by /kael/models.
        agent:
          type: string
        images:
          type: array
          items:
            oneOf:
              - type: string
                format: uri
              - type: object
                properties:
                  url:
                    type: string
                    format: uri
                  base64:
                    type: string
                  media_type:
                    type: string
        tenant_key:
          type: string
          writeOnly: true
          description: Prefer the x-tenant-key header for server-side integrations.
      anyOf:
        - required: [message]
        - required: [images]
    Model:
      type: object
      required: [key, label, tier]
      properties:
        key:
          type: string
        label:
          type: string
        tier:
          type: string
    User:
      type: object
      additionalProperties: true
      properties:
        sub:
          type: string
        email:
          type: string
          format: email
        username:
          type: string
        arm_tier:
          type: string
        avatar:
          type: string
          format: uri
    ChatMessage:
      type: object
      required: [role, content]
      properties:
        role:
          type: string
          enum: [user, assistant, system]
        content:
          oneOf:
            - type: string
            - type: array
              items: {}
    SessionRequest:
      type: object
      properties:
        sessionId:
          type: string
    IdRequest:
      type: object
      required: [id]
      properties:
        id:
          type: string
    HistorySummary:
      type: object
      properties:
        id:
          type: string
        session_id:
          type: string
        title:
          type: string
        message_count:
          type: integer
        updated_at:
          type: string
          format: date-time
    Memory:
      type: object
      required: [key, value]
      properties:
        key:
          type: string
        value: {}
        updated_at:
          type: string
          format: date-time
