---
openapi: 3.0.1
info:
  title: CurryCMS API
  version: v1
  description: REST API for consuming curriculum content from CurryCMS
paths:
  "/api/v1/content_nodes/{id}":
    get:
      summary: Get content node with children
      tags:
      - Content Nodes
      description: |
        Returns a content node with its direct children (lazy-loading pattern).
        Each node includes `has_children` boolean to indicate if deeper children exist.
        Use this endpoint recursively to traverse the tree on demand.
      operationId: getContentNode
      security:
      - bearer_auth: []
      parameters:
      - name: id
        in: path
        required: true
        description: Content node ID
        schema:
          type: string
      responses:
        '200':
          description: Content node with children retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                        enum:
                        - content_node
                      attributes:
                        type: object
                        properties:
                          title:
                            type: string
                          node_type:
                            type: object
                          workflow_status:
                            type: string
                          position:
                            type: integer
                          depth:
                            type: integer
                          has_children:
                            type: boolean
                            description: True if this node has child nodes
                          attributes:
                            type: object
                      relationships:
                        type: object
                        properties:
                          curriculum:
                            type: object
                            properties:
                              data:
                                type: object
                                properties:
                                  id:
                                    type: string
                                  type:
                                    type: string
                          parent:
                            type: object
                            properties:
                              data:
                                type: object
                                nullable: true
                          children:
                            type: object
                            properties:
                              data:
                                type: array
                                description: Direct children with full attributes
                                items:
                                  "$ref": "#/components/schemas/content_node_with_has_children"
                  meta:
                    type: object
                    properties:
                      children_count:
                        type: integer
                      ancestry_depth:
                        type: integer
                  errors:
                    type: array
        '404':
          description: Content node not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/envelope_response"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/envelope_response"
  "/api/v1/curricula":
    get:
      summary: List curricula
      tags:
      - Curricula
      description: Returns a paginated list of curricula for the authenticated account
      operationId: listCurricula
      security:
      - bearer_auth: []
      parameters:
      - name: page
        in: query
        required: false
        description: 'Page number (default: 1)'
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 20, max: 100)'
        schema:
          type: integer
      - name: status
        in: query
        required: false
        description: Filter by status (e.g., "published")
        schema:
          type: string
      - name: root_only
        in: query
        required: false
        description: Exclude variants, show only base curricula
        schema:
          type: boolean
      responses:
        '200':
          description: Curricula retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/curriculum"
                  meta:
                    type: object
                    properties:
                      total_count:
                        type: integer
                      page:
                        type: integer
                      per_page:
                        type: integer
                  errors:
                    type: array
                    items:
                      type: object
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/envelope_response"
  "/api/v1/curricula/{id}":
    get:
      summary: Get curriculum with root nodes
      tags:
      - Curricula
      description: |
        Returns a curriculum with its root-level content nodes only (lazy-loading pattern).
        Each node includes `has_children` boolean to indicate if children exist.
        Use GET /content_nodes/:id to fetch children on demand.
      operationId: getCurriculum
      security:
      - bearer_auth: []
      parameters:
      - name: id
        in: path
        required: true
        description: Curriculum ID
        schema:
          type: string
      - name: status
        in: query
        required: false
        description: Filter nodes by status (e.g., "published")
        schema:
          type: string
      responses:
        '200':
          description: Curriculum with root nodes retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    allOf:
                    - "$ref": "#/components/schemas/curriculum"
                    - type: object
                      properties:
                        relationships:
                          type: object
                          properties:
                            content_nodes:
                              type: object
                              properties:
                                data:
                                  type: array
                                  items:
                                    "$ref": "#/components/schemas/content_node_with_has_children"
                  meta:
                    type: object
                    properties:
                      root_count:
                        type: integer
                        description: Number of root-level nodes
                      total_node_count:
                        type: integer
                        description: Total nodes in curriculum (all depths)
                  errors:
                    type: array
        '404':
          description: Curriculum not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/envelope_response"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/envelope_response"
  "/api/v1/health":
    get:
      summary: Health check
      tags:
      - System
      description: Returns API health status. No authentication required. Can optionally
        include auth to verify token validity.
      operationId: healthCheck
      security: []
      responses:
        '200':
          description: API is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  data:
                    type: object
                    properties:
                      status:
                        type: string
                        example: healthy
                      version:
                        type: string
                        example: v1
                      timestamp:
                        type: string
                        format: date-time
                  meta:
                    type: object
                    properties:
                      rails_env:
                        type: string
                        example: production
                      account_id:
                        type: string
                        nullable: true
                        description: Present when authenticated
                  errors:
                    type: array
                    items:
                      type: object
servers:
- url: "{protocol}://{host}"
  variables:
    protocol:
      default: https
      enum:
      - http
      - https
    host:
      default: currycms.example.com
components:
  securitySchemes:
    bearer_auth:
      type: http
      scheme: bearer
      description: API token authentication. Get token from Settings > Developer.
  schemas:
    envelope_response:
      type: object
      properties:
        status:
          type: string
          enum:
          - ok
          - error
        data:
          type: object
          nullable: true
        meta:
          type: object
        errors:
          type: array
          items:
            "$ref": "#/components/schemas/error"
      required:
      - status
      - errors
    error:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
        field:
          type: string
          nullable: true
      required:
      - code
      - message
    curriculum:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
          enum:
          - curriculum
        attributes:
          type: object
          properties:
            name:
              type: string
            description:
              type: string
              nullable: true
            structure_name:
              type: string
            node_count:
              type: integer
            is_variant:
              type: boolean
            parent_id:
              type: string
              nullable: true
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
    content_node:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
          enum:
          - content_node
        attributes:
          type: object
          properties:
            title:
              type: string
            node_type:
              type: string
            workflow_status:
              type: string
              enum:
              - draft
              - in_review
              - approved
              - published
            position:
              type: integer
            depth:
              type: integer
            attributes:
              type: object
              additionalProperties: true
    content_node_with_has_children:
      type: object
      description: Content node with has_children indicator for lazy-loading tree
        traversal
      properties:
        id:
          type: string
        type:
          type: string
          enum:
          - content_node
        attributes:
          type: object
          properties:
            title:
              type: string
            node_type:
              type: object
              properties:
                name:
                  type: string
                icon:
                  type: string
                  nullable: true
            ordinal_label:
              type: string
              nullable: true
            type_display:
              type: string
            workflow_status:
              type: string
              enum:
              - draft
              - in_review
              - approved
              - published
            position:
              type: integer
            depth:
              type: integer
            has_children:
              type: boolean
              description: True if this node has child nodes (use GET /content_nodes/:id
                to fetch them)
            attributes:
              type: object
              additionalProperties: true
security:
- bearer_auth: []
