Posts Tagged ‘API’
Want a successful API program? Think like a product manager.
Kin Lane, the API Evangelist, had a really good post on maturing an API program, with the not-so-brief title of “I Have An API Deployed, And A Base Presence Established, What Can I Do To Help Me Get The Word Out?” You should definitely go read that because there’s some really good advice there.
What was very clear to me is much of what Kin and others talk about is essentially turning your API into a product and applying the discipline of product management. Set goals, identify your prospects, create marketing material, highlight the success of your customers, understand your competitors, provide good support, etc. I think it’s important for the technical audience to understand that these concepts aren’t new, even though they might be new to the technical crowd. As I know from my own experience, we technologists will flock to new technology just because it’s a shiny new thing to try out. Unfortunately, that doesn’t make for a good product strategy. Just as a blog of mine a long time ago on communications suggested bringing a communications expert onto your IT team, it’s also a good idea to have someone with product management experience work with you on your API program efforts.
The one thing in Kin’s post that I had a slight disagreement with was his section on goals. While his goals were valid, these are really secondary goals to what is absolutely the number one goal: revenue. Now, I’ve read enough of his other posts that I know he gets this, but I don’t think it can be emphasized enough. I began my career in development and have always been on the IT side of the house, and for many, many reasons that I won’t go into in this post, too many people in IT really don’t understand the revenue models of their companies. So, if you don’t understand how your API program will impact revenue, go back and figure it out. You may be able to charge directly for API use and fund your own operations. It may be less direct revenue, such as how Walgreens’ photo APIs eventually result in revenue through in-store photo printing, rather than a fee for API use. Growth in new users might be great, but if there isn’t a revenue model, it will eventually become a cost sink. One only needs to look at the number of press releases about public APIs being shut down to understand the importance of this.
All in all, Kin’s post is really, really good. It calls out a number of specific things to do when your product is an API, so follow these things but also complement your efforts with some general purpose product management knowledge and you’ll be in a position to make good decisions.
API Design: Compartments
I’ve been reviewing the FHIR (Fast Healthcare Interoperability Resources, http://www.hl7.org/fhir) specification and they have an interesting concept called a compartment. Per the spec:
Each resource may belong to one or more logical compartments. A compartment is a logical grouping of resources which share a common property. Compartments have two principal roles:
- Function as an access mechanism for finding a set of related resources quickly
- Provide a definitional basis for applying access control to resources quickly
Let’s look at these statements one at a time. First, the component concept provides an access mechanism for finding related resources. One very common compartment in the specification is Patient. Other resources, like Condition, clearly have a relationship with Patient. So, if I want to find all conditions that a particular patient has, I actually have two paths for doing this.
- GET /Patient/[id]/Condition
- GET /Condition/?patient=[id]
[id] is the unique identifier in question. In this case, both of these requests should return the same thing. But it’s not quite that simple. Take another resource, Communication, which deals with secure messages sent as part of patient care. In this case, we have:
- GET /Patient/[id]/Communication
- GET /Communication/?subject=[id]
- GET /Communication/?sender=[id]
- GET /Communication/?recipient=[id]
The first example returns any communication that involves the identified patient, whether to, from, or about. The Communication specific inquiries only allow for inquiry by the attribute of the resource where a Patient identifier can be specified. It just so happens that in the earlier case, the relationship within Condition is represented in a patient attribute.
Independent of whether you think this is a good or bad thing, this approach where there are two ways of getting to the same resources creates a decision point for the organization. In a large enterprise, it’s entirely possible that the implementation for different resources may be handled by different teams. With two (or more) different ways of doing this, it creates the risk of two (or more) different implementations. It also creates a situation where a resource that can be a compartment needs to make sure that any time a new related resource is defined and implemented, they also need to make a modification to provide the compartment-based inquiry. Once again, if this is a separate team, this means coordination. Anyone who’s worked in an enterprise knows that the more teams that get involved, the more challenging it becomes.
These are not insurmountable difficulties by any stretch of the imagination. In the case of the implementation, the compartment resource should simply act like a façade and make the appropriate calls to the resource (i.e. the implementation of the first URL in the examples above simply turns around and makes the call(s) below them to complete the inquiry, such as Patient calling Condition, or Patient calling Communication). In the case of the coordination, that’s a matter of education and oversight to make sure it happens. The greater risk is probably that too many things get defined as a sub-structure within the compartment resource, rather than defined as standalone resources. This can be avoided by recognizing when a proposed resource has multiple compartments. Take the following requests:
- GET /Practitioner/[id]/Condition
- GET /Condition?asserter=[id]
These inquiry would give me a collection of all conditions that a particular practitioner has ever dealt with. If Condition wasn’t a standalone resource, and instead a sub-structure within Patient, how would I go about forming this query? It can be done, but it’s probably not going to look as simple as what is shown above. This is where I see the hidden strength of this compartment concept. By recognizing where we can have multiple ways of organizing a particular collection of data and traversing relationships, we can then make good design decisions on what our resources should be.
Finally, FHIR also mentions that the compartment concept can also play a role in access control. I haven’t dug into this one as much, but I think it may have some potential. The challenge lies with data that really has multiple owners. As a patient, I may want to use an OAuth model to grant access to my health records to a mobile app I’ve downloaded. My doctor may want to do the same thing for an application he or she uses as part of my care. The compartment approach could give independent access paths for each of these channels with their own policies. Again, I need to give this one more thought, but I can definitely understand why HL7 put the bullet point about access control in their specification.
What are your thoughts about this notion of compartments? Good thing? Bad thing? Have you implemented a similar approach? What were the pros and cons of it? Let’s start the discussion.
Dynamic Data in REST
I had an interesting conversation with some colleagues around resource design that I thought would be helpful to share.
The starting point was a simple question:
Should price generation be a HTTP POST or HTTP GET?
There’s solid reasoning for either of them. Let’s start with HTTP GET.
From a consumer’s perspective, a GET probably seems very intuitive. For how most people think about prices, it’s static information, so why wouldn’t it just be an attribute included on a GET of some other resource, like a Product, right?
For the purposes of this conversation, however, price is something that is computed at the time of the request. In other words, some supporting static information exists (like list price), but the actual “price” charged to the customer is dependent on other contextual parameters. Cases where this exists are the end price you pay at Amazon after taking into account shipping preferences, account status (e.g. Prime member?) or the price you pay when you buy a car. These prices are determined on the fly and may only be good for a limited amount of time, because the contextual information is subject to change. Hopefully, you can also see that “price” is actually a complicated piece of information.
Is HTTP POST beginning to sound better? Where this fits very well is that the “Price” is really a custom resource generated for that particular context. The customer, even though they may use the phrase “get me a price,” is really saying, “generate me a quote.” At this point, we’re creating a new resource.
But there’s one more thing. What if price calculation is expensive? If I make this a POST and generate this every time, won’t my costs go through the roof? Well, they don’t have to. There’s no reason that a subsequent POST with the same data can’t return a resource from cache in this scenario. In reality, you are probably updating the expiration date of the resource, so POST still makes sense. Furthermore, if you provide a unique ID for the calculated price resource, HTTP GET can be used to retrieve it again, it just shouldn’t update the expiration policy.
So, out of this, I came up with the following guiding principles on deciding whether calculated/derived data should be its own resource:
- Can the data stand on its own? That’s always a question for any resource.
- Does the calculation require contextual data from the consumer to perform the calculation, or are all the parameters already part of the potential parent resource?
- Is there value in keeping the calculated data around for some time to avoid re-calculation?
Hopefully these guiding principles will help you out. If you have other suggestions on factors that help this design decision, please feel free to share in comments or via your own blog post.