Ask 100 developers where a semicolon should go, and you’ll either get 100 answers, or a all-on-all fist fight. To save this from happening at work, most folks implement a style guide, which beyond helping with consistent style to avoid new developers getting shouted at for “doing it wrong”. Linters can advise best practices, shout about things which are technically allowed but likely to cause trouble, and shape the API of code as it’s being written (snake_case that method!) This is always done for code, and is becoming increasingly popular for API descriptions.
When it comes to API descriptions, most companies of a certain size end up with a “Style Guide”, “Style Book”, “Design Guide”, etc. These are often on a Google Doc, wiki, or some other sort of docs/content management system. I’ve seen loads of these, and written plenty. Many companies even publish them.
🔗 Text-based Style Guides are a Time Suck
The trouble with these text-based documents is that they are large, terse, unexciting documents, which developers rarely read. If developers do read them cover to cover, and remember everything in there, that knowledge becomes partially out of date when new rules are added because they won’t know about them until they re-read everything cover to cover again.
At API the Docs I saw a talk from Kelsey Lambert at Salesforce, and their style guide is an example OpenAPI description document which they ask people to check now and then when they are working on something to get ideas of the sorts of things they should use. Salesforce… The giant company with 238479347 APIs who maintain 40 major versions per API, their style guide enforcement approach is eyeballing and memory. Agh I feel for you folks! I have been here and it was bad.
No developers can be blamed for any of this mess. API developers are busy, and the folks writing style guides are just trying to figure it out as they go along. This mess is an industry problem, but thankfully tools have popped up which can enforce these same style guide concepts through automation.
- api-linter by Google
- graphql-doctor by Cap Collectif
- graphql-schema-linter by Christian Joudrey
- Spectral by Stoplight
Each one of these projects sets out to do relatively similar things, but for different types of API.
🔗 Spectral for HTTP APIs
Spectral is a JSON/YAML data linter, with built in rules for OpenAPI v2/v3 and JSON Schema.
Running the default OpenAPI ruleset on the average document will find plenty of suggestions, which can be helpful for developers not entirely familiar with OpenAPI. Something as small as reminding people to add parameter-descriptions can help make human-readable docs more useful, and they might not have even realized that was possible.
You can use Spectral to create rulesets, and these rulesets can have custom rules, and even custom functions!
These custom rules can look a bit like this:
This one is a popular one. OpenAPI does not care how you capitalize your models, but a lot of code generators will use the model names for code, and having inconsistent class names will upset people.
Let’s take it a step further:
This rule is actually looking beyond the metadata of your API descriptions, and is looking at the actual API design itself. This is saying that the “paths” (endpoints) must be hyphenated, so /recent-files is good but /recent_files is not ok.
You can start to get really creative with this.
I don’t know why but at some point during the lifecycle of any given API, some developer will suggest adding an X-Foo header, despite over a decade of it causing issues. Well, we can keep them outta here with this rule.
Done early enough, this will shape the actual API as it is being developed. If you are doing code first then ok, you have to go back and change a bunch of code. Hopefully you didn’t ship it, because now you need to go and make a bunch of redirects for /recent_files /recent_files. If you use an API design first workflow, then you notice this early on when you’ve just got some YAML, and your API gets built right in the first place.
Seeing as Spectral is a CLI/JS tool, enforcing this style guide can be done in all sorts of ways.
If you’re using Stoplight Studio then it’s baked right into the editor, so people designing APIs just do it all correctly straight away. No need to alt tab away to the CLI or wait until a PR is made.
I am trying to find time to take a style guides from Heroku or PayPal and turn them into a huge example ruleset. At the very least, I can take some inspiration for a new ruleset I’m putting together: The OpenAPI Contrib > Style Guide. This should be an interesting community effort.
🔗 GraphQL Doctor & Schema Linter
GraphQL has it’s own built-in type system, which has some of the same sort of keywords as OpenAPI / JSON Schema based stuff.
GraphQL makes some design decisions easier, like how you handle relationships. No need to pick between nesting/embedding related resources, inlining everything with a compound documents, or using hyperlinks to link to related data, GraphQL decides that for you. Still, there is a lot of inconsistency that can occur outside of the default decisions GraphQL makes. GraphQL people do not escape the need to lint, but luckily a great linter exists: GraphQL Schema Linter.
Custom rules can be written for this one too, so you can automate your style guide in CI. No bot or GitHub Action that I can see, but they aren’t too tough to knock together.
One schema tool in GraphQL land with a great bot is GraphQL Doctor. It seems like it wants to help with a lot more linting in general, but so far it is focused on detecting breaking changes. Like any type system, there is a fine line between careful evolution and recklessly changing stuff, and GraphQL Doctor will spot the latter.
It would be nice to see the two tools merge, or maybe the GraphQL Doctor bot can bake in support for GraphQL Schema Linter, but for now it’s a two-stop shop.
🔗 Google’s “API Linter”
Google is doing some pretty interesting work in the API space. They were one of the first big players in the API space consistently explaining “Sometimes you want REST, sometimes you want RPC”, and they’re keeping at it with a general tool that works for gRPC and HTTP-in-general too. API linter operates on the protobuf surface layer, but can be set up to work with HTTP endpoints:
When using protocol buffers, each RPC must define the HTTP method and path using the google.api.http annotation:
The core ruleset for API Linter is rather impressive, and focuses a lot on awkward bits in the HTTP specification which are a bit unclear. Like, should GET have a body? The answer is a very squishy kinda maybe it can, but probably don’t, depends on the tool you are building, ugh. Help.
Google decided to just answer that with: nope.
They also decided to persuade teams upgrade from proto2 to proto3.
🔗 Rule Ideas
You can automate pretty much anything with this stuff, and I’ve been thinking a lot of rules that go beyond the common use cases of enforcing naming or pluralization.
- Ban HTTP Basic entirely
- Make sure every endpoint has some sort of security (OAuth 2, API Key, but not both)
- Every response should support application/vnd.api+json (JSON:API) not just plain-old JSON
- ID’s as integers let people crawl your API incredibly easily, switch to UUID
- Your 20X response seems to have errors in it, why do you hate your consumers
- There are no URLs in your errors, how can anyone find out more information about what went wrong
- Error format should be RFC 7807
- Keep version numbers out of the URL
- Version numbers in headers please
- Ban all versioning and demand evolution (prepare for battle)
Many of these rules are HTTP API specific but you get the idea. Over time I’ll be working on some of these and adding them to OpenAPI Contrib’s Style Guide, and if you’d like to contribute I’ll be happy to guide you through the process over on GitHub.
If you’ve heard the term API Governance, this is pretty much what most people are talking about. Currently a lot of the people trying to do governance are eyeballing API descriptions on every single PR, and training people to memorize all the quality rules they’ve come up with.
Manual API training is a thankless, inefficient, never-ending task, and it can be replaced (or drastically streamlined) with a linter baked into an editor, git hook, CI pipeline, GitHub Action, or a bot.
Don’t waste customers time forcing them to try and figure out your inconsistencies. Don’t waste all API developers time learning to memorizing style guides. Don’t waste the API governance teams time reviewing APIs manually. Don’t waste everyone’s time fixing inconsistencies in production later.