At Upvest we are an API-first (in fact, API-only) company. We build robust and scalable software infrastructure for investment and banking. We expose our software, via our Public API, to clients who in turn integrate with our platform to provide their end users with investment products as part of their own offering.
We don’t build apps or end-user products ourselves, we provide capabilities for others to do so. We do have some internal user facing apps to facilitate our own operations, but we consider ourselves an API-company. What does this mean?
API as a product
Our Public API is the tangible product we offer. There is a lot of collateral material of course that comes with it in the form of documentation, guides, tutorials, and in the future we’ll also offer SDKs. We also support all of this with our own expertise. We help you to figure out how the product setup fits into your offering with the help of our amazing growth, product and DevX-colleagues.
To do this we have to follow proper product management and API lifecycle processes that define how we build and evolve our Public API according to our Secure Software Development/Delivery Lifecycle (SSDLC).
API first
What does being API first mean?
It describes an approach to the design of software products that expose a public interface.
In practise, before we consider any technical design, we’ve gone through a process of validating our ideas:
- why is this functionality valuable to our clients?
- why is it valuable to us as a company?
- is it feasible for us to offer this functionality in a sustainable, scalable and profitable manner?
- can we build it at all?
Once we’re certain of all these things we start on the Public API. This is what we mean by “API First”. Before we do any system design or write any code, we design the Public API for that new functionality. What the resources related to the functionality are, what attributes they have, what the JSON schema for them look like, and how actions on those resources would be exposed via the HTTPS/JSON API using HTTP methods, in a manner consistent with our API styleguide. Finally we expose the new design in our OpenAPI description of our Public API.
API as a contract
Once we have described the functionality in the Public API, it is a part of our “contract” to our clients. Clients will integrate with it in their systems and will rely on it for their business. This means that we are committed then to supporting it until such time that it is sunset via a deprecation process and/or superceded by some other functionality or no longer relevant to our clients.
This means that when we change things in our Public API we have to be conscious of the impact it will have on our clients. We can’t introduce breaking changes to the API without a proper process. Managing this process, and communicating about it both externally and internally is a complex business. This is why API versioning becomes a critical part of providing a Public API.
API versioning
We follow a semantic versioning approach to our API versioning. Stay tuned for a post about that from Geoffrey, our Head of DevX, later. In a semantic versioning scheme the version number consists of three components in the patternMAJOR.MINOR.PATCH
.This means is that now that we have gone to market with the first major version of our API, the version will be 1.0.0 (or some 1.x.y).
- When we fix something in our API in a backward compatible fashion, we increment the
PATCH
number of the version, for example from 1.0.0 to 1.0.1. - When we add new functionality in a backward compatible fashion (nothing breaks in existing integrations), we increment the
MINOR
version number, for example from 1.0.1 to 1.1.0 - When we at some point in time may have to introduce a change that would break an existing integration, we would increment the
MAJOR
version number, for example from 1.1.0 to 2.0.0
When a breaking change is necessary, we will also make sure that the old version will keep existing alongside the new version for a contractually agreed upon timeframe called the deprecation period. During this time we will add a HTTP deprecation header to the responses. Client integrations can request either one of the live MAJOR
-versions of the API with a header upvest-api-version
in the HTTP-request. Within a MAJOR-version you will always get the latest MINOR.PATCH
version as those changes are backwards compatible.
The deprecation period gives our clients enough time to migrate their integration and make the necessary changes to their software in order to use the newer version of the API. Once all client integrations have been migrated and no integration is using the old MAJOR
-version of the API, we will sunset it and remove it from the available API.