Learn the importance of documenting web APIs, the different approaches available, and the tools you can leverage to document web APIs.
Application Programming Interfaces (APIs) are intermediaries that allow applications to communicate with each other. An example of this would be a frontend app retrieving data via the GitHub API to find out the number of stars a project has.
Web APIs (REST, GraphQL, gRPC) can send and receive data from other web APIs and frontend applications — from the web browser and mobile apps — over the HTTP protocol using the client-server model. This means a frontend application or web API (the client) sends a request to another web API (the server). The server replies with a response — data or an error — back to the client.
Before the client sends a request, it requires a number of details — the protocol, the URL/IP address where it's sending the request to, the structure of the request, route params and request queries, HTTP method and headers. The web API documentation provides these details for a developer to effectively use the API in their application.
This article will discuss why you should document web APIs, the benefits, tools available, and bonus tools to improve web API development.
What is API Documentation?
API documentation is a manual describing instructions on how to use an API — REST, gRPC or GraphQL. The documentation outlines the data structures, functions, arguments, return types, classes, etc., developers can refer to.
Building an API is half the job. An API lacking documentation would lead to friction between different teams building products. Manual updates to documentation are a common problem that exists because they are prone to error. Failing to keep documentation up-to-date creates a point of failure for others who depend on it.
"...if there's no documentation, it doesn't matter how good the API is... If you do that wrong, people aren't going to be able to use it..."
Why document APIs?
An adequately documented API accrues the following benefits:
1. Maintainable APIs
API documentation advocates for a design-first approach when building applications. This means developers create an API specification before writing any code. This makes the API adaptable to future needs and less painful to maintain. From the specification, the team can:
- Identify issues before the development begins.
- Create a high-level overview of how the API is expected to work.
- Split implementation of the tasks.
2. Predictable APIs
Documentation describes expected returned data structures for different operations. Frontend applications, services, or microservices dependent on it would "be aware" of the data structures returned, reducing the odds of something breaking. When types change in one section of the application, the compiler will notify you and throw errors or warnings of the affected parts of the application that require an update for the app to run.
3. Improves collaboration
Documentation provides a reference for other teams and developers rely to on when building applications. Developers can depend on the documentation to describe usage and also to understand errors and the structure of the API. Great documentation has the potential to vastly improve the developer experience when working with an API.
The documentation can be used to track the progress of an APIs implementation, understand the abstractions created, and keep the team aligned on the objectives of the API.
Tools
This section will explore different tools that can help you and your team create compelling documentation for your web APIs.
Swagger
Swagger is a tool implementing the Open API specification which defines a standard, language-agnostic interface for describing HTTP-based APIs.
Swagger is used for documenting REST APIs. The API defines the operations that can be performed — stating the request parameters, query or body, and response object and code. The documentation also defines the data structures expected to be sent or received by the API. Documentation generated using Swagger can create API test cases, automate API-dependent processes, and create an interactive environment to test the API.
Another benefit swagger provides is client SDKs and server stubs generation by using Swagger Codegen.
There are different implementations of Swagger for different languages and frameworks, such as NestJS, among many others.
Hello world swagger example with NestJS
Download the rest-nestjs example from the prisma-examples repository in your working directory:
curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/typescript/rest-nestjsCopy
Install npm dependencies:
cd rest-nestjsnpm installCopy
Run the following command to create a SQLite database file and create the User
and Post
tables defined in prisma/prisma.schema
:
npx prisma migrate dev --name initCopy
Install the swagger dependencies required for NestJs:
npm install @nestjs/swagger swagger-ui-expressCopy
Update src/main.ts
to initialize Swagger:
// src/main.tsimport { NestFactory } from '@nestjs/core'import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'import { AppModule } from './app.module'async function bootstrap() {const app = await NestFactory.create(AppModule)const config = new DocumentBuilder().setTitle('Prisma Examples').setDescription('The prisma-examples REST API definition').setVersion('1.0').build();const document = SwaggerModule.createDocument(app, config);SwaggerModule.setup('api', app, document);await app.listen(3000)}bootstrap()Copy
Start your REST API with the following command:
npm run dev
When the application is running, open your browser and navigate to http://localhost:3000/api, and you should see the following:
The @nestjs/swagger
module makes use of the decorators that define API requests to generate the Swagger documentation.
Postman
Postman provides a suite of tools to use during API development such as automated testing, organizing requests, mocking, monitoring tools, among other services. Among these services is Postman's API Platform that you can use to create documentation - for both REST and GraphQL APIs.
This works by creating a collection on Postman and organizing your requests in different folders. To successfully publish your collection, you'll need to sign in to your account first. Once you hit publish, Postman generates documentation based on the collection.
For this example, you can refer to this collection containing the requests for the REST API-based Prisma examples. You can import the collection on Postman and try it out for yourself from here.
You can enforce type-safety in this workflow by converting the JSON-formatted responses into TypeScript interfaces for the front-end applications using a tool like JSON2Ts.
GraphQL
GraphQL is a query language for APIs that enables declarative data fetching. GraphQL APIs are composed of two main components: the schema definition and resolvers. The schema describes the behaviour of the API. Resolvers are functions that implement the schema definition.
Documentation is a first-class feature of the GraphQL type system. Out of the box, GraphQL is self-documenting thanks to its schema. This feature reduces the possibility of human error as it is not dependent on manually updating documentation. The GraphQL API queries the defined schema and generates the documentation that tools like GraphQL Playground or GraphiQL display.
According to the GraphQL specification, all types in the introspection system provide include a description field that provides more information about a given field or type. As intuitive as GraphQL operations and types may be, you can always provide more additional information by adding comments to the different types and API operations.
Hello world GraphQL example
Download the graphql-sdl-first example from the prisma-examples repository in your working directory:
curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/typescript/graphql-sdl-firstCopy
Install npm dependencies:
cd graphql-sdl-firstnpm installCopy
Run the following command to create a SQLite database file and create the User
and Post
tables defined in prisma/prisma.schema
:
npx prisma migrate dev --name initCopy
Update type Post
in src/schema.ts
to include the following details:
"""createdAt and updatedAt fields are updated by the database automatically"""type Post {author: Usercontent: StringcreatedAt: DateTime!id: Int!published: Boolean!title: String!updatedAt: DateTime!viewCount: Int!}Copy
Start your GraphQL API with the following command:
npm run dev
When the application is running, open your browser and navigate to http://localhost:4000 to explore the API. Expand the Docs section on the GraphQL Playground. The generated schema would contain the comment under the Post field:
Protocol buffers
Protocol buffers, also known as Protobuf, is the most commonly used Interface Definition Language (IDL) for gRPC. gRPC is a framework for working with Remote Procedure Calls (RPC). RPC is a form of client-server communication used to call a function on other remote systems.
The request message format is stored in a .proto
file.
The message definition holds the fields of key-value pairs, specifying the types of each piece of the message data.
An example .proto
file looks like this:
package blog;
service Blog { rpc Feed(FeedRequest) returns (FeedResponse) {}}
message Post { optional int32 id = 1; optional string createdAt = 2; optional string updatedAt = 3; required string title = 4; optional string content = 5; optional bool published = 6;}
message FeedRequest {}
message FeedResponse { repeated Post feed = 1}
Each field of the message is assigned a unique number. These numbers are used to define the fields in the message binary format. Comments may be added to provide additional information for the different fields using the C/C++ style.
The video below is from TSConf 2018. Mohsen Azimi covers using Protocol buffers as a source of truth for your web API.
JSON Schema
JSON Schema is a tool for validating the structure of JSON data. It can be used together with Swagger to define the schema which contains the request and response objects of an API endpoint. JSON Schema is a flexible tool that can be used in other use cases such as authoring user interfaces with Microsoft's Adaptive Cards, among others.
A schema contains six main properties referred to as keywords. These keywords include:
$schema
- states the standard and draft of the schema.$id
- defines the URL of the schema.title
anddescription
- are descriptive keywords for your schema.types
- data type constraint for the JSON data.properties
- validation specifying what the value of each object should resemble
Using the feed
request from the prisma-examples - REST API - returns the following response:
{ "posts": [ { "title": "Join the Prisma Slack", "content": "https://slack.prisma.io", "published": true, "createdAt": "2020-06-30T23:01:18.943Z", "updatedAt": "2020-06-30T23:01:18.943Z", "authorId": 1, } ]}
Based on the example, you can use the following JSON schema to validate your response:
{ "definitions": {}, "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://example.com/object1618650097.json", "title": "Root", "type": "object", "required": [ "posts" ], "properties": { "posts": { "title": "Posts", "type": "array", "default": [], "items":{ "title": "Post", "type": "object", "required": ["title", "content", "published", "createdAt", "updatedAt", "authorId", "author"], "properties": { "title": { "title": "title", "type": "string", }, "content": { "title": "content", "type": "string", }, "published": { "title": "published", "type": "boolean", }, "createdAt": { "title": "createdAt", "type": "string", }, "updatedAt": { "title": "updatedAt", "type": "string", }, "authorId": { "title": "authorid", }, } }
} }}
The above schema is not exhaustive of all the properties that can be used to validate your data. You can refer to the JSON Schema specification for more details.
Conclusion
In conclusion, web API documentation is important for both internal and external teams because it offers better developer experience. Writing documentation may be tedious but it brings more good to the team by improving API design, promoting development of maintainable and predictable APIs, and boosts collaboration.