This service checks a list of Tidal API endpoints and exposes the current snapshot as JSON. Each poll run is stored in SQLite. It can send email alerts to 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
- monitor Apple Music wrapper account endpoints (
http://host:30020/) by checkingdev_tokenandmusic_token - delete instances
- subscribe to email alerts for a specific API even without authentication
- review and delete all email subscriptions from the admin UI
APP_HOST=0.0.0.0APP_PORT=8000CHECK_INTERVAL_SECONDS=300REQUEST_TIMEOUT_SECONDS=10DATABASE_PATH=data/uptime.dbHISTORY_RETENTION_RUNS=4320STATUS_PAGE_WINDOW_HOURS=168MAX_TRACK_RETRIES=2USER_AGENT=...SEARCH_QUERY=the weekndREFERENCE_API_VERSION_SOURCE_URL=...REFERENCE_API_VERSION_CACHE_PATH=data/reference_api_version.jsonREFERENCE_API_VERSION_REFRESH_SECONDS=86400ADMIN_PASSWORD=change-meAUTH_COOKIE_NAME=tidal_uptime_authAUTH_COOKIE_SECRET=change-this-cookie-secretAUTH_COOKIE_MAX_AGE_SECONDS=604800EMAIL_ALERTS_ENABLED=trueALERT_FAILURE_STREAK=2ALERT_RECOVERY_ENABLED=trueALERT_RECOVERY_STREAK=1ALERT_TRIGGER_STATES=outage,degradedALERT_TRIGGER_PROBES=api,search,trackMETRICS_MAX_PAYLOAD_BYTES=200000
SMTP settings are stored in a separate .smtp.toml file.
The current probe track list is hardcoded in app/settings.py: 134858527, 125155092, 204567804.
Global alert behavior is controlled by:
ALERT_FAILURE_STREAK- failed polls in a row before first incident alertALERT_RECOVERY_ENABLED- whether to send recovery notificationsALERT_RECOVERY_STREAK- successful polls in a row before recovery alertALERT_TRIGGER_STATES- incident states to alert on:outage,degradedALERT_TRIGGER_PROBES- probes to consider:api,search,track
Per monitor, alert types can be enabled/disabled in the Manager UI:
- primary outage (
alert_on_outage) - search/sub-check degradation (
alert_on_search) - track degradation (
alert_on_track) - recovery (
alert_on_recovery)
Each endpoint sends only one incident alert per condition; a new alert for the same condition is sent only after recovery.
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 168 hours (7 days) 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: 2016 checks over ~168h · every 5m.
To change the history window or how often the monitor checks endpoints, edit .env:
STATUS_PAGE_WINDOW_HOURS=168
CHECK_INTERVAL_SECONDS=300Examples:
STATUS_PAGE_WINDOW_HOURS=168withCHECK_INTERVAL_SECONDS=300->2016checksSTATUS_PAGE_WINDOW_HOURS=168withCHECK_INTERVAL_SECONDS=60->10080checks
Legend:
Operational- both search and track checks workDegraded- the base API works, but search or track failsOutage- the base API is unreachable
The dashboard also includes an Incidents view with:
- incident log (
startedAt,resolvedAt,duration,reason) - per-monitor reliability metrics:
MTTR(mean time to recovery) andMTBF(mean time between failures)
All incident calculations are based on the currently visible history window (STATUS_PAGE_WINDOW_HOURS).
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, but never below the visible status window - 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