openapi: 3.0.3
info:
  title: Talents.kids School Integration API
  description: |
    API for school integration with children's AI-based talent analysis platform.

    ## Authentication
    Use API key in format: `Bearer sk_school_[timestamp]_[hash]`

    ## Base URL
    Production: `https://www.talents.kids/api/school/v1`

    ## Key Features
    - **Talent Analysis**: AI-powered analysis of student work with 15+ talent categories
    - **ADHD Insights**: Optional ADHD assessment across 6 domains (when adhd=true)
    - **Educational Materials**: Generate personalized PDF worksheets and learning materials
    - **Visual Content**: Create coloring pages and visual worksheets
    - **Comprehensive Reports**: Full talent profiles with actionable recommendations

    ## Rate Limiting & Subscription Plans

    All endpoints are rate-limited based on your subscription plan. Users with credits balance > 0 automatically get **Beacon** tier limits.

    ### Subscription Plans

    | Plan | Base Limit (rpm/rph) | Monthly Cost | Description |
    |------|---------------------|--------------|-------------|
    | **School** | 100 rpm / 2000 rph | Premium | Large institutions |
    | **Kindergarten** | 50 rpm / 1000 rph | Standard | Medium schools |
    | **Beacon** | 80 rpm / 1500 rph | Enterprise | Maximum tier (auto for users with credits) |
    | **Flame** | 50 rpm / 800 rph | Professional | Growing schools |
    | **Spark** | 30 rpm / 500 rph | Starter | Small schools |
    | **Free** | 10 rpm / 100 rph | $0 | Trial users |

    ### Endpoint Multipliers

    Different endpoints have different rate limits based on computational cost:

    - `/analyze` - **2x** multiplier (e.g., 200 rpm for school plan)
    - `/analyze/status/*` - **5x** multiplier (lightweight polling)
    - `/students` POST - **0.5x** multiplier (database writes)
    - `/students/*/materials/generate` - **0.3x** multiplier (resource intensive)

    ### Burst Allowance

    All plans include **150% burst allowance** for 10-second windows to handle traffic spikes (e.g., school plan can burst to 150 rpm for 10 seconds).

    ### Automatic Retry Queue

    When rate limited, requests to `/analyze` are automatically queued and retried when limits reset. Check `retry_queued` and `queue_position` in 429 responses.

    ## New in v1.3 (Language Support)
    - **Multi-language AI responses**: Support for 10 languages (en, de, fr, it, es, pt, ru, ar, hi, ko)
    - **Hindi (हिन्दी), Korean (한국어) support**: For India and South Korea markets
    - **Cultural adaptation**: AI responses adapted to target language culture
    - **JSON structure preserved**: Category IDs and keys remain in English

    ## New in v1.2
    - Enhanced rate limiting with 6 subscription plans
    - Endpoint-specific rate multipliers
    - Burst allowance for traffic spikes
    - Automatic retry queue for failed requests
    - Credits users get maximum (beacon) limits

    ## New in v1.1
    - ADHD analysis parameter for detailed behavioral insights
    - Enhanced context support for better analysis accuracy
    - Materials generation with PDF download URLs
    - Visual content generation with base64-encoded images
    - Improved async processing with webhook support
  version: 1.3.0
  contact:
    name: Talents.kids Support to get API key
    email: support@talents.kids
    url: https://www.talents.kids/contact

servers:
  - url: http://localhost:3000/api/school/v1
    description: Local development server
  - url: https://www.talents.kids/api/school/v1
    description: Production server

