{
  "openapi": "3.1.0",
  "info": {
    "title": "API pública de Preopol",
    "version": "1.0.0",
    "description": "Endpoints públicos de https://preopol.es: consulta de planes y páginas, formularios de contacto e informe, y un servidor MCP de solo lectura. Sin autenticación (no hay datos privados). Versionado por ruta (/api/v1/) y cabecera API-Version. Los cambios incompatibles salen en /api/v2/; un endpoint a retirar emite las cabeceras Deprecation y Sunset. Los errores de /api/ son JSON {error:{code,message,hint,docs,openapi}}. No hay límite de tasa ni cabeceras RateLimit. Documentación: https://preopol.es/developers/",
    "contact": {
      "name": "Preopol",
      "email": "info@preopol.es",
      "url": "https://preopol.es/contacto/"
    }
  },
  "servers": [
    {
      "url": "https://preopol.es"
    }
  ],
  "paths": {
    "/api/v1/planes/": {
      "get": {
        "operationId": "listarPlanes",
        "summary": "Planes y precios",
        "responses": {
          "200": {
            "description": "Lista de planes",
            "headers": {
              "API-Version": {
                "description": "Versión de la API",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "moneda": {
                      "type": "string"
                    },
                    "planes": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "405": {
            "description": "method_not_allowed",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/paginas/": {
      "get": {
        "operationId": "listarPaginas",
        "summary": "URLs principales del sitio",
        "responses": {
          "200": {
            "description": "Lista de URLs",
            "headers": {
              "API-Version": {
                "description": "Versión de la API",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "paginas": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uri"
                      }
                    },
                    "sitemap": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          },
          "405": {
            "description": "method_not_allowed",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacto/": {
      "post": {
        "operationId": "enviarContacto",
        "summary": "Solicitar información",
        "description": "Envía una solicitud de información al equipo de Preopol.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "telefono",
                  "oposicion",
                  "privacidad"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  },
                  "telefono": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "privacidad": {
                    "type": "string",
                    "description": "Aceptación de la política de privacidad (obligatoria)"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "telefono",
                  "oposicion",
                  "privacidad"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  },
                  "telefono": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "privacidad": {
                    "type": "string",
                    "description": "Aceptación de la política de privacidad (obligatoria)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enviado correctamente",
            "headers": {
              "API-Version": {
                "description": "Versión de la API",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "Descartado (campo señuelo `empresa` rellenado)"
          },
          "400": {
            "description": "invalid_request: datos incompletos o inválidos",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "method_not_allowed",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "upstream_error: el proveedor de email rechazó el envío",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "not_configured: formulario no configurado",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/informe/": {
      "post": {
        "operationId": "solicitarInforme",
        "summary": "Solicitar el informe gratuito",
        "description": "Solicita el informe de la oposición por email.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "oposicion"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "oposicion"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enviado correctamente",
            "headers": {
              "API-Version": {
                "description": "Versión de la API",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "Descartado (campo señuelo `empresa` rellenado)"
          },
          "400": {
            "description": "invalid_request: datos incompletos o inválidos",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "method_not_allowed",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "upstream_error: el proveedor de email rechazó el envío",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "not_configured: formulario no configurado",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/mcp/": {
      "post": {
        "operationId": "mcp",
        "summary": "Servidor MCP (Streamable HTTP, JSON-RPC 2.0, solo lectura)",
        "description": "Métodos: initialize, ping, tools/list, tools/call. Herramientas: contacto, planes, paginas.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "const": "2.0"
                  },
                  "id": {
                    "type": [
                      "integer",
                      "string"
                    ]
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "initialize",
                      "ping",
                      "tools/list",
                      "tools/call"
                    ]
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Respuesta JSON-RPC",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "202": {
            "description": "Notificación aceptada"
          }
        }
      }
    },
    "/api/contacto/": {
      "post": {
        "operationId": "enviarContacto",
        "summary": "Solicitar información",
        "description": "Alias sin versión de la v1 (lo usan los formularios del sitio).",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "telefono",
                  "oposicion",
                  "privacidad"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  },
                  "telefono": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "privacidad": {
                    "type": "string",
                    "description": "Aceptación de la política de privacidad (obligatoria)"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "telefono",
                  "oposicion",
                  "privacidad"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  },
                  "telefono": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "privacidad": {
                    "type": "string",
                    "description": "Aceptación de la política de privacidad (obligatoria)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enviado correctamente",
            "headers": {
              "API-Version": {
                "description": "Versión de la API",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "Descartado (campo señuelo `empresa` rellenado)"
          },
          "400": {
            "description": "invalid_request: datos incompletos o inválidos",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "method_not_allowed",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "upstream_error: el proveedor de email rechazó el envío",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "not_configured: formulario no configurado",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/informe/": {
      "post": {
        "operationId": "solicitarInforme",
        "summary": "Solicitar el informe gratuito",
        "description": "Alias sin versión de la v1 (lo usan los formularios del sitio).",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "oposicion"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "nombre",
                  "email",
                  "oposicion"
                ],
                "properties": {
                  "nombre": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 500
                  },
                  "oposicion": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Oposición de interés (p. ej. Policía Local Comunitat Valenciana)"
                  },
                  "empresa": {
                    "type": "string",
                    "description": "Campo señuelo antirrobots: debe ir vacío"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enviado correctamente",
            "headers": {
              "API-Version": {
                "description": "Versión de la API",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "Descartado (campo señuelo `empresa` rellenado)"
          },
          "400": {
            "description": "invalid_request: datos incompletos o inválidos",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "method_not_allowed",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "upstream_error: el proveedor de email rechazó el envío",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "not_configured: formulario no configurado",
            "headers": {
              "API-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "hint"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "not_found",
                  "method_not_allowed",
                  "upstream_error",
                  "not_configured"
                ]
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": "string"
              },
              "docs": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Documentación para desarrolladores",
    "url": "https://preopol.es/developers/"
  }
}
