Skip to content

Instantly share code, notes, and snippets.

@iSenne

iSenne/README.md Secret

Last active December 7, 2022 09:02
Show Gist options
  • Save iSenne/2d225e99f7772df59e661522e9b8757f to your computer and use it in GitHub Desktop.
Save iSenne/2d225e99f7772df59e661522e9b8757f to your computer and use it in GitHub Desktop.
PostNL notification (for Home Assistant)

For Dutch users only. A flow that gets all shipments from the PostNL App API and sends a notification (through Home Assistant) for upcoming deliveries.

Sample PostNL

You need the PostNL app (tested with IOS) and setup a proxy (like Charles Proxy) to retrieve the necessary information.

Replace the following items from information regarding the app:

In the Set Payload Refresh Token node

  • GET_REFRESH_TOKEN_FROM_APP
  • GET_USER_AGENT_FROM_APP

Refresh token PostNL

In the Get PostNL API node

  • GET_DEVICE_TOKEN_FROM_APP
  • GET_USER_AGENT_FROM_APP

Device token and User agent PostNL

You can only see the refresh token when the access token on your device is expired. Make sure your proxy is setup before you open the app, otherwise you'll have to wait an hour.

This flow will retrieve an access_token first, before asking the api for shipments. You can replace the Home Assistant notifications for something else.

This is not tied to an official API, so it may stop working. I've been running this for a few day's, so it seems to work fine for now.

Like this flow? Then please encourage me to make more!

Buy Me A Coffee

