Authenticating Opto API calls with HTTP request

Here are some tips to using Opto API’s like groov Manage, groov View, and PAC Control with the standard HTTP request core node. In this post I’ll go over how to set the apiKey header object and how to enable SSL/TLS in the request node.

Note that this doesn’t and shouldn’t replace the groov IO nodes, groov View,or the PAC Control nodes – it just provides a way to use API endpoints that are not exposed through those nodes. For example there is no way to use a node to unmount an installed USB drive, but you could do it with an HTTP post command to /api/v1/system/usb/unmount! This opens up a lot of possibilities, especially when used in Node-RED.

In order to make an admin-level request like this you will need the API key from a groov or LDAP user with system-wide administrator permissions, and you will need to provide that to the HTTP request node. Because of this, I recommend making a separate account for Node-RED so you can reset the key / delete the user if needed, without affecting anything else.

Here are two basic versions of separate “get”/read and “post”/write flows:

The first inject just sets the function node to set the required properties: URL, headers, and the payload (payload is only required when posting). The URL can also be hard-coded in the HTTP request node, but here it is handed in as a message property so you can easily modify it if needed, for example building up the URL based on some other input.
For building up the URL I recommend generating it directly on your device using the “REST APIs” page under the “Info and Help” menu, but you can also find the API reference on the developer site:

groov Manage
groov View
PAC Control

Here is what the code looks like – note the curly brackets for msg.headers and msg.payload, these are required to create the correct JSON structure for the API. Also, msg.payload is only included because this is a POST example, if you’re running a GET request you won’t need a payload at all.

msg.url = "https://localhost/pac/device/strategy/vars/strings/test_string";
msg.headers = { apiKey : "mR4VG3sRSrRJok4ZouNGJN7iNJQpfKER" };
msg.payload = { value : msg.payload };
return msg;

This will write any incoming string in msg.payload to “test_string” in the PAC Control strategy running on the EPIC when sent as a POST request. You can read it back in with the following:

msg.url = "https://localhost/pac/device/strategy/vars/strings";
msg.headers = { apiKey : "mR4VG3sRSrRJok4ZouNGJN7iNJQpfKER" };
return msg;

If you want to avoid using JavaScript in the function for any reason you can also set these properties with a change node and it will work exactly the same way as long as the URL is set as a string, the headers property is a JSON object, and the payload (if posting) is reformatted using JSONata.
Here’s an example:


Once the function node is taken care of, the next thing to set up is the HTTP request node. You will need to enable SSL/TLS, since the API must go through https://localhost/..., but you do not need to provide any certificate files unless you’re sending the requests to another groov device.

In the configuration menu just untick “Verify server certificate” and click “Add” in the top right to enable TLS for this node. You only need to do this once, in any other HTTP request nodes just select this same TLS configuration.

Once that is done, choose the request method based on whether you’re reading data from or writing data to the API, and you’re good to go!

Here is the example flow JSON you can import to try this yourself – just remember to replace the API key!
Happy coding.

[{"id":"92b33a5eb6a076b5","type":"http request","z":"dce8c2751b5385ee","name":"HTTP GET","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"3e36307c3ee7d40b","persist":false,"proxy":"","authType":"","x":530,"y":400,"wires":[["d604128c5214fb51"]]},{"id":"bb94c633fe7aa4e7","type":"function","z":"dce8c2751b5385ee","name":"set properties","func":"msg.url = \"https://localhost/pac/device/strategy/vars/strings\";\nmsg.headers = { apiKey : \"mR4VG3sRSrRJok4ZouNGJN7iNJQpfKER\" };\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":400,"wires":[["92b33a5eb6a076b5"]]},{"id":"3bd6810eb8ba468f","type":"inject","z":"dce8c2751b5385ee","name":"inject","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":170,"y":400,"wires":[["bb94c633fe7aa4e7"]]},{"id":"d604128c5214fb51","type":"debug","z":"dce8c2751b5385ee","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":710,"y":400,"wires":[]},{"id":"7f9ba603316099c3","type":"http request","z":"dce8c2751b5385ee","name":"HTTP POST","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"3e36307c3ee7d40b","persist":false,"proxy":"","authType":"","x":530,"y":460,"wires":[["621a1ab4101a93c3"]]},{"id":"621a1ab4101a93c3","type":"debug","z":"dce8c2751b5385ee","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":710,"y":460,"wires":[]},{"id":"c8099a6784af17c8","type":"inject","z":"dce8c2751b5385ee","name":"inject","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"test","payloadType":"str","x":170,"y":460,"wires":[["dfe1dc30cd3b30c4"]]},{"id":"dfe1dc30cd3b30c4","type":"function","z":"dce8c2751b5385ee","name":"set properties","func":"msg.url = \"https://localhost/pac/device/strategy/vars/strings/test_string\";\nmsg.headers = { apiKey : \"mR4VG3sRSrRJok4ZouNGJN7iNJQpfKER\" };\nmsg.payload = { value : msg.payload };\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":460,"wires":[["7f9ba603316099c3"]]},{"id":"3e36307c3ee7d40b","type":"tls-config","name":"localhost","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","servername":"","verifyservercert":false,"alpnprotocol":""}]