{
 "openapi": "3.1.0",
 "info": {
  "title": "HolidayAtlas",
  "version": "0.1.0",
  "contact": {"name": "Apiverd"},
  "description": "Festivos laborales de España consultables por código postal, con fuente legal (BOE o boletín autonómico) en cada entrada. Cobertura: toda España a nivel nacional y autonómico (año 2026); festivos locales por municipio disponibles hoy en Illes Balears y creciendo. Cada municipio indica su `local_coverage`. Si un código postal cruza varios municipios (30% de los CP en España), la respuesta devuelve todos los candidatos con su peso: aviso honesto en vez de dato falso, incluso cuando cruzan comunidades autónomas distintas.\n\nAtribución del mapeo postal: CartoCiudad (c) Instituto Geográfico Nacional de España, CC-BY 4.0.\n\nTérminos: base de datos (c) Apiverd, protegida por el derecho sui generis (Directiva 96/9/CE). Consulta y evaluación libres; redistribución o uso comercial del dataset requieren licencia (admin@apiverd.com). Datos elaborados con la máxima diligencia; para usos críticos, verifica la fuente legal citada en cada entrada.",
  "termsOfService": "https://apiverd.com"
 },
 "paths": {
  "/v1/es/is-holiday": {
   "get": {
    "summary": "¿Es festivo? Un código postal y una fecha (o rango), respuesta simple",
    "description": "La consulta directa: sí o no. Usa el municipio dominante del CP. Si un festivo solo aplica a un núcleo del municipio, no cambia el sí/no y se lista en locality_holidays.",
    "parameters": [
     {"name": "postal_code", "in": "query", "required": true, "schema": {"type": "string", "pattern": "^\\d{5}$"}, "example": "07141"},
     {"name": "date", "in": "query", "required": false, "description": "Una fecha concreta. Alternativa: from y to.", "schema": {"type": "string", "format": "date"}, "example": "2026-06-30"},
     {"name": "from", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}},
     {"name": "to", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}},
     {"name": "municipality_id", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^\\d{5}$"}}
    ],
    "responses": {
     "200": {
      "description": "Con date: el día con su veredicto. Con from y to: un array days con un veredicto por día.",
      "content": {
       "application/json": {
        "examples": {
         "una fecha": {
          "value": {
           "country": "ES",
           "postal_code": "07141",
           "municipality": "Marratxí",
           "municipality_id": "07036",
           "date": "2026-06-30",
           "holiday": true,
           "name": {"ca": "Sant Marçal"},
           "scope": "local"
          }
         },
         "rango": {
          "value": {
           "country": "ES",
           "postal_code": "07141",
           "municipality": "Marratxí",
           "municipality_id": "07036",
           "from": "2026-06-28",
           "to": "2026-06-30",
           "days": [
            {"date": "2026-06-28", "holiday": false},
            {"date": "2026-06-29", "holiday": true, "name": null, "scope": "local"},
            {"date": "2026-06-30", "holiday": true, "name": {"ca": "Sant Marçal"}, "scope": "local"}
           ]
          }
         }
        }
       }
      }
     },
     "400": {"$ref": "#/components/responses/BadRequest"},
     "404": {"$ref": "#/components/responses/NotFound"}
    }
   }
  },
  "/v1/es/holidays": {
   "get": {
    "summary": "Festivos aplicables a un código postal",
    "parameters": [
     {"name": "postal_code", "in": "query", "required": true, "schema": {"type": "string", "pattern": "^\\d{5}$"}, "example": "07600"},
     {"name": "year", "in": "query", "required": true, "schema": {"type": "string", "pattern": "^\\d{4}$"}, "example": "2026"},
     {"name": "municipality_id", "in": "query", "required": false, "description": "Código INE para desambiguar un CP que cruza municipios", "schema": {"type": "string", "pattern": "^\\d{5}$"}},
     {"name": "format", "in": "query", "required": false, "schema": {"type": "string", "enum": ["json", "ics"], "default": "json"}}
    ],
    "responses": {
     "200": {
      "description": "Festivos del CP. Con format=ics devuelve text/calendar (candidato dominante salvo municipality_id).",
      "content": {
       "application/json": {
        "example": {
         "country": "ES",
         "postal_code": "07600",
         "year": 2026,
         "municipality_id_system": "INE",
         "ambiguous": true,
         "disambiguation": "El CP cruza varios municipios: los candidatos llevan peso (proporcion de portales). Usa municipality_id para quedarte con uno.",
         "municipalities": [
          {
           "municipality_id": "07040",
           "name": "Palma",
           "weight": 0.6596,
           "localities": null,
           "holidays": [
            {"date": "2026-01-01", "name": {"es": "Año Nuevo", "ca": "Cap d'Any"}, "scope": "national", "source": {"ref": "BOE-A-2025-21667", "url": "https://www.boe.es/diario_boe/txt.php?id=BOE-A-2025-21667"}},
            {"date": "2026-01-20", "name": {"ca": "Sant Sebastià"}, "scope": "local", "subdivision": "ES-IB", "locality": null, "source": {"ref": "BOIB núm. 129, de 27/09/2025 (resolució 10694)", "url": "https://www.caib.es/eboibfront/pdf/ca/2025/129/1201461"}}
           ]
          }
         ]
        }
       }
      }
     },
     "400": {"$ref": "#/components/responses/BadRequest"},
     "404": {"$ref": "#/components/responses/NotFound"}
    }
   }
  },
  "/v1/es/working-days": {
   "get": {
    "summary": "Días laborables entre dos fechas para un código postal",
    "description": "Descuenta fines de semana y festivos del municipio (el dominante si el CP es ambiguo). Los festivos que solo aplican a un núcleo del municipio no descuentan de working_days pero sí de working_days_min: el valor real está entre los dos.",
    "parameters": [
     {"name": "postal_code", "in": "query", "required": true, "schema": {"type": "string", "pattern": "^\\d{5}$"}, "example": "07141"},
     {"name": "from", "in": "query", "required": true, "schema": {"type": "string", "format": "date"}, "example": "2026-06-25"},
     {"name": "to", "in": "query", "required": true, "schema": {"type": "string", "format": "date"}, "example": "2026-07-05"},
     {"name": "municipality_id", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^\\d{5}$"}}
    ],
    "responses": {
     "200": {
      "description": "Cómputo con el detalle de días no laborables.",
      "content": {
       "application/json": {
        "example": {
         "country": "ES",
         "postal_code": "07141",
         "municipality_id": "07036",
         "municipality": "Marratxí",
         "ambiguous": false,
         "from": "2026-06-25",
         "to": "2026-07-05",
         "total_days": 11,
         "working_days": 5,
         "working_days_min": 5,
         "non_working": [
          {"date": "2026-06-27", "reason": "weekend"},
          {"date": "2026-06-29", "reason": "holiday", "scope": "local", "name": null},
          {"date": "2026-06-30", "reason": "holiday", "scope": "local", "name": {"ca": "Sant Marçal"}}
         ]
        }
       }
      }
     },
     "400": {"$ref": "#/components/responses/BadRequest"},
     "404": {"$ref": "#/components/responses/NotFound"}
    }
   }
  },
  "/data/es/index.json": {
   "get": {
    "summary": "Años disponibles y cobertura",
    "responses": {"200": {"description": "Índice del dataset", "content": {"application/json": {"example": {"country": "ES", "years": ["2026"], "postal_codes": 159, "coverage": ["ES-IB"]}}}}}
   }
  },
  "/data/es/{postal_code}.json": {
   "get": {
    "summary": "Asset crudo de un código postal (todos los años)",
    "parameters": [{"name": "postal_code", "in": "path", "required": true, "schema": {"type": "string", "pattern": "^\\d{5}$"}}],
    "responses": {"200": {"description": "Candidatos con pesos y festivos por año"}, "404": {"description": "CP fuera de cobertura"}}
   }
  }
 },
 "components": {
  "responses": {
   "BadRequest": {
    "description": "Parámetros inválidos",
    "content": {"application/json": {"example": {"error": "invalid_postal_code", "message": "postal_code debe ser un codigo postal español de 5 digitos."}}}
   },
   "NotFound": {
    "description": "CP fuera de cobertura, año sin datos o municipio no candidato",
    "content": {"application/json": {"example": {"error": "year_not_available", "message": "Sin datos del año 2027. Años disponibles: 2026."}}}
   }
  }
 }
}
