Tithe.ly Engineering

Specifying APIs for the Future

by Shawn Pyle on February 19, 2024

In a recent project, our team was tasked with creating a new API. Many of the Tithe.ly engineering teams already had specifications for their internal APIs using OpenAPI. API specifications provide the contract between back-end API development and front-end API consumption. With this contract firmly in place, both back-end and front-end teams could work in parallel to provide the finished project.

What are API specifications?

API specifications serve as a bridge in API architecture, acting as a standardized contract between API providers and consumers. Drawing inspiration from the work of OpenAPI and SmartBear these specifications define the structure, expected behavior, and potential responses of an API. They encapsulate the essence of the API, offering a comprehensive guide to its design and functionality. This contract outlines not only the architectural blueprint of the API but also details the anticipated behavior and potential error conditions, providing a clear roadmap for developers on both ends of the interaction. Utilizing formats such as JSON or YAML schemas, API specifications contribute to seamless integration between disparate systems, fostering a common language for effective communication and collaboration in the software development process.

Importance of API specifications

API specifications become a single point of reference for both back-end and front-end engineers, or yourself if you do full stack. Not only a guide to both teams, it can be a record of changes to the API. This is helpful to communicate when the front end must be updated to accommodate modifications. It provides common language for both teams to communicate and understand the API.

At Tithe.ly, we use pitches to detail the features and work needed for a project. The API specifications were built first and anticipating all the data required by the front end.

If both back-end and front-end teams agree on this API contract, work can begin in parallel by stubbing the responses. In our recent project, front-end work completed around the same time the back-end work finished. This parallel development is only possible with a clear API specification.

How to write API specifications

As the primary developer of the API specification for this project, and being the first time to have created such a document, I wanted to share my process and tools for creating the API specification.

Process

With any software development, getting a clear objective and feature set is the first step. Our Product and Design teams provided a clear pitch of the features needed. The API specification should be a reflection of the features and data required by the front-end.

  1. Evaluate each feature in the pitch. If there are questions, get them answered quickly as designs and user flows may need to change. Jidoka!
  2. Create a simple text outline of the items required in the API.
  3. Identify overlaps and distinct data required.
  4. Assign the endpoint paths that the API will support.
  5. For complicated processes, create a flow chart or sequence diagram to clarify the process. Ask for feedback or get clarity when needed.
  6. Create a JSON or YAML file that outlines the API specification.
  7. Share the API specification with the front-end team for feedback.
  8. Address any feedback and update the API specification.
  9. Publish the API specification to a location that is accessible to both teams. At Tithe.ly, we use SwaggerHub.
  10. Repeat updates-feedback-publish cycle until project is complete.

Tools

Here are some wonderful tools that I found were immensely helpful while designing an API specification.

  1. VSCode - This is my go-to editor for all things, including writing this article.
  2. Markdown Preview Mermaid Support - This plugin allows me to create flow charts and sequence diagrams and display them inline with the markdown preview.
  3. OpenAPI (Swagger) Editor - This allowed me to visualize the API specification as if it was hosted in SwaggerHub, which is where it eventually get’s published.
  4. openapi-lint - This provides real-time linting of the API specification. It’s like having a spell checker for your API specification.
  5. Add @stoplight/spectral-cli as package.json devDependencies entry to lint and validate the specification.
  6. Add the following package.json scripts for easy linting with yarn lint. Be sure to replace PATH/TO/YOUR/api.yml with the path to your API specification.
     "scripts": {
         "prelint-api": "yarn global list | grep -q 'spectral-cli'; if [ $? -eq 1 ]; then yarn global add @stoplight/spectral-cli; asdf reshim; fi",
         "lint-api": "spectral lint --verbose --fail-severity=hint PATH/TO/YOUR/api.yml",
         "lint": "yarn lint-api",
     }
    
  7. Add .githooks/pre-commit to validate the api.yml file when committing to the repository.

     #!/bin/zsh
    
     yarn lint-api
    

Realtime Validation

One of our Tithe.ly teams uses the API specification to do real-time request parameter checking using the PHP library openapi-validation-middleware. This appears to be available for Rails as well but we did not use it due to timing and other project constraints.

API Versioning

There is one drawback to API specifications in a single file, there isn’t a way to specify multiple versions that are available or deprecated. We devised a way to house these versions in a separate versions.yml alongside the api.yml file.

# Describe the available API versions in this file. Backwards compatible changes and deprecations do not need a version. Breaking changes do require a new version.
versions:
  -
    status: active
    version: 2024-01-01
    released_at: 2024-01-01T00:00:00Z
    changes:
      - Initial release of the /api/v1 endpoints
      - Added /organizations/:id/* endpoints
    deprecations:
      - /org/:id/* endpoints are deprecated

This file will be available at /api/v1/versions endpoint and provide detail about each version.

[
	{
		"version": "2024-01-01",
		"status": "active",
		"released_at": "2024-01-01T00:00:00.000Z",
		"changes": [
			"Initial release of the /api/v1 endpoints",
			"Added /health, /versions, and /organizations/:id/* endpoints"
		],
		"deprecations": [
			"/org/:id/* endpoints are deprecated"
		]
	}
]

Conclusion

The API specification is a useful tool in developing APIs that work and getting everyone on the same page. Utilizing the growing set of tools around OpenAPI Specification makes it easy to create quality specifications the first time.