This service checks a list of Tidal API endpoints every 5 minutes and exposes the current snapshot as JSON. Each poll run is stored in SQLite. It can also send alerts to a Discord webhook and email subscribers.
Checks performed for each URL:
GET /- the endpoint must return JSON withversionGET /search/?s=the weeknd- the endpoint must return a non-emptydata.itemsGET /track/- the endpoint must return non-emptydata.manifestHashanddata.manifest
Track validation uses the following track id list: 134858527, 125155092, 204567804, with up to 2 retries on a different id.
If step 1 succeeds, the URL is included in api.
If both search and track checks succeed, the URL is treated as operational.
If the base API is reachable but search or track fails, the endpoint is treated as degraded.
If the base API itself fails, the endpoint is treated as outage.
If /track/ returns assetPresentation: "PREVIEW", it is treated as an invalid track response and reported as Preview only (premium expired).
docker compose up --build -dAfter startup:
http://localhost:8000/- HTML dashboardhttp://localhost:8000/status.json
From the dashboard you can:
- add new API instances
- edit existing URLs
- delete instances
- subscribe to email alerts for a specific API even without authentication
- review and delete all email subscriptions from the admin UI
CHECK_INTERVAL_SECONDS=300REQUEST_TIMEOUT_SECONDS=6DATABASE_PATH=data/uptime.dbSTATUS_PAGE_WINDOW_HOURS=8MAX_TRACK_RETRIES=2ADMIN_PASSWORD=change-meAUTH_COOKIE_SECRET=change-this-cookie-secretAUTH_COOKIE_MAX_AGE_SECONDS=604800APP_HOST=0.0.0.0APP_PORT=8000USER_AGENT=...SEARCH_QUERY=the weekndDISCORD_WEBHOOK_URL=...DISCORD_ALERTS_ENABLED=trueDISCORD_ALERT_USERNAME=Tidal UptimeDISCORD_ALERT_FAILURE_STREAK=2DISCORD_ALERT_RECOVERY_ENABLED=trueDISCORD_ALERT_RECOVERY_STREAK=1DISCORD_ALERT_TRIGGER_STATES=outage,degradedDISCORD_ALERT_TRIGGER_PROBES=api,search,trackEMAIL_ALERTS_ENABLED=true
SMTP settings are stored in a separate .smtp.toml file.
The current probe track list is hardcoded in [app/settings.py](c:\Users\dmitry\Desktop\tidal uptime\app\settings.py): 134858527, 125155092, 204567804.
An alert is sent only if DISCORD_WEBHOOK_URL is configured and DISCORD_ALERTS_ENABLED=true.
Each endpoint sends only one alert per incident. A new alert for the same endpoint can be sent only after recovery.
Flexible settings:
DISCORD_ALERT_FAILURE_STREAK- how many failed polls in a row are required before the first alert is sentDISCORD_ALERT_RECOVERY_ENABLED- whether to send a recovery notificationDISCORD_ALERT_RECOVERY_STREAK- how many successful polls in a row are required before recovery is sentDISCORD_ALERT_TRIGGER_STATES- alert states:outage,degradedDISCORD_ALERT_TRIGGER_PROBES- which checks are considered:api,search,track
Examples:
-
Alert only when the base API is fully down after 3 failed polls in a row:
DISCORD_ALERT_TRIGGER_STATES=outageDISCORD_ALERT_TRIGGER_PROBES=apiDISCORD_ALERT_FAILURE_STREAK=3 -
Alert on any degradation, but without recovery notifications:
DISCORD_ALERT_TRIGGER_STATES=outage,degradedDISCORD_ALERT_TRIGGER_PROBES=api,search,trackDISCORD_ALERT_RECOVERY_ENABLED=false
Each endpoint card includes a bell button. Any user can use it to subscribe an email address to alerts for that specific API.
Subscriptions receive the same event types that are enabled for the endpoint itself:
outagesearchtrackrecovery
If a specific alert type is disabled for an endpoint, subscribers for that endpoint will not receive that event by email either.
To enable email alerts:
- keep
EMAIL_ALERTS_ENABLED=truein.env - configure SMTP settings in
.smtp.toml SMTP_USE_STARTTLS=truefor standard SMTP with STARTTLSSMTP_USE_SSL=truefor SMTPS over implicit TLS
Supported SMTP fields:
smtp_hostsmtp_portsmtp_usernamesmtp_passwordsmtp_from_namesmtp_from_emailsmtp_reply_tosmtp_message_stream_headersmtp_use_starttlssmtp_use_sslsmtp_timeout_seconds
Example .smtp.toml for Postmark:
smtp_host = "smtp-broadcasts.postmarkapp.com"
smtp_port = 587
smtp_username = "..."
smtp_password = "..."
smtp_from_name = "Spotisaver"
smtp_from_email = "hi@spotisaver.online"
smtp_reply_to = "hi@spotisaver.online"
smtp_message_stream_header = "X-PM-Message-Stream: broadcast"
smtp_use_starttls = true
smtp_use_ssl = false
smtp_timeout_seconds = 10All subscriptions can be reviewed and deleted from the authenticated Subscriptions popup in the dashboard.
The dashboard timeline shows the last 8 hours by default.
The number of columns is calculated automatically from STATUS_PAGE_WINDOW_HOURS and CHECK_INTERVAL_SECONDS.
The dashboard summary also shows the effective poll interval, for example: 96 checks over ~8h · every 5m.
To change the history window or how often the monitor checks endpoints, edit .env:
STATUS_PAGE_WINDOW_HOURS=8
CHECK_INTERVAL_SECONDS=300Examples:
STATUS_PAGE_WINDOW_HOURS=12withCHECK_INTERVAL_SECONDS=300->144checksSTATUS_PAGE_WINDOW_HOURS=8withCHECK_INTERVAL_SECONDS=60->480checks
Legend:
Operational- both search and track checks workDegraded- the base API works, but search or track failsOutage- the base API is unreachable
SQLite defaults to data/uptime.db.
In docker-compose.yml, the folder is mounted as ./data:/app/data, so data survives container restarts.
Storage details:
- SQLite runs in
WALmode - only the latest detailed endpoint status is stored as the current snapshot
- uptime history is stored compactly using
endpoint_id + poll_run_id + state - old runs are pruned automatically according to
HISTORY_RETENTION_RUNS - alert state is stored separately so container restarts do not resend duplicate alerts
- email subscriptions are stored in SQLite and are deleted automatically when the related endpoint is deleted