{"id":5235,"date":"2023-12-23T17:00:00","date_gmt":"2023-12-23T17:00:00","guid":{"rendered":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/?page_id=5235"},"modified":"2025-05-26T14:02:42","modified_gmt":"2025-05-26T13:02:42","slug":"nibe-heat-pump-monitoring-via-myuplink-api","status":"publish","type":"page","link":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/?page_id=5235","title":{"rendered":"NIBE Heat Pump Monitoring via myUplink API"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Introduction<\/h1>\n\n\n\n<p>The other pages on this site which describe using scripts to interact with the NIBE Uplink API have proved quite popular, especially in explaining the requirements for OAuth2 Authentication. In late 2023, the NIBE Uplink service is being decommissioned and NIBE heat pump owners are being encouraged to move to the alternative <a href=\"https:\/\/myuplink.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">myUplink<\/a> service, so this page specifically covers that alternative API instead.<\/p>\n\n\n\n<p>It was only the older NIBE F-series heat pumps that used NIBE Uplink anyway; the newer S-series have always used myUplink. Other people have had good success using variants of the NIBE Uplink scripts to access myUplink since the APIs are similar and the authentication requirements are the same, but the structure of the API calls is different (arguably better and simpler &#8211; more logical and fewer calls required to return the same data).<\/p>\n\n\n\n<p>This page intentionally duplicates a lot of the content from the earlier <a href=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/?page_id=4988\" data-type=\"page\" data-id=\"4988\">NIBE Heat Pump Monitoring via NIBE Uplink API (Python Version)<\/a> since I expect most new users will arrive at this page and it&#8217;s less confusing if the instructions are self-contained and if the screenshots reflect the myUplink look-and-feel.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Disclaimer<\/h1>\n\n\n\n<p>This procedure works for me and I\u2019m publishing it here as a Proof of Concept in case it helps other people trying to accomplish the same objective. It may not work for you. It may not get updated in line with changes to the myUplink API service. You are responsible for complying with the terms of the myUplink API Services Agreement and for keeping the application Identifier, Secret and any generated user Tokens confidential.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">My Use Case<\/h1>\n\n\n\n<p>I have an 8kW NIBE F1145 Ground Source Heat Pump which was installed in 2016 and was originally configured to send data to the NIBE Uplink service. Towards the end of 2023 NIBE have been migrating NIBE Uplink users over to the newer myUplink service and these notes were written in support of that migration.<\/p>\n\n\n\n<p>The uploaded data is accessible via the myUplink website and the myUplink smartphone app, but those apps use the API \u2018under the covers\u2019 and it\u2019s possible to call the API directly from a custom program or script to access all the same data \u2013 and then do more interesting things with it.<\/p>\n\n\n\n<p>I have a script which invokes the myUplink API on a timed schedule (every few minutes) to download the parameters I\u2019m interested in which I then re-publish using\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/MQTT\" target=\"_blank\" rel=\"noreferrer noopener\">MQTT<\/a>\u00a0(my personal preference; in no sense essential) to integrate them with data from other sources (Meter-Bus electricity and heat meters, Dallas Semiconductor One-Wire sensors, Oregon Scientific temperature \/ humidity sensors \u2013 see other pages on this Blog for more details of those if you\u2019re interested). Everything then gets loaded into an\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/InfluxDB\" target=\"_blank\" rel=\"noreferrer noopener\">InfluxDB<\/a>\u00a0time-series database from which it can be extracted and graphed with\u00a0<a href=\"http:\/\/grafana.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>\u00a0(again my personal preferences but these tools work well for me).<\/p>\n\n\n\n<p>At the risk of straying even further off-topic, some of my myUplink data gets further re-published to <a href=\"https:\/\/heatpumpmonitor.org\/\" data-type=\"link\" data-id=\"https:\/\/heatpumpmonitor.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">HeatpumpMonitor.org<\/a> (a community dashboard of heat pump performance data). Since that also needs a feed of Electricity Consumption and Heat Output data, which are not part of the myUplink dataset, I found it easier to source the data from InfluxDB and upload to <a href=\"https:\/\/emoncms.org\/\" data-type=\"link\" data-id=\"https:\/\/emoncms.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">emoncms.org<\/a> (which drives HeatPumpMonitor.org) in one go.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Pre-Requisites<\/h1>\n\n\n\n<p>At a bare minimum you will need the following to use this procedure:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>A\u00a0<a href=\"https:\/\/myuplink.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">myUplink<\/a>\u00a0account with at least one NIBE heat pump registered to it and reporting data which is viewable via the website or one of the smartphone apps.\n<ul class=\"wp-block-list\">\n<li>Anyone can use the \u201cRegister an account\u201d button on the main myUplink page to create an account if you don\u2019t have one, but unless you have a heat pump linked to the account the API won\u2019t return any meaningful data.<\/li>\n\n\n\n<li>It doesn&#8217;t <em>strictly<\/em> have to be your own heat pump; other people can grant your myUplink account &#8216;Viewer&#8217; access to their heat pump.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>A computer which is able to access the Internet and which will run the Python script to download data via the API.\n<ul class=\"wp-block-list\">\n<li>It doesn\u2019t need to be particularly powerful \u2013 an old\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Raspberry_Pi\" target=\"_blank\" rel=\"noreferrer noopener\">Raspberry Pi<\/a>\u00a0or similar single-board-computer is perfectly adequate. It could also be a virtual server hosted in the Cloud, or a Windows desktop or laptop.<\/li>\n\n\n\n<li>It doesn\u2019t need to run a web browser or have a graphical display attached \u2013 remote access via a terminal window using a tool like PuTTY or \u2018ssh\u2019 is sufficient.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>An Internet-connected computer with a standard graphical web browser (Firefox, Chrome, Edge, Safari etc.) which can be used to complete Steps 1 and 2 in the procedure described below. This can be any platform you like \u2013 potentially even a Smartphone \u2013 and certainly could be the same computer described at Item 2 above if that meets the requirements, though typically it will be a different machine.\n<ul class=\"wp-block-list\">\n<li>If the computer running the browser is not the same as the one running the script, then ensure you can connect to the computer running the script, since you will need to copy-and-paste a long text string between the two, accurately and quickly.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>A basic knowledge of the&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Python_(programming_language)\" target=\"_blank\">Python<\/a>&nbsp;scripting language, editing files and installing software packages on your chosen platform.<\/li>\n<\/ol>\n\n\n\n<h1 class=\"wp-block-heading\">myUplink API \u2013 Documentation and Underpinning Technologies<\/h1>\n\n\n\n<p>The official documentation for the myUplink API is at\u00a0<a href=\"https:\/\/dev.myuplink.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/dev.myuplink.com\/<\/a>\u00a0(note you need to login to access that page). The detail is described on those pages but in summary:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It\u2019s a&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\" target=\"_blank\" rel=\"noreferrer noopener\">RESTful<\/a>&nbsp;API accessed over HTTPS<\/li>\n\n\n\n<li>Data is encoded using&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/JSON\" target=\"_blank\" rel=\"noreferrer noopener\">JSON<\/a><\/li>\n\n\n\n<li>Requests are authenticated using&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/OAuth#OAuth_2.0\" target=\"_blank\" rel=\"noreferrer noopener\">OAuth2<\/a><\/li>\n\n\n\n<li>OAuth2 presents the single biggest challenge for using the API because you need to obtain a valid Token and then Refresh that whenever it Expires<\/li>\n<\/ul>\n\n\n\n<p>The older NIBE Uplink API only supported OAuth2&#8217;s <a href=\"https:\/\/requests-oauthlib.readthedocs.io\/en\/latest\/oauth2_workflow.html#web-application-flow\" data-type=\"link\" data-id=\"https:\/\/requests-oauthlib.readthedocs.io\/en\/latest\/oauth2_workflow.html#web-application-flow\" target=\"_blank\" rel=\"noreferrer noopener\">Authorization Code Grant Flow<\/a> (also known as the Web Application Flow); the myUplink API also supports OAuth2&#8217;s <a href=\"https:\/\/requests-oauthlib.readthedocs.io\/en\/latest\/oauth2_workflow.html#backend-application-flow\" data-type=\"link\" data-id=\"https:\/\/requests-oauthlib.readthedocs.io\/en\/latest\/oauth2_workflow.html#backend-application-flow\" target=\"_blank\" rel=\"noreferrer noopener\">Client Credentials Grant Flow<\/a> (also known as the Backend Application Flow) which appears somewhat simpler. The current page concentrates on the Authorization Code Grant Flow since that replicates the old NIBE Uplink behaviour. There&#8217;s more info on the Authentication options at <a href=\"https:\/\/dev.myuplink.com\/auth\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/dev.myuplink.com\/auth<\/a> and probably the simpler Client Credentials Grant Flow would be a better match to the requirements of most hobbyist users. Maybe I&#8217;ll address that in a future update to this page.<\/p>\n\n\n\n<p>Personally I found the biggest barrier to getting the API working was understanding what the OAuth2&nbsp;<strong>Callback URL<\/strong>&nbsp;was all about and what would be an acceptable value to use for that (there are several constraints). Actually it\u2019s not all&nbsp;<em>that<\/em>&nbsp;complicated and it only needs to be used once, in order to initially get an Access Token. Importantly, it\u2019s possible to run some steps in the procedure on different machines (as long as they\u2019re done in quick succession). Here\u2019s a summary of how it works:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When one of your application\u2019s users (most likely yourself in this scenario) enters their myUplink credentials in a browser window and agrees to grant your application access to their data, the myUplink website redirects them to the&nbsp;<strong>Callback URL<\/strong>, attaching an Authorization Code which is only valid for a limited time and can only be presented once<\/li>\n\n\n\n<li>Before the code expires, it\u2019s necessary to present it to the myUplink&nbsp;<strong>Token URL<\/strong>&nbsp;together with other application-specific parameters in order to be allocated an Access Token and an accompanying Refresh Token<\/li>\n\n\n\n<li>As long as you can get the Authentication Code presented to the Token URL before it expires, you can do that from anywhere \u2013 it doesn\u2019t need to be from the same machine as is hosting the&nbsp;<strong>Callback URL<\/strong>&nbsp;though that is typically the scenario described in other OAuth2 documentation<\/li>\n<\/ul>\n\n\n\n<p>I believe it\u2019s necessary for the&nbsp;<strong>Callback URL<\/strong>&nbsp;to use HTTP<strong>S<\/strong>&nbsp;and since that can be problematic to configure I\u2019m hosting a simple script on the same server as this Blog which anyone should be able to specify as their&nbsp;<strong>Callback URL<\/strong>&nbsp;\u2013 it will simply print out the generated Authorization Code (or any error message). That URL is:&nbsp;<a href=\"https:\/\/www.marshflattsfarm.org.uk\/nibeuplink\/oauth2callback\/index.php\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.marshflattsfarm.org.uk\/nibeuplink\/oauth2callback\/index.php<\/a>&nbsp;(which will complain unless you call it with the right parameters \u2013 see later).<\/p>\n\n\n\n<p>If you want to host your own installation of the\u00a0<strong>Callback URL<\/strong>\u00a0the PHP script code I\u2019m using can be download from GitHub\u00a0<a href=\"https:\/\/github.com\/MarshFlattsFarm\/myUplink-API\/blob\/main\/oauth2callback\/index.php\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>The Python library\u00a0<a href=\"https:\/\/requests-oauthlib.readthedocs.io\/en\/latest\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">Requests-OAuthlib<\/a>\u00a0is used to hide much of the complexity of OAuth2 processing. The documentation at that link explains how to use it though in principle if you exactly follow the procedure outlined below you don\u2019t need to understand in detail how it works.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Step-By-Step Procedure<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 0 \u2013 Prepare the Python Computer<\/h2>\n\n\n\n<p>The computer which will run the script that calls the myUplink API needs some preparation to ensure the Python environment and the necessary supporting Python libraries are available.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The first requirement is a working Python3 environment\n<ul class=\"wp-block-list\">\n<li>On Windows, follow the instructions at&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/www.python.org\/downloads\/windows\/\" target=\"_blank\">Python Releases for Windows<\/a><\/li>\n\n\n\n<li>On Raspberry Pi OS, run:&nbsp;<code>sudo apt-get install python3<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>The second requirement is the Requests-OAuthlib library\n<ul class=\"wp-block-list\">\n<li>On Windows, use a Command Prompt to run:&nbsp;<code>pip3 install requests-oauthlib<\/code><\/li>\n\n\n\n<li>On Raspberry Pi OS, can install this with:\u00a0<code>sudo pip3 install requests-oauthlib<\/code>\n<ul class=\"wp-block-list\">\n<li>If that doesn\u2019t work, you might need to first run:\u00a0<code>sudo apt-get install python3-pip<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1 &#8211; Register your \u2018Application\u2019<\/h2>\n\n\n\n<p>The Python script you are about to create that will call the myUplink API is what the API calls an \u2018Application\u2019 so start by Registering a new Application at the myUplink website so that you get allocated your various unique ID strings which will be required later.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Connect to\u00a0<a href=\"https:\/\/dev.myuplink.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/dev.myuplink.com\/<\/a>\u00a0using your favourite web browser on any machine you like (it does not need to be the machine which will later run the Python script)<\/li>\n\n\n\n<li>Login with your myUplink username and password<\/li>\n\n\n\n<li>Click on the\u00a0<strong>Applications<\/strong>\u00a0tab (or go to <a href=\"https:\/\/dev.myuplink.com\/apps\">https:\/\/dev.myuplink.com\/apps<\/a>)<\/li>\n\n\n\n<li>Press the grey\u00a0<strong>Create New Application<\/strong> button on the left<\/li>\n\n\n\n<li>Populate the\u00a0<strong>Name<\/strong>,\u00a0<strong>Description<\/strong>\u00a0and\u00a0<strong>Callback URL<\/strong>\u00a0fields\n<ul class=\"wp-block-list\">\n<li>Choose your own values for\u00a0<strong>Name<\/strong>\u00a0(maybe \u201cPython API Script\u201d as shown) and\u00a0<strong>Description<\/strong>\u00a0and either specify your own\u00a0<strong>Callback URL<\/strong>\u00a0(if you\u2019ve set one up hosting the PHP code mentioned above) or use\u00a0<a href=\"https:\/\/www.marshflattsfarm.org.uk\/nibeuplink\/oauth2callback\/index.php\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.marshflattsfarm.org.uk\/nibeuplink\/oauth2callback\/index.php<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Read the\u00a0<strong>Services Agreement<\/strong>, click to confirm your acceptance of that \u2013 at this point the screen should look like the image below:<br><br><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"448\" class=\"wp-image-5244\" style=\"width: 640px;\" src=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CreateApplication.png\" alt=\"\" srcset=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CreateApplication.png 1222w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CreateApplication-300x210.png 300w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CreateApplication-1024x716.png 1024w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CreateApplication-768x537.png 768w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CreateApplication-429x300.png 429w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/li>\n\n\n\n<li>Press the <strong>Create<\/strong> button<\/li>\n\n\n\n<li>Record the allocated\u00a0<strong>Client Identifier<\/strong>\u00a0and\u00a0<strong>Client Secret<\/strong>\u00a0credentials and\u00a0<strong><em>keep them secret!<\/em><\/strong>\u00a0(you can view them later under\u00a0<strong>Applications<\/strong>\u00a0if required)<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2 &#8211; Create an Access Token using an Authorization Code<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Download the first sample Python script from the GitHub repository\n<ul class=\"wp-block-list\">\n<li>If you\u2019re familiar with Git(Hub) and you have the \u2018git\u2019 client software installed, you might wish to \u2018clone\u2019 the repository (don\u2019t worry if those words don\u2019t mean anything to you \u2013 do one of the following instead)<\/li>\n\n\n\n<li>Alternatively, browse to the\u00a0<a href=\"https:\/\/github.com\/MarshFlattsFarm\/myUplink-API\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub repository page<\/a>\u00a0and download the\u00a0<code>request_token.py<\/code>\u00a0file<\/li>\n\n\n\n<li>Alternatively, run this command in a terminal window:\u00a0<code>wget https:\/\/github.com\/MarshFlattsFarm\/myUplink-API\/raw\/main\/request_token.py<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Edit the downloaded Python script with whichever editor you prefer and replace the definitions of\u00a0<code>client_id<\/code>\u00a0and\u00a0<code>client_secret<\/code>\u00a0with the\u00a0<strong>Client Identifier<\/strong>\u00a0and\u00a0<strong>Client Secret<\/strong>\u00a0strings from Step 1<\/li>\n\n\n\n<li>This next bit (as far as Step 9) is the time-sensitive bit: In a terminal window, run the command:\u00a0<code>python3 request_token.py<\/code><\/li>\n\n\n\n<li>The script will display a long URL which you should copy and paste into a Web Browser window<\/li>\n\n\n\n<li>If you\u2019re already logged in to the myUplink API website (e.g. having just created your Application) in the same Browser you might not be prompted for your credentials, otherwise expect to have to enter your myUplink Username and Password<\/li>\n\n\n\n<li>Expect to see a page like the screenshot below (you\u2019ll see the\u00a0<strong>Name<\/strong>\u00a0you specified rather than \u201cPython API Script\u201d if you changed it). This is myUplink asking you to grant permission for your script to act on behalf of your user account.<br><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"279\" class=\"wp-image-5247\" style=\"width: 640px;\" src=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-Allow-1.png\" alt=\"\" srcset=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-Allow-1.png 1167w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-Allow-1-300x131.png 300w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-Allow-1-1024x446.png 1024w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-Allow-1-768x334.png 768w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-Allow-1-500x218.png 500w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/li>\n\n\n\n<li>Press the\u00a0<strong>Yes, Allow<\/strong>\u00a0button<\/li>\n\n\n\n<li>If everything works you\u2019ll see a very simple web page which looks like the following (which is generated by the\u00a0<strong>Callback URL<\/strong>):<br><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"52\" class=\"wp-image-5248\" style=\"width: 640px;\" src=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CODE.png\" alt=\"\" srcset=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CODE.png 1006w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CODE-300x24.png 300w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CODE-768x63.png 768w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CODE-1000x82.png 1000w, https:\/\/www.marshflattsfarm.org.uk\/wordpress\/wp-content\/uploads\/2023\/12\/myUplink-CODE-500x41.png 500w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/li>\n\n\n\n<li>That value for\u00a0<strong>Parameter \u2018code\u2019<\/strong>\u00a0(pixelized in the screenshot) is your\u00a0<strong>Authorization Code<\/strong>\u00a0which you\u2019ll need to copy-and-paste into the terminal window where the Python script will still be waiting \u2013 <em>before the code expires<\/em><\/li>\n\n\n\n<li>The script should confirm to which file it has written the Token obtained using the\u00a0<strong>Code<\/strong>\u00a0\u2013 if you see an error message instead the code might have expired, so try the procedure again but paste the code as soon as you see it in the browser<\/li>\n\n\n\n<li>Once you get confirmation the Token has been written to file, that&#8217;s the time-sensitive part of the procedure completed. The file includes both a &#8216;currently-valid&#8217; token and also a second token which can be used to refresh the token when it expires.<\/li>\n\n\n\n<li>Note that anyone who can read the file containing the Token will be able to access the myUplink API as your account; if it\u2019s on a shared computer you will want to change the permissions to ensure nobody else can read it<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3 &#8211; Call the NIBE Uplink API<\/h2>\n\n\n\n<p>Now we have an Access Token we can&nbsp;<em>actually<\/em>&nbsp;call the API \u2013 and now things are less time-critical because the Token will be automatically renewed as required.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Download the second sample Python script from the GitHub repository \u2013 this one is called:&nbsp;<code>simple_call_to_protected_api.py<\/code><\/li>\n\n\n\n<li>Edit this sample script to set&nbsp;<code>client_id<\/code>&nbsp;and&nbsp;<code>client_secret<\/code>&nbsp;as before<\/li>\n\n\n\n<li>Run the script with:&nbsp;<code>python3 simple_call_to_protected_api.py<\/code><\/li>\n\n\n\n<li>If it works as expected it will list out the systemId number(s) and name(s) of the heat pump(s) assigned to your myUplink account<\/li>\n<\/ol>\n\n\n\n<p>If that worked OK then you can also try the third sample Python script in the GitHub repository, called:\u00a0<code>get_DevicePoints_for_Devices_for_Systems.py<\/code><\/p>\n\n\n\n<p>You will have to edit&nbsp;<code>client_id<\/code>&nbsp;and&nbsp;<code>client_secret<\/code>&nbsp;as before&nbsp;(the first part of this script is identical to the previous script). This third script:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Retrieves the list of Systems defined for the authorized User, together with their associated Devices<\/li>\n\n\n\n<li>For each of those Devices, retrieves the associated DataPoints (like BT1, the Outdoor Temperature)<\/li>\n<\/ul>\n\n\n\n<p>These details are simply printed out but the script could be adapted to publish them as MQTT messages or re-formatted as XML or JSON or similar and sent to a Home Automation system or database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Next Steps<\/h2>\n\n\n\n<p>If this procedure works for you, great! Please leave a Comment to let me know. If it doesn\u2019t work or doesn\u2019t makes sense please also leave a Comment and I\u2019ll try to help.<\/p>\n\n\n\n<p>Clearly just printing out the systemIds isn\u2019t very interesting but the myUplink API Documentation describes the other API calls in some detail.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Further Reading<\/h2>\n\n\n\n<p>I found the following resources useful for understanding how to get OAuth2 working:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/oauth.net\/2\/\" target=\"_blank\" rel=\"noreferrer noopener\">The main OAuth2 website<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/aaronparecki.com\/2012\/07\/29\/2\/oauth2-simplified\" target=\"_blank\" rel=\"noreferrer noopener\">Aaron Parecki\u2019s &#8220;OAuth2 Simplified&#8221; web page<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/20missionglass.tumblr.com\/post\/60787835108\/programming-an-oauth2-client-app-in-php\" target=\"_blank\" rel=\"noreferrer noopener\">Programming an OAuth2 Client App in PHP<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Introduction The other pages on this site which describe using scripts to interact with the NIBE Uplink API have proved quite popular, especially in explaining the requirements for OAuth2 Authentication. In late 2023, the NIBE Uplink service is being decommissioned &hellip; <a href=\"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/?page_id=5235\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":5866,"menu_order":1,"comment_status":"open","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-5235","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/5235","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5235"}],"version-history":[{"count":14,"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/5235\/revisions"}],"predecessor-version":[{"id":5253,"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/5235\/revisions\/5253"}],"up":[{"embeddable":true,"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/5866"}],"wp:attachment":[{"href":"https:\/\/www.marshflattsfarm.org.uk\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}