Track parcels from Norwegian and Nordic carriers in Home Assistant.
| Carrier | Auth Type | Manual Tracking |
|---|---|---|
| Bring (Posten Norge) | Mybring email + API key | Yes |
| Postnord | API key | Yes |
| Helthjem | OAuth2 (Client ID + Secret) | Yes |
Note: Auto-fetch (automatically discovering parcels from your account) is not supported β none of the carriers expose a public API for listing parcels tied to a consumer account. Tracking numbers must be added manually via the service call or dashboard card below.
- Open HACS in Home Assistant
- Click the three dots menu β Custom repositories
- Add this repository URL and select Integration
- Search for "Nordic Parcel" and install
- Restart Home Assistant
Copy the custom_components/nordic_parcel directory into your Home Assistant config/custom_components/ directory and restart.
- Go to Settings β Devices & Services β Add Integration
- Search for "Nordic Parcel"
- Select your carrier and enter credentials
You can add multiple carriers by adding the integration multiple times.
- Create or log in to your Mybring account
- Go to Settings β API to find your API key
- Your Mybring email and API key are needed
- Register at developer.postnord.com
- Create an application to get your API key
- Contact integrations@helthjem.no to request API access
- You will receive a Client ID and Client Secret
- Note: You must be an existing Helthjem customer
Once configured, the integration creates a sensor for each tracked parcel. Sensors show the current status (e.g., "In Transit", "Delivered") with detailed attributes.
Use the nordic_parcel.add_tracking service:
service: nordic_parcel.add_tracking
data:
tracking_id: "370000000000123456"
carrier: bring # Optional: bring, postnord, or helthjemservice: nordic_parcel.remove_tracking
data:
tracking_id: "370000000000123456"You can set up a dashboard card to add parcels and view all currently tracked parcels without using Developer Tools.
Go to Settings > Devices & Services > Helpers and create:
- Dropdown named
Parcel Carrierwith options:bring,postnord,helthjem - Text named
Parcel Tracking IDwith min length0and max length50
Or add them via YAML:
input_select:
parcel_carrier:
name: Parcel Carrier
options:
- bring
- postnord
- helthjem
input_text:
parcel_tracking_id:
name: Parcel Tracking ID
min: 0
max: 50
mode: text
initial: ""This automation triggers when you enter a tracking ID, adds it to the integration, and clears the field:
automation:
- alias: "Add parcel tracking from dashboard"
trigger:
- platform: state
entity_id: input_text.parcel_tracking_id
condition:
- condition: template
value_template: >-
{{ trigger.to_state.state not in ['', 'unknown', 'unavailable']
and trigger.to_state.state | length > 4 }}
action:
- service: nordic_parcel.add_tracking
data:
tracking_id: "{{ states('input_text.parcel_tracking_id') | string }}"
carrier: "{{ states('input_select.parcel_carrier') | string }}"
- service: input_text.set_value
target:
entity_id: input_text.parcel_tracking_id
data:
value: ""Add this card to your Lovelace dashboard to get an input form and a live list of tracked parcels:
type: vertical-stack
cards:
- type: entities
title: Track a Parcel
entities:
- entity: input_select.parcel_carrier
name: Carrier
- entity: input_text.parcel_tracking_id
name: Tracking ID
- type: markdown
title: Current Parcels
content: >-
{% set icons = {
'Pre Transit': 'π¦',
'In Transit': 'π',
'Customs': 'π',
'Out For Delivery': 'π',
'Ready For Pickup': 'π¬',
'Delivered': 'β
',
'Returned': 'β©οΈ',
'Failed': 'β',
'Unknown': 'β'
} %}
{% for state in states.sensor
if state.attributes.get('carrier') in ['bring', 'postnord', 'helthjem'] %}
{{ icons.get(state.state, 'π¦') }} **{{ state.attributes.sender or state.attributes.tracking_id }}**
{{ state.attributes.carrier | title }} Β· {{ state.state }}
{% else %}
*No parcels being tracked.*
{% endfor %}Select a carrier, type the tracking ID, and hit enter. The parcel appears in the list below automatically.
Each tracked parcel gets its own sensor with the following attributes:
carrierβ Which carrier is handling the parceltracking_idβ The tracking numbersenderβ Sender name (when available)recipientβ Recipient name (when available)estimated_deliveryβ Estimated delivery date/timelast_event_descriptionβ Most recent tracking eventlast_event_timeβ When the last event occurredlast_event_locationβ Where the last event occurredevent_countβ Number of tracking events
Possible states: Unknown, Pre-transit, In transit, Customs, Out for delivery, Ready for pickup, Delivered, Returned, Failed.
A global Nordic Parcel Summary sensor aggregates all tracked parcels across every configured carrier:
- State: Number of active (non-delivered) parcels
- Attributes:
- Status breakdown β
in_transit,out_for_delivery,customs, etc. (only statuses with count > 0) - Carrier breakdown β
carrier_bring,carrier_postnord,carrier_helthjem total_activeβ Same as state valuetotal_deliveredβ Delivered parcels still being tracked before auto-cleanup
- Status breakdown β
Use this to build conditional dashboard cards (e.g., only show the parcel card when total_active > 0).
The integration fires events on the Home Assistant event bus that you can use in automations:
| Event | Fired when | Data |
|---|---|---|
nordic_parcel_status_changed |
Any parcel status transition | tracking_id, carrier, sender, old_status, new_status |
nordic_parcel_delivered |
A parcel is first marked as delivered | tracking_id, carrier |
nordic_parcel_out_for_delivery |
Parcel is out for delivery | tracking_id, carrier, sender, old_status, new_status |
nordic_parcel_ready_for_pickup |
Parcel is ready for pickup | tracking_id, carrier, sender, old_status, new_status |
nordic_parcel_returned |
Parcel was returned to sender | tracking_id, carrier, sender, old_status, new_status |
nordic_parcel_failed |
Delivery failed | tracking_id, carrier, sender, old_status, new_status |
nordic_parcel_customs |
Parcel entered customs | tracking_id, carrier, sender, old_status, new_status |
The granular events fire in addition to nordic_parcel_status_changed, so you can listen to either the generic event or the specific one. No events fire on the first poll after adding a parcel (only on subsequent transitions).
The integration surfaces issues in Settings > System > Repairs:
| Issue | Severity | Fixable | Condition |
|---|---|---|---|
| Stale tracking | Warning | Yes (removes tracking) | No tracking update for 14+ days |
| Stuck in customs | Warning | No (informational) | In customs for 7+ days |
| Authentication failed | Error | No (use reauth flow) | Carrier API credentials invalid |
Issues auto-clear when conditions resolve (e.g., parcel updates, leaves customs, reauth succeeds).
Delivered parcels are automatically removed after a configurable number of days (default: 3). Change this in the integration options. Set to 0 to disable auto-cleanup.
This single automation covers all parcels β current and future β with no manual configuration:
automation:
- alias: "Notify on any parcel update"
trigger:
- platform: event
event_type: nordic_parcel_status_changed
action:
- service: notify.mobile_app
data:
title: "Parcel Update"
message: >-
{{ trigger.event.data.carrier | title }}
({{ trigger.event.data.sender }}):
{{ trigger.event.data.old_status | replace('_', ' ') | title }}
β {{ trigger.event.data.new_status | replace('_', ' ') | title }}automation:
- alias: "Notify when parcel is out for delivery"
trigger:
- platform: event
event_type: nordic_parcel_out_for_delivery
action:
- service: notify.mobile_app
data:
title: "Parcel on its way!"
message: >-
Your {{ trigger.event.data.carrier | title }} parcel
from {{ trigger.event.data.sender }} is out for delivery.automation:
- alias: "Notify on parcel delivery"
trigger:
- platform: event
event_type: nordic_parcel_delivered
action:
- service: notify.mobile_app
data:
title: "Parcel delivered!"
message: >-
Your {{ trigger.event.data.carrier | title }} parcel
{{ trigger.event.data.tracking_id }} has been delivered.| Option | Default | Description |
|---|---|---|
| Update interval | 900s (15 min) | How often to poll the carrier API |
| Cleanup days | 3 | Days after delivery before removing the sensor (0 = never) |
MIT