Fare Watchtower Operations

Schedule Active
Last Run: 06:00 UTC
3 Alerts Pending
Flights Tracked
847
across 12 routes
Hotels Tracked
412
across 8 cities
Price Drops Today
23
avg -14.2% from baseline
Est. Savings
$4,280
this week
Uptime
99.7%
last 30 days
Audit Logs
1,204
immutable run records
Flight Price Drops
RouteBaseNowDrop7dProviderConfAlert
SFO→NRT$1,240$879-29.1%AmadeusHighSent
LAX→LHR$890$712-20.0%SkyscannerHighSent
JFK→CDG$760$648-14.7%KiwiMedSent
ORD→HND$1,450$1,290-11.0%AmadeusMedPending
Hotel Price Drops
HotelCityBaseNowDrop7dConfAlert
Park HyattTokyo$520$385-26.0%HighSent
The SavoyLondon$480$392-18.3%HighSent
Le BristolParis$610$538-11.8%MedPending
Aman TokyoTokyo$780$702-10.0%MedPending

Route Watchlist

SFO → NRT (Jun 15–22)Target: <$900
LAX → LHR (Jul 1–10)Target: <$750
JFK → CDG (Aug 5–12)Target: <$650
ORD → HND (Sep 20–30)Target: <$1,200

Hotel Watchlist

Park Hyatt Tokyo (Jun 15–22)Target: <$400/n
The Savoy London (Jul 1–10)Target: <$380/n
Le Bristol Paris (Aug 5–12)Target: <$500/n
Aman Tokyo (Sep 20–30)Target: <$680/n

Automation Workflow

🕑
Daily Schedule
06:00 UTC cron
✈️
Flight API
Amadeus / Kiwi
🏨
Hotel API
Booking / Agoda
🔄
Normalize
Schema unify
📈
Compare Baseline
Delta calc
💾
Save to Drive
/fare-watchtower/
📨
Alert Summary
Threshold filter
🌐
Page Dashboard
Static deploy

Drive Archive Structure

/fare-watchtower/
  2026-04-28/
    flights.jsonraw flight API response (847 records)
    hotels.jsonraw hotel API response (412 records)
    drops.jsonfiltered price drops exceeding threshold
    run-log.jsonexecution metadata, timing, errors
    dashboard-data.jsonpre-computed dashboard payload
  2026-04-27/
    ... (same structure)

Implementation Snippets

Python — Computer Job # fare_watchtower.py — MuleRun Computer scheduled task # Example API endpoints — not production URLs import os, json, hashlib from datetime import date from mulerun import Drive, Page # Keys from env vars — never hardcoded FLIGHT_KEY = os.environ["FLIGHT_API_KEY"] HOTEL_KEY = os.environ["HOTEL_API_KEY"] DAY = date.today().isoformat() def fetch_flights(): # Example: https://api.example.com/v1/flights/search resp = requests.get("https://api.example.com/v1/flights/search", headers={"Authorization": f"Bearer {FLIGHT_KEY}"}, params={"routes": WATCHLIST_ROUTES}) return resp.json() def hash_traveler(email): return hashlib.sha256(email.encode()).hexdigest()[:12] # Save to Drive with date partition drive = Drive(folder="/fare-watchtower") drive.write(f"{DAY}/flights.json", flights) drive.write(f"{DAY}/drops.json", drops) drive.write(f"{DAY}/dashboard-data.json", dashboard)
Shell — Cron Setup # MuleRun Computer scheduled task $ mulerun computer schedule create \ --name "fare-watchtower" \ --cron "0 6 * * *" \ --command "python3 /opt/fare_watchtower.py" \ --env FLIGHT_API_KEY="$FLIGHT_API_KEY" \ --env HOTEL_API_KEY="$HOTEL_API_KEY" # Deploy static dashboard $ mulerun page deploy \ --name "fare-watchtower" \ --source "/opt/output/index.html"

Security Practices

🔒

Environment Variable API Keys

All API credentials stored as encrypted env vars on the Computer instance. Never committed to code or stored in Drive files.

📑

No Secrets in Drive

Drive archive contains only normalized pricing data and metadata. No API keys, tokens, or PII in any stored JSON file.

🛡️

Least-Privilege Drive Folder

The /fare-watchtower/ folder uses scoped write-only access for the automation and read-only access for the dashboard deployer.

🔐

Hashed Traveler IDs

All traveler identifiers are SHA-256 hashed before storage. No reversible PII exists in any archived file.

Outcome Metrics

12.4 hrs
Time Saved / Week
97%
Missed Drops Avoided
$4,280
Avg Weekly Savings
1,204
Immutable Audit Logs