[
{
"id": "26ad711013720db1",
"type": "inject",
"z": "6bd02c2a2c231ca5",
"name": "",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "true",
"payloadType": "bool",
"x": 130,
"y": 380,
"wires": [
[
"7390eecb2a68187b"
]
]
},
{
"id": "7390eecb2a68187b",
"type": "change",
"z": "6bd02c2a2c231ca5",
"name": "Set Payload Refresh Token",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "refresh_token=GET_REFRESH_TOKEN_FROM_APP&client_id=pnl-app&grant_type=refresh_token",
"tot": "str"
},
{
"t": "set",
"p": "headers.content-type",
"pt": "msg",
"to": "application/x-www-form-urlencoded; charset=UTF-8",
"tot": "str"
},
{
"t": "set",
"p": "headers.user-agent",
"pt": "msg",
"to": "GET_USER_AGENT_FROM_APP",
"tot": "str"
},
{
"t": "set",
"p": "headers.accept",
"pt": "msg",
"to": "*/*",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 380,
"wires": [
[
"bb95aaed0e1ab77a"
]
]
},
{
"id": "bb95aaed0e1ab77a",
"type": "http request",
"z": "6bd02c2a2c231ca5",
"name": "Get Bearer Token",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://jouw.postnl.nl/identity/connect/token",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 590,
"y": 380,
"wires": [
[
"9b8af9562bd9b403"
]
]
},
{
"id": "9b8af9562bd9b403",
"type": "switch",
"z": "6bd02c2a2c231ca5",
"name": "Check access_token key",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "hask",
"v": "access_token",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 830,
"y": 380,
"wires": [
[
"c73bfa4f62f12627"
],
[
"3db74ddcab5f9fd1"
]
]
},
{
"id": "c73bfa4f62f12627",
"type": "change",
"z": "6bd02c2a2c231ca5",
"name": "Set Bearer Token",
"rules": [
{
"t": "set",
"p": "token",
"pt": "msg",
"to": "\"Bearer \" & msg.payload.access_token",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 190,
"y": 480,
"wires": [
[
"51f06d75d07accfc"
]
]
},
{
"id": "3db74ddcab5f9fd1",
"type": "api-call-service",
"z": "6bd02c2a2c231ca5",
"name": "Notify Mobile on error",
"server": "0eecc4b4dd856bd2",
"version": 5,
"debugenabled": false,
"domain": "notify",
"service": "notify",
"areaId": [],
"deviceId": [],
"entityId": [],
"data": "{\t \"title\": \"PostNL\",\t \"message\": \"PostNL flow broken\"\t}",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"x": 1120,
"y": 380,
"wires": [
[]
]
},
{
"id": "51f06d75d07accfc",
"type": "http request",
"z": "6bd02c2a2c231ca5",
"name": "Get PostNL API",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://jouw.postnl.nl/services/serverdrivenui/api/Screen/OverviewTab",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [
{
"keyType": "other",
"keyValue": "app-version",
"valueType": "other",
"valueValue": "5.7.3"
},
{
"keyType": "other",
"keyValue": "api-version",
"valueType": "other",
"valueValue": "1.5.1"
},
{
"keyType": "other",
"keyValue": "app-platform",
"valueType": "other",
"valueValue": "iOS"
},
{
"keyType": "other",
"keyValue": "device-token",
"valueType": "other",
"valueValue": "GET_DEVICE_TOKEN_FROM_APP"
},
{
"keyType": "other",
"keyValue": "user-agent",
"valueType": "other",
"valueValue": "GET_USER_AGENT_FROM_APP"
},
{
"keyType": "other",
"keyValue": "app-country",
"valueType": "other",
"valueValue": "NL"
},
{
"keyType": "other",
"keyValue": "authorization",
"valueType": "msg",
"valueValue": "token"
}
],
"x": 400,
"y": 480,
"wires": [
[
"233e69e220541b2d"
]
]
},
{
"id": "233e69e220541b2d",
"type": "change",
"z": "6bd02c2a2c231ca5",
"name": "Get Shipments (From section 1)",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "msg.payload.screen.sections[1].items",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 650,
"y": 480,
"wires": [
[
"d8f40413e2ddd21b"
]
]
},
{
"id": "d8f40413e2ddd21b",
"type": "split",
"z": "6bd02c2a2c231ca5",
"name": "Split Shipments (From array)",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "",
"x": 940,
"y": 480,
"wires": [
[
"f9f76e584b87828f"
]
]
},
{
"id": "f9f76e584b87828f",
"type": "change",
"z": "6bd02c2a2c231ca5",
"name": "Change Track & Trace URL",
"rules": [
{
"t": "change",
"p": "payload.action.url",
"pt": "msg",
"from": "https://jouw.postnl.nl/services/serverdrivenui/api/TrackAndTrace/",
"fromt": "str",
"to": "https://jouw.postnl.nl/track-and-trace/",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 580,
"wires": [
[
"8e9a58fd6ffe92be"
]
]
},
{
"id": "8e9a58fd6ffe92be",
"type": "switch",
"z": "6bd02c2a2c231ca5",
"name": "Check Shipments Today",
"property": "payload.title",
"propertyType": "msg",
"rules": [
{
"t": "cont",
"v": "Vandaag",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 610,
"y": 580,
"wires": [
[
"da1b704d1cdab83b"
]
]
},
{
"id": "da1b704d1cdab83b",
"type": "api-call-service",
"z": "6bd02c2a2c231ca5",
"name": "Notify Mobile",
"server": "0eecc4b4dd856bd2",
"version": 5,
"debugenabled": false,
"domain": "notify",
"service": "notify",
"areaId": [],
"deviceId": [],
"entityId": [],
"data": "{\t \"title\": \"PostNL\",\t \"message\": msg.payload.contentDescription.description,\t \"data\": {\t \"actions\": [\t {\t \"action\": \"URI\",\t \"title\": \"Track & Trace\",\t \"uri\": msg.payload.action.url\t }\t ]\t }\t}",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"x": 890,
"y": 580,
"wires": [
[]
]
},
{
"id": "0eecc4b4dd856bd2",
"type": "server",
"name": "Home Assistant",
"version": 5,
"addon": false,
"rejectUnauthorizedCerts": true,
"ha_boolean": "y|yes|true|on|home|open",
"connectionDelay": true,
"cacheJson": true,
"heartbeat": false,
"heartbeatInterval": "30",
"areaSelector": "friendlyName",
"deviceSelector": "friendlyName",
"entitySelector": "friendlyName",
"statusSeparator": ": ",
"statusYear": "hidden",
"statusMonth": "short",
"statusDay": "numeric",
"statusHourCycle": "default",
"statusTimeFormat": "h:m",
"enableGlobalContextStore": false,
"credentials": {
"host": "",
"access_token": ""
}
}
]
@Lxxrxns
Copy link

Lxxrxns commented Dec 7, 2022

How do I implement this in Home Assistant? Does it need any addons?

@iSenne85
Copy link

iSenne85 commented Dec 7, 2022

How do I implement this in Home Assistant? Does it need any addons?

It's only the notification part that uses Home Assistant. The code (flow) itself is for Node-RED. You can install Node RED in Home Assistant or standalone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment