Crafting Superior APIs with Design Guidelines: Set Up For Success

Crafting Superior APIs with Design Guidelines: Set Up For Success

Create better APIs by utilizing an API design guideline. Ideas on how to write an API design guideline to help you create and maintain a good API.

Building APIs – especially public-facing ones – is hard. There are a lot of decisions to be made, starting with the API concept (GraphQL, REST, etc.) to be used, infrastructure, and much more. But having this is just the foundation of your API, and you have to build a good API on top of it (whatever "good" means in your case). This is where an API design guideline can come into play.

This article is the first in a series of GraphQL-related articles. We will start with the importance of an API design guideline and how it could help you and your team to write a good API. It also should provide ideas on what to include in such a guideline.

This article won't cover the initially touched fundamental decisions (like REST vs. GraphQL) or the infrastructure it is running on. I'll proceed with GraphQL as an example because that is what we have chosen for our main API. This article is neither about implementations. It is about concepts and ideas.

API Design Guideline and Why It Is Important

What Is An API Design Guideline?

First of all, what is "API design"? API design refers to the process of creating the interface that allows different software applications to communicate and exchange data with each other. Good API design can involve creating a well-structured, intuitive, and easy-to-use interface that meets the needs of its users while also being scalable, secure, and reliable. Again, how you define a "good" API design is depending on your needs.

💡
A good API design is depending on your own needs.

What about the term "guidelines"? Guidelines in general provide a set of best practices, conventions, and recommendations.

Bringing those definitions together: An API design guideline is a set of best practices, conventions, and recommendations for creating the interface that allows different software applications to communicate and exchange data with each other. These guidelines aim to promote good API design practices, ensure consistency, and improve the quality of the API.

GraphQL API Design Guideline On a High Level

Before diving into technicalities in your guideline, make sure to define the goals and non-goals of the guideline and how or by whom it will be updated. This helps to evolve the guideline and keep it focused. Speaking of keeping it focused: Make sure to get to the point and don't write lengthy documents. People won't read it or find the desired content otherwise.

You don't have to reinvent an API design guideline from scratch. You can stand on the shoulder of giants and get inspiration from other popular APIs (Shopify, GitHub) etc. There are even design guidelines or tutorials out there like Shopify GraqhQL Design Tutorial.

💡
Stand on the shoulders of giants.

Make sure to include examples. Examples are easier to understand if you provide "dos" and "don'ts" – and highlight them accordingly. This is what an example could look like (from our naming conventions section):

type Publication {
  # ...
    # We have a field called metaHTML in the database
    # but it has no meaning to consumers
  metaHTML: String
}

✅
type Publication {
  # ...
  descriptionSEO: String
}

❌
type Address {
  # How could the country look like? "GER", "Germany", "🇩🇪"? 🤔
  country: String!
}

(✅)
type Address {
  # Even this could mean ISO alpha-2 or alpha-3,
  # but this could be clarified in a description.
  countryCode: String!
}

A few additional ideas that might improve your guideline document:

  • use toggles to hide some secondary content

  • provide resources; where is the idea coming from?

  • a short intro for a section on why it is important

  • use examples from your domain

  • KISS (Keep It Short Simple) – nobody will read a book about your API

  • highlight important keywords

🤔
Any important things that you would add?

Impressions From Our Guideline

In this section, I will share a few impressions of our current GraphQL API design guideline. Maybe we will make it public at some point if we think it is good enough.

Please note that our current public GraphQL API has been created before having those guidelines. The guidelines were (and are) used for our new, internal API that we will release to the public at some point.

First of all, this is the table of contents of the current version of our GraphQL API design guide (yes, we use Notion 😜):

I won't go into detail here but here are some things that our guideline includes. I'll copy some pieces, rephrase others, or provide ideas on what the section could include. Copied parts are shown as a quote.

General Naming Convention

😵‍💫
“There are only two hard things in Computer Science: cache invalidation and naming things.”

Naming is a hard task. When a thing is named and being consumed by a client, there is almost no going back without a breaking change. To avoid this, try to be specific and avoid abstract names.

Instead:

  • Choose field names based on what makes sense

  • Don’t be influenced by legacy APIs or what the field is called in the database (DB Schema ≠ GQL Schema)

  • Choose self-documenting names

    Resources

    Designing a scalable GraphQl schema

Note: Here we are providing the examples that I provided in the previous section.

Node Interface

Types that represent entities that have a lifetime (and are usually stored in their own database table) should implement the Node interface.

Example:

interface Node {
  id: ID!
}

type Post implements Node {
  id: ID!
  # ...
}

Booleans

Booleans are almost always non-nullable. Only make them optional if there is actual meaning in being null as opposed to false.

If there are more states than two, consider using an enum instead.

Custom Scalars

When should you create custom scalars? Unnecessarily introducing custom scalars can make your live harder evolving the API because you'll more likely introduce breaking changes.

How should they be named? We use PascalCase.

Not use custom scalars for validation, e.g. first_Int_NotNull_min_1_max_20.

Queries – Single Entities

  • use the singular entity name, e.g. post (don’t use HTTP verbs like in getPost)

  • if multiple unique filters are required (e.g. by id and slug) use a single query with inputs optional and throw an error if either no arguments or multiple provided

  • use an optional return value to denote a “not found” rather than returning an error; only if not finding something really is an error it should be modeled as such (see me in examples)

Queries – Multiple Entities

This section should answer questions such as:

  • How to name a query returning multiple entities?

  • How to deal with pagination? When should pagination be added?

  • How to deal with Filtering and Sorting?

Mutations

This is another bigger section in our document and I'll just provide some ideas:

  • Naming convention: e.g. publishPost vs. postPublish

  • We don't follow CRUD (Create, Read, Update, Delete), e.g. createPost, updatePost etc. We use more business-specific names and more fine-granular mutations.

  • How to name arguments and outputs?

  • What should you return? (Most often the whole entity, but that might not be the case for every mutation)

Reading Recommendations

These are the reading recommendations that we have listed in our guideline:

Docs, Blog Posts, etc.

Example Implementations

YouTube

Conclusion

In my opinion, an API design guideline is essential for a team with more than a few people to create and evolve an API that feels consistent, is easy to use, and maintainable.

Hopefully, this article gave you an idea of why an API design guideline is helpful and provided some ideas about what to include and how to write it.

Is there anything that you think is a must in an API guideline?