PArns/v4.api.park.fan

api.park.fan

TypeScript

1

1,752 commits

updated Oct 19, 2026

See the code

README

🎒 park.fan API v4

Real-time theme park intelligence powered by machine learning

NestJS TypeScript PostgreSQL Docker

Aggregating wait times, weather forecasts, park schedules, and ML-powered predictions for optimal theme park experiences worldwide.


πŸ“– Quick Navigation


✨ Features

  • πŸš€ Real-time Wait Times β€” Live queue data for attractions, shows, and restaurants
  • πŸ€– ML Predictions β€” Machine learning forecasts for wait times and crowd levels
  • 🌀️ Weather Integration β€” Current conditions and 16-day forecasts for all parks
  • πŸ“… Park Schedules β€” Opening hours, special events, and operating calendars
  • πŸ•΅οΈ Smart Gaps β€” Reconstruction of historical opening hours from ride activity when official data is missing
  • 🌍 Multi-Source Data β€” Aggregated from multiple providers for maximum coverage
  • πŸ“Š Analytics Ready β€” TimescaleDB-powered time-series data for insights
  • ⚑ High Performance β€” Redis caching and Bull queue processing
  • 🎯 RESTful API β€” Clean endpoints with full Swagger/OpenAPI documentation

πŸ› οΈ Tech Stack

CategoryTechnology
BackendNestJS 11 Β· TypeScript (strict mode)
DatabasePostgreSQL 16 Β· TimescaleDB
Cache & QueueRedis 7 Β· Bull Queue
ML ServicePython 3.11 Β· CatBoost Β· FastAPI
DevOpsDocker Compose Β· GitHub Actions
TestingJest Β· Supertest Β· Testcontainers

πŸ“… Special Logic: Schedules & Seasons

The API implements advanced logic to handle parks without official API schedules (e.g., Efteling, Hellendoorn) and seasonal closures.

1. hasOperatingSchedule Flag

All park objects include a hasOperatingSchedule boolean:

  • true: The park provides official operating hours via an API.
  • false: The park does not provide official hours. Opening times are either null (future) or reconstructed from activity (past).

2. Historical Hour Reconstruction

For past days without official data, the system reconstructs opening hours from ride activity.

  • Opening Time: First 15min window with >= 10% ride activity, rounded down.
  • Closing Time: Last 15min window with activity, rounded up.
  • Rounding: Both times are rounded to the nearest full hour for maximum plausibility.

3. Seasonal Detection

The system automatically identifies "Seasonal Parks" (parks with winter gaps > 21 days).

  • Seasonal Parks: Future dates outside the known operating range are marked as CLOSED (suppressing crowd predictions).
  • Year-Round Parks: Future dates without schedules remain UNKNOWN, allowing ML-powered crowd and wait-time predictions for trip planning.

πŸš€ Quick Start

Prerequisites

  • Node.js 20+
  • pnpm 11+ (corepack enable picks up the pinned packageManager version)
  • Docker & Docker Compose
  • Git

Installation

# Clone the repository
git clone https://github.com/PArns/v4.api.park.fan.git
cd v4.api.park.fan

# Install dependencies
pnpm install

# Copy environment configuration
cp .env.example .env

# Start infrastructure (PostgreSQL + Redis)
pnpm docker:up

# Start development server
pnpm dev

Access Points

Once running, you can access:


πŸ“š API Documentation

πŸ₯ Health & Monitoring

System health checks and monitoring endpoints.

GET /v1/health              # System health status
GET /v1/health/db           # Database connectivity

Response includes:

  • System uptime
  • Database connection status
  • Last sync timestamps (wait times, park metadata)
  • Active jobs and queue status

🎑 Parks

Core endpoints for park information, weather, schedules, and wait times. All routes use the full geographic path structure for consistency and SEO-friendly URLs.

Geographic Routes:

