Getting started¶
What you need¶
- Home Assistant 2024.7 or newer
- HACS installed
Every integration in this suite is distributed through HACS as a custom repository.
1. Add the carriers you use¶
Repeat this for each carrier that delivers to you — the full list is here.
- Open HACS → Integrations → ⋮ → Custom repositories
- Paste the repository URL (for example
https://github.com/ha-parcel-integrations/ha-postnl) and pick category Integration - Search for the carrier and install it
- Restart Home Assistant
- Go to Settings → Devices & Services → Add Integration and search for the carrier
What step 5 asks you for depends on the carrier: a tracking code, a tracking code plus postal code, or an account login. The Connect with column on the carriers page tells you which before you start.
At this point you are done. Each carrier integration is fully standalone: it gives you its own sensors, its own events and its own device page, and it needs nothing else installed to work.
2. Optional: add the aggregator¶
Only worth it if you use more than one carrier and would rather write one automation than one per carrier. It is not a dependency of anything — skip it and every carrier keeps working exactly as it does now.
Do this once, after at least one carrier is set up.
- Add
https://github.com/ha-parcel-integrations/ha-parcel-aggregatoras a custom repository, category Integration - Install it, restart, then add it under Settings → Devices & Services
- There is nothing to configure — no credentials, no options
It discovers your carrier sensors on its own, and keeps watching the entity registry, so a carrier you install next month is picked up without a reload.
You get:
| Entity | What it holds |
|---|---|
sensor.parcel_aggregator_incoming_parcels |
Active incoming parcels across all carriers |
sensor.parcel_aggregator_outgoing_parcels |
Active outgoing parcels |
sensor.parcel_aggregator_delivered_parcels |
Recently delivered incoming parcels |
sensor.parcel_aggregator_outgoing_delivered_parcels |
Recently delivered outgoing parcels |
sensor.parcel_aggregator_awaiting_pickup |
Parcels headed for a pickup point |
sensor.parcel_aggregator_next_delivery |
Earliest expected delivery, with the parcel on parcel |
Each one carries the merged parcel list on its parcels attribute and a
per-carrier breakdown on by_carrier.
Plus a calendar, calendar.parcel_aggregator_deliveries, holding every expected
delivery from every carrier in one agenda. It is read-only, does no polling of
its own, and is enabled by default — drop it on a dashboard, or disable the
entity if you would rather not see it.
3. Build something¶
Head to the automation cookbook for notifications and summaries, or dashboard cards to put your parcels on screen — both are paste-as-is. Read the parcel contract first if you would rather write your own.
Those snippets use the aggregator's unified events and sensors. Without
it, the same recipes work per carrier — swap parcel_aggregator_ for the
carrier's own domain (postnl_, dhl_nl_, …) and its own sensors. The parcel
data inside is identical either way, which is the point of the
contract.
Polling and rate limits¶
Each carrier integration polls automatically — there is no fixed interval to tune. How often it checks adjusts to what your parcels are actually doing:
- No polling between 00:00–06:00 local time, aside from one catch-up check right at each end of that window, so an overnight update is never missed.
- Checks every 15 minutes while a tracked parcel is out for delivery today, starting an hour before its delivery window opens.
- Checks every 30–60 minutes otherwise — for a carrier you log into with an account, this is also the minimum cadence, since it's the only way to discover a new shipment that appeared on your account without you doing anything.
- For carriers you add by tracking code, polling stops entirely once every tracked parcel has been delivered (or none are tracked) — adding a parcel back starts it again immediately.
Delivery-day precision comes from the carrier's own data, not from how often you ask, and the cadence above is chosen to be polite to the carrier's own API — asking more often than that would just get you rate-limited, not faster updates.
When something looks wrong¶
- A parcel shows
unknown— the carrier returned a status the integration has not mapped yet. It logs a warning containing a ready-made report link; opening that issue is what gets it mapped. - An integration is marked "Early release" — it works, but its status vocabulary was inferred rather than confirmed against real shipments. Your reports are what move it to 1.0.
- Nothing appears at all — check Settings → System → Logs, then open an issue on that carrier's own repository with the diagnostics download from its device page.