Working with IO - A Technical Perspective
A few weeks ago we announced that PowerPlanner's Adviser Portal now integrates with Intelligent Office for smooth and speedy case submission.
Working with any new API can always throw up a few snags, so, for the benefit of others trying to do likewise, here's a technical post that covers how to work around some of the challenges you may encounter. This is not intended to be a comprehensive walkthrough or a detailed guide to developing an app; it's just a point of reference that I hope will be helpful.
Intelliflo's API uses OAuth to establish trust between the two systems sharing data. This can sound really complicated at first because IO supports a few different mechanisms (code flows) for establishing this trust and acquiring an authorisation code.
The first challenge is deciding which code flow to use for your use case. Basically, if you are planning to do server-to-server, programmatic communication that doesn't involve users then you will be looking at Tenant Client Flow. On the other hand, if you want individual IO users to be responsible for granting access to your software then you'll probably want Authorization Code Flow. It's possible that one of the other variants may actually be better for you, but, if in doubt, I've found Intelliflo's developer support team to be extremely helpful so you can always reach out to them.
To visualise how these flows work, I'll run through a quick example of each:
Tenant Client Flow
When you create your App, you'll also need to create OAuth 2.0 Credentials. When you do this, you'll choose which code flow you want to use. If you support multiple flows you'll need a set of credentials for each one. This example assumes you have created a Tenant Client Credentials flow.
- Concatenate the Client ID, a colon (:) and the Client Secret together as a string.
- Encode this string using Base 64 encoding.
- Use this string to obtain an access token by including it in an HTTP POST as a header named "Authorization" with a value of "Basic " concatenated with your encoded string. The POST URI will look something like this:
- The server responds with a JSON object containing an access token (it should start with "eyJhb") that you can then use to interact with IO via the API.
Note that for this code flow to work you need to know the Tenant ID of the IO instance with which you want to communicate (the ID in this example is IO's test system). See below for how to find this.
When designing your App, you must bear in mind that Tenant Client Flow has no way of validating access rights applied to IO user accounts! As such, if you need users to interact with IO via your own software then you should consider using Authorization Code Flow instead, or you may have difficulty getting your app approved for publishing by Intelliflo.
Authorization Code Flow
This mechanism requires an Intelligent Office user to interact with the system. Let's call her Alice Administrator.
- Use the Client ID that corresponds to your App credentials designated for Authorization Code Flow.
- Ask Alice Administrator to click a link to grant permissions for your software to access IO in the scopes needed. This link will look something like this:
Remember that the URI given here for redirection must be in the list of those provided when the application was registered in IO.
- Upon clicking this link, Alice is presented with a web page served by Intelliflo saying "PowerPlanner wants access to Intelligent Office, do you agree?" or words to that effect.
- Alice clicks "Allow" and IO then POSTs to its own endpoint (
/core/consent), which redirects to
/core/connect/authorize/callback, which then redirects to your specified
redirect_urivia a HTTP GET that looks like:
- The value of this
codeparameter is then used to get the access token from
https://identity.intelliflo.com/core/connect/token. It's a similar process to TCF above, except you pass
redirect_uri=instead of the
- Once the access token has been returned, you can then use this in your software to interact with all Alice Administrator's clients on IO.
For testing these processes, the IO docs recommend using Postman for the callback & redirection URIs. I didn't actually need this in the end because I have access to a public-facing web server, so I just got IO to call back to this and tailed the log files as the requests came in. In fact, as all the redirects for the Authorization Code Flow happen via the user's browser, you can even work with things like
http://localhost:8080/auth-code-granted when testing locally.
Using the API
Now you've got your access token via the chosen code flow, you can start using it to query the API.
With the Intelligent Office API being a standard RESTful interface, it's pretty easy and intuitive to use. All you need to do is ensure you have
Authorization: Bearer eyJhb...access code here... and
x-api-key: app-...app's API key here... as HTTP headers on each request and then it's just a matter of hitting URLs and reading the JSON responses.
As simple as this sounds, there are, however, a couple of things worth bearing in mind:
Beware the Apostrophe Delimiter
When querying using a
filter parameter, IO requires you to use the apostrophe (') as a delimiter for quoting strings. This is fine until you have a client called O'Sullivan or something like that, in which case you end up getting back a 400 Bad Request because of a broken query string!
To work around this, you need to escape the apostrophe in the name with a backslash, and then use URI encoding for the name. As such, "O'Sullivan" becomes "O\'Sullivan" which has to be encoded as "O%5C%27Sullivan" in the query string. This will allow IO to use the name as intended.
You Cannot Assume the Presence of Key Data
IO seems to provide very little in the way of presence checking data validation, so many values you'd intuitively think must surely be stored (such as a date of birth for a client) may in fact be absent from a record.
As such, you have to code pretty defensively, which can be a pain if your JSON parsing library of choice is really strict about null values. If you can use sensible defaults when deserialising from JSON then that'll probably help, but one thing you really won't get away with is assuming a certain field is always non-null.
Subscribing to Intelliflo Platform Events
The API also supports event notifications via WebHooks. If you're using Tenant Client Flow then you'll definitely need this, as the only way to find out a customer's tenant ID is to subscribe your App to the "appinstalled" event.
Setting this up is relatively simple. With a valid access token, you simply ask IO to call a particular endpoint on your server whenever an event is received. This endpoint is specified in a
hub.callback parameter when you subscribe, for example:
Note that this needs to be sent as a POST request.
Once received, IO will immediately send a GET to the the URI you specify for the callback along with some parameters. One of these is named
hub.challenge, the value of which must be echoed back in the HTTP response with a response code of 200 OK. Any other response code from your server, even a 202 Accepted, won't work.
This exchange verifies the subscription, and IO will now send POST requests containing JSON to your server whenever the relevant event occurs for your app. You can refer to the Intelliflo API events page to see the sort of JSON that you can expect to receive.
Overall, it's been a pleasure to work with the Intelligent Office API. Its quality documentation along with the great support that Intelliflo provide for developers make it one of the better system integration interfaces out there. However, for those times when common use cases throw up unexpected challenges, I hope the information in this post will be helpful.