openapi: "3.1.0"
info:
  title: AEVNI API
  description: |
    Token Intelligence — optimize and create prompts programmatically.
    BYOK (Bring Your Own Key): pass your provider API key in each request.
    Rate limit: 20 requests/min per IP.
  version: "1.0.0"
  contact:
    name: AEVNI
    url: https://aevni.website

servers:
  - url: https://aevni.website
    description: Production

tags:
  - name: Optimize
    description: Reduce tokens in an existing prompt
  - name: Create
    description: Generate a new prompt from a description
  - name: Share
    description: Share a prompt via a public link
  - name: Meta
    description: Providers, models directory, health

paths:

  /api/optimize:
    post:
      tags: [Optimize]
      summary: Optimize a prompt (synchronous)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OptimizeRequest'
            example:
              prompt: "Hola, por favor podrías analizar este código Python y decirme si tiene bugs."
              provider: pollinations
              mode: auto
      responses:
        "200":
          description: Optimization result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OptimizeResponse'
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/MissingKey'
        "413":
          $ref: '#/components/responses/TooLarge'
        "429":
          $ref: '#/components/responses/RateLimit'
        "503":
          $ref: '#/components/responses/ProviderDown'

  /api/optimize/stream:
    post:
      tags: [Optimize]
      summary: Optimize a prompt (streaming SSE)
      description: |
        Same as `/api/optimize` but streams tokens via Server-Sent Events.
        Events: `token` (partial text), `done` (full result), `error`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OptimizeRequest'
      responses:
        "200":
          description: SSE stream
          content:
            text/event-stream:
              schema:
                type: string
                description: |
                  Newline-delimited SSE events.
                  `data: {"type":"token","text":"..."}` — partial chunk
                  `data: {"type":"done",...full OptimizeResponse...}` — final result
                  `data: {"type":"error","message":"..."}` — error

  /api/create:
    post:
      tags: [Create]
      summary: Generate a new prompt from a description
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRequest'
      responses:
        "200":
          description: Generated prompt
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResponse'
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/MissingKey'
        "429":
          $ref: '#/components/responses/RateLimit'

  /api/create/stream:
    post:
      tags: [Create]
      summary: Generate a new prompt (streaming SSE)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRequest'
      responses:
        "200":
          description: SSE stream (same event format as /api/optimize/stream)
          content:
            text/event-stream:
              schema:
                type: string

  /api/share:
    post:
      tags: [Share]
      summary: Create a shareable link for a prompt
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [text_es, op]
              properties:
                text_es:
                  type: string
                  description: Prompt text in Spanish (or original language)
                text_en:
                  type: string
                  description: Prompt text in English (optional)
                op:
                  type: string
                  enum: [optimize, create]
                prompt_type:
                  type: string
      responses:
        "200":
          description: Share link created
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    example: "aB3xYz9q"
                  url:
                    type: string
                    example: "https://aevni.website/p/aB3xYz9q"

  /api/models:
    get:
      tags: [Meta]
      summary: Model directory with use-case rankings
      responses:
        "200":
          description: Directory of models organized by use case
          content:
            application/json:
              schema:
                type: object
                properties:
                  directory:
                    type: array
                    items:
                      type: object

  /api/providers:
    get:
      tags: [Meta]
      summary: List supported providers
      responses:
        "200":
          description: Provider list
          content:
            application/json:
              schema:
                type: object
                properties:
                  providers:
                    type: array
                    items:
                      type: string
                    example: [pollinations, gemini, openai, anthropic, groq, deepseek, cerebras, sambanova, openrouter]

  /health:
    get:
      tags: [Meta]
      summary: Health check
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  version:
                    type: string
                    example: "5.0"

  /ping:
    get:
      tags: [Meta]
      summary: Keep-alive ping
      responses:
        "200":
          description: pong
          content:
            text/plain:
              schema:
                type: string
                example: pong

