Home Assistant automations

Wire the event Goalfeed actually fires into a goal horn and a light flash — the reason most people install this.

The one thing to know: it's always goal

Goalfeed authenticates to Home Assistant with a long-lived access token (or, on the add-on, the Supervisor handles that for you) and posts every event — a real goal, a touchdown, a home run, a period-start notice, and even a synthetic test-goals event — to the same endpoint, POST /api/events/goal. That means every automation you write triggers on the Home Assistant event type goal, never on a sport-specific event name:

yaml
trigger:
  - platform: event
    event_type: goal

Filter on the event's teamCode field (and leagueId if you watch the same team code across two leagues), not on the payload's internal type field — type is only populated for Olympic hockey events today and left empty for NHL/MLB/NFL/CFL, so a filter on it will silently miss every event from the four leagues that actually fire live goals (see WebSocket reference for the same gap on the WebSocket feed). Goalfeed does its own team filtering server-side before it ever calls Home Assistant — only teams you've configured in watch.* generate events at all — but the HA event itself carries no such restriction, so your automation's event_data condition is what keeps a multi-team install from ringing every team's goal horn.

Event payload

The payload is a flattened JSON object; at minimum it carries:

FieldExample
teamCodeWPG
teamNameWinnipeg Jets
opponentCode / opponentName TOR / Toronto Maple Leafs
leagueId / leagueName 1 / NHL — see the leagues reference for every ID
gameCodeopaque per-game identifier
period2
gameStatea nested, mostly-stub { home, away, status } object — treat it as best-effort, most fields aren't populated yet for most leagues
A 7-point NFL touchdown fires seven events

Goal/score detection is a raw score-diff for every league except Olympic hockey: Goalfeed compares the last-seen score to the current score and fires one event per point of increase. For NHL and MLB that's exactly right — one goal, one event. For NFL and CFL, a touchdown-plus-conversion (7 points) fires seven separate goal events in the same second, not one "touchdown" event. If your automation plays a sound or flashes a light per event without debouncing, a football score will trigger it seven times in a row. See Architecture for why this is a design consequence, not a bug to be filed.

A complete automation: goal horn + light flash

Real, working YAML — not simplified for the docs. This one waits a configurable delay (useful if your broadcast feed runs ahead of or behind the live play), plays a sound, and flashes a light, scoped to a single team via event_data:

automations.yaml
automation:
  - alias: "Goalfeed - Jets score"
    trigger:
      - platform: event
        event_type: goal
        event_data:
          teamCode: WPG
    action:
      - service: media_player.play_media
        target:
          entity_id: media_player.living_room_speaker
        data:
          media_content_id: /local/sounds/goal_horn.mp3
          media_content_type: music
      - service: light.turn_on
        target:
          entity_id: light.living_room
        data:
          color_name: blue
          flash: long
      - delay: "00:00:03"
      - service: light.turn_on
        target:
          entity_id: light.living_room
        data:
          color_name: white

Prefer a delayed, toggle-driven version with a separate "turn it back off" automation (closer to what the project wiki has historically shown, and easier to re-trigger mid-flash)? Use an input_number for the delay and an input_boolean as a "celebration in progress" flag:

configuration.yaml
input_number:
  goalfeed:
    name: Goalfeed Delay
    initial: 30
    min: 0
    max: 180
    step: 1

input_boolean:
  goaling:
    name: Goal Celebration Active
    initial: off
automations.yaml
automation:
  - alias: "NHL Goal Celebration"
    trigger:
      - platform: event
        event_type: goal
        event_data:
          teamCode: WPG
    action:
      - delay: "00:00:{{ states.input_number.goalfeed.state | int }}"
      - service: homeassistant.turn_on
        entity_id: input_boolean.goaling
      - service: media_player.play_media
        data:
          entity_id: media_player.your_media_player
          media_content_id: /local/sounds/goal_horn.mp3
          media_content_type: music

  - alias: "Turn off goal"
    trigger:
      - platform: state
        entity_id: input_boolean.goaling
        to: "on"
        for:
          seconds: 30
    action:
      - service: media_player.stop_media
        data:
          entity_id: media_player.your_media_player
      - service: homeassistant.turn_off
        entity_id: input_boolean.goaling

Test either version without waiting for a real game: set test-goals: true in config.yaml (or test_goals: true on the add-on) and restart — a synthetic event with teamCode: TEST fires once a minute. Scope your test automation's event_data to teamCode: TEST while iterating, exactly as the getting-started tutorial does.

Per-team sensors (no automation needed)

Alongside events, Goalfeed publishes a set of Home Assistant sensor.*/binary_sensor.* entities for every monitored team, named sensor.goalfeed_<league>_<team>_<metric> (e.g. sensor.goalfeed_nhl_wpg_team_current_score). Baseline values are published once at startup so the entities exist even before a game starts; the set includes team_status, team_has_active_game, team_current_score, team_opponent, team_clock, team_period, plus sport-specific ones (team_shots for hockey, team_down/team_distance for football, team_balls/team_strikes/team_outs for baseball). Build a dashboard card from these without listening for the event at all.

Confirming the connection

Check whether Goalfeed can currently reach Home Assistant, and which source it's using (Supervisor vs. your own config.yaml):

bash
curl -s http://localhost:8080/api/homeassistant/status

Full field list: API reference.

Next

Nothing firing? — Troubleshooting has the exact error text for the common failure modes, including a rejected Home Assistant URL (see Security for why that check exists).