How we practice API-first development to build Kampus Merdeka
When developing for the web, there are two popular approaches:
- Code-first, in which developers start by writing back-end code, and API documentation is generated afterward.
- API design-first, in which developers start by designing an API contract first, then implement it.
In the development team of Kampus Merdeka, we value standardized and intuitive APIs. Therefore, we adopt an API design-first approach when building our products. Here’s how it goes!
Process
We start by having product engineers participate in a technical planning session to hash out requirements from our product and design team. When building a feature, we encourage developers to take not only the final set of requirements but also an understanding of the feature’s motivation and how it fits into the rest of the product.
Once we are comfortable with our understanding, we start designing the APIs. Three parties are involved to ensure our APIs are sound, complete, and well-designed: back-end engineers, front-end engineers, and API experts from our software architect team. After a quick chat for ideation, back-end engineers usually kick-start the process by proposing the API. Then, front-end engineers ensure that the specifications designed have fulfilled their needs. Finally, our API experts help to refine the API structure.
The process we follow is not very rigid. When the APIs we need to build are more complex, we recommend engaging our API experts earlier in the ideation process. The extent of front-end engineer involvement also varies depending on the task's complexity. Ideation can take longer or shorter or be done in multiple iterations as well.
Tooling
Our development process revolves around some tools that we use.
API Specification — API Blueprint
API Blueprint is a great tool for design-first development because of its human-readable syntax. Let’s explore the following example:
# Indicator Management Module
### Create Indicator [POST /indicators/]
API to create an indicator.
+ Request (application/json)
+ Headers
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ.L8i6g3PfcHlioHCCPURC9pmXT7gdJpx3kOoyAfNUwCc
+ Attributes
+ Include Create-Indicator-Request
+ Body
+ Response 200 (application/json)
+ Attributes
+ data (Indicator-Response, required)
# Data Structures
## `Indicator-Field-Response` (object)
+ id: 10 (number, required)
+ title: `Supporting document` (string, required)
+ type: `file` (string, enum[file, text, number, date, boolean], required)
## `Indicator-Response` (object)
+ id: 1 (number, required)
+ title: `Indikator` (string, nullable, required)
+ description: `Indikator indikasi` (string, nullable, required)
+ created_at: `2021-01-01T00:00:00Z` (string, required)
+ updated_at: `2021-01-01T00:00:00Z` (string, required)
+ indicator_fields: (array[Indicator-Field-Response], required)
## `Create-Indicator-Field-Request` (object)
+ title: `Supporting document` (string, required)
+ type: `file` (string, enum[file, text, number, date, boolean], required)
## `Create-Indicator-Request` (object)
+ title: `Indikator` (string, required)
+ description: `Indikator indikasi` (string, required)
+ indicator_fields: (array[Create-Indicator-Field-Request], required)
This syntax is easy to read and understand, even for developers unfamiliar with it. Furthermore, it is easy to generate HTML documentation from API Blueprint definitions, making it a great option for those who prioritize human readability and ease of use in their API design process.
The downside is that the open-source version of the API blueprint is no longer being actively maintained (although Apiary still has a product that uses it). Tooling around the specification has practically stalled, too, so we will likely move to another format. If you have any suggestions on this area, let us know :)
API Convention
We maintain our own set of conventions for our APIs, following best practices for RESTful APIs. We find this format to be easy to maintain and understood by our engineers.
Gitlab
We simply use Gitlab’s Merge Requests feature to collaborate and refine our APIs. We take advantage of API Blueprint’s readability to conduct reviews and discussions directly on the contract artifact.
Conclusion
In this article, we shared how Kampus Merdeka development team’s API design-first approach ensures a focus on standardized, intuitive, and well-designed APIs. We discussed how our process encourages developer understanding and cross-functional collaboration to deliver high-quality APIs. We also shared a few tools we currently use and their strengths and weaknesses. We hope the reader benefits from this article and welcome further contributions on this topic!