components:

  schemas:

    OptimizeRequest:
      type: object
      required: [prompt]
      properties:
        prompt:
          type: string
          description: The prompt text to optimize (max 500,000 chars)
          example: "Hola, buenos días. Por favor me gustaría que analizaras este código Python."
        provider:
          type: string
          enum: [pollinations, gemini, openai, anthropic, groq, deepseek, cerebras, sambanova, openrouter]
          default: pollinations
        mode:
          type: string
          enum: [auto, pro, lite]
          default: auto
          description: |
            auto — picks pro or lite based on prompt content;
            pro — XML schema (higher quality);
            lite — plain dense text (fewer tokens)
        api_key:
          type: string
          description: Your provider API key (required for all providers except Pollinations)

    OptimizeResponse:
      type: object
      properties:
        optimized:
          type: string
          description: Optimized prompt in original language (ES or EN)
        optimized_en:
          type: string
          description: Optimized prompt in English
        report:
          $ref: '#/components/schemas/EfficiencyReport'
        quality:
          $ref: '#/components/schemas/QualityScore'
        recommendation:
          type: object
          description: Recommended models for this prompt
        warnings:
          type: array
          items:
            type: object
        bad_practices:
          type: array
          items:
            type: object
          description: Bad prompt practices detected and removed
        prompt_type:
          type: string
          example: task_structured
        meta:
          type: object
          properties:
            provider:
              type: string
            mode:
              type: string
            mode_resolved:
              type: string
            cached:
              type: boolean
              description: true if result was served from cache

    EfficiencyReport:
      type: object
      properties:
        original_tokens:
          type: integer
        optimized_tokens:
          type: integer
        tokens_saved:
          type: integer
        token_reduction_pct:
          type: number
          format: float
        original_chars:
          type: integer
        optimized_chars:
          type: integer
        chars_saved:
          type: integer
        detected_language:
          type: string
          enum: [es, en]
        density_original:
          type: number
        density_optimized:
          type: number

    QualityScore:
      type: object
      description: Heuristic quality score 0-100, no API call
      properties:
        original:
          $ref: '#/components/schemas/QualityResult'
        optimized:
          $ref: '#/components/schemas/QualityResult'

    QualityResult:
      type: object
      properties:
        score:
          type: integer
          minimum: 0
          maximum: 100
        grade:
          type: string
          enum: [A, B, C, D]
        breakdown:
          type: object
          properties:
            accion:
              type: integer
              description: Clear action / imperative verb (0-25)
            sin_ruido:
              type: integer
              description: No fluff / politeness (0-25)
            especificidad:
              type: integer
              description: Constraints, format, context (0-25)
            eficiencia:
              type: integer
              description: Lexical density in optimal range (0-25)

    CreateRequest:
      type: object
      required: [description]
      properties:
        description:
          type: string
          description: What the prompt should do
        requirements:
          type: string
          description: One constraint per line
        output_format:
          type: string
          description: Expected output format (JSON, Markdown, etc.)
        tone:
          type: string
          enum: [neutral, formal, technical, simple, direct]
          default: neutral
        audience:
          type: string
          enum: [general, developer, manager, student, expert]
          default: general
        forced_type:
          type: string
          description: Force a specific prompt type (leave empty for auto-detection)
        provider:
          type: string
          default: pollinations
        api_key:
          type: string

    CreateResponse:
      type: object
      properties:
        created_prompt_es:
          type: string
        created_prompt_en:
          type: string
        prompt_type:
          type: string
          enum: [conversational, task_structured, system_prompt, agentic, creative]
        tokens_es:
          type: integer
        tokens_en:
          type: integer
        explanation:
          type: string
        tips:
          type: array
          items:
            type: string

  responses:

    BadRequest:
      description: Invalid parameters
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              code:
                type: string

    MissingKey:
      description: API key missing or invalid
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              code:
                type: string
                example: missing_api_key

    TooLarge:
      description: Prompt exceeds 500,000 characters
      content:
        application/json:
          schema:
            type: object

    RateLimit:
      description: Rate limit exceeded (20 req/min)
      content:
        application/json:
          schema:
            type: object

    ProviderDown:
      description: Provider temporarily unavailable
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              code:
                type: string
                example: provider_unavailable
