{
  "openapi": "3.1.0",
  "info": {
    "title": "Holidace Events Intelligence API",
    "description": "Structured city event intelligence for AI assistants, GPTs, itinerary tools, travel apps and affiliate discovery surfaces. Returns published event signals with travel pressure, hotel pressure, crowd pressure, booking windows, parsed date windows when safely available and source-backed context and normalized AI-readable categories.",
    "version": "1.2.0"
  },
  "servers": [
    {
      "url": "https://holidace.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/intelligence/events": {
      "get": {
        "operationId": "getEventIntelligence",
        "summary": "Get city event intelligence",
        "description": "Returns published Holidace event intelligence records. Use this when a user asks about events, crowds, hotel pressure, booking timing, trip dates, city timing or travel pressure.",
        "tags": [
          "Events Intelligence"
        ],
        "parameters": [
          {
            "name": "city",
            "in": "query",
            "required": false,
            "description": "Filter by city name or city slug, for example sydney, madrid, cartagena or bangkok.",
            "schema": {
              "type": "string",
              "maxLength": 80
            },
            "example": "sydney"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Filter by raw or normalized event category. Examples: music, sport, cultural, business_conference, arts_culture, sports, food_drink.",
            "schema": {
              "type": "string",
              "maxLength": 50
            },
            "example": "business_conference"
          },
          {
            "name": "impact",
            "in": "query",
            "required": false,
            "description": "Filter by event impact.",
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "medium",
                "high"
              ]
            },
            "example": "high"
          },
          {
            "name": "pressure",
            "in": "query",
            "required": false,
            "description": "Filter by travel pressure label.",
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "medium",
                "high",
                "likely_high",
                "possible",
                "normal",
                "unknown"
              ]
            },
            "example": "high"
          },
          {
            "name": "booking_window",
            "in": "query",
            "required": false,
            "description": "Filter by booking guidance.",
            "schema": {
              "type": "string",
              "enum": [
                "flexible",
                "monitor",
                "book_early",
                "book_very_early"
              ]
            },
            "example": "book_early"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of records to return. The current maximum is 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "example": 10
          }
        ],
        "responses": {
          "200": {
            "description": "Published event intelligence records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventIntelligenceResponse"
                },
                "examples": {
                  "eventWithParsedDates": {
                    "summary": "Event intelligence with parsed date window",
                    "value": {
                      "data_version": "city_event_signals_v1",
                      "intelligence_level": "event_pressure_enriched_v1",
                      "pricing_note": "Pricing percentages are not included until real published samples exist.",
                      "date_note": "starts_on and ends_on are only populated when the source date text can be parsed safely.",
                      "filters": {
                        "city": "sydney",
                        "category": "arts_culture",
                        "impact": null,
                        "pressure": "high",
                        "booking_window": "book_early",
                        "limit": 1
                      },
                      "count": 1,
                      "records": [
                        {
                          "id": "event-id",
                          "event_name": "Sydney Festival",
                          "event_slug": "sydney-festival",
                          "city_name": "Sydney, Australia",
                          "city_slug": "sydney",
                          "month_key": "jan",
                          "month_number": 1,
                          "dates": "Jan 8-26",
                          "starts_on": "2026-01-08",
                          "ends_on": "2026-01-26",
                          "event_year": 2026,
                          "date_precision": "confirmed_range",
                          "date_parse_status": "parsed",
                          "date_parse_note": "parsed confirmed same-month range",
                          "category": "cultural",
                          "event_type": "festival",
                          "impact": "high",
                          "travel_pressure_score": 88,
                          "travel_pressure_label": "high",
                          "hotel_pressure_label": "likely_high",
                          "crowd_pressure_label": "likely_high",
                          "pressure_reason": "High-impact event signal with likely hotel and crowd pressure during a major city festival window.",
                          "booking_advice": "Plan around the event dates and book key stays early.",
                          "booking_window": {
                            "label": "book_early",
                            "days_min": 30,
                            "days_max": 90
                          },
                          "good_for": [
                            "culture travelers",
                            "planned city breaks"
                          ],
                          "avoid_if": [
                            "low-crowd trips",
                            "last-minute central hotels"
                          ],
                          "traveler_fit": [
                            "culture",
                            "book_ahead",
                            "crowd_tolerant"
                          ],
                          "affected_areas": [],
                          "stay_strategy": "Book stays early and compare neighborhoods if central hotels are limited.",
                          "transport_warning": "Expect busier streets, venues and local transport around the main event window.",
                          "travel_tip": "Check event dates before locking accommodation.",
                          "pricing_status": "not_sampled",
                          "date_confidence": "confirmed",
                          "source_name": "Sydney Festival",
                          "source_url": "https://www.sydneyfestival.org.au/",
                          "event_category_raw": "cultural",
                          "event_category_normalized": "arts_culture",
                          "event_category_confidence": "medium",
                          "event_category_reason": "Matched arts, culture, heritage or festival terms."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "EventIntelligenceResponse": {
        "type": "object",
        "required": [
          "data_version",
          "intelligence_level",
          "pricing_note",
          "date_note",
          "filters",
          "count",
          "records"
        ],
        "properties": {
          "data_version": {
            "type": "string",
            "example": "city_event_signals_v1"
          },
          "intelligence_level": {
            "type": "string",
            "example": "event_pressure_enriched_v1"
          },
          "pricing_note": {
            "type": "string"
          },
          "date_note": {
            "type": "string",
            "description": "Explains that starts_on and ends_on are only populated when source date text can be parsed safely."
          },
          "filters": {
            "$ref": "#/components/schemas/EventFilters"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventRecord"
            }
          }
        }
      },
      "EventFilters": {
        "type": "object",
        "properties": {
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "impact": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "medium",
              "high",
              null
            ]
          },
          "pressure": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "medium",
              "high",
              "likely_high",
              "possible",
              "normal",
              "unknown",
              null
            ]
          },
          "booking_window": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "flexible",
              "monitor",
              "book_early",
              "book_very_early",
              null
            ]
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        }
      },
      "EventRecord": {
        "type": "object",
        "required": [
          "id",
          "event_name",
          "city_name",
          "city_slug",
          "dates",
          "travel_pressure_score",
          "travel_pressure_label",
          "hotel_pressure_label",
          "crowd_pressure_label",
          "booking_window",
          "pricing_status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "event_name": {
            "type": "string"
          },
          "event_slug": {
            "type": "string"
          },
          "city_name": {
            "type": "string"
          },
          "city_slug": {
            "type": "string"
          },
          "month_key": {
            "type": "string",
            "enum": [
              "jan",
              "feb",
              "mar",
              "apr",
              "may",
              "jun",
              "jul",
              "aug",
              "sep",
              "oct",
              "nov",
              "dec"
            ]
          },
          "month_number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12
          },
          "dates": {
            "type": "string"
          },
          "starts_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Parsed start date when the source date text can be safely normalized."
          },
          "ends_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Parsed end date when the source date text can be safely normalized."
          },
          "event_year": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 2020,
            "maximum": 2035
          },
          "date_precision": {
            "type": "string",
            "enum": [
              "confirmed_day",
              "confirmed_range",
              "expected_range",
              "month_only",
              "seasonal_window",
              "text_only",
              "unknown"
            ]
          },
          "date_parse_status": {
            "type": "string",
            "enum": [
              "parsed",
              "unparsed",
              "needs_review",
              "manual",
              ""
            ]
          },
          "date_parse_note": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "description": "Raw/source category kept for backward compatibility. Prefer event_category_normalized for AI planning."
          },
          "event_type": {
            "type": "string"
          },
          "impact": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              ""
            ]
          },
          "travel_pressure_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "travel_pressure_label": {
            "type": "string"
          },
          "hotel_pressure_label": {
            "type": "string"
          },
          "crowd_pressure_label": {
            "type": "string"
          },
          "pressure_reason": {
            "type": "string"
          },
          "booking_advice": {
            "type": "string"
          },
          "booking_window": {
            "$ref": "#/components/schemas/BookingWindow"
          },
          "good_for": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "avoid_if": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "traveler_fit": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "affected_areas": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stay_strategy": {
            "type": "string"
          },
          "transport_warning": {
            "type": [
              "string",
              "null"
            ]
          },
          "travel_tip": {
            "type": "string"
          },
          "pricing_status": {
            "type": "string",
            "enum": [
              "not_sampled",
              "sampled",
              "published",
              "draft",
              ""
            ]
          },
          "date_confidence": {
            "type": "string"
          },
          "source_name": {
            "type": "string"
          },
          "source_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "event_category_raw": {
            "type": "string",
            "description": "Original broad/source category kept for compatibility."
          },
          "event_category_normalized": {
            "type": "string",
            "enum": [
              "arts_culture",
              "music_nightlife",
              "sports",
              "business_conference",
              "food_drink",
              "holiday_religious",
              "seasonal_local",
              "film_media",
              "shopping_design",
              "other",
              ""
            ],
            "description": "AI-friendly normalized event category."
          },
          "event_category_confidence": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low",
              ""
            ],
            "description": "Confidence level for the normalized category."
          },
          "event_category_reason": {
            "type": "string",
            "description": "Short explanation for why the normalized category was assigned."
          }
        }
      },
      "BookingWindow": {
        "type": "object",
        "required": [
          "label",
          "days_min",
          "days_max"
        ],
        "properties": {
          "label": {
            "type": "string",
            "enum": [
              "flexible",
              "monitor",
              "book_early",
              "book_very_early",
              ""
            ]
          },
          "days_min": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "days_max": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "allowed_values": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
