Getting started with groov's APIs

04 Jan 2017

I’m a developer on groov, and our just released R3.3a version includes a new place to store arbitrary data (we call it the Data Store), and our first public API: a way to get data in and out of those Data Stores. We also included support for CORS, so you can use it from a web page as well.

CORS can be a bit confusing, and on top of that a bunch of our customers use self-signed SSL certificates on their groov instances, so I thought I’d write down a getting started guide to get people past all of those bumps.

Overview

  1. Authorization to groov’s public API is provided via an API key. That key can be passed as a header, or via a query parameter. Each user in your groov project has an automatically generated API key, and administrators can generate a new key at any time.
  2. While every user has a key (it’s also used for Trend data downloads), the Data Store API is currently limited to Editor and Admin users only.
  3. In order to use the API from a web page, the domain that the page resides on must be whitelisted in your groov project settings. We don’t allow wildcard origins.
  4. Your web browser must trust the SSL certificate that your groov instance is using, otherwise any JavaScript initiated requests to it are going to fail silently. If you’re using a certificate signed by a well known certificate authority this won’t be a problem, but self-signed certificates will need to be marked trusted before this will work.

Getting at your API keys

There are two ways you can find your API keys. The official way is: an Administrator needs to log into groov Build and look in the Manage Accounts dialog. (Configure menu -> Manage Accounts…) API keys for your users will be listed there.

groov Build's Manage Accounts dialog

Remember, only Editor and Administrator users have access to the Data Store API.

The other, unofficial way is: log into groov, then in the same browser session visit https://your.groov/api/whoami.

Whitelisting your domain for CORS access

In your Project Settings (Configure menu -> Project…), under General Settings, you’ll see a configuration option titled “Allowed Cross-Origin Request Domains”. That’s the whitelist for CORS access. You’ll need to add the domain where your webpage will live, as well as a domain for where you’re doing your development. For example, this blog is built using Jekyll, and as I’m writing this I have a local server running on port 4000, so I’ll add http://localhost:4000 as an allowed domain. Along with that, it will eventually be deployed on my real website, so I’ll add http://www.jonathanfischer.net as well. If you’re developing without a server running, file:// works, but in practice browsers seem kind of flaky about loading JavaScript locally.

Configuring the CORS whitelist in groov Build

You’ll need to click the Save Settings button at the top of the Project Settings panel for changes here to take effect.

Note: CORS access controls apply only to JavaScript running within a web page. Non-browser clients, such as a shell script making requests via Curl or JavaScript running within Node-RED, don’t do CORS checks.

Trusting certificates

You’re on your own here. :) Basically, just visit your groov instance in the browser you intend on using and make sure it accepts your certificate without complaint.

Making requests

Ok, here’s the fun part. First: the API is specced using Swagger, so if that’s your bag you can use it to automatically generate an API wrapper. You can find groov’s Swagger specification at Opto 22’s Developer Site (the groov part might not be live yet), or on your groov instance at /swagger.yaml. There’s also a Swagger-UI installation running on your groov instance at /swagger-ui: you can use that to get a quick overview of what API calls are available, and how to use them.

So for example, if your groov instance is at https://groov.jonathanfischer.net, you can download the Swagger spec at https://groov.jonathanfischer.net/swagger.yaml, and reach Swagger-UI at https://groov.jonathanfischer.net/swagger-ui.

Note: if you’re already logged into groov when you visit your Swagger-UI installation, you’ll be able to use all of the GET endpoints in there without authenticating. groov has already set a cookie that the API endpoints recognize. POST endpoints will still require your API key though.

For the rest of this I’ll assume the groov instance is at https://groov.jonathanfischer.net, replace that with your own instance if you’re following along.

Let’s get a list of all the tags defined in your groov instance. The endpoint for that is GET /api/v1/data-store/tags, and we’ll need to add our API key to it. The full request we need to make then is:

GET https://groov.jonathanfischer.net/api/v1/data-store/tags?api_key=ABCDEF

Where the api_key parameter gets replaced with a valid key. Doing that in raw JavaScript looks like this:

var request = new XMLHttpRequest();
request.addEventListener("load", function () {
    console.log(this.responseText);
}
request.open("GET", "https://groov.jonathanfischer.net/api/v1/data-store/tags?api_key=ABCDEF");
request.send();

And assuming all went well, you’ll see a response in your console log:

[ {
	"id": 21,
	"deviceId": 2,
	"name": "String Table",
	"dataType": "stringArray",
	"length": 15
  },
  {
	"id": 22,
	"deviceId": 3,
	"name": "A Jolly Good Boolean",
	"dataType": "boolean"
  },
  {
	"id": 23,
	"deviceId": 3,
	"name": "A Tale of Two Floats",
	"dataType": "floatArray",
	"length": 2
  },
  {
	"id": 24,
	"deviceId": 3,
	"name": "String Theory",
	"dataType": "string"
  },
  {
	"id": 25,
	"deviceId": 4,
	"name": "😡",
	"dataType": "boolean"
  }]

I might have been testing out Unicode support on that particular project.

Errors you might run into

Along with those, you might just not get an error: your load event handler won’t be called. (The error handler will be called if you provide one.) That will happen when the browser blocks your request for some reason (either it fails the CORS pre-flight check or it doesn’t like your SSL certificate), or if you get your hostname wrong. As far I can tell, the browsers won’t tell you the reason for the failure via the error handler: you’ll have to look in your console log to figure it out. For example, if Firefox fails the CORS pre-flight check, I get a generic error in my error handler, but this helpful message in the console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://jfischer-ar1.opto22.com/api/v1/data-store/tags. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Whew, that went longer than I thought. Have fun out there, groov users!

P.S. - Sneaky users might notice other endpoints being called by groov View. Basically, if it’s not under /api/v1, /api/info, or /api/whoami, we make no guarantees that said endpoint will remain stable. They can and frequently do change between releases. Don’t rely on them.