{
    "openapi": "3.0.3",
    "info": {
        "title": "RAE API",
        "description": "API no oficial para consultar el diccionario de la Real Academia Española.\nPermite obtener definiciones, conjugaciones, etimología y más.\n\nEsta especificación es la fuente de verdad para la documentación; se mantiene\nalineada con el backend (rae-api cmd/server).\n\nRate limiting: Free (sin API key) 10 req/min, 100 req/día. Developer\n60 req/min, 5.000 req/día. Extended 300 req/min, 50.000 req/día.\nAPI key opcional por query (?api_key=...) o cabecera (X-API-Key).\nLos endpoints de juegos (/api/games/*) están exentos del rate limiting.\n",
        "version": "1.0.0",
        "contact": {
            "name": "RAE API Organization",
            "url": "https://rae-api.com"
        }
    },
    "servers": [
        {
            "url": "https://rae-api.com"
        }
    ],
    "paths": {
        "/api/words/{palabra}": {
            "get": {
                "summary": "Obtener información de una palabra",
                "description": "Devuelve definiciones, origen y conjugaciones verbales (si aplica) de una palabra. API key opcional para mayor cuota.",
                "parameters": [
                    {
                        "name": "palabra",
                        "in": "path",
                        "required": true,
                        "description": "Palabra a consultar",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "api_key",
                        "in": "query",
                        "required": false,
                        "description": "API key opcional (tier Developer o superior)",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Éxito",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WordEntryResponse"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "NOT_FOUND",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Límite de velocidad superado (middleware ratelimit)",
                        "headers": {
                            "Retry-After": {
                                "description": "Segundos hasta poder reintentar",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "X-RateLimit-Minute-Limit": {
                                "description": "Límite de peticiones por minuto del tier",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Remaining": {
                                "description": "Peticiones restantes en la ventana actual",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Reset": {
                                "description": "Unix timestamp de reseteo del contador por minuto",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Limit": {
                                "description": "Límite diario (o \"unlimited\")",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Remaining": {
                                "description": "Peticiones diarias restantes (o \"unlimited\")",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Tier": {
                                "description": "Tier del cliente (free, developer, extended)",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RateLimitExceededResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/random": {
            "get": {
                "summary": "Obtener una palabra aleatoria",
                "description": "Devuelve una palabra aleatoria del diccionario. API key opcional.",
                "parameters": [
                    {
                        "name": "min_length",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "description": "Longitud mínima de la palabra"
                    },
                    {
                        "name": "max_length",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "description": "Longitud máxima de la palabra"
                    },
                    {
                        "name": "api_key",
                        "in": "query",
                        "required": false,
                        "description": "API key opcional",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Éxito",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WordOnlyResponse"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Límite de velocidad superado",
                        "headers": {
                            "Retry-After": {
                                "description": "Segundos hasta reintentar",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "X-RateLimit-Minute-Limit": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Remaining": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Reset": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Limit": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Remaining": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Tier": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RateLimitExceededResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/daily": {
            "get": {
                "summary": "Obtener la palabra del día",
                "description": "Devuelve la palabra del día. API key opcional.",
                "parameters": [
                    {
                        "name": "api_key",
                        "in": "query",
                        "required": false,
                        "description": "API key opcional",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Éxito",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WordOnlyResponse"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Límite de velocidad superado",
                        "headers": {
                            "Retry-After": {
                                "description": "Segundos hasta reintentar",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "X-RateLimit-Minute-Limit": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Remaining": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Reset": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Limit": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Remaining": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Tier": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RateLimitExceededResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/search": {
            "get": {
                "summary": "Buscar palabras por contenido",
                "description": "Búsqueda fuzzy en definiciones y contenido. El parámetro `q` es obligatorio.\nSi se omite, responde 400 con `error` \"QUERY_MISSING\".\nMotor `eng`: `linear` (por defecto) o `hits`.\n",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "required": true,
                        "description": "Términos de búsqueda (obligatorio)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "eng",
                        "in": "query",
                        "required": false,
                        "description": "Motor de búsqueda",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "linear",
                                "hits"
                            ],
                            "default": "linear"
                        }
                    },
                    {
                        "name": "api_key",
                        "in": "query",
                        "required": false,
                        "description": "API key opcional",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array de resultados (doc + hits por elemento)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SearchResponse"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Falta el parámetro q",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                },
                                "example": {
                                    "ok": false,
                                    "error": "QUERY_MISSING"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Límite de velocidad superado",
                        "headers": {
                            "Retry-After": {
                                "description": "Segundos hasta reintentar",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "X-RateLimit-Minute-Limit": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Remaining": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Minute-Reset": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Limit": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Daily-Remaining": {
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Tier": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RateLimitExceededResponse"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "ApiKeyQuery": {
                "type": "apiKey",
                "in": "query",
                "name": "api_key",
                "description": "API key opcional para mayor cuota (solicitar en GitHub)."
            },
            "ApiKeyHeader": {
                "type": "apiKey",
                "in": "header",
                "name": "X-API-Key",
                "description": "Misma API key por cabecera (opcional)."
            }
        },
        "schemas": {
            "WordEntryResponse": {
                "type": "object",
                "required": [
                    "ok",
                    "data"
                ],
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "example": true
                    },
                    "data": {
                        "$ref": "#/components/schemas/WordEntry"
                    }
                }
            },
            "WordOnlyResponse": {
                "type": "object",
                "required": [
                    "ok",
                    "data"
                ],
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "example": true
                    },
                    "data": {
                        "type": "object",
                        "required": [
                            "word"
                        ],
                        "properties": {
                            "word": {
                                "type": "string",
                                "description": "Palabra (en /api/random y /api/daily solo se devuelve la palabra, no la ficha completa)"
                            }
                        },
                        "example": {
                            "word": "casa"
                        }
                    }
                }
            },
            "WordEntry": {
                "type": "object",
                "properties": {
                    "word": {
                        "type": "string"
                    },
                    "meanings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Meaning"
                        }
                    }
                }
            },
            "Meaning": {
                "type": "object",
                "properties": {
                    "homonym_index": {
                        "type": "integer",
                        "description": "Index for homonymous words (e.g. comer¹ vs comer²). 0 if not a homonym."
                    },
                    "origin": {
                        "$ref": "#/components/schemas/Origin"
                    },
                    "senses": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Definition"
                        }
                    },
                    "locutions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Locution"
                        },
                        "description": "Locutions (idiomatic expressions) associated with this meaning."
                    },
                    "conjugations": {
                        "$ref": "#/components/schemas/Conjugations"
                    }
                }
            },
            "Origin": {
                "type": "object",
                "properties": {
                    "raw": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string"
                    },
                    "voice": {
                        "type": "string"
                    },
                    "text": {
                        "type": "string"
                    }
                }
            },
            "Definition": {
                "type": "object",
                "properties": {
                    "raw": {
                        "type": "string"
                    },
                    "meaning_number": {
                        "type": "integer"
                    },
                    "category": {
                        "type": "string",
                        "enum": [
                            "noun",
                            "verb",
                            "adjective",
                            "adverb",
                            "pronoun",
                            "article",
                            "preposition",
                            "conjunction",
                            "interjection"
                        ]
                    },
                    "verb_category": {
                        "type": "string",
                        "nullable": true
                    },
                    "gender": {
                        "type": "string",
                        "nullable": true
                    },
                    "article": {
                        "$ref": "#/components/schemas/Article"
                    },
                    "usage": {
                        "type": "string",
                        "enum": [
                            "common",
                            "rare",
                            "outdated",
                            "colloquial",
                            "obsolete",
                            "unknown"
                        ]
                    },
                    "description": {
                        "type": "string"
                    },
                    "usage_notes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Appended usage marks (e.g. \"U. t. c. s.\", \"U. menos c. f.\")."
                    },
                    "regions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Region"
                        },
                        "description": "Geographic marks of the sense (country or region)."
                    },
                    "fields": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Subject-area marks (e.g. Marina, Química, Derecho)."
                    },
                    "examples": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Usage examples extracted from the RAE entry."
                    },
                    "cross_references": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Cross-references to other RAE dictionary entries."
                    },
                    "synonyms": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Synonym words (plain strings for backwards compatibility)."
                    },
                    "antonyms": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Antonym words (plain strings for backwards compatibility)."
                    },
                    "synonyms_v2": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RelatedWord"
                        },
                        "description": "Synonyms with usage labels (e.g. colloquial, latin_america)."
                    },
                    "antonyms_v2": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RelatedWord"
                        },
                        "description": "Antonyms with usage labels."
                    }
                }
            },
            "RelatedWord": {
                "type": "object",
                "properties": {
                    "word": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string",
                        "description": "Usage label (e.g. colloquial, latin_america, spain, vulgar, dialectal). Empty if no label."
                    }
                }
            },
            "Region": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "ISO 3166 alpha-2 country code. Empty for supranational/subnational marks."
                    },
                    "name": {
                        "type": "string",
                        "description": "Region name (e.g. México, América, Murcia)."
                    }
                }
            },
            "Locution": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "The idiomatic expression (e.g. \"comer el coco\")"
                    },
                    "senses": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Definition"
                        },
                        "description": "Definitions/senses of the locution."
                    }
                }
            },
            "Article": {
                "type": "object",
                "properties": {
                    "category": {
                        "type": "string",
                        "enum": [
                            "definite",
                            "indefinite",
                            "neuter"
                        ]
                    },
                    "gender": {
                        "type": "string",
                        "enum": [
                            "masculine",
                            "feminine",
                            "masculine_and_feminine",
                            "unknown"
                        ]
                    }
                }
            },
            "Conjugations": {
                "type": "object",
                "properties": {
                    "non_personal": {
                        "$ref": "#/components/schemas/ConjugationNonPersonal"
                    },
                    "indicative": {
                        "$ref": "#/components/schemas/ConjugationIndicative"
                    },
                    "subjunctive": {
                        "$ref": "#/components/schemas/ConjugationSubjunctive"
                    },
                    "imperative": {
                        "$ref": "#/components/schemas/ConjugationImperative"
                    }
                }
            },
            "ConjugationNonPersonal": {
                "type": "object",
                "properties": {
                    "infinitive": {
                        "type": "string"
                    },
                    "participle": {
                        "type": "string"
                    },
                    "gerund": {
                        "type": "string"
                    },
                    "compound_infinitive": {
                        "type": "string"
                    },
                    "compound_gerund": {
                        "type": "string"
                    }
                }
            },
            "ConjugationIndicative": {
                "type": "object",
                "properties": {
                    "present": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "present_perfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "imperfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "past_perfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "preterite": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "past_anterior": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "future": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "future_perfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "conditional": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "conditional_perfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    }
                }
            },
            "ConjugationSubjunctive": {
                "type": "object",
                "properties": {
                    "present": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "present_perfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "imperfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "past_perfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "future": {
                        "$ref": "#/components/schemas/Conjugation"
                    },
                    "future_perfect": {
                        "$ref": "#/components/schemas/Conjugation"
                    }
                }
            },
            "ConjugationImperative": {
                "type": "object",
                "properties": {
                    "singular_second_person": {
                        "type": "string"
                    },
                    "singular_formal_second_person": {
                        "type": "string"
                    },
                    "plural_second_person": {
                        "type": "string"
                    },
                    "plural_formal_second_person": {
                        "type": "string"
                    }
                }
            },
            "Conjugation": {
                "type": "object",
                "properties": {
                    "singular_first_person": {
                        "type": "string"
                    },
                    "singular_second_person": {
                        "type": "string"
                    },
                    "singular_formal_second_person": {
                        "type": "string"
                    },
                    "singular_third_person": {
                        "type": "string"
                    },
                    "plural_first_person": {
                        "type": "string"
                    },
                    "plural_second_person": {
                        "type": "string"
                    },
                    "plural_formal_second_person": {
                        "type": "string"
                    },
                    "plural_third_person": {
                        "type": "string"
                    }
                }
            },
            "ErrorResponse": {
                "type": "object",
                "required": [
                    "ok",
                    "error"
                ],
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "example": false
                    },
                    "error": {
                        "type": "string",
                        "description": "NOT_FOUND (404) o QUERY_MISSING (400 en /api/search)",
                        "example": "NOT_FOUND"
                    },
                    "suggestions": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Solo en 404 de /api/words; palabras sugeridas",
                        "example": [
                            "palabra",
                            "palabras"
                        ]
                    }
                }
            },
            "RateLimitExceededResponse": {
                "description": "Respuesta del middleware de rate limit (internal/middleware/ratelimit.go)",
                "type": "object",
                "required": [
                    "ok",
                    "error",
                    "message",
                    "retry_after"
                ],
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "example": false
                    },
                    "error": {
                        "type": "string",
                        "example": "RATE_LIMIT_EXCEEDED"
                    },
                    "message": {
                        "type": "string",
                        "description": "Mensaje con enlace para solicitar API key gratuita",
                        "example": "Rate limit exceeded. Request a FREE API key: https://rae-api.com/dashboard"
                    },
                    "retry_after": {
                        "type": "integer",
                        "description": "Segundos hasta poder reintentar (coincide con cabecera Retry-After)",
                        "example": 42
                    }
                }
            },
            "SearchResponse": {
                "type": "array",
                "items": {
                    "$ref": "#/components/schemas/SearchResult"
                }
            },
            "SearchResult": {
                "type": "object",
                "properties": {
                    "doc": {
                        "$ref": "#/components/schemas/SearchDoc"
                    },
                    "hits": {
                        "type": "integer",
                        "description": "Número de coincidencias encontradas"
                    }
                }
            },
            "SearchDoc": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Palabra encontrada"
                    },
                    "raw": {
                        "type": "string",
                        "description": "Datos completos de la palabra en formato JSON"
                    }
                }
            }
        }
    }
}