Contract First API Development Primer

On this page

Purpose

This document discusses the concept of Contract First API Development and how it helps in building robust and sustainable APIs. The Contract First approach described here helps to align with the GC API Standards particularly in the following areas:

Contract First vs Code First

The development process of APIs is divided into 2 general approaches:

Contract First – Start by defining the API contract based on the requirements of API consumers. The code is then developed to map the contract to the backend system which the API exposes.

Code First – Start by writing the business logic code of exposing the system. The API contract is generated from the code using various software development toolkits.

Why Contract First?

The API contract defines how consumers are to interact with the API. Defining it up front gives the API consumers something concrete to design and develop against while enforcing a level of decoupling between the interface and the backend system.

User-Centric Design for APIs

API consumers are the users of APIs. If we want to apply an user-centric design approach to building APIs, then we should consider that that the API contract should be dictated by requirements from API consumers (i.e., how developers of the consuming systems expect to interact with the API) rather than by how the backend system is structured.

For example, consumers may need to verify an address of an individual, but may not have authority to search addresses. Rather than simply providing a secure search through records, an API could have an endpoint that takes in an address and name and returns a simple valid/invalid response.

Enforced Loose Coupling

Loose coupling of systems is not achieved simply because we deploy APIs. Designing the API contract first based on the needs of API consumers, it forces the business logic within the API to decouple the interface from the backend system. Separating the design of the contract from the business logic removes any opportunity to accidentally insert tightly coupled elements (e.g., raw or relational data structures, stateful interactions).

For example, by keeping customer and order systems loosely coupled, looking up an order status should not require pulling customer details or billing information. In this case, order status requests can remain quick since they isolate the necessary data and are more secure because they won’t accidentally allow access to sensitive information.

Parallel Development

APIs and consuming systems are developed and iterated on in parallel. The coordination of change between multiple technical teams can become extremely complex. The establishment of a firm contract with strict change control rules is the only practical means of enabling parallel development. The API contract serves as a common point of consistency between teams. Defining an API contract first allows mechanisms like API mocks and virtualized services to be deployed, which then allows development and testing of consuming systems to occur without the actual API being available.

This aspect is especially beneficial when working on multiple integrations simultaneously. For instance, developing in parallel while integrating with multiple payment processor options ensures that the proper information is being captured and communicated so that all processor requirements can be met.

Early Identification of Design Gaps

Many systems are not originally designed to be integrated with easily. While an API may be easily exposed, the ability to consistently map and index data by external systems may be lacking. Project teams often take for granted that their interactions are the de-facto standard for approaching a subject, and might overlook the need for other formats that are necessary for other consumers.

For example, a personnel directory that does not employ a GUID or UID for each record can be accessed in a read-only fashion, but there is actually no reliable way to update a record via an API as there is no consistent way to uniquely identify a given person. Starting with the contract will ensure that these system gaps and limitations are identified during the design phase. Generating the contract from code often results in these limitations being discovered during testing and deployment instead, which becomes significantly more difficult and costly to address.

What’s Challenging About Contract First?

The various benefits of Contract First API Development come with some overhead and trade-offs. At the very least, it is more time consuming and requires more discipline than a Code First approach. While these challenges should be addressed, they are manageable and should not be used as reasons to avoid Contract First API Development. Addressing these challenges help teams become more mature in delivering modern software in a scalable and agile fashion and are not unique to just API development.

Defining the Schema

Defining the contract typically requires defining the data schema from scratch. While Code First generates the schema from the various object and entity models within the API business logic, Contract First is effectively a blank page. Organizations adopting Contract First should invest in training and skills development on the topic of designing data and interface schemas.

Producing a schema definition requires deep domain knowledge and an understanding of business requirements. Rather than seeing this process as an obstacle, approach it as an opportunity to engage business and development simultaneously to ensure that everyone is working towards the same outcomes. These practices will help ensure that true value is the result of a project.

Increased Code Complexity

Loose coupling means the API code has to do more heavy lifting in terms of data mapping, translation, and transformation. A contract that is not a direct one-to-one representation of the backend data structure means that simply there will be more code to be written within the API, which increases the effort and time to develop.

In order to manage code complexity, it is important to make use of tools and practices such as continuous integration and continuous deployment (CI/CD) for both automated and acceptance testing, as well as code reviews and peer programming to achieve high-quality code. The rise of these practices in modern software development are directly related to creating more robust and skilled development teams.

Version Management is Mandatory

A contract is only useful if changes are strictly controlled. The API development team should implement proper versioning of the API contract and any changes to the contract be clearly communicated to the various consuming systems’ teams. Version control and communication processes should be established and agreed to between API development and consumer teams.

Version management is essential in either Contract First or Code First solutions. Failure to allow for versioning in Code First solutions often results in increased complexity over time or accidental broken contracts. Working Contract First puts version management at the forefront of continuous improvement and ensures long-term success for an API.

Repeatable and Automated Tests

Testing is critical when teams are building system components in parallel. Tests are used to establish functional and performance baselines and should be used as a proof of consistency against the API contract. Contracts alone cannot completely represent the full functionality of a given API as it doesn’t describe business logic or things like data validation scenarios. Repeatable tests should be written up front which provide robust enough coverage of the functional scope of the API to give API consumers a high level of confidence that the API is functioning as expected. These tests should then be automated and executed on every release of API code. Ideally, these test scenarios would also be used to generate API mocks/stubs which return dynamic responses so that testing of consuming systems can happen even before the API development is complete.

When used in conjunction with CI/CD pipelines, automated tests become the first line of validation for new code. Contract First development allows developers to catch problems in their execution before it goes to others, ends up in acceptance testing, or even potentially production. These tools empower developers to solve problems early, before they have a chance to impact the project. Automating tests also results in test scenarios becoming reusable and sharable digital assets (e.g., unit tests, test scripts, test data) which can be published. This allows API consumers and providers to both test against a consistent baseline as an ongoing check-and-balance as changes are deployed.

When Not to Use Contract First?

As with all technology concepts, Contract First is not a universal silver bullet to developing APIs. There are some scenarios where the value of Contract First is not justified by the additional overhead or when it is simply not possible.

Internal Utility APIs

APIs are not just used to expose functionality to external systems. APIs are often used to simply decouple code components inside a system to provide flexibility in terms of scalability or future extensibility. When an API is simply used as an internal abstraction and where both the API code and the code of any consuming components are managed by the same team or even developer, Code First may be more appropriate to deliver functionality more quickly.

Before designating an API “internal use only”, proper analysis should be used to make the determination. It is recommended that adjacent business groups be consulted to make sure that they do not or will not have a need to have access to the API. What is considered only internal today might be shared tomorrow.

Data Science or Analytics

APIs exposing statistical or large data sets for data science or analytics applications are very different from business APIs. These types of APIs need to offer maximum flexibility and performance and should not interfere with the representation of data. The typical concepts of defining API contracts don’t really apply here. Geospatial data also falls into this category.

SaaS and COTS Limitations

The definition of API contracts may simply not be possible when working with SaaS and COTS. Vendor software often come with out-of-box or generated APIs and there is very little scope or opportunity to configure or customize them. If the vendor provided APIs are either too loosely defined or can change frequently due to small changes in SaaS/COTS configuration, it is good practice to consider placing a business API proxy in front of these APIs where a more stable contract can be defined and translated to the vendor provided APIs. When constructing these API proxies, it is best practice to work Contract First since it ensures the effort will provide a solid contract on the outside of these solutions.

Page details

Date modified: