{
    "name": "Prime Services - API de contenido",
    "description": "API pública de solo lectura. Sin autenticación.",
    "version": "v1",
    "openapi": "https://primeservices.es/openapi.json",
    "mcp": "https://primeservices.es/mcp",
    "mcpCard": "https://primeservices.es/.well-known/mcp.json",
    "docs": "https://primeservices.es/desarrolladores/",
    "servidor": "https://primeservices.es/wp-json/ps/v1",
    "formato": "JSON (UTF-8). Todas las operaciones son GET.",
    "operations": [
        {
            "operationId": "buscar_contenido",
            "summary": "Buscar por síntoma o servicio",
            "descripcion": "Busca en las páginas publicadas por síntoma, aparato, oficio o municipio y devuelve las URLs más relevantes con un extracto. Es el punto de entrada normal: pasa después la URL a leer_pagina. En la API REST, el texto va en el parámetro consulta (?consulta=...).",
            "metodo": "GET",
            "url": "https://primeservices.es/wp-json/ps/v1/buscar_contenido",
            "parametros": [
                {
                    "nombre": "consulta",
                    "en": "query",
                    "obligatorio": true,
                    "tipo": "string",
                    "descripcion": "Texto en español. Funciona mejor con el síntoma que con el nombre comercial: \"nevera no enfría\", \"lavadora no centrifuga\", \"termo sin agua caliente\", \"cerrajero Arona\"."
                },
                {
                    "nombre": "ubicacion",
                    "en": "query",
                    "obligatorio": false,
                    "tipo": "string",
                    "descripcion": "Ubicación por su slug, que es el sufijo de las URLs: \"tenerife\" (provincia de Santa Cruz de Tenerife), \"las-palmas\" (provincia de Las Palmas), \"madrid\", \"a-coruna\"... \"todas\" para no filtrar. Por defecto, todas."
                },
                {
                    "nombre": "provincia",
                    "en": "query",
                    "obligatorio": false,
                    "tipo": "string",
                    "descripcion": "Alias antiguo de \"ubicacion\", que se mantiene por compatibilidad. Acepta los mismos slugs; \"ambas\" equivale a \"todas\". Si llegan los dos, manda \"ubicacion\"."
                },
                {
                    "nombre": "limite",
                    "en": "query",
                    "obligatorio": false,
                    "tipo": "integer",
                    "descripcion": "Número máximo de resultados, de 1 a 25. Por defecto, 8."
                }
            ],
            "ejemplo": "curl \"https://primeservices.es/wp-json/ps/v1/buscar_contenido?consulta=nevera+no+enfria&ubicacion=madrid&limite=3\"",
            "autenticacion": "ninguna"
        },
        {
            "operationId": "leer_pagina",
            "summary": "Leer una página en Markdown",
            "descripcion": "Devuelve el texto completo de una página publicada, convertido a Markdown y sin menús ni pie. Acepta la URL completa, la ruta o el slug.",
            "metodo": "GET",
            "url": "https://primeservices.es/wp-json/ps/v1/leer_pagina",
            "parametros": [
                {
                    "nombre": "url",
                    "en": "query",
                    "obligatorio": true,
                    "tipo": "string",
                    "descripcion": "URL completa (https://primeservices.es/fontaneros-tenerife/), ruta (/fontaneros-tenerife/) o slug (fontaneros-tenerife)."
                }
            ],
            "ejemplo": "curl \"https://primeservices.es/wp-json/ps/v1/leer_pagina?url=https%3A%2F%2Fprimeservices.es%2Fcontacto%2F\"",
            "autenticacion": "ninguna"
        },
        {
            "operationId": "listar_servicios",
            "summary": "Listar servicios publicados",
            "descripcion": "Devuelve el catálogo completo de páginas publicadas: los oficios por ubicación y el servicio técnico por tipo de aparato. Útil para saber qué cubre el servicio antes de buscar.",
            "metodo": "GET",
            "url": "https://primeservices.es/wp-json/ps/v1/listar_servicios",
            "parametros": [
                {
                    "nombre": "ubicacion",
                    "en": "query",
                    "obligatorio": false,
                    "tipo": "string",
                    "descripcion": "Ubicación por su slug, que es el sufijo de las URLs: \"tenerife\" (provincia de Santa Cruz de Tenerife), \"las-palmas\" (provincia de Las Palmas), \"madrid\", \"a-coruna\"... \"todas\" para no filtrar. Por defecto, todas."
                },
                {
                    "nombre": "provincia",
                    "en": "query",
                    "obligatorio": false,
                    "tipo": "string",
                    "descripcion": "Alias antiguo de \"ubicacion\", que se mantiene por compatibilidad. Acepta los mismos slugs; \"ambas\" equivale a \"todas\". Si llegan los dos, manda \"ubicacion\"."
                },
                {
                    "nombre": "tipo",
                    "en": "query",
                    "obligatorio": false,
                    "tipo": "string",
                    "descripcion": "\"oficio\" para electricistas, fontaneros, cerrajeros y demás; \"aparato\" para el servicio técnico de electrodomésticos; \"todos\" para el catálogo entero. Por defecto, todos."
                }
            ],
            "ejemplo": "curl \"https://primeservices.es/wp-json/ps/v1/listar_servicios?ubicacion=tenerife&tipo=aparato\"",
            "autenticacion": "ninguna"
        },
        {
            "operationId": "datos_empresa",
            "summary": "Datos de la empresa, modelo de servicio y cobertura",
            "descripcion": "Razón social, NIF, Registro Mercantil, domicilio, teléfono, correo, ubicaciones cubiertas, impuesto (IVA o IGIC según el territorio) y modelo de servicio: Prime Services asigna cada aviso a un profesional colaborador de la zona, que presupuesta, ejecuta, factura y garantiza el trabajo. Úsalo cuando haya que verificar quién está detrás del sitio, quién hace el trabajo o cómo dar un aviso.",
            "metodo": "GET",
            "url": "https://primeservices.es/wp-json/ps/v1/datos_empresa",
            "parametros": [],
            "ejemplo": "curl \"https://primeservices.es/wp-json/ps/v1/datos_empresa\"",
            "autenticacion": "ninguna"
        }
    ],
    "operacionesConToken": [
        {
            "operationId": "estado",
            "summary": "Estado de cuota del cliente",
            "descripcion": "Devuelve la cuota del cliente identificado: política aplicada, límite por minuto, peticiones consumidas y segundos que faltan para el reinicio de la ventana. Es la única operación que exige token.",
            "metodo": "GET",
            "url": "https://primeservices.es/wp-json/ps/v1/estado",
            "scope": "cuota:leer",
            "autenticacion": "Authorization: Bearer TOKEN",
            "ejemplo": "curl -H \"Authorization: Bearer TOKEN\" \"https://primeservices.es/wp-json/ps/v1/estado\""
        }
    ],
    "auth": {
        "obligatoria": false,
        "para_que_sirve": "Identificarse no abre contenido nuevo: sube la cuota de 60 a 600 peticiones por minuto.",
        "metodo": "OAuth 2.0 client_credentials; el token va en Authorization: Bearer",
        "metadatos": "https://primeservices.es/.well-known/oauth-authorization-server",
        "recurso": "https://primeservices.es/.well-known/oauth-protected-resource/wp-json/ps/v1",
        "alta": "https://primeservices.es/oauth/register",
        "token": "https://primeservices.es/oauth/token",
        "documentacion": "https://primeservices.es/auth.md",
        "ejemplo": {
            "registro": "curl -X POST https://primeservices.es/oauth/register -H \"Content-Type: application/json\" -d '{\"client_name\":\"mi-agente\"}'",
            "token": "curl -u CLIENT_ID:CLIENT_SECRET -X POST https://primeservices.es/oauth/token -d grant_type=client_credentials"
        }
    },
    "errores": {
        "formato": "{\"code\":\"...\",\"message\":\"...\",\"data\":{\"status\":404,\"hint\":\"qué hacer\"}}",
        "codigos": {
            "400": "Falta un parámetro obligatorio o es inválido; data.hint dice cuál.",
            "401": "Token inválido o ausente donde hace falta; WWW-Authenticate apunta a los metadatos.",
            "404": "Ruta o página inexistente.",
            "429": "Cuota agotada; Retry-After dice cuántos segundos esperar."
        },
        "siempre_json": true
    },
    "empezar": {
        "gratis": "Sí. Sin planes de pago ni prueba que caduque.",
        "sin_clave": "La lectura funciona sin credenciales: GET https://primeservices.es/wp-json/ps/v1/datos_empresa",
        "claves": "Autoservicio: POST https://primeservices.es/oauth/register da client_id y client_secret al instante, sin aprobación humana ni formulario de ventas.",
        "sandbox": "No hace falta uno aparte: la API es de solo lectura y producción es inocua de probar. Comprobación en vivo: https://primeservices.es/api/sandbox",
        "documentacion": "https://primeservices.es/auth.md"
    },
    "sandbox": "https://primeservices.es/api/sandbox",
    "versionado": {
        "version": "v1",
        "donde": "En la ruta: https://primeservices.es/wp-json/ps/v1/ y en la cabecera API-Version.",
        "compatibles": "Campos y operaciones nuevos se añaden dentro de v1 sin aviso; ignora lo que no conozcas.",
        "incompatibles": "Salen en una versión nueva (v2). La anterior sigue viva al menos 90 días tras anunciar su retirada.",
        "plazo_minimo_dias": 90,
        "aviso": "Deprecation and sunset policy: una versión en retirada responde con Deprecation (RFC 9745) y Sunset (RFC 8594). Hoy ninguna lo está, así que no se envían.",
        "en_retirada": [],
        "politica": "https://primeservices.es/desarrolladores/#versionado",
        "contrato": "https://primeservices.es/openapi.json"
    },
    "rateLimit": {
        "anonimo": "60 peticiones / 60 s por IP",
        "identificado": "600 peticiones / 60 s por client_id",
        "cabeceras": [
            "RateLimit",
            "RateLimit-Policy",
            "RateLimit-Limit",
            "RateLimit-Remaining",
            "RateLimit-Reset",
            "Retry-After"
        ]
    }
}