openapi: 3.0.3
info:
  title: All The Words API
  description: |
    Word finder API for Wordle, Scrabble, crossword puzzles, and anagram solving.
    Supports 60+ languages with pattern matching, anagram solving, and dictionary statistics.
    
    **Features:**
    - Pattern matching with wildcards (`_` and `?`)
    - Anagram solving with blank tile support (`_` and `?`)
    - Dictionary statistics and analytics
    - Multi-language support
    - MCP (Model Context Protocol) JSON-RPC endpoint
    - OpenAI-compatible chat completions
    
    **Rate Limiting:**
    - 120 requests per 60 seconds for all endpoints except `/api/v1/healthz`
    - Rate limit headers: `X-RateLimit-Limit`, `X-RateLimit-Window`, `Retry-After`
  version: 1.0.0
  contact:
    name: All The Words
    url: https://allthewords.app
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.allthewords.app
    description: Production server

paths:
  /api/v1/healthz:
    get:
      tags:
        - Health
      summary: Health check
      description: Health check endpoint for uptime and deployment probes. Returns service status.
      operationId: healthz
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "ok"
        '503':
          description: Service is unavailable
      security: []

  /api/v1/languages:
    get:
      tags:
        - Languages
      summary: List supported languages
      description: Returns all supported languages with their dictionary sizes and word counts.
      operationId: listLanguages
      responses:
        '200':
          description: List of supported languages
          content:
            application/json:
              schema:
                type: object
                properties:
                  languages:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                          description: ISO 639-1 language code
                          example: "en"
                        name:
                          type: string
                          description: Language name
                          example: "English"
                        localized_name:
                          type: string
                          description: Language name in its native form
                          example: "English"
                        word_count:
                          type: integer
                          description: Total number of words in dictionary
                          example: 450000
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

  /api/v1/search/pattern:
    get:
      tags:
        - Search
      summary: Pattern search
      description: |
        Find words matching a pattern. Perfect for Wordle, crossword puzzles, and word games.
        
        **Wildcards:**
        - Use `_` or `?` for unknown positions
        - Example: `_ _ A _ E` finds 5-letter words with A in position 3 and E at position 5
      operationId: searchPattern
      parameters:
        - name: lang
          in: query
          required: true
          schema:
            type: string
          description: Language code (e.g., 'en', 'es', 'fr')
          example: "en"
        - name: pattern
          in: query
          required: true
          schema:
            type: string
          description: Pattern with wildcards (_ or ? for unknown positions)
          example: "_a_e"
        - name: contains
          in: query
          required: false
          schema:
            type: string
          example: "r"
        - name: excludes
          in: query
          required: false
          schema:
            type: string
          example: "t"
        - name: min_length
          in: query
          required: false
          schema:
            type: integer
          description: Minimum word length
          example: 3
        - name: max_length
          in: query
          required: false
          schema:
            type: integer
          description: Maximum word length
          example: 7
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
            maximum: 200
          description: Number of results to return (max 200)
          example: 20
        - name: offset
          in: query
          required: false
          schema:
            type: integer
            default: 0
          description: Number of results to skip (for pagination)
          example: 0
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/LanguageNotFound'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

  /api/v1/search/anagram:
    get:
      tags:
        - Search
      summary: Anagram solver
      description: |
        Find all words that can be formed from a set of letters. Perfect for Scrabble, Wordfeud, and anagram puzzles.
        
        **Blank Tiles:**
        - Use `?` or `_` for blank tiles (wildcards)
        - Example: `react?` finds words formable from letters r,e,a,c,t plus one blank tile
      operationId: searchAnagram
      parameters:
        - name: lang
          in: query
          required: true
          schema:
            type: string
          description: Language code (e.g., 'en', 'es', 'fr')
          example: "en"
        - name: letters
          in: query
          required: true
          schema:
            type: string
          description: Letters to form words from (2-50 characters). Use ? or _ for blanks.
          example: "react"
        - name: min_length
          in: query
          required: false
          schema:
            type: integer
          description: Minimum word length
          example: 3
        - name: max_length
          in: query
          required: false
          schema:
            type: integer
          description: Maximum word length
          example: 7
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
            maximum: 200
          description: Number of results to return (max 200)
          example: 20
        - name: offset
          in: query
          required: false
          schema:
            type: integer
            default: 0
          description: Number of results to skip (for pagination)
          example: 0
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/LanguageNotFound'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

  /api/v1/stats/languages/{lang}:
    get:
      tags:
        - Statistics
      summary: Language statistics
      description: Returns detailed dictionary and usage-behavior statistics for a specific language.
      operationId: getLanguageStats
      parameters:
        - name: lang
          in: path
          required: true
          schema:
            type: string
          description: Language code (e.g., 'en', 'es', 'fr')
          example: "en"
      responses:
        '200':
          description: Language statistics
          content:
            application/json:
              schema:
                type: object
                properties:
                  dictionary:
                    type: object
                    properties:
                      word_count:
                        type: integer
                        example: 450000
                      average_length:
                        type: number
                        example: 8.5
                      average_points:
                        type: number
                        example: 12.3
                      max_word_length:
                        type: integer
                        example: 45
                  behavior:
                    type: object
                    properties:
                      total_visits:
                        type: integer
                        example: 15000
                      total_searches:
                        type: integer
                        example: 45000
                      top_search_patterns:
                        type: array
                        items:
                          type: object
        '404':
          $ref: '#/components/responses/LanguageNotFound'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

  /api/v1/stats/global:
    get:
      tags:
        - Statistics
      summary: Global statistics
      description: Returns aggregate dictionary and behavioral statistics across all languages.
      operationId: getGlobalStats
      responses:
        '200':
          description: Global statistics
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_languages:
                    type: integer
                    example: 60
                  total_words:
                    type: integer
                    example: 15000000
                  top_languages_by_size:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        name:
                          type: string
                        word_count:
                          type: integer
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

  /mcp:
    post:
      tags:
        - MCP
      summary: MCP JSON-RPC endpoint
      description: |
        Model Context Protocol (MCP) JSON-RPC 2.0 endpoint for tool-based interactions.
        
        **Methods:**
        - `initialize` - Initialize connection
        - `tools/list` - List available tools
        - `tools/call` - Execute a tool
        
        **Available Tools:**
        - `list_languages` - List supported languages
        - `search_pattern` - Pattern search
        - `search_anagram` - Anagram solver
        - `get_language_stats` - Language statistics
        - `get_global_stats` - Global statistics
      operationId: mcpEndpoint
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - jsonrpc
                - method
              properties:
                jsonrpc:
                  type: string
                  enum: ["2.0"]
                id:
                  type: [string, integer, null]
                method:
                  type: string
                  enum: ["initialize", "tools/list", "tools/call"]
                params:
                  type: object
            examples:
              initialize:
                summary: Initialize connection
                value:
                  jsonrpc: "2.0"
                  id: 1
                  method: initialize
              listTools:
                summary: List available tools
                value:
                  jsonrpc: "2.0"
                  id: 2
                  method: tools/list
              callTool:
                summary: Call search_pattern tool
                value:
                  jsonrpc: "2.0"
                  id: 3
                  method: tools/call
                  params:
                    name: search_pattern
                    arguments:
                      lang: en
                      pattern: _a_e
      responses:
        '200':
          description: JSON-RPC response
          content:
            application/json:
              schema:
                type: object
                properties:
                  jsonrpc:
                    type: string
                  id:
                    type: [string, integer, null]
                  result:
                    type: object
                  error:
                    type: object
                    properties:
                      code:
                        type: integer
                      message:
                        type: string
        '405':
          description: Method not allowed (MCP requires POST)
        '413':
          description: Request body exceeds 64KB limit
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

  /v1/models:
    get:
      tags:
        - OpenAI Compatible
      summary: List models
      description: Returns available models for OpenAI-compatible clients. Lists the MCP-enabled model.
      operationId: listModels
      responses:
        '200':
          description: List of available models
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: "list"
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: "allthewords-mcp-1"
                        object:
                          type: string
                          example: "model"
                        created:
                          type: integer
                          example: 1700000000
                        owned_by:
                          type: string
                          example: "allthewords"
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

  /v1/chat/completions:
    post:
      tags:
        - OpenAI Compatible
      summary: Chat completions
      description: |
        OpenAI-compatible chat completions endpoint supporting tool-calling style interactions.
        Maps to the same functionality exposed via MCP tools.
        
        **Features:**
        - Text-based chat completions
        - Tool-calling with function definitions
        - Same tool set as MCP endpoint
        
        **Note:** Streaming is not supported.
      operationId: chatCompletions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - messages
              properties:
                model:
                  type: string
                  example: "allthewords-mcp-1"
                messages:
                  type: array
                  items:
                    type: object
                    required:
                      - role
                    properties:
                      role:
                        type: string
                        enum: ["system", "user", "assistant", "tool"]
                      content:
                        type: [string, object, null]
                      name:
                        type: string
                      tool_call_id:
                        type: string
                tools:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                      function:
                        type: object
                tool_choice:
                  type: [string, object]
                stream:
                  type: boolean
                  description: Not supported - will error if true
            examples:
              simple:
                summary: Simple completion
                value:
                  model: allthewords-mcp-1
                  messages:
                    - role: user
                      content: "Find anagrams for react"
              withTools:
                summary: With tool calling
                value:
                  model: allthewords-mcp-1
                  messages:
                    - role: user
                      content: "Search for pattern"
                  tools:
                    - type: function
                      function:
                        name: search_pattern
                        description: Find words matching a pattern
      responses:
        '200':
          description: Chat completion response
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  object:
                    type: string
                  created:
                    type: integer
                  model:
                    type: string
                  choices:
                    type: array
                    items:
                      type: object
                      properties:
                        index:
                          type: integer
                        message:
                          type: object
                          properties:
                            role:
                              type: string
                            content:
                              type: string
                            tool_calls:
                              type: array
                        finish_reason:
                          type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'