security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: "API key format: sk_school_[timestamp]_[hash]"

  schemas:
    ADHDDomain:
      type: object
      properties:
        score:
          type: number
          minimum: 0
          maximum: 10
          description: Score for this ADHD domain
        indicators:
          type: array
          items:
            type: string
          description: Observed indicators for this domain
        analysis:
          type: string
          description: Detailed analysis of this domain
        severity:
          type: string
          enum: [none, mild, moderate, severe]
          description: Severity level for this domain

    Student:
      type: object
      required:
        - external_student_id
        - name
      properties:
        id:
          type: string
          format: uuid
          description: Internal student ID
          readOnly: true
        external_student_id:
          type: string
          description: Your school's student ID
          example: "STU-2025-001"
        name:
          type: string
          description: Student full name
          example: "John Smith"
        age:
          type: integer
          minimum: 3
          maximum: 18
          description: Student age
          example: 12
        grade_level:
          type: string
          description: Grade or class level
          example: "7th grade"
        created_at:
          type: string
          format: date-time
          readOnly: true
        analysis_count:
          type: integer
          readOnly: true
          description: Total number of analyses
        last_analysis_date:
          type: string
          format: date-time
          readOnly: true
        recent_talents:
          type: array
          items:
            type: string
          readOnly: true
          description: Recently identified talents

    AnalysisRequest:
      type: object
      required:
        - student_id
        - student_age
        - document_type
        - media
      properties:
        student_id:
          type: string
          description: External student ID
        student_age:
          type: integer
          minimum: 3
          maximum: 18
        document_type:
          type: string
          enum:
            - plain_text_files
            - code_files
            - general_images
            - math_formulas
            - audio_recordings
            - video_content
          description: Type of content being analyzed
        preset_activated:
          type: string
          description: |
            Optional override to force the general preset and skip automatic mapping by document_type.
            Allowed values: "general". For backward compatibility, "talent_general" is also accepted and normalized to "general".
          enum: [general, talent_general]
          example: general
        media:
          type: array
          minItems: 1
          items:
            type: object
            required:
              - file
              - filename
              - mime_type
            properties:
              file:
                type: string
                format: byte
                description: Base64 encoded file content
              filename:
                type: string
                example: "essay.txt"
              mime_type:
                type: string
                example: "text/plain"
        adhd:
          type: boolean
          description: Enable ADHD-specific analysis and insights
          default: false
        context:
          type: object
          description: Additional context about the student's work
          properties:
            feelings:
              type: string
              enum:
                - excited
                - focused
                - confident
                - frustrated
                - confused
              description: Student's emotional state during work
            time_spent:
              type: integer
              minimum: 1
              maximum: 300
              description: Time spent on the task in minutes
            effort:
              type: string
              enum:
                - low
                - medium
                - high
              description: Level of effort put into the work
            additional_info:
              type: string
              maxLength: 500
              description: Any additional context or observations
        language:
          type: string
          enum: [en, de, fr, it, es, pt, ru, ar, hi, ko]
          default: en
          description: |
            Language for AI analysis response (reasoning and suggestions).
            Supported languages:
            - en: English (default)
            - de: German (Deutsch)
            - fr: French (Français)
            - it: Italian (Italiano)
            - es: Spanish (Español)
            - pt: Portuguese (Português)
            - ru: Russian (Русский)
            - ar: Arabic (العربية)
            - hi: Hindi (हिन्दी) - NEW in v1.3.0
            - ko: Korean (한국어) - NEW in v1.3.0

            Note: JSON structure and category IDs remain in English regardless of language setting.
        webhook_url:
          type: string
          format: uri
          description: Optional webhook URL for async processing

    AnalysisResponse:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Analysis ID
        status:
          type: string
          enum: [pending, processing, completed, failed]
        student_id:
          type: string
        created_at:
          type: string
          format: date-time
        estimated_completion_time:
          type: integer
          description: Estimated seconds to completion
        message:
          type: string

    AnalysisResult:
      type: object
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          enum: [completed]
        analysis_result:
          type: object
          properties:
            keyTalents:
              type: array
              items:
                type: string
              description: Identified talent categories
            detailedInsights:
              type: object
              description: Detailed analysis by category
            overallSummary:
              type: string
              description: General summary of findings
            confidence_score:
              type: number
              format: float
              minimum: 0
              maximum: 100
            finalTalentProfile:
              type: object
              description: Detailed talent scores and insights
              additionalProperties:
                type: object
                properties:
                  finalScore:
                    type: integer
                    minimum: 0
                    maximum: 10
                  finalReasoning:
                    type: string
                  finalSuggestions:
                    type: array
                    items:
                      type: string
            adhdInsights:
              type: object
              description: ADHD-specific analysis (when adhd=true)
              properties:
                overallAssessment:
                  type: object
                  properties:
                    riskLevel:
                      type: string
                      enum: [low, moderate, high]
                    confidence:
                      type: number
                      minimum: 0
                      maximum: 100
                domains:
                  type: object
                  properties:
                    impulsivity:
                      $ref: "#/components/schemas/ADHDDomain"
                    inattention:
                      $ref: "#/components/schemas/ADHDDomain"
                    hyperactivity:
                      $ref: "#/components/schemas/ADHDDomain"
                    sensoryProcessing:
                      $ref: "#/components/schemas/ADHDDomain"
                    executiveFunctions:
                      $ref: "#/components/schemas/ADHDDomain"
                    emotionalRegulation:
                      $ref: "#/components/schemas/ADHDDomain"
                recommendations:
                  type: object
                  properties:
                    forParents:
                      type: array
                      items:
                        type: string
                    forTeachers:
                      type: array
                      items:
                        type: string
                    professionalSupport:
                      type: array
                      items:
                        type: string

    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
        details:
          type: string
          description: Additional error details
        timestamp:
          type: string
          format: date-time
        retry_queued:
          type: boolean
          description: "(429 only) Whether request was automatically queued for retry"
        queue_position:
          type: integer
          description: "(429 only) Position in retry queue"
        message:
          type: string
          description: "(429 only) Additional message about retry queue status"

    Pagination:
      type: object
      properties:
        page:
          type: integer
          minimum: 1
        limit:
          type: integer
          minimum: 10
          maximum: 100
        total:
          type: integer
        has_more:
          type: boolean

  responses:
    Unauthorized:
      description: Authentication failed
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error: "Invalid API key"
            details: "The provided API key is invalid or inactive"

    RateLimitExceeded:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            standard:
              summary: Standard rate limit error
              value:
                error: "Rate limit exceeded"
                details: "You have exceeded the rate limit for this endpoint"
                timestamp: "2024-11-15T10:30:00Z"
            with_retry_queue:
              summary: Rate limit with automatic retry queue (analyze endpoint)
              value:
                error: "Rate limit exceeded"
                details: "You have exceeded the rate limit for this endpoint"
                retry_queued: true
                queue_position: 5
                message: "Request queued for retry when rate limit resets"
                timestamp: "2024-11-15T10:30:00Z"
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: Request limit per window (varies by plan and endpoint multiplier)
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Remaining requests in current window
        X-RateLimit-Reset:
          schema:
            type: integer
          description: Unix timestamp when limit resets
        X-RateLimit-Plan:
          schema:
            type: string
            enum: [school, kindergarten, beacon, flame, spark, free]
          description: Current subscription plan
        X-RateLimit-Burst-Remaining:
          schema:
            type: integer
          description: Remaining burst allowance (150% of base limit for 10 seconds)

