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:
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:
| Field | Example |
|---|---|
teamCode | WPG |
teamName | Winnipeg Jets |
opponentCode / opponentName |
TOR / Toronto Maple Leafs |
leagueId / leagueName |
1 / NHL — see the
leagues reference for every ID |
gameCode | opaque per-game identifier |
period | 2 |
gameState | a nested, mostly-stub
{ home, away, status } object — treat it as best-effort,
most fields aren't populated yet for most leagues |
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:
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:
input_number:
goalfeed:
name: Goalfeed Delay
initial: 30
min: 0
max: 180
step: 1
input_boolean:
goaling:
name: Goal Celebration Active
initial: off
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):
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).