GET /v1/parks                                                      # List all parks (paginated)
GET /v1/parks/:continent                                          # Parks by continent
GET /v1/parks/:continent/:country                                 # Parks by country
GET /v1/parks/:continent/:country/:city                           # Parks by city
GET /v1/parks/:continent/:country/:city/:parkSlug                 # Get park by location
GET /v1/parks/:continent/:country/:city/:parkSlug/calendar        # Integrated calendar
GET /v1/parks/:continent/:country/:city/:parkSlug/weather         # Current weather & history
GET /v1/parks/:continent/:country/:city/:parkSlug/weather/forecast # 16-day forecast
GET /v1/parks/:continent/:country/:city/:parkSlug/schedule        # Operating hours
GET /v1/parks/:continent/:country/:city/:parkSlug/wait-times       # Live wait times
GET /v1/parks/:continent/:country/:city/:parkSlug/predictions/yearly # Yearly crowd predictions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions     # List park attractions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions/:attractionSlug # Get attraction

Query Parameters:

  • continent, country, city β€” Filter by location (in list endpoint)
  • sort β€” Sort order (name, popularity, etc.)
  • page, limit β€” Pagination (default: page=1, limit=10)
  • from, to β€” Date range for weather/schedule (YYYY-MM-DD format)

Example Geographic Route:

GET /v1/parks/north-america/united-states/orlando/magic-kingdom

Example Response:

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "Magic Kingdom",
  "slug": "magic-kingdom",
  "url": "/v1/parks/north-america/united-states/orlando/magic-kingdom",
  "continent": "North America",
  "country": "United States",
  "city": "Orlando",
  "timezone": "America/New_York",
  "currentStatus": "OPERATING",
  "currentLoad": {
    "crowdLevel": "moderate",
    "occupancy": 0.65
  },
  "coordinates": { "lat": 28.3772, "lng": -81.5707 },
  "attractions": [
    {
      "id": "...",
      "name": "Space Mountain",
      "slug": "space-mountain",
      "url": "/v1/parks/north-america/united-states/orlando/magic-kingdom/attractions/space-mountain"
    }
  ]
}

🎒 Attractions

Detailed attraction data with ML predictions and historical analytics. Access attractions through their park's geographic route.

Routes:

GET /v1/parks/:continent/:country/:city/:parkSlug/attractions              # List park attractions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions/:attractionSlug # Get attraction details

Query Parameters:

  • page, limit β€” Pagination for attraction list (default: page=1, limit=10)

The detail route includes:

  • Live wait times and status (OPERATING, CLOSED, DOWN, REFURBISHMENT)
  • 24-hour ML-powered wait time forecasts
  • Daily predictions with confidence scores
  • Historical statistics (average, percentiles)
  • Downtime tracking and reliability metrics
  • Full geographic URL for easy navigation

The list route includes none of that. It joins no live data: no status, no queues, no forecasts, no statistics β€” the stored catalog of the park and nothing else. Read the park payload or the detail route for live state.

Example Response (detail route):

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "Space Mountain",
  "slug": "space-mountain",
  "url": "/v1/parks/north-america/united-states/orlando/magic-kingdom/attractions/space-mountain",
  "park": {
    "id": "...",
    "name": "Magic Kingdom",
    "slug": "magic-kingdom"
  },
  "category": "RIDE",
  "currentWaitTime": 45,
  "status": "OPERATING",
  "lastUpdate": "2025-12-23T19:30:00Z",
  "forecast": [
    { "hour": "20:00", "predictedWaitTime": 50, "confidence": 0.87 },
    { "hour": "21:00", "predictedWaitTime": 35, "confidence": 0.82 }
  ],
  "stats": {
    "averageWaitTime": 42,
    "p50": 40,
    "p75": 55,
    "p90": 70
  }
}

🌍 Geographic Discovery

Navigate parks by geographic hierarchy for route generation and exploration.

GET /v1/discovery/geo                        # Full geo hierarchy
GET /v1/discovery/continents                 # List continents
GET /v1/discovery/continents/:continent      # Countries in continent

