Skip to content
ntfy and webhook

ntfy and webhook

ntfy

coachd sends an ntfy notice when a workout is ready to review (“Workout for Tue 28 Oct ready to review”), with a Review action that opens it on the page. The notice carries only the date, never workout or health data. In built-in mode it also tells you when an app connects, or is revoked for reusing a token.

  1. Create a topic with default access deny-all and an access token for coachd, and subscribe your phone.

  2. Set the topic URL and store the token:

    .env
    COACHD_NTFY_URL=https://ntfy.sh/<secret-topic>
    put_secret ntfy_token 65532:65532     # the helper from Secrets
    docker compose up -d --force-recreate coachd

ntfy needs the public lane and COACHD_PUBLIC_URL. coachd reads the token only at start, so recreate it after changing the token.

Post-run webhook

With COACHD_WEBHOOK_URL set, coachd POSTs an event to your own automation when a recent activity (started in the last 48 hours) is stored, with its FIT file and per-step numbers in. It carries IDs, a date and a sport only:

{"event":"activity.stored","activity_id":24745625144,"date":"2026-10-26","sport":"running","proposal_id":"cc7b5c9c..."}

proposal_id is the delivered workout the activity carried out, or null. Point it at n8n, Home Assistant or anything that can start your agent: the agent then calls get_activity with detail laps to review the run, and can send_message to the watch.

  • Retries 5xx and network errors twice (after 5 s and 25 s); gives up on other 4xx.
  • It doesn’t make coachd poll Garmin more often: the activity arrives on the next hourly sync, or sooner when the agent calls request_sync.
  • Treat the URL as a secret (an unguessable path). Plain http:// works for a LAN receiver, with a warning in the log.

For a bearer token as well, store it with put_secret webhook_token 65532:65532 and mount it with a compose override:

compose.override.yaml
services:
  coachd:
    environment:
      COACHD_WEBHOOK_TOKEN_FILE: /run/secrets/webhook_token
    secrets: [webhook_token]
secrets:
  webhook_token:
    file: ./secrets/webhook_token
Last updated on