{"openapi":"3.1.0","info":{"title":"Hoy en Cancún API","version":"1.0.0","summary":"Eventos, recintos y avisos de Cancún (hora America/Cancun).","description":"API pública de lectura. Todas las fechas son de Cancún (UTC−5, sin horario de verano). Sin autenticación: 60 peticiones/min por IP. Para más volumen, envía `x-api-key`. Atribución requerida: cita y enlaza la `url` canónica de cada evento. También hay un servidor MCP en https://hoyencancun.mx/mcp.","termsOfService":"https://hoyencancun.mx/llms.txt"},"servers":[{"url":"https://hoyencancun.mx"}],"security":[{},{"apiKey":[]}],"tags":[{"name":"events"},{"name":"venues"},{"name":"organizers"},{"name":"notices"}],"paths":{"/api/v1/events":{"get":{"operationId":"listEvents","tags":["events"],"summary":"Buscar eventos","description":"Un elemento por evento con su próxima ocurrencia dentro del rango (`next`) y cuántas fechas más tiene (`more_dates`). Sin parámetros de fecha: próximos desde ahora.","parameters":[{"name":"date","in":"query","description":"Día o periodo en hora de Cancún: today, tomorrow, weekend (vie–dom; si hoy es vie/sáb/dom empieza hoy), week (hoy + 6 días) o YYYY-MM-DD. Incompatible con from/to.","schema":{"anyOf":[{"type":"string","enum":["today","tomorrow","weekend","week"]},{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}]}},{"name":"from","in":"query","description":"Primer día (inclusive, YYYY-MM-DD, Cancún). Sin `to` = 30 días. Máximo 92 días de rango.","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","description":"Último día (inclusive, YYYY-MM-DD, Cancún). Sin `from` = desde hoy.","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"category","in":"query","description":"Categoría: clave o slug ES/EN.","schema":{"type":"string","examples":["live-music","party","theater","dance","film","art","markets","food","sports","wellness","family","tech","environment","culture","community"]}},{"name":"zone","in":"query","description":"Zona de Cancún: clave o slug ES/EN.","schema":{"type":"string","examples":["hotel-zone","downtown","huayacan","puerto-cancun","tajamar","tulum-coba","region-100","puerto-juarez","isla-mujeres","puerto-morelos"]}},{"name":"free","in":"query","description":"Sólo eventos gratuitos.","schema":{"type":"string","enum":["1","true","0","false"]}},{"name":"family","in":"query","description":"Sólo planes para familia (categoría family o etiqueta familia).","schema":{"type":"string","enum":["1","true","0","false"]}},{"name":"near","in":"query","description":"Punto `lat,lng` para buscar cerca (requiere recinto geocodificado).","schema":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?,-?\\d+(\\.\\d+)?$","examples":["21.1357,-86.7446"]}},{"name":"radius_km","in":"query","description":"Radio para `near` en km.","schema":{"type":"number","default":5,"maximum":50,"exclusiveMinimum":0}},{"name":"lang","in":"query","description":"Idioma de títulos, resúmenes y URLs canónicas.","schema":{"type":"string","enum":["es","en"],"default":"es"}},{"name":"q","in":"query","description":"Texto libre (título, resumen, recinto).","schema":{"type":"string","maxLength":100}},{"name":"limit","in":"query","description":"Máximo de eventos (en .ics: de ocurrencias; por defecto 1000).","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicEvent"}},"meta":{"$ref":"#/components/schemas/ListMeta"}}}}}},"400":{"description":"Parámetro inválido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"API key inválida o revocada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones excedido (60/min por IP sin API key).","headers":{"Retry-After":{"schema":{"type":"integer"}},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/events.ics":{"get":{"operationId":"eventsCalendarFeed","tags":["events"],"summary":"Feed iCalendar suscribible","description":"Mismos filtros que /api/v1/events. Incluye todas las ocurrencias del rango (por defecto, hoy + 60 días). Se refresca cada 6 h.","parameters":[{"name":"date","in":"query","description":"Día o periodo en hora de Cancún: today, tomorrow, weekend (vie–dom; si hoy es vie/sáb/dom empieza hoy), week (hoy + 6 días) o YYYY-MM-DD. Incompatible con from/to.","schema":{"anyOf":[{"type":"string","enum":["today","tomorrow","weekend","week"]},{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}]}},{"name":"from","in":"query","description":"Primer día (inclusive, YYYY-MM-DD, Cancún). Sin `to` = 30 días. Máximo 92 días de rango.","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","description":"Último día (inclusive, YYYY-MM-DD, Cancún). Sin `from` = desde hoy.","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"category","in":"query","description":"Categoría: clave o slug ES/EN.","schema":{"type":"string","examples":["live-music","party","theater","dance","film","art","markets","food","sports","wellness","family","tech","environment","culture","community"]}},{"name":"zone","in":"query","description":"Zona de Cancún: clave o slug ES/EN.","schema":{"type":"string","examples":["hotel-zone","downtown","huayacan","puerto-cancun","tajamar","tulum-coba","region-100","puerto-juarez","isla-mujeres","puerto-morelos"]}},{"name":"free","in":"query","description":"Sólo eventos gratuitos.","schema":{"type":"string","enum":["1","true","0","false"]}},{"name":"family","in":"query","description":"Sólo planes para familia (categoría family o etiqueta familia).","schema":{"type":"string","enum":["1","true","0","false"]}},{"name":"near","in":"query","description":"Punto `lat,lng` para buscar cerca (requiere recinto geocodificado).","schema":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?,-?\\d+(\\.\\d+)?$","examples":["21.1357,-86.7446"]}},{"name":"radius_km","in":"query","description":"Radio para `near` en km.","schema":{"type":"number","default":5,"maximum":50,"exclusiveMinimum":0}},{"name":"lang","in":"query","description":"Idioma de títulos, resúmenes y URLs canónicas.","schema":{"type":"string","enum":["es","en"],"default":"es"}},{"name":"q","in":"query","description":"Texto libre (título, resumen, recinto).","schema":{"type":"string","maxLength":100}},{"name":"limit","in":"query","description":"Máximo de eventos (en .ics: de ocurrencias; por defecto 1000).","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"iCalendar (RFC 5545).","content":{"text/calendar":{"schema":{"type":"string"}}}},"400":{"description":"Parámetro inválido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"API key inválida o revocada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones excedido (60/min por IP sin API key).","headers":{"Retry-After":{"schema":{"type":"integer"}},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/events/{idOrSlug}":{"get":{"operationId":"getEvent","tags":["events"],"summary":"Detalle de un evento","description":"Por id o slug (ES o EN). Los eventos pasados no dan 404: `is_past` = true. Añade `.ics` al final (`/api/v1/events/{id}.ics`) para descargar el evento en iCalendar.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"}},{"name":"lang","in":"query","description":"Idioma de títulos, resúmenes y URLs canónicas.","schema":{"type":"string","enum":["es","en"],"default":"es"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"allOf":[{"$ref":"#/components/schemas/PublicEvent"},{"type":"object","required":["occurrences","is_past"],"properties":{"occurrences":{"type":"array","items":{"$ref":"#/components/schemas/Occurrence"}},"is_past":{"type":"boolean"}}}]},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"400":{"description":"Parámetro inválido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"API key inválida o revocada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones excedido (60/min por IP sin API key).","headers":{"Retry-After":{"schema":{"type":"integer"}},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/venues/{slug}":{"get":{"operationId":"getVenue","tags":["venues"],"summary":"Recinto y sus próximos eventos","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"lang","in":"query","description":"Idioma de títulos, resúmenes y URLs canónicas.","schema":{"type":"string","enum":["es","en"],"default":"es"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Venue"},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"400":{"description":"Parámetro inválido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"API key inválida o revocada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones excedido (60/min por IP sin API key).","headers":{"Retry-After":{"schema":{"type":"integer"}},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/organizers/{slug}":{"get":{"operationId":"getOrganizer","tags":["organizers"],"summary":"Organizador y sus próximos eventos","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"lang","in":"query","description":"Idioma de títulos, resúmenes y URLs canónicas.","schema":{"type":"string","enum":["es","en"],"default":"es"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Organizer"},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"400":{"description":"Parámetro inválido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"API key inválida o revocada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones excedido (60/min por IP sin API key).","headers":{"Retry-After":{"schema":{"type":"integer"}},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/notices":{"get":{"operationId":"listNotices","tags":["notices"],"summary":"Avisos del día (clima, tráfico, cierres, ecología)","parameters":[{"name":"date","in":"query","description":"today, tomorrow o YYYY-MM-DD (Cancún).","schema":{"anyOf":[{"type":"string","enum":["today","tomorrow"]},{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}],"default":"today"}},{"name":"lang","in":"query","description":"Idioma de títulos, resúmenes y URLs canónicas.","schema":{"type":"string","enum":["es","en"],"default":"es"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Notice"}},"meta":{"allOf":[{"$ref":"#/components/schemas/Meta"},{"type":"object","properties":{"count":{"type":"integer"},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}}]}}}}}},"400":{"description":"Parámetro inválido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"API key inválida o revocada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones excedido (60/min por IP sin API key).","headers":{"Retry-After":{"schema":{"type":"integer"}},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"x-api-key","description":"Opcional; sube el límite de peticiones."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","examples":["invalid_parameter","not_found","rate_limited"]},"message":{"type":"string"}}}}},"Meta":{"type":"object","required":["lang","generated_at","attribution","docs"],"properties":{"lang":{"type":"string","enum":["es","en"]},"generated_at":{"type":"string","description":"Instante de generación (ISO 8601 con desfase de Cancún).","format":"date-time"},"attribution":{"type":"string"},"docs":{"type":"string","format":"uri"}}},"ListMeta":{"allOf":[{"$ref":"#/components/schemas/Meta"},{"type":"object","required":["count","range"],"properties":{"count":{"type":"integer"},"range":{"oneOf":[{"type":"null"},{"type":"object","required":["from","to"],"properties":{"from":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}}],"description":"Rango de días (inclusive); null = próximos desde ahora."}}}]},"Occurrence":{"type":"object","required":["id","start","end","date","all_day","status"],"properties":{"id":{"type":"string"},"start":{"type":"string","description":"Inicio, ISO 8601 con desfase -05:00.","format":"date-time"},"end":{"type":"string","description":"Fin (si no se conoce, inicio + 3 h).","format":"date-time"},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Fecha local de Cancún."},"all_day":{"type":"boolean"},"status":{"type":"string","enum":["scheduled","cancelled","postponed"]},"notes":{"type":["string","null"]}}},"Taxon":{"type":"object","required":["key","name"],"properties":{"key":{"type":"string"},"name":{"type":"string"}}},"PublicEvent":{"type":"object","required":["id","url","url_es","url_en","title","summary","status","price","tags"],"properties":{"id":{"type":"string"},"url":{"type":"string","description":"URL canónica en el idioma pedido. Cítala siempre.","format":"uri"},"url_es":{"type":"string","format":"uri"},"url_en":{"type":"string","format":"uri"},"title":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string","enum":["published","cancelled","postponed"]},"next":{"$ref":"#/components/schemas/Occurrence","description":"Primera ocurrencia en el rango (o la próxima)."},"more_dates":{"type":"integer","description":"Ocurrencias adicionales dentro del rango."},"category":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Taxon"}]},"tags":{"type":"array","items":{"type":"string"}},"zone":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Taxon"}]},"venue":{"oneOf":[{"type":"null"},{"type":"object","properties":{"name":{"type":"string"},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"url":{"type":"string","format":"uri"},"directions_url":{"type":["string","null"],"format":"uri"}}}]},"location_note":{"type":["string","null"]},"price":{"type":"object","required":["is_free","currency","text"],"properties":{"is_free":{"type":"boolean"},"min":{"type":["number","null"]},"max":{"type":["number","null"]},"currency":{"type":"string","examples":["MXN"]},"text":{"type":"string"}}},"ticket_url":{"type":["string","null"],"format":"uri"},"registration_url":{"type":["string","null"],"format":"uri"},"age_restriction":{"type":["string","null"]},"languages":{"type":"array","items":{"type":"string"}},"organizer":{"oneOf":[{"type":"null"},{"type":"object","properties":{"name":{"type":"string"},"verified":{"type":"boolean"},"url":{"type":"string","format":"uri"}}}]},"image":{"oneOf":[{"type":"null"},{"type":"object","properties":{"url":{"type":"string","format":"uri"},"alt":{"type":"string"}}}]},"verified":{"type":"boolean"},"source":{"type":"string","enum":["organizer","agent","editor"]},"source_url":{"type":["string","null"],"format":"uri"},"updated_at":{"type":"string","format":"date-time"}}},"Venue":{"type":"object","required":["id","slug","url","name","upcoming_events"],"properties":{"id":{"type":"string"},"slug":{"type":"string"},"url":{"type":"string","format":"uri"},"url_es":{"type":"string","format":"uri"},"url_en":{"type":"string","format":"uri"},"name":{"type":"string"},"description":{"type":["string","null"]},"address":{"type":["string","null"]},"locality":{"type":"string"},"postal_code":{"type":["string","null"]},"zone":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Taxon"}]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"directions_url":{"type":["string","null"],"format":"uri"},"website":{"type":["string","null"]},"phone":{"type":["string","null"]},"social":{"type":"array","items":{"type":"string"}},"capacity":{"type":["integer","null"]},"accessibility":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"},"upcoming_events":{"type":"array","items":{"$ref":"#/components/schemas/PublicEvent"}}}},"Organizer":{"type":"object","required":["id","slug","url","name","upcoming_events"],"properties":{"id":{"type":"string"},"slug":{"type":"string"},"url":{"type":"string","format":"uri"},"url_es":{"type":"string","format":"uri"},"url_en":{"type":"string","format":"uri"},"name":{"type":"string"},"type":{"type":"string","enum":["gobierno","recinto","promotor","colectivo","marca"]},"verified":{"type":"boolean"},"description":{"type":["string","null"]},"website":{"type":["string","null"]},"social":{"type":"array","items":{"type":"string"}},"updated_at":{"type":"string","format":"date-time"},"upcoming_events":{"type":"array","items":{"$ref":"#/components/schemas/PublicEvent"}}}},"Notice":{"type":"object","required":["id","type","severity","title","body","starts_at"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["weather","traffic","closure","ecology","health","other"]},"severity":{"type":"string","enum":["info","warning","alert"]},"title":{"type":"string"},"body":{"type":"string"},"zone":{"type":["string","null"]},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"]},"source_url":{"type":["string","null"],"format":"uri"}}}}}}