openapi: 3.0.3
info:
  title: TAFMEDS API
  description: |
    TAFMEDS is a fluency-building platform for behaviour-analytic certification exams
    (BCBA, BCaBA, RBT), operated by ClassroomPulse.io.

    This document describes the endpoints that are reachable without a support ticket.
    Most product functionality is exposed to agents through the Model Context Protocol
    server rather than REST — see `/mcp/mcp` below, the agent instructions at
    https://tafmeds.com/agents.md, and the developer documentation at
    https://tafmeds.com/developers.

    Content negotiation: every public page URL also serves a Markdown representation
    when requested with `Accept: text/markdown` (https://acceptmarkdown.com).

    Versioning: every `/api/...` path is also reachable under `/api/v1/...`
    (for example `/api/v1/health?probe=liveness`). Responses carry an
    `X-API-Version` header.
  version: 1.1.0
  contact:
    name: TAFMEDS Support
    email: support@tafmeds.com
    url: https://tafmeds.com/contact
  license:
    name: Proprietary
    url: https://tafmeds.com/terms

servers:
  - url: https://tafmeds.com
    description: Production

externalDocs:
  description: TAFMEDS developer and API documentation
  url: https://tafmeds.com/developers

tags:
  - name: Platform
    description: Unauthenticated platform status.
  - name: Agents
    description: Machine-readable entry points for AI agents.

paths:
  /api/health:
    get:
      operationId: getHealthStatus
      tags: [Platform]
      summary: Platform health
      description: |
        Liveness is public: call with `probe=liveness` and no credentials to get a small
        status document. Readiness and deep checks expose configuration detail and require
        the internal API key, so any other combination of parameters returns 401 to an
        anonymous caller.
      parameters:
        - name: probe
          in: query
          description: |
            `liveness` is answerable anonymously. `readiness` (the default) requires
            authentication.
          required: false
          schema:
            type: string
            enum: [liveness, readiness]
            default: readiness
        - name: deep
          in: query
          description: |
            Include database connectivity in the check. Requires authentication.
          required: false
          schema:
            type: string
            enum: ['true', 'false']
            default: 'false'
      responses:
        '200':
          description: Platform is healthy
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/PublicHealthStatus'
                  - $ref: '#/components/schemas/HealthStatus'
        '401':
          description: |
            Authentication required. Returned to anonymous callers for anything other
            than `probe=liveness`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Platform is unhealthy

  /mcp/mcp:
    post:
      operationId: callMcpServer
      tags: [Agents]
      summary: TAFMEDS Model Context Protocol server
      description: |
        JSON-RPC 2.0 over MCP Streamable HTTP. `initialize`, `tools/list`, and the
        `generate_flashcards` and `quiz_me` tools need no credentials. The learner-scoped
        tools (`get_user_decks`, `get_deck_cards`, `get_user_progress`, `get_due_cards`,
        `submit_review`) take the learner's own Firebase ID token as an `auth_token`
        argument; users mint one at Settings → API Access.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JsonRpcRequest'
            examples:
              listTools:
                summary: List the available tools
                value:
                  jsonrpc: '2.0'
                  id: 1
                  method: tools/list
      responses:
        '200':
          description: |
            JSON-RPC result. Delivered as a `text/event-stream` message frame.
          content:
            text/event-stream:
              schema:
                type: string
        '400':
          description: Malformed JSON-RPC request

components:
  schemas:
    PublicHealthStatus:
      type: object
      description: Anonymous liveness response.
      properties:
        status:
          type: string
          enum: [healthy]
        probe:
          type: string
          enum: [liveness]
        timestamp:
          type: string
          format: date-time
      required: [status, probe, timestamp]

    HealthStatus:
      type: object
      description: Authenticated readiness response.
      properties:
        status:
          type: string
          enum: [healthy, degraded, unhealthy]
        probe:
          type: string
          enum: [liveness, readiness]
        deep:
          type: boolean
        timestamp:
          type: string
          format: date-time
        uptime:
          type: integer
          description: Server uptime in seconds
        version:
          type: string
        checks:
          type: object
          description: Per-service configuration and readiness detail.

    JsonRpcRequest:
      type: object
      properties:
        jsonrpc:
          type: string
          enum: ['2.0']
        id:
          oneOf:
            - type: string
            - type: integer
        method:
          type: string
          description: e.g. `initialize`, `tools/list`, `tools/call`
        params:
          type: object
      required: [jsonrpc, method]

    Error:
      type: object
      properties:
        error:
          type: string
      required: [error]
