Unofficial integration — not affiliated with or endorsed by Spond.
A native Home Assistant integration that syncs Spond events and tasks — one calendar per tracked member, per-member sensors, and real-time events on the HA event bus.
Built for households where one or more Spond accounts cover overlapping group members. Events are deduplicated across accounts and matched to the right member by first name.
- Per-member calendars — one calendar entity per tracked member showing upcoming Spond events with status, location, and task details.
- Task events — tasks assigned to a member appear as separate calendar
entries (
📋prefix) at the event's start time. - Multi-account — add multiple Spond accounts; events are deduplicated across them automatically.
- Status-aware — accepted / declined / unanswered / waitinglist /
cancelled shown as emoji prefixes. Declined events are hidden from the
calendar. Cancelled events stay visible with a
🚫prefix. - Per-member sensors — event count for today and task count, with full detail in attributes.
- HA event bus — fires
spond_event_added,spond_event_removed,spond_event_changed,spond_event_cancelled, andspond_task_assignedbetween polls. Use these to drive notifications and automations. - Localization — calendar text and sensor names in English (default) or
Norwegian Bokmål (
nb). Follows your HA language setting automatically.
- HACS → menu (top right) → Custom repositories
- URL:
https://github.com/agjendem/ha-spond-tracker, Category: Integration - ADD, then find Spond Tracker in the Integration list → Download
- Restart Home Assistant.
- Go to Settings → Devices & Services → Add Integration → Spond Tracker and follow the setup wizard.
Copy custom_components/spond_tracker/ into your HA config directory under
custom_components/. Restart Home Assistant, then add the integration via UI.
- Home Assistant 2026.1 or newer
- One or more Spond accounts
Setup is fully UI-based. The wizard walks through:
- Credentials — Spond username (email or phone number) and password.
- Members — multi-select which family members to track. Members are discovered from your Spond events automatically; one entry per first name.
After setup, go to Options to:
- Change the poll interval (default 30 minutes, range 5–1440).
- Add a second (or third) Spond account.
- Remove an account.
One calendar.<member> entity per tracked member. Each entry shows:
- Summary:
{emoji} {event title}— emoji reflects the RSVP status - Description: status, location, address, your tasks, full task list
- Task entries:
📋 {task name} — {event title}at the event's start time
| Sensor | State | Attributes |
|---|---|---|
sensor.spond_<member> |
Events today (int) | today_events, next_event, upcoming_events |
sensor.spond_<member>_tasks |
Active tasks (int) | tasks list with event, time, co-assignees |
| Event | Fired when | Key fields |
|---|---|---|
spond_event_added |
New event appears between polls | member, title, start, status, uid |
spond_event_removed |
Event disappears | member, title, start, uid |
spond_event_changed |
Field changed (title, time, location, status) | member, title, start, changed_fields, uid |
spond_event_cancelled |
Event flipped to cancelled | member, title, start, location, uid |
spond_task_assigned |
New task assigned to member | member, title, start, task, uid |
member is the lowercased first name (e.g. alice).
alias: "Spond: new task assigned"
trigger:
- platform: event
event_type: spond_task_assigned
event_data:
member: alice
action:
- service: notify.mobile_app_alice_phone
data:
title: "New Spond task"
message: "{{ trigger.event.data.task }} ({{ trigger.event.data.title }})"The repo ships four blueprints that turn event-bus events into mobile notifications without writing automation YAML. Import via the badges below:
task reminder (N min before task)
The most common use case is sending a mobile push notification whenever something changes in Spond — a new training is scheduled, a match is cancelled, a time slot is updated, or a task is assigned. The integration fires HA bus events between polls for all of these:
| Event | When |
|---|---|
spond_event_added |
New training/match/event discovered |
spond_event_changed |
Title, time, location, or status changed |
spond_event_cancelled |
Event flipped to cancelled |
spond_event_removed |
Event disappeared entirely |
spond_task_assigned |
A duty/task assigned to the member |
The four importable blueprints in this repo cover the most common scenarios out of the box (see Automation blueprints). For custom logic you can target any event directly:
alias: "Spond: notify cancelled event (Alice)"
trigger:
- platform: event
event_type: spond_event_cancelled
event_data:
member: alice
action:
- service: notify.mobile_app_alice_phone
data:
title: "Event cancelled ❌"
message: >
{{ trigger.event.data.title }}
({{ trigger.event.data.start | as_timestamp | timestamp_custom('%a %b %-d %H:%M') }})alias: "Spond: notify new event (Alice)"
trigger:
- platform: event
event_type: spond_event_added
event_data:
member: alice
action:
- service: notify.mobile_app_alice_phone
data:
title: "New Spond event 📅"
message: >
{{ trigger.event.data.title }}
{{ trigger.event.data.start | as_timestamp | timestamp_custom('%a %b %-d %H:%M') }}
{% if trigger.event.data.location %} — {{ trigger.event.data.location }}{% endif %}alias: "Spond: notify new task (Alice)"
trigger:
- platform: event
event_type: spond_task_assigned
event_data:
member: alice
action:
- service: notify.mobile_app_alice_phone
data:
title: "New Spond task 📋"
message: >
{{ trigger.event.data.task }}
for {{ trigger.event.data.title }}
({{ trigger.event.data.start | as_timestamp | timestamp_custom('%a %b %-d %H:%M') }})Repeat each automation per family member with their own notification target.
Each tracked member has a sensor.spond_<member> with today's event count
and a full calendar.spond_<member> entity. Combine these in a morning
briefing — either as a dashboard card or as a spoken/text notification sent
at a fixed time each day.
Template sensor — today's events as a text summary:
template:
- sensor:
- name: "Alice Spond today"
state: "{{ state_attr('sensor.spond_alice', 'today_count') }} event(s)"
attributes:
summary: >
{% set evs = state_attr('sensor.spond_alice', 'today_events') %}
{% if evs %}
{% for e in evs %}
{{ e.title }} at {{ e.start | as_timestamp | timestamp_custom('%H:%M') }}
({{ e.status }}){{ '\n' if not loop.last }}
{% endfor %}
{% else %}
No events today.
{% endif %}Morning notification — sent at 07:00:
alias: "Spond: morning summary"
trigger:
- platform: time
at: "07:00:00"
action:
- service: notify.mobile_app_family_group
data:
title: "Spond today"
message: >
{% for member in ['alice', 'bob'] %}
{% set s = 'sensor.spond_' ~ member %}
{% set n = state_attr(s, 'today_count') | int(0) %}
{% if n > 0 %}
{{ member | title }}: {{ n }} event(s)
{% for e in state_attr(s, 'today_events') %}
• {{ e.title }} {{ e.start | as_timestamp | timestamp_custom('%H:%M') }}
{% endfor %}
{% endif %}
{% endfor %}Dashboard card — use the calendar card and add calendar.spond_alice,
calendar.spond_bob, etc. as sources. You get a shared family activity view
directly on your Home Assistant dashboard, including tasks as separate entries.
The integration polls Spond once every 30 minutes by default. You can change the interval in Options (Settings → Devices & Services → Spond Tracker → Configure) to any value between 5 and 1440 minutes.
Each poll fetches events starting from now and up to 60 days ahead (max 200 events per account). Calendar entities and sensors are refreshed immediately after a successful poll. If a poll fails, the previous data remains available and entities stay in their last-known state; if all accounts fail, entities are marked unavailable and a warning is logged.
Change detection runs after every poll and fires HA bus events for any additions, removals, or changes since the previous poll.
- Same first name — member matching uses the first token of the Spond first name (lowercased). Two group members with the same first name will collide and share a single tracked member. There is no workaround within the integration today.
- 60-day window — only events starting within the next 60 days are fetched. Events further in the future will not appear in the calendar.
- Poll-based change detection — event bus events (
spond_event_added, etc.) are fired between polls, not in real time. Expect up to one poll-interval of delay. - Spond API — this integration uses the unofficial Olen/Spond Python client. Spond has no public API, so breaking changes in the app backend may require an update to the library.
Sensor attributes (today_events, upcoming_events, tasks) contain full
event dicts and grow with the number of events. If you don't need history for
these attributes, exclude them in configuration.yaml to keep your database
small:
recorder:
exclude:
entity_globs:
- sensor.spond_*To keep the numeric state but skip the large attributes, use
exclude_attributes (available in HA 2024.2+).
- No events appearing — check HA logs (Settings → System → Logs) for
errors under the
spond_trackerdomain. The integration logs each poll. - Entities unavailable — the coordinator marks all entities unavailable when every configured account fails to fetch. Check credentials in Options. The integration logs a warning when this happens and an info message when it recovers.
- Poll not running — the poll interval is configurable in Options (Settings → Devices & Services → Spond Tracker → Configure).
- Member name collision — see Known limitations.
- Settings → Devices & Services → Spond Tracker
- Click the three-dot menu → Delete
- Confirm. HA unloads all entities automatically.
Requires Python 3.13+ (the test suite targets HA 2026.x).
git clone https://github.com/agjendem/ha-spond-tracker.git
cd ha-spond-tracker
python3.13 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txtRun the same checks CI runs:
ruff check .
ruff format --check .
pytestSee CONTRIBUTING.md for commit conventions and the release workflow.
GPL-3.0 — see LICENSE. This project depends on Olen/Spond which is GPL-3.0, so the same license applies here.
Built on top of the unofficial Olen/Spond Python client.