Rulesets

Speccy ships with two rulesets, default and strict. These rulesets can be invoked with `--rules=`, and of course `default` is used by default. You can also create your own custom rulesets.

Remember, linting is more than validaiton, so these rules will do more than simply make sure your files are valid. They'll make your specs better than valid, they'll make them useful.

Default

$ speccy lint openapi.yaml --rules=default
Name OpenAPI Object Description
parameter-description parameter parameter objects should have a description

Descriptions help human beings understand what sort of value a property should have, beyond the obvious type and format. If the field is distance and the format is float, you can tell the reader if that field is meant to be kilometers, meters, feet, inches, miles, or yards. Same goes for currency, is this Pounds Sterling or Yen?

operation-operationId operation operation should have an operationId

Each operation should have an operationId, which is helpful for referencing the operation later.

Some documentation systems will use it for the URL, meaning folks are going to share links to that operation. If you add an operationId later, it’ll break that URL, so best to create one as early as possible. operationIds are also often used by code-generation tools to name route-handling functions.

operation-summary-or-description operation operation should have summary or description

A summary (short) or description (longer) help humans understand what this operation is meant to be doing. Without explaining it for a human, they have to guess, and guessing leads to unexpected outcomes.

operation-tags operation operation should have non-empty tags array

Documentation systems use tags for grouping navigation, which is especially useful for larger APIs. Tags can be defined in the top level tags object, and the operations tags array is simply a list of tag names.

openapi: 3.0.1

tags:
  - name: Pokèmon

paths:
  /pokemons:
    get:
      operationId: get-pokemons
      tags:
        - Pokèmon
server-trailing-slash server server url should not have a trailing slash

The url in the server object should not have a trailing slash, because that / is actually the first character of the path. Having it in both places will confuse some vendor tooling and you might see // showing up in the full URL.

Good

servers:
  - url: https://example.org/api

Bad

servers:
  - url: https://example.org/api/
path-keys-no-trailing-slash paths paths should not end with a slash

A keys in the paths objects should not have a trailing slash, because / is actually the first character of the path. Having it in both places will confuse some vendor tooling and you might see // showing up in the full URL.

Good

paths:
  /pokemons/{pokemon_id}

Bad

paths:
  /pokemons/{pokemon_id}/
openapi-tags openapi openapi object should have non-empty tags array

Documentation systems use tags for grouping navigation, which is especially useful for larger APIs. Although tags can be defined on the fly in operations without defining them, a top-level tags object allows you to control both the order tags are displayed in many tools and their descriptions.

Find all of the tags used in various operations, and define them in the top-level tags object.

openapi: 3.0.1

tags:
  - name: Gym
  - name: Pokèmon

paths:
  /pokemons:
    get:
      operationId: get-pokemons
      tags:
        - Pokèmon
  /gyms:
    get:
      operationId: get-gyms
      tags:
        - Gym
openapi-tags-alphabetical openapi openapi object should have alphabetical tags

Seeing as some tools render tags in the order they’re defined, it’s just a Good Idea™ to define them in alphabetical order.

reference-no-other-properties reference reference objects should only have a $ref property

You should avoid having other keywords sat next to a $ref, as the OpenAPI spec instructs tools to ignore any siblings. Due to that, putting things there is not only going against the spec, but it’s pointless, and potentially confusing to people reading the files. It may also trigger errors in some validators.

example-value-or-externalValue example example should have either value or externalValue

The value and externalValue keywords are mutually exclusive, but both optional. An example is of little use without one or the other!

no-script-tags-in-markdown everything markdown descriptions should not contain script tags

Putting script tags in markdown descriptions is a recipe for disaster, as it might try to run arbitrary JavaScript on documentation views, or who knows what else.

If the specs come from an untrusted source, this would be considered a security concern.

info-contact info info object should contain contact object

Users of your API should be able to contact you, so put your contact information in the info object.

openapi: 3.0.1
info:
  contact:
  name: API Support
  url: http://www.example.com/support
  email: [email protected]
license-apimatic-bug license license url should not point at gruntjs

There was a funny little bug with the Apimatic Transformer a while back where all transformed OpenAPI specifications would have the license set to MIT with a URL to the license file in the gruntjs repository.

This was fixed, but if you have that floating around in your spec you probably want to point that somewhere else.

Good

info:
  license:
    url: https://opensource.org/licenses/MIT

Bad

info:
  license:
    url: http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
no-eval-in-descriptions everything markdown descriptions should not contain 'eval('

Letting specification authors eval random code is probably a Bad Idea™.

Strict

$ speccy lint openapi.yaml --rules=strict
Name OpenAPI Object Description
contact-properties contact contact object should have name, url and email

To make contact info the most useful, all of the options should be used. Including a URL and an email address means the user has the most options to be able to get in touch, maybe including a URL to your slack channel, or to a support portal, and the email could be a team/company address to avoid having a single human as a bottleneck.

license-url license license object should include url

Having a license is generally a helpful idea, it lets potential users know how they are allowed to leverage your API. Pick one from this great list, anywhere else, or make your own and link to it.

server-not-example.com server server url should not point at example.com

You can do better than example.com! Set up at least a mock server, maybe even a sandbox, or an actual implementation for users to play with.

tag-description tag tag object should have a description

Adding descriptions to tags is a great way to explain business logic for the concept.

Often specifications will explain that there is a POST /foos and that creates a foo, and there is a GET /foos which gets a bunch of foos, but nobody really explains what a Foo is at any point.

openapi: 3.0.1
tags:
    - name: Foo
      description: |
        Multiple lines of text explain all about the concept of a foo in this system, how
        they might related to other items, what sort of stage in the workflow are they
        created, etc.

        You can even put *markdown* in here!

You can also create your own rulesets with a simple `.json` file.