components:
  schemas:
    Word:
      type: object
      properties:
        word:
          type: string
          description: The word itself
          example: "care"
        length:
          type: integer
          description: Number of letters in the word
          example: 4
        points:
          type: integer
          description: Scrabble/Wordfeud point value
          example: 6
      required:
        - word
        - length
        - points

    SearchResponse:
      type: object
      properties:
        tool:
          type: string
          description: Tool used for the search
          enum: ["pattern", "anagram"]
          example: "pattern"
        language:
          type: string
          description: Language code
          example: "en"
        query:
          type: string
          description: The search query
          example: "_a_e"
        contains:
          type: string
          description: Letters required in the word (if specified)
          example: "r"
        excludes:
          type: string
          description: Letters excluded from the word (if specified)
          example: "t"
        min_length:
          type: string
          description: Minimum length filter (if specified)
          example: "3"
        max_length:
          type: string
          description: Maximum length filter (if specified)
          example: "7"
        total:
          type: integer
          description: Total number of matching words
          example: 42
        offset:
          type: integer
          description: Current offset in pagination
          example: 0
        limit:
          type: integer
          description: Current limit in pagination
          example: 20
        returned:
          type: integer
          description: Number of words returned in this response
          example: 20
        has_more:
          type: boolean
          description: Whether more results are available
          example: true
        description:
          type: string
          description: Human-readable description of the search
          example: "Searching for words matching pattern '_a_e' in English"
        words:
          type: array
          description: List of matching words
          items:
            $ref: '#/components/schemas/Word'
      required:
        - tool
        - language
        - query
        - total
        - offset
        - limit
        - returned
        - has_more
        - description
        - words

    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Error code for programmatic handling
              example: "missing_pattern"
            message:
              type: string
              description: Human-readable error message
              example: "Missing required parameter: pattern"
            details:
              type: object
              description: Additional error details (optional)

  responses:
    BadRequest:
      description: Bad request - missing or invalid parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missingParam:
              summary: Missing required parameter
              value:
                error:
                  code: "missing_pattern"
                  message: "Missing required parameter: pattern"
            invalidLength:
              summary: Invalid length range
              value:
                error:
                  code: "invalid_length_range"
                  message: "min_length cannot exceed max_length"

    LanguageNotFound:
      description: Language not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: "invalid_language"
              message: "Language not supported: xx"

    RateLimitExceeded:
      description: Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: Maximum requests allowed in the window
        X-RateLimit-Window:
          schema:
            type: integer
          description: Time window in seconds
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait before retrying
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: "rate_limited"
              message: "Too many requests. Please slow down."

  securitySchemes: {}

security: []
