{
    "openapi": "3.1.0",
    "info": {
        "title": "Top Solution - API de contenido",
        "summary": "Consulta de solo lectura del contenido publicado de topsolution.es.",
        "description": "API pública de solo lectura sobre el contenido publicado de topsolution.es (Top Solution, marca de Rapid Services Enterprise, S.L.). Top Solution, nombre comercial de Rapid Services Enterprise, S.L., presta servicios de mantenimiento, reparación e instalación para el hogar y la empresa: oficios como electricidad, fontanería, cerrajería, desatascos o reformas y servicio técnico de electrodomésticos a domicilio, con páginas propias para 21 ubicaciones de España. Top Solution recibe el aviso por teléfono o por correo, da una horquilla de precio y una hora antes de que salga nadie, el técnico diagnostica en el domicilio y, si aparece algo que cambia el presupuesto, se para y se consulta. Después se ejecuta el trabajo y se factura, con la garantía correspondiente.\n\nSirve para: localizar la página que trata un servicio o un problema (search_pages, con el texto en el parámetro query), leer su texto en Markdown (read_page) y obtener los datos de la empresa, cómo contactar y el catálogo de servicios y ciudades (get_company_info).\n\nEjemplo: GET https://topsolution.es/wp-json/agentes/v1/search_pages?query=cerrajero%20Madrid\n\nNO sirve para reservar, contratar ni pagar: no hay ninguna operación de escritura y el sitio no vende en línea.\n\nAutenticación: opcional. Todas las operaciones de contenido responden igual sin token. Registrarse (POST https://topsolution.es/oauth/register, automático y gratuito) sube la cuota de 60 a 600 peticiones por minuto y da acceso a /quota.\n\nGetting started (English): free to use, no paid plans and no trial that expires. No API key is needed to read. Self-serve API keys: POST https://topsolution.es/oauth/register returns a client_id and client_secret instantly, with no human approval or sales contact; exchange them at https://topsolution.es/oauth/token (client_credentials) for a higher rate limit. Sandbox: the API is read-only, so production is safe to test against and doubles as the sandbox (https://topsolution.es/api/sandbox).\n\nDeprecation and sunset policy (English): this is v1, in the path and in the API-Version header. Backward-compatible changes ship within v1; breaking changes ship as v2, and v1 keeps working for at least 90 days after its deprecation is announced with the Deprecation (RFC 9745) and Sunset (RFC 8594) headers. Policy: https://topsolution.es/desarrolladores/#versionado\n\nCuota: cada respuesta trae RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, RateLimit y RateLimit-Policy; un 429 añade Retry-After.\n\nEmpezar: es gratis, la lectura funciona sin claves, las claves son de autoservicio (sin aprobación humana ni ventas) y no hay sandbox aparte porque la API es de solo lectura: producción es inocua de probar (https://topsolution.es/api/sandbox).\n\nVersionado y retirada (deprecation and sunset policy): esta es la v1, en la ruta y en la cabecera API-Version. Los cambios compatibles entran en v1; los incompatibles salen como v2 y v1 sigue viva al menos 90 días tras anunciar su retirada, con las cabeceras Deprecation (RFC 9745) y Sunset (RFC 8594). Política: https://topsolution.es/desarrolladores/#versionado\n\nLas mismas operaciones están disponibles como herramientas MCP en POST https://topsolution.es/mcp.",
        "version": "1.0.0",
        "contact": {
            "name": "Top Solution",
            "url": "https://topsolution.es/contacto/",
            "email": "info@rapidservicesenterprise.com"
        },
        "x-api-lifecycle": {
            "version": "v1",
            "deprecation_policy": "https://topsolution.es/desarrolladores/#versionado",
            "minimum_notice_days": 90,
            "signals": [
                "Deprecation (RFC 9745)",
                "Sunset (RFC 8594)",
                "Link rel=deprecation"
            ],
            "deprecated_versions": []
        },
        "x-sandbox": {
            "url": "https://topsolution.es/api/sandbox",
            "required": false,
            "note": "Read-only API: production is safe to test against."
        }
    },
    "servers": [
        {
            "url": "https://topsolution.es/wp-json/agentes/v1",
            "description": "Producción"
        }
    ],
    "externalDocs": {
        "description": "Documentación para desarrolladores y agentes",
        "url": "https://topsolution.es/desarrolladores/"
    },
    "tags": [
        {
            "name": "contenido",
            "description": "Lectura del contenido publicado: búsqueda, páginas, catálogo y datos de la empresa. No exige token."
        },
        {
            "name": "cuenta",
            "description": "Estado del cliente identificado. Exige token."
        }
    ],
    "security": [
        {},
        {
            "oauth2": [
                "content:read"
            ]
        }
    ],
    "paths": {
        "/search_pages": {
            "get": {
                "operationId": "search_pages",
                "summary": "Buscar páginas del sitio",
                "description": "Busca en las páginas publicadas de Top Solution por servicio, problema o ciudad y devuelve las URLs más relevantes con un extracto. Es el punto de entrada normal: pasa después la URL a read_page. Si hay más resultados, la respuesta trae next_cursor para pedir la página siguiente.",
                "tags": [
                    "contenido"
                ],
                "security": [
                    {},
                    {
                        "oauth2": [
                            "content:read"
                        ]
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Resultado de la operación.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "total": {
                                            "type": "integer",
                                            "description": "Resultados en esta página."
                                        },
                                        "results": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "title": {
                                                        "type": "string"
                                                    },
                                                    "url": {
                                                        "type": "string"
                                                    },
                                                    "city": {
                                                        "type": "string",
                                                        "description": "Slug de la ciudad de la página; vacío si es general."
                                                    },
                                                    "excerpt": {
                                                        "type": "string"
                                                    }
                                                },
                                                "required": [
                                                    "title",
                                                    "url",
                                                    "city",
                                                    "excerpt"
                                                ]
                                            }
                                        },
                                        "next_cursor": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "Para pedir la página siguiente; null si no hay más resultados."
                                        }
                                    },
                                    "required": [
                                        "total",
                                        "results",
                                        "next_cursor"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Parámetros inválidos; data.hint dice cuál.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Se ha mandado un bearer token que no vale o ha caducado. Sin token, la operación responde 200.",
                        "headers": {
                            "WWW-Authenticate": {
                                "description": "Lleva resource_metadata con la URL de los metadatos del recurso (RFC 9728).",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Operación o página inexistente.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Cuota agotada. Espera lo que diga Retry-After.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            },
                            "Retry-After": {
                                "description": "Segundos que hay que esperar antes de volver a intentarlo.",
                                "schema": {
                                    "type": "integer"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Error interno.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "query",
                        "in": "query",
                        "required": true,
                        "description": "Texto en español, por ejemplo \"cerrajero Madrid\". Funciona mejor con el servicio o el problema concreto que con frases largas.",
                        "schema": {
                            "type": "string",
                            "minLength": 2,
                            "maxLength": 200
                        }
                    },
                    {
                        "name": "city",
                        "in": "query",
                        "required": false,
                        "description": "Ciudad por su slug, el que aparece en las URLs (por ejemplo \"madrid\"), o \"todas\" para no filtrar. Por defecto, todas.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "tenerife",
                                "las-palmas",
                                "mallorca",
                                "madrid",
                                "valladolid",
                                "barcelona",
                                "zaragoza",
                                "valencia",
                                "alicante",
                                "elche",
                                "murcia",
                                "sevilla",
                                "malaga",
                                "cordoba",
                                "granada",
                                "bilbao",
                                "pamplona",
                                "oviedo",
                                "gijon",
                                "a-coruna",
                                "vigo",
                                "todas"
                            ]
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Resultados por página, de 1 a 25. Por defecto, 8.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 25
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "required": false,
                        "description": "El next_cursor de la respuesta anterior, para pedir la página siguiente de resultados.",
                        "schema": {
                            "type": "string",
                            "maxLength": 12
                        }
                    }
                ]
            }
        },
        "/read_page": {
            "get": {
                "operationId": "read_page",
                "summary": "Leer una página en Markdown",
                "description": "Devuelve el texto completo de una página publicada de Top Solution, convertido a Markdown y sin menús ni pie. Acepta la URL completa, la ruta o el slug.",
                "tags": [
                    "contenido"
                ],
                "security": [
                    {},
                    {
                        "oauth2": [
                            "content:read"
                        ]
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Resultado de la operación.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "title": {
                                            "type": "string"
                                        },
                                        "url": {
                                            "type": "string"
                                        },
                                        "markdown": {
                                            "type": "string"
                                        },
                                        "truncated": {
                                            "type": "boolean"
                                        }
                                    },
                                    "required": [
                                        "title",
                                        "url",
                                        "markdown",
                                        "truncated"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Parámetros inválidos; data.hint dice cuál.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Se ha mandado un bearer token que no vale o ha caducado. Sin token, la operación responde 200.",
                        "headers": {
                            "WWW-Authenticate": {
                                "description": "Lleva resource_metadata con la URL de los metadatos del recurso (RFC 9728).",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Operación o página inexistente.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Cuota agotada. Espera lo que diga Retry-After.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            },
                            "Retry-After": {
                                "description": "Segundos que hay que esperar antes de volver a intentarlo.",
                                "schema": {
                                    "type": "integer"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Error interno.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "url",
                        "in": "query",
                        "required": true,
                        "description": "URL completa (https://topsolution.es/contacto/), ruta (/contacto/) o slug (contacto) de una página de este sitio.",
                        "schema": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                        }
                    }
                ]
            }
        },
        "/get_company_info": {
            "get": {
                "operationId": "get_company_info",
                "summary": "Datos de la empresa, servicios y cobertura",
                "description": "Marca, razón social, NIF, domicilio, contacto y horario de Top Solution, su modelo de servicio (quién hace, presupuesta, factura y garantiza el trabajo), impuestos, precios orientativos y la lista de servicios y ciudades con sus URLs. Úsalo para verificar quién está detrás del sitio o para decirle al usuario cómo pedir un servicio. Con section se pide solo una parte.",
                "tags": [
                    "contenido"
                ],
                "security": [
                    {},
                    {
                        "oauth2": [
                            "content:read"
                        ]
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Resultado de la operación.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "brand": {
                                            "type": "string"
                                        },
                                        "legal_name": {
                                            "type": "string"
                                        },
                                        "tax_id": {
                                            "type": "string",
                                            "description": "NIF de la sociedad."
                                        },
                                        "address": {
                                            "type": "string"
                                        },
                                        "phone": {
                                            "type": "string",
                                            "description": "Vacío si el sitio no publica teléfono."
                                        },
                                        "email": {
                                            "type": "string"
                                        },
                                        "whatsapp": {
                                            "type": "string",
                                            "description": "Vacío si el sitio no publica WhatsApp."
                                        },
                                        "hours": {
                                            "type": "string"
                                        },
                                        "website": {
                                            "type": "string"
                                        },
                                        "coverage": {
                                            "type": "string"
                                        },
                                        "tax": {
                                            "type": "string"
                                        },
                                        "prices": {
                                            "type": "string"
                                        },
                                        "service_model": {
                                            "type": "object",
                                            "properties": {
                                                "description": {
                                                    "type": "string"
                                                },
                                                "performed_by": {
                                                    "type": "string"
                                                },
                                                "quoted_by": {
                                                    "type": "string"
                                                },
                                                "invoiced_by": {
                                                    "type": "string"
                                                },
                                                "warranty": {
                                                    "type": "string"
                                                },
                                                "online_booking": {
                                                    "type": "boolean",
                                                    "description": "false: no se contrata ni se paga en línea desde este sitio."
                                                }
                                            },
                                            "required": [
                                                "description",
                                                "online_booking"
                                            ]
                                        },
                                        "services": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "url": {
                                                        "type": "string"
                                                    }
                                                },
                                                "required": [
                                                    "name",
                                                    "url"
                                                ]
                                            }
                                        },
                                        "cities": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "slug": {
                                                        "type": "string"
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "url": {
                                                        "type": "string"
                                                    }
                                                },
                                                "required": [
                                                    "slug",
                                                    "name",
                                                    "url"
                                                ]
                                            }
                                        },
                                        "pages": {
                                            "type": "object",
                                            "additionalProperties": {
                                                "type": "string"
                                            }
                                        }
                                    },
                                    "required": [
                                        "brand",
                                        "website"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Parámetros inválidos; data.hint dice cuál.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Se ha mandado un bearer token que no vale o ha caducado. Sin token, la operación responde 200.",
                        "headers": {
                            "WWW-Authenticate": {
                                "description": "Lleva resource_metadata con la URL de los metadatos del recurso (RFC 9728).",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Operación o página inexistente.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Cuota agotada. Espera lo que diga Retry-After.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            },
                            "Retry-After": {
                                "description": "Segundos que hay que esperar antes de volver a intentarlo.",
                                "schema": {
                                    "type": "integer"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Error interno.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "section",
                        "in": "query",
                        "required": false,
                        "description": "Qué parte devolver: all (todo, por defecto), contact (contacto y horario), service_model (cómo funciona el servicio, precios e impuestos), coverage (ciudades con su URL) o services (servicios con su URL).",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "contact",
                                "service_model",
                                "coverage",
                                "services"
                            ]
                        }
                    }
                ]
            }
        },
        "/quota": {
            "get": {
                "operationId": "get_quota",
                "summary": "Cuota del cliente identificado",
                "description": "Devuelve la cuota del cliente identificado: política, límite por minuto, peticiones consumidas y segundos hasta el reinicio. Es la única operación que exige token (scope quota:read).",
                "tags": [
                    "cuenta"
                ],
                "security": [
                    {
                        "oauth2": [
                            "quota:read"
                        ]
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Cuota del cliente identificado.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "client_id": {
                                            "type": "string"
                                        },
                                        "scope": {
                                            "type": "string"
                                        },
                                        "policy": {
                                            "type": "string",
                                            "enum": [
                                                "anonimo",
                                                "identificado"
                                            ]
                                        },
                                        "limit": {
                                            "type": "integer",
                                            "description": "Peticiones admitidas por ventana."
                                        },
                                        "window_seconds": {
                                            "type": "integer"
                                        },
                                        "used": {
                                            "type": "integer"
                                        },
                                        "remaining": {
                                            "type": "integer"
                                        },
                                        "reset_seconds": {
                                            "type": "integer"
                                        }
                                    },
                                    "required": [
                                        "client_id",
                                        "policy",
                                        "limit",
                                        "remaining",
                                        "reset_seconds"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Falta el token o no vale.",
                        "headers": {
                            "WWW-Authenticate": {
                                "description": "Lleva resource_metadata (RFC 9728).",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "El token no tiene el scope quota:read.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Cuota agotada.",
                        "headers": {
                            "RateLimit": {
                                "description": "Campo estructurado del borrador del IETF: r = peticiones que quedan, t = segundos hasta el reinicio.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";r=57;t=34"
                                    ]
                                }
                            },
                            "RateLimit-Policy": {
                                "description": "La política aplicada: q = cuota por ventana, w = ventana en segundos.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "\"anonimo\";q=60;w=60"
                                    ]
                                }
                            },
                            "RateLimit-Limit": {
                                "description": "Peticiones admitidas en la ventana (forma clásica).",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Remaining": {
                                "description": "Peticiones que quedan en la ventana en curso.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "RateLimit-Reset": {
                                "description": "Segundos que faltan para que el contador vuelva a empezar.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "API-Version": {
                                "description": "Versión mayor de la API que ha respondido.",
                                "schema": {
                                    "type": "string",
                                    "examples": [
                                        "1"
                                    ]
                                }
                            },
                            "Retry-After": {
                                "description": "Segundos que hay que esperar antes de volver a intentarlo.",
                                "schema": {
                                    "type": "integer"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "oauth2": {
                "type": "oauth2",
                "description": "OAuth 2.0 con client_credentials. Alta automática y gratuita (RFC 7591): POST https://topsolution.es/oauth/register. Identificarse no abre contenido nuevo: sube la cuota de 60 a 600 peticiones por minuto. Metadatos en https://topsolution.es/.well-known/oauth-authorization-server.",
                "flows": {
                    "clientCredentials": {
                        "tokenUrl": "https://topsolution.es/oauth/token",
                        "scopes": {
                            "content:read": "Leer el contenido publicado con la cuota ampliada. Los mismos datos que la API sirve sin token.",
                            "quota:read": "Consultar la cuota del propio cliente en /wp-json/agentes/v1/quota."
                        }
                    }
                }
            }
        },
        "schemas": {
            "Error": {
                "type": "object",
                "description": "Error estructurado. Siempre JSON, nunca HTML.",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "Identificador estable del error."
                    },
                    "message": {
                        "type": "string",
                        "description": "Explicación legible de qué ha fallado."
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "status": {
                                "type": "integer",
                                "description": "Código HTTP."
                            },
                            "hint": {
                                "type": "string",
                                "description": "Qué hacer para arreglarlo."
                            }
                        },
                        "required": [
                            "status"
                        ]
                    }
                },
                "required": [
                    "code",
                    "message"
                ]
            }
        }
    }
}