Response Structure:

{
  "continents": [
    {
      "continent": "North America",
      "countries": [
        {
          "country": "United States",
          "cities": [
            {
              "city": "Orlando",
              "parks": [
                {
                  "name": "Magic Kingdom",
                  "url": "/north-america/united-states/orlando/magic-kingdom",
                  "status": "OPERATING",
                  "analytics": {
                    "statistics": {
                      "avgWaitTime": 35,
                      "operatingAttractions": 42,
                      "closedAttractions": 3,
                      "totalAttractions": 45,
                      "crowdLevel": "moderate"
                    }
                  },
                  "attractions": [...]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Note: analytics.statistics.crowdLevel is co-present with avgWaitTime whenever the park has a valid P90 baseline (with P50 as fallback). See Crowd Levels for the rating system.


🏰 Destinations

Resort-level aggregation grouping multiple parks. Destinations are used internally for data organization but are not exposed as top-level API endpoints. Parks are accessed directly via their geographic routes.

Examples:

  • Walt Disney World (Magic Kingdom, EPCOT, Hollywood Studios, Animal Kingdom)
  • Disneyland Paris (Disneyland Park, Walt Disney Studios Park)

🎭 Shows & Dining

Entertainment and dining options are available through the park endpoints. Shows and restaurants are not exposed as top-level API endpoints but are included in park responses and can be accessed via the search endpoint.


Global search with enriched results across parks and attractions.

GET /v1/search?q=disney                    # Search all types
GET /v1/search?q=thunder&type=attraction  # Filter by type
GET /v1/search?q=paris                   # Search by city

Search Features:

  • Multi-entity search: Parks and attractions
  • Geographic search: By city, country, or continent
  • Per-type counts: Shows returned vs total results
  • Enriched results: Coordinates, wait times, park hours, full geographic URLs
  • Smart filtering: Type-based filtering with max 5 results per type
  • Fast response: Redis-cached for 5min, <3ms cached response

Response Structure:

{
  "query": "disney",
  "counts": {
    "park": {"returned": 5, "total": 13},
    "attraction": {"returned": 5, "total": 156}
  },
  "results": [
    {
      "type": "park",
      "name": "Disneyland Park",
      "status": "OPERATING",
      "load": "normal",
      "parkHours": {...},
      "coordinates": {...}
    },
    {
      "type": "attraction",
      "name": "Space Mountain",
      "waitTime": 45,
      "load": "higher",
      "parentPark": {...}
    }
  ]
}

πŸŽ‰ Holidays

Public holiday data affecting park crowds and operating hours. Holidays are used internally for ML predictions and analytics but are not exposed as top-level API endpoints.


πŸ“ Project Structure

v4.api.park.fan/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ config/                    # App configuration & environment
β”‚   β”œβ”€β”€ common/                    # Shared utilities, filters, interceptors
β”‚   β”œβ”€β”€ database/                  # Database utilities & migrations
β”‚   β”œβ”€β”€ queues/                    # Bull queue setup & processors
β”‚   β”œβ”€β”€ health/                    # Health check endpoints
β”‚   β”œβ”€β”€ destinations/              # Resort/destination grouping
β”‚   β”œβ”€β”€ parks/                     # Parks, weather, schedules
β”‚   β”œβ”€β”€ attractions/               # Attractions & data sources
β”‚   β”œβ”€β”€ shows/                     # Entertainment shows
β”‚   β”œβ”€β”€ restaurants/               # Dining locations
β”‚   β”œβ”€β”€ queue-data/                # Wait time data & history
β”‚   β”œβ”€β”€ ml/                        # ML prediction integration
β”‚   β”œβ”€β”€ analytics/                 # Statistics & analytics
β”‚   β”œβ”€β”€ holidays/                  # Public holiday data
β”‚   β”œβ”€β”€ date-features/             # Date-based features for ML
β”‚   β”œβ”€β”€ discovery/                 # Geographic discovery endpoints
β”‚   └── search/                    # Global search functionality
β”œβ”€β”€ ml-service/                    # Python ML service (CatBoost)
β”‚   β”œβ”€β”€ train.py                   # Model training script
β”‚   β”œβ”€β”€ main.py                    # FastAPI prediction service
β”‚   β”œβ”€β”€ features.py                # Feature engineering
β”‚   └── db.py                      # Database connection
β”œβ”€β”€ docker/                        # Docker configurations
β”œβ”€β”€ scripts/                       # Utility & debug scripts
β”œβ”€β”€ migrations/                    # Database migrations
└── test/                          # E2E tests

🐳 Docker Commands

# Start all services (PostgreSQL + Redis)
pnpm docker:up

# Stop all services
pnpm docker:down

# View logs
pnpm docker:logs

# Restart services
pnpm docker:restart

# Reset database (WARNING: deletes all data)
pnpm db:reset

Production Deployment:

docker-compose -f docker-compose.production.yml up -d

πŸ§ͺ Testing

# Run unit tests
pnpm test

# Run e2e tests
pnpm test:e2e

# Run all tests with coverage
pnpm test:all:cov

# Watch mode for development
pnpm test:watch

# Specific test file
pnpm test wait-times.processor.spec.ts

Code Quality:

# Lint code
pnpm lint

# Format code
pnpm format

# Type check
pnpm build

πŸ”§ Environment Variables

Application Settings

NODE_ENV=development              # development | production | test
PORT=3000                         # API server port
API_PREFIX=v1                     # API version prefix

Database Configuration

# PostgreSQL with TimescaleDB
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=parkfan
DB_PASSWORD=your_secure_password
DB_DATABASE=parkfan
DB_SYNCHRONIZE=true               # ⚠️ Set to false in production!
DB_LOGGING=false                  # Enable for debugging
DB_SSL_ENABLED=false              # Enable for production

Caching & Queue

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=                   # Optional, recommended for production

# Bull Queue
BULL_PREFIX=parkfan

External APIs

# Google APIs (Geocoding, Places)
GOOGLE_API_KEY=your_google_api_key

# Weather Data: Open-Meteo (no API key required)

# Data Sources (optional, for enhanced coverage)
QUEUE_TIMES_API_KEY=              # Queue-Times.com
THEMEPARKS_API_KEY=               # ThemeParks.wiki

ML Service

# ML Service Configuration
ML_SERVICE_URL=http://localhost:8000        # Development
# ML_SERVICE_URL=http://ml-service:8000     # Production (Docker)
MODEL_DIR=/app/models                       # Model storage directory
MODEL_VERSION=v1.1.0                        # Current model version (ml-service setting)

Sync & Processing

# Data Sync Intervals (cron expressions)
SYNC_WAIT_TIMES_CRON=*/5 * * * *           # Every 5 minutes
SYNC_PARK_METADATA_CRON=0 6 * * *          # Daily at 6 AM
SYNC_WEATHER_CRON=0 * * * *                # Hourly

🀝 Contributing

This is a private project. For questions or collaboration inquiries, please contact the maintainer.


πŸ“„ License

UNLICENSED β€” Private project by Patrick Arns


πŸ™ Powered By

This project aggregates data from multiple sources:

  • Queue-Times.com β€” Real-time wait time data
  • ThemeParks.wiki β€” Comprehensive park information and live data
  • Wartezeiten.app β€” Wait times, crowd levels, and opening hours enrichment
  • Open-Meteo.com β€” Weather forecasts, current conditions, and historical weather data (Weather data by Open-Meteo.com, licensed under CC BY 4.0; built on open data from DWD, ECMWF, NOAA, MΓ©tΓ©o-France and other national weather services)

Special thanks to these services for making real-time theme park data accessible.


Made with ❀️ for theme park enthusiasts worldwide

API Documentation Β· Frontend

PArns/v4.api.park.fan

api.park.fan

TypeScript

1

1,752 commits

updated Oct 19, 2026

See the code

README

🎒 park.fan API v4

Real-time theme park intelligence powered by machine learning

NestJS TypeScript PostgreSQL Docker

Aggregating wait times, weather forecasts, park schedules, and ML-powered predictions for optimal theme park experiences worldwide.


πŸ“– Quick Navigation


✨ Features

  • πŸš€ Real-time Wait Times β€” Live queue data for attractions, shows, and restaurants
  • πŸ€– ML Predictions β€” Machine learning forecasts for wait times and crowd levels
  • 🌀️ Weather Integration β€” Current conditions and 16-day forecasts for all parks
  • πŸ“… Park Schedules β€” Opening hours, special events, and operating calendars
  • πŸ•΅οΈ Smart Gaps β€” Reconstruction of historical opening hours from ride activity when official data is missing
  • 🌍 Multi-Source Data β€” Aggregated from multiple providers for maximum coverage
  • πŸ“Š Analytics Ready β€” TimescaleDB-powered time-series data for insights
  • ⚑ High Performance β€” Redis caching and Bull queue processing
  • 🎯 RESTful API β€” Clean endpoints with full Swagger/OpenAPI documentation

πŸ› οΈ Tech Stack

CategoryTechnology
BackendNestJS 11 Β· TypeScript (strict mode)
DatabasePostgreSQL 16 Β· TimescaleDB
Cache & QueueRedis 7 Β· Bull Queue
ML ServicePython 3.11 Β· CatBoost Β· FastAPI
DevOpsDocker Compose Β· GitHub Actions
TestingJest Β· Supertest Β· Testcontainers

πŸ“… Special Logic: Schedules & Seasons

The API implements advanced logic to handle parks without official API schedules (e.g., Efteling, Hellendoorn) and seasonal closures.

1. hasOperatingSchedule Flag

All park objects include a hasOperatingSchedule boolean:

  • true: The park provides official operating hours via an API.
  • false: The park does not provide official hours. Opening times are either null (future) or reconstructed from activity (past).

2. Historical Hour Reconstruction

For past days without official data, the system reconstructs opening hours from ride activity.

  • Opening Time: First 15min window with >= 10% ride activity, rounded down.
  • Closing Time: Last 15min window with activity, rounded up.
  • Rounding: Both times are rounded to the nearest full hour for maximum plausibility.

3. Seasonal Detection

The system automatically identifies "Seasonal Parks" (parks with winter gaps > 21 days).

  • Seasonal Parks: Future dates outside the known operating range are marked as CLOSED (suppressing crowd predictions).
  • Year-Round Parks: Future dates without schedules remain UNKNOWN, allowing ML-powered crowd and wait-time predictions for trip planning.

πŸš€ Quick Start

Prerequisites

  • Node.js 20+
  • pnpm 11+ (corepack enable picks up the pinned packageManager version)
  • Docker & Docker Compose
  • Git

Installation

# Clone the repository
git clone https://github.com/PArns/v4.api.park.fan.git
cd v4.api.park.fan

# Install dependencies
pnpm install

# Copy environment configuration
cp .env.example .env

# Start infrastructure (PostgreSQL + Redis)
pnpm docker:up

# Start development server
pnpm dev

Access Points

Once running, you can access:


πŸ“š API Documentation

πŸ₯ Health & Monitoring

System health checks and monitoring endpoints.

GET /v1/health              # System health status
GET /v1/health/db           # Database connectivity

Response includes:

  • System uptime
  • Database connection status
  • Last sync timestamps (wait times, park metadata)
  • Active jobs and queue status

🎑 Parks

Core endpoints for park information, weather, schedules, and wait times. All routes use the full geographic path structure for consistency and SEO-friendly URLs.

Geographic Routes:

GET /v1/parks                                                      # List all parks (paginated)
GET /v1/parks/:continent                                          # Parks by continent
GET /v1/parks/:continent/:country                                 # Parks by country
GET /v1/parks/:continent/:country/:city                           # Parks by city
GET /v1/parks/:continent/:country/:city/:parkSlug                 # Get park by location
GET /v1/parks/:continent/:country/:city/:parkSlug/calendar        # Integrated calendar
GET /v1/parks/:continent/:country/:city/:parkSlug/weather         # Current weather & history
GET /v1/parks/:continent/:country/:city/:parkSlug/weather/forecast # 16-day forecast
GET /v1/parks/:continent/:country/:city/:parkSlug/schedule        # Operating hours
GET /v1/parks/:continent/:country/:city/:parkSlug/wait-times       # Live wait times
GET /v1/parks/:continent/:country/:city/:parkSlug/predictions/yearly # Yearly crowd predictions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions     # List park attractions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions/:attractionSlug # Get attraction

Query Parameters:

  • continent, country, city β€” Filter by location (in list endpoint)
  • sort β€” Sort order (name, popularity, etc.)
  • page, limit β€” Pagination (default: page=1, limit=10)
  • from, to β€” Date range for weather/schedule (YYYY-MM-DD format)

Example Geographic Route:

GET /v1/parks/north-america/united-states/orlando/magic-kingdom

Example Response:

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "Magic Kingdom",
  "slug": "magic-kingdom",
  "url": "/v1/parks/north-america/united-states/orlando/magic-kingdom",
  "continent": "North America",
  "country": "United States",
  "city": "Orlando",
  "timezone": "America/New_York",
  "currentStatus": "OPERATING",
  "currentLoad": {
    "crowdLevel": "moderate",
    "occupancy": 0.65
  },
  "coordinates": { "lat": 28.3772, "lng": -81.5707 },
  "attractions": [
    {
      "id": "...",
      "name": "Space Mountain",
      "slug": "space-mountain",
      "url": "/v1/parks/north-america/united-states/orlando/magic-kingdom/attractions/space-mountain"
    }
  ]
}

🎒 Attractions

Detailed attraction data with ML predictions and historical analytics. Access attractions through their park's geographic route.

Routes:

GET /v1/parks/:continent/:country/:city/:parkSlug/attractions              # List park attractions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions/:attractionSlug # Get attraction details

Query Parameters:

  • page, limit β€” Pagination for attraction list (default: page=1, limit=10)

The detail route includes:

  • Live wait times and status (OPERATING, CLOSED, DOWN, REFURBISHMENT)
  • 24-hour ML-powered wait time forecasts
  • Daily predictions with confidence scores
  • Historical statistics (average, percentiles)
  • Downtime tracking and reliability metrics
  • Full geographic URL for easy navigation

The list route includes none of that. It joins no live data: no status, no queues, no forecasts, no statistics β€” the stored catalog of the park and nothing else. Read the park payload or the detail route for live state.

Example Response (detail route):

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "Space Mountain",
  "slug": "space-mountain",
  "url": "/v1/parks/north-america/united-states/orlando/magic-kingdom/attractions/space-mountain",
  "park": {
    "id": "...",
    "name": "Magic Kingdom",
    "slug": "magic-kingdom"
  },
  "category": "RIDE",
  "currentWaitTime": 45,
  "status": "OPERATING",
  "lastUpdate": "2025-12-23T19:30:00Z",
  "forecast": [
    { "hour": "20:00", "predictedWaitTime": 50, "confidence": 0.87 },
    { "hour": "21:00", "predictedWaitTime": 35, "confidence": 0.82 }
  ],
  "stats": {
    "averageWaitTime": 42,
    "p50": 40,
    "p75": 55,
    "p90": 70
  }
}

🌍 Geographic Discovery

Navigate parks by geographic hierarchy for route generation and exploration.

GET /v1/discovery/geo                        # Full geo hierarchy
GET /v1/discovery/continents                 # List continents
GET /v1/discovery/continents/:continent      # Countries in continent

Response Structure:

{
  "continents": [
    {
      "continent": "North America",
      "countries": [
        {
          "country": "United States",
          "cities": [
            {
              "city": "Orlando",
              "parks": [
                {
                  "name": "Magic Kingdom",
                  "url": "/north-america/united-states/orlando/magic-kingdom",
                  "status": "OPERATING",
                  "analytics": {
                    "statistics": {
                      "avgWaitTime": 35,
                      "operatingAttractions": 42,
                      "closedAttractions": 3,
                      "totalAttractions": 45,
                      "crowdLevel": "moderate"
                    }
                  },
                  "attractions": [...]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Note: analytics.statistics.crowdLevel is co-present with avgWaitTime whenever the park has a valid P90 baseline (with P50 as fallback). See Crowd Levels for the rating system.


🏰 Destinations

Resort-level aggregation grouping multiple parks. Destinations are used internally for data organization but are not exposed as top-level API endpoints. Parks are accessed directly via their geographic routes.

Examples:

  • Walt Disney World (Magic Kingdom, EPCOT, Hollywood Studios, Animal Kingdom)
  • Disneyland Paris (Disneyland Park, Walt Disney Studios Park)

🎭 Shows & Dining

Entertainment and dining options are available through the park endpoints. Shows and restaurants are not exposed as top-level API endpoints but are included in park responses and can be accessed via the search endpoint.


Global search with enriched results across parks and attractions.

GET /v1/search?q=disney                    # Search all types
GET /v1/search?q=thunder&type=attraction  # Filter by type
GET /v1/search?q=paris                   # Search by city

Search Features:

  • Multi-entity search: Parks and attractions
  • Geographic search: By city, country, or continent
  • Per-type counts: Shows returned vs total results
  • Enriched results: Coordinates, wait times, park hours, full geographic URLs
  • Smart filtering: Type-based filtering with max 5 results per type
  • Fast response: Redis-cached for 5min, <3ms cached response

Response Structure:

{
  "query": "disney",
  "counts": {
    "park": {"returned": 5, "total": 13},
    "attraction": {"returned": 5, "total": 156}
  },
  "results": [
    {
      "type": "park",
      "name": "Disneyland Park",
      "status": "OPERATING",
      "load": "normal",
      "parkHours": {...},
      "coordinates": {...}
    },
    {
      "type": "attraction",
      "name": "Space Mountain",
      "waitTime": 45,
      "load": "higher",
      "parentPark": {...}
    }
  ]
}

πŸŽ‰ Holidays

Public holiday data affecting park crowds and operating hours. Holidays are used internally for ML predictions and analytics but are not exposed as top-level API endpoints.


πŸ“ Project Structure

v4.api.park.fan/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ config/                    # App configuration & environment
β”‚   β”œβ”€β”€ common/                    # Shared utilities, filters, interceptors
β”‚   β”œβ”€β”€ database/                  # Database utilities & migrations
β”‚   β”œβ”€β”€ queues/                    # Bull queue setup & processors
β”‚   β”œβ”€β”€ health/                    # Health check endpoints
β”‚   β”œβ”€β”€ destinations/              # Resort/destination grouping
β”‚   β”œβ”€β”€ parks/                     # Parks, weather, schedules
β”‚   β”œβ”€β”€ attractions/               # Attractions & data sources
β”‚   β”œβ”€β”€ shows/                     # Entertainment shows
β”‚   β”œβ”€β”€ restaurants/               # Dining locations
β”‚   β”œβ”€β”€ queue-data/                # Wait time data & history
β”‚   β”œβ”€β”€ ml/                        # ML prediction integration
β”‚   β”œβ”€β”€ analytics/                 # Statistics & analytics
β”‚   β”œβ”€β”€ holidays/                  # Public holiday data
β”‚   β”œβ”€β”€ date-features/             # Date-based features for ML
β”‚   β”œβ”€β”€ discovery/                 # Geographic discovery endpoints
β”‚   └── search/                    # Global search functionality
β”œβ”€β”€ ml-service/                    # Python ML service (CatBoost)
β”‚   β”œβ”€β”€ train.py                   # Model training script
β”‚   β”œβ”€β”€ main.py                    # FastAPI prediction service
β”‚   β”œβ”€β”€ features.py                # Feature engineering
β”‚   └── db.py                      # Database connection
β”œβ”€β”€ docker/                        # Docker configurations
β”œβ”€β”€ scripts/                       # Utility & debug scripts
β”œβ”€β”€ migrations/                    # Database migrations
└── test/                          # E2E tests

🐳 Docker Commands

# Start all services (PostgreSQL + Redis)
pnpm docker:up

# Stop all services
pnpm docker:down

# View logs
pnpm docker:logs

# Restart services
pnpm docker:restart

# Reset database (WARNING: deletes all data)
pnpm db:reset

Production Deployment:

docker-compose -f docker-compose.production.yml up -d

πŸ§ͺ Testing

# Run unit tests
pnpm test

# Run e2e tests
pnpm test:e2e

# Run all tests with coverage
pnpm test:all:cov

# Watch mode for development
pnpm test:watch

# Specific test file
pnpm test wait-times.processor.spec.ts

Code Quality:

# Lint code
pnpm lint

# Format code
pnpm format

# Type check
pnpm build

πŸ”§ Environment Variables

Application Settings

NODE_ENV=development              # development | production | test
PORT=3000                         # API server port
API_PREFIX=v1                     # API version prefix

Database Configuration

# PostgreSQL with TimescaleDB
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=parkfan
DB_PASSWORD=your_secure_password
DB_DATABASE=parkfan
DB_SYNCHRONIZE=true               # ⚠️ Set to false in production!
DB_LOGGING=false                  # Enable for debugging
DB_SSL_ENABLED=false              # Enable for production

Caching & Queue

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=                   # Optional, recommended for production

# Bull Queue
BULL_PREFIX=parkfan

External APIs

# Google APIs (Geocoding, Places)
GOOGLE_API_KEY=your_google_api_key

# Weather Data: Open-Meteo (no API key required)

# Data Sources (optional, for enhanced coverage)
QUEUE_TIMES_API_KEY=              # Queue-Times.com
THEMEPARKS_API_KEY=               # ThemeParks.wiki

ML Service

# ML Service Configuration
ML_SERVICE_URL=http://localhost:8000        # Development
# ML_SERVICE_URL=http://ml-service:8000     # Production (Docker)
MODEL_DIR=/app/models                       # Model storage directory
MODEL_VERSION=v1.1.0                        # Current model version (ml-service setting)

Sync & Processing

# Data Sync Intervals (cron expressions)
SYNC_WAIT_TIMES_CRON=*/5 * * * *           # Every 5 minutes
SYNC_PARK_METADATA_CRON=0 6 * * *          # Daily at 6 AM
SYNC_WEATHER_CRON=0 * * * *                # Hourly

🀝 Contributing

This is a private project. For questions or collaboration inquiries, please contact the maintainer.


πŸ“„ License

UNLICENSED β€” Private project by Patrick Arns


πŸ™ Powered By

This project aggregates data from multiple sources:

  • Queue-Times.com β€” Real-time wait time data
  • ThemeParks.wiki β€” Comprehensive park information and live data
  • Wartezeiten.app β€” Wait times, crowd levels, and opening hours enrichment
  • Open-Meteo.com β€” Weather forecasts, current conditions, and historical weather data (Weather data by Open-Meteo.com, licensed under CC BY 4.0; built on open data from DWD, ECMWF, NOAA, MΓ©tΓ©o-France and other national weather services)

Special thanks to these services for making real-time theme park data accessible.


Made with ❀️ for theme park enthusiasts worldwide

API Documentation Β· Frontend