paths:
  /health:
    get:
      summary: Health check
      description: Check API availability and authentication
      operationId: healthCheck
      tags:
        - System
      responses:
        "200":
          description: API is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "healthy"
                  school:
                    type: object
                    properties:
                      id:
                        type: string
                      name:
                        type: string
                  timestamp:
                    type: string
                    format: date-time
        "401":
          $ref: "#/components/responses/Unauthorized"

  /students:
    get:
      summary: List students
      description: Get all students for your school
      operationId: listStudents
      tags:
        - Students
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 10
            maximum: 100
            default: 20
        - name: search
          in: query
          schema:
            type: string
          description: Search by name or ID
      responses:
        "200":
          description: List of students
          content:
            application/json:
              schema:
                type: object
                properties:
                  students:
                    type: array
                    items:
                      $ref: "#/components/schemas/Student"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"

    post:
      summary: Create student
      description: Register a new student in the system
      operationId: createStudent
      tags:
        - Students
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - external_student_id
                - name
              properties:
                external_student_id:
                  type: string
                name:
                  type: string
                age:
                  type: integer
                  minimum: 3
                  maximum: 18
                grade_level:
                  type: string
      responses:
        "201":
          description: Student created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Student"
        "400":
          description: Invalid request data
        "401":
          $ref: "#/components/responses/Unauthorized"
        "409":
          description: Student already exists
        "429":
          $ref: "#/components/responses/RateLimitExceeded"

  /students/{id}:
    get:
      summary: Get student details
      description: Get detailed information about a specific student
      operationId: getStudent
      tags:
        - Students
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Student details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Student"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          description: Student not found

  /students/{id}/analyses:
    get:
      summary: Get student analyses
      description: Get all analyses for a specific student
      operationId: getStudentAnalyses
      tags:
        - Students
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: List of analyses
          content:
            application/json:
              schema:
                type: object
                properties:
                  analyses:
                    type: array
                    items:
                      $ref: "#/components/schemas/AnalysisResult"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          description: Student not found

  /analyze:
    post:
      summary: Submit analysis request
      description: Submit student work for talent analysis
      operationId: submitAnalysis
      tags:
        - Analysis
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AnalysisRequest"
      responses:
        "200":
          description: Analysis submitted successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalysisResponse"
        "400":
          description: Invalid request data
        "401":
          $ref: "#/components/responses/Unauthorized"
        "402":
          description: Insufficient balance
        "429":
          $ref: "#/components/responses/RateLimitExceeded"

  /analyze/status/{id}:
    get:
      summary: Check analysis status
      description: Get the current status of an analysis
      operationId: getAnalysisStatus
      tags:
        - Analysis
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Analysis status
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  status:
                    type: string
                    enum: [pending, processing, completed, failed]
                  progress:
                    type: integer
                    minimum: 0
                    maximum: 100
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          description: Analysis not found

  /analyses/{id}/result:
    get:
      summary: Get analysis results
      description: Retrieve the completed analysis results
      operationId: getAnalysisResult
      tags:
        - Analysis
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Analysis results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalysisResult"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          description: Analysis not found
        "425":
          description: Analysis not yet complete

  /analytics:
    get:
      summary: Get analytics
      description: Get usage analytics and statistics
      operationId: getAnalytics
      tags:
        - Analytics
      parameters:
        - name: period
          in: query
          schema:
            type: string
            enum: [day, week, month, year]
            default: month
      responses:
        "200":
          description: Analytics data
          content:
            application/json:
              schema:
                type: object
                properties:
                  overview:
                    type: object
                    properties:
                      total_students:
                        type: integer
                      total_analyses:
                        type: integer
                      period_analyses:
                        type: integer
                      unique_talents_identified:
                        type: integer
                  top_talents:
                    type: array
                    items:
                      type: object
                      properties:
                        talent:
                          type: string
                        count:
                          type: integer
        "401":
          $ref: "#/components/responses/Unauthorized"

  /balance:
    get:
      summary: Check balance
      description: Get current credit balance and usage
      operationId: getBalance
      tags:
        - Billing
      responses:
        "200":
          description: Balance information
          content:
            application/json:
              schema:
                type: object
                properties:
                  balance:
                    type: number
                    format: float
                  usage:
                    type: object
                    properties:
                      current_month:
                        type: integer
                      total:
                        type: integer
        "401":
          $ref: "#/components/responses/Unauthorized"

  /students/{id}/materials/generate:
    post:
      summary: Generate education materials (PDF)
      description: Generate subject-specific learning materials for the student and return a signed download URL. The PDF includes tasks, answer keys, rubrics, and an upload page for students.
      operationId: generateStudentMaterials
      tags:
        - Students
      parameters:
        - name: id
          in: path
          required: true
          description: Student UUID (internal ID)
          schema:
            type: string
            format: uuid
            example: "0cc8a723-ac98-4fe7-97cd-66aa9a540da7"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - talentId
              properties:
                talentId:
                  type: string
                  description: Subject/talent identifier
                  example: "math"
                  enum: [math, physics, chemistry, biology, linguistics]
                materialType:
                  type: string
                  enum: [worksheet, mini-project, reading]
                  default: worksheet
                  description: Type of educational material
                difficulty:
                  type: string
                  enum: [easy, medium, hard]
                  default: medium
                  description: Difficulty level of the material
                gradeLevel:
                  type: integer
                  minimum: 1
                  maximum: 12
                  description: Student's grade level (optional, uses student profile if not provided)
                timeAvailable:
                  type: string
                  enum: [short, medium, long]
                  default: medium
                  description: Available time for completion
                interestLevel:
                  type: string
                  enum: [low, medium, high]
                  default: medium
                  description: Student's interest level in the subject
                language:
                  type: string
                  enum: [en, de, fr, it, es, pt, ru, ar, hi, ko]
                  default: en
                  description: Language for the materials (all 10 supported languages)
      responses:
        "200":
          description: Materials generated successfully with PDF download URL
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "success"
                  message:
                    type: string
                    example: "Educational materials generated"
                  downloadUrl:
                    type: string
                    format: uri
                    description: Signed URL to download the PDF (valid for 1 hour)
                    example: "https://storage.supabase.co/materials/math-worksheet.pdf?token=..."
                  metadata:
                    type: object
                    properties:
                      materialId:
                        type: string
                      subject:
                        type: string
                      gradeLevel:
                        type: integer
                      difficulty:
                        type: string
                      materialType:
                        type: string
                      estimatedTimeMin:
                        type: integer
                      pageCount:
                        type: integer
                      language:
                        type: string
                      generatedAt:
                        type: string
                        format: date-time
        "400":
          description: Invalid request data
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"

  /students/{id}/visuals/generate:
    post:
      summary: Generate visuals (coloring pages/worksheets)
      description: Generate printable coloring pages or visual worksheets based on student's talents and interests. Returns base64-encoded images.
      operationId: generateStudentVisuals
      tags:
        - Students
      parameters:
        - name: id
          in: path
          required: true
          description: Student UUID (internal ID)
          schema:
            type: string
            format: uuid
            example: "0cc8a723-ac98-4fe7-97cd-66aa9a540da7"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                  enum: [coloring, worksheet]
                  default: coloring
                  description: Type of visual to generate
                count:
                  type: integer
                  minimum: 1
                  maximum: 6
                  default: 1
                  description: Number of images to generate
                ratio:
                  type: string
                  enum: ["1:1", "2:3", "3:2"]
                  default: "1:1"
                  description: Aspect ratio for the images
                age:
                  type: integer
                  minimum: 3
                  maximum: 18
                  description: Override student's age (optional)
                theme:
                  type: string
                  description: Optional theme for the visuals
                  example: "space adventure"
      responses:
        "200":
          description: Visuals generated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "success"
                  message:
                    type: string
                    example: "Visuals generated"
                  images:
                    type: array
                    description: Array of generated images
                    items:
                      type: object
                      properties:
                        dataUrl:
                          type: string
                          description: Base64-encoded image data URL
                          example: "data:image/png;base64,iVBORw0..."
                        mimeType:
                          type: string
                          example: "image/png"
                        width:
                          type: integer
                          example: 1024
                        height:
                          type: integer
                          example: 1024
                  metadata:
                    type: object
                    properties:
                      prompt:
                        type: string
                        description: The prompt used for generation
                      theme:
                        type: string
                      studentTalents:
                        type: array
                        items:
                          type: string
                        description: Student's talents used for personalization
                      generatedAt:
                        type: string
                        format: date-time
        "400":
          description: Invalid request data
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"

  /students/{id}/talents/full-report:
    post:
      summary: Generate full talents report
      description: Generate a comprehensive PDF report with all student's talent analyses.
      operationId: generateFullTalentsReport
      tags:
        - Students
      parameters:
        - name: id
          in: path
          required: true
          description: Student UUID (internal ID)
          schema:
            type: string
            format: uuid
            example: "0cc8a723-ac98-4fe7-97cd-66aa9a540da7"
      responses:
        "200":
          description: Report generation result with access URL and token
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "success"
                  message:
                    type: string
                    example: "Full report link generated"
                  reportUrl:
                    type: string
                    format: uri
                    description: Web URL to view the report online
                    example: "https://www.talents.kids/school/students/0cc8a723/report"
                  accessToken:
                    type: string
                    description: JWT token for accessing the web report
                  studentName:
                    type: string
                    example: "John Smith"
                  studentId:
                    type: string
                    format: uuid
                  reportData:
                    type: object
                    description: Basic report metadata
                    properties:
                      generatedAt:
                        type: string
                        format: date-time
                      studentName:
                        type: string
                      studentId:
                        type: string
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"

tags:
  - name: System
    description: System endpoints
  - name: Students
    description: Student management
  - name: Analysis
    description: Talent analysis operations
  - name: Analytics
    description: Usage analytics
  - name: Billing
    description: Balance and usage
