5 Best Practices for Spec-First API Development
The spec-first API development is an alternative to implementation-first API development and holds the promise of a more thoughtful and consistent API design.
Join the DZone community and get the full member experience.Join For Free
Spec-first API development is an alternative to implementation-first API development and holds the promise of a more thoughtful and consistent API design., especially when multiple teams are involved. Benefits of the spec-first approach include:
- Tight feedback loops: feedback can be provided in minutes or hours, not days.
- Design feedback: The review feedback is specific to the API design, vs. implementation details.
- Reduced effort: The OpenAPI spec can be used for code generation, documentation, code generation, and contract validation for both the Providers and Consumers.
- Contract testing for safety: We get immediate feedback in our tests when we make a breaking change to our API implementation by validating against our API spec.
This article covers some best practices for spec-first API development used to not only build hundreds of REST API endpoints across many engineering teams but where the specification is also used for:
- API routing and throttling via an API gateway
- API documentation rendering via an API reference
- SDK model and path code via code generation
The best practices from our learnings cover the following areas:
- Consistency via Style Guide
- Efficiency using Authoring Tools
- Scaling Specs and Services
- Ensuring Spec Compliance
- Leveraging the Spec for API Adoption
This article focuses on REST APIs and the OpenAPI specification but can be adapted to other types of APIs.
To begin, it’s useful to define these terms:
- API implementation: API that is exposed by a service.
- API specification: Machine-readable API definition using a specification such as OpenAPI Specification.
- Spec-first API development: Development process where the API specification is provided as input to the implementation engineering team. In software development, the specification can be seen as analogous to a UI / UX mockup, which is often created before and uses input to implementation.
- Implementation-first API development: Development process where the API specification is created after the implementation. In traditional, software development, the specification can be seen as application documentation, which is also often created after an engineering implementation.
1. Consistent API Design — The Foundation of a Usable API
Managing API design at scale requires having different teams author API designs in the same manner. At scale, this requires documenting the requirements and standards for API style, which can be thought of as an API Style Guide. The API Style Guide should have buy-in from all the relevant teams which should be reasonably easy to establish as consistency is a logical goal. That being said, it is important to make consistency easy to implement and verify.
Three parts of this include:
- Creating a Style Guide: This is a document that tells your team how APIs are to be built in your organization so that decisions can be made without a formal review. A list of API Design Guidelines is maintained by API Stylebook. This includes guidelines from companies such as Atlassian, Google, Microsoft, PayPal, Red Hat, etc.
- Validating API Specs via a Style Guide Linter and CI/CD: To scale, it is important to perform an automated review of style guides. This can be accomplished using tools such as Spectral which can be incorporated into your CI/CD process so tests can fail before a human review is performed.
- API Governance Committee: When there are things that cannot be covered in the style guide and testing, a human API governance committee review is useful. Building on the style guide is useful to help guide the conversation and reduce work for the committee.
2. Efficient Authoring—Ensuring Thoughtful Design
API specification such as OpenAPI Spec is easy for machines to read but not necessarily that easy for humans to read. Even though these can be implemented in YAML and JSON which are human-readable to an extent, there can be a lot of information in an API specification, even for a single endpoint.
There are two types of editors, IDEs and text editors.
- IDE: A full purpose-built IDE is now available for OpenAPI specifications from Stoplight.io. This enables users to switch between a form editor and a text editor to edit both common and uncommon/proprietary properties in the spec.
- Text Editors: Editors that enable you to edit, validate and render YAML or JSON are useful and can be used if (a) users are familiar with such editors and (b) extensions are used. Two popular text editors include VS Code and SwaggerHub.
These tools can be integrated with a style guide linter to alert authors to style guide deviations in real-time so they can be fixed immediately and not propagated to other teams for review and remediation.
Spectral is a popular API style guide linter that comes built into Stoplight and as a VS Code extension.
3. Scaling Specs and Services
Running services at scale can mean multiple services and engineering teams. API gateways are a common approach to proxy API requests to various backend services while providing a single entry point and consistent authentication and throttling. Some approaches to managing this at scale include:
- API gateway & microservice pattern: API gateways can use OpenAPI spec to define supported endpoints and redirect requests to the relevant microservice.
- Spec per microservice: Teams can limit the number of specs they interact with to the microservices they work on.
- Spec repository and merging tools: Specifications can be stored in git for each microservice to do version tracking and merged when needed to load into an API gateway, render documentation, or generate client SDK code. While merging specs can be proprietary to your implementation, Spectrum provides a rules-based approach to do so easily.
4. Contract Validation
Validating the API matches the specification using a spec-first approach requires a more care than an implementation-first approach. In the latter, a specification can be autogenerated via code annotations and can be ensured to be correct (to the extent of the software) since the spec generation is based on the actual implementation code. When using a spec-first approach, there are two useful approaches:
- Creating API services boilerplate and stubs: After the specification has been created, the service code with API stubs can be auto-generated from the spec using various tools such as the multi-language OpenAPI Generator project and various language-specific projects such as oapi-codegen.
- Contract validation: After services are created, a way to ensure correctness and ease of use is to implement an API client using a code generation tool such as the OpenAPI Generator project and then use that tool as part of the service’s CI/CD process to create requests and parse responses.
5. Leveraging the Spec for API Adoption
After both the Spec and API are available, the Spec can be further used as:
- API Reference documentation and API Explorer interactive webpages: Tools have evolved to combine documentation and interactive API call test tools. Some OpenAPI spec-based tools that can be used include: Stoplight, Readme, and Redocly. Open source solutions are also available from Redoc and Readme.io.
- Postman support: Tools such as Postman can either import OpenAPI specs directly or they can be converted to enhanced Postman’s Collection format..
- Client SDK code generation: It can be challenging to create and maintain client SDK code for many languages. Documentation can simply link to a code generation tool or generated SDKs can be hosted. Some tools include OpenAPI Generator, Swagger Codegen, and RC Codegen. Of note, both OpenAPI Generator and Swagger Codegen rely on the OperationId for SDK paths while RC Codegen uses the API path.
The best practices outlined here will enable your project to both improve your REST API services reduce efforts for your implementations.
They have been proven and deployed for the RingCentral Developers API which are used for API design, spec validation, contract validation, API reference/explorer generation, and SDK code generation.
Opinions expressed by DZone contributors are their own.