Simple flight deal scanner that scans flights based on criteria in config.json and emails the best deals.
- Scans international flights from SLC/PVU for 6-10 day trips during summer break
- Filters by price thresholds and stops
- In-memory rate limiting to prevent API cost overruns
- Email notifications with best deals (or summary when no deals found)
- All configuration in
config.json
-
Install dependencies:
pip install -r requirements.txt
-
Create a
.envfile in the project root with your credentials:# Create .env file touch .envAdd the following to
.env:RAPIDAPI_KEY=your-rapidapi-key-here EMAIL_SMTP_USER=your-email@gmail.com EMAIL_SMTP_PASSWORD=your-app-password-here EMAIL_TO=recipient@example.com
Note: For Gmail, you'll need to use an App Password instead of your regular password.
-
Configure
config.json(optional):- Adjust origins, date ranges, trip lengths, and price thresholds as needed
- Set rate limits to match your API plan
- Note: Secrets are loaded from
.env, notconfig.json
Start the API server:
uvicorn app.main:app --reloadPOST /scan- Scans flights and immediately emails the best deals found (or summary if no deals)GET /status- Shows rate limit usage
Secrets (in .env file - not committed to git):
RAPIDAPI_KEY- Your RapidAPI keyEMAIL_SMTP_USER- Email address for sendingEMAIL_SMTP_PASSWORD- Email app passwordEMAIL_TO- Email address to receive deals
Non-secret settings (in config.json - can be committed):
origins- Origin airports with coordinatesdate_ranges- Date ranges to scantrip_lengths- Trip lengths in days (array)filters- Max stops and price thresholds by regionrate_limits- Monthly and daily API limitsapi.results_per_request- Number of results per API callapi.min_delay_seconds- Delay between API calls (to avoid 429 errors)email.smtp_host- SMTP server hostnameemail.smtp_port- SMTP server portscan.max_deals_per_notification- Max deals per email
The app enforces strict rate limits to prevent API cost overruns:
- Monthly limit (default: 300 requests)
- Daily limit (default: 10 requests)
- Limits are configurable in
config.json - Rate limiting is in-memory only (resets on server restart)
- Call
POST /scanto trigger a scan - The app searches for flights matching your criteria (scans in weekly chunks to cover the full date range)
- Best deals are automatically sorted by price
- Top deals are immediately emailed to you (or a summary if no deals found)
- No persistent storage - each scan is independent
Test scripts are available in the scripts/ directory:
test_api.py- Test API endpointstest_email.py- Test email configuration
- Rate limiting resets when the server restarts (in-memory only)
- The scan will automatically stop if API quota is exceeded (429 errors)
- Full scan requires ~180 API requests (spread across multiple days with default daily limit)