Spectral has a built-in "oas" ruleset, with OAS being shorthand for the OpenAPI Specification.
In your ruleset file you can add extends: "spectral:oas"
and you'll get all of the following rules applied, depending on the appropriate OpenAPI version used (detected through formats).
These rules apply to both OpenAPI v2 and v3.
Operation must have at least one 2xx
or 3xx
response. Any API operation (endpoint) can fail, but presumably it is also meant to do something constructive at some point. If you forget to write out a success case for this API, then this rule will let you know.
Recommended: Yes
Bad Example
paths:
/path:
get:
responses:
418:
description: teapot
Every operation must have a unique operationId
.
Why? A lot of documentation systems use this as an identifier, some SDK generators convert them to a method name, all sorts of things like that.
Recommended: Yes
Bad Example
paths:
/pet:
patch:
operationId: "update-pet"
responses:
200:
description: ok
put:
operationId: "update-pet"
responses:
200:
description: ok
Good Example
paths:
/pet:
patch:
operationId: "update-pet"
responses:
200:
description: ok
put:
operationId: "replace-pet"
responses:
200:
description: ok
Operation parameters are unique and non-repeating.
- Operations must have unique
name
+in
parameters. - Operation cannot have both
in: body
andin: formData
parameters. (OpenAPI v2.0) - Operation must have only one
in: body
parameter. (OpenAPI v2.0)
Recommended: Yes
Path parameters are correct and valid.
-
For every parameters referenced in the path string (i.e:
/users/{userId}
), the parameter must be defined in eitherpath.parameters
, oroperation.parameters
objects (Non standard HTTP operations will be silently ignored.) -
every
path.parameters
andoperation.parameters
parameter must be used in the path string.
Recommended: Yes
The info-contact rule will ask you to put in a contact object, and this rule will make sure it's full of the most useful properties: name
, url
and email
.
Putting in the name of the developer/team/department/company responsible for the API, along with the support email and help-desk/GitHub Issues/whatever URL means people know where to go for help. This can mean more money in the bank, instead of developers just wandering off or complaining online.
Recommended: No
Good Example
openapi: "3.0.2"
info:
title: Awesome API
description: A very well defined API
version: "1.0"
contact:
name: A-Team
email: a-team@goarmy.com
url: goarmy.com/apis/support
Info object should contain contact
object.
Hopefully your API description document is so good that nobody ever needs to contact you with questions, but that is rarely the case. The contact object has a few different options for contact details.
Recommended: Yes
Good Example
openapi: "3.0.2"
info:
title: Awesome API
version: "1.0"
contact:
name: A-Team
email: a-team@goarmy.com
OpenAPI object info description
must be present and non-empty string.
Examples can contain Markdown so you can really go to town with them, implementing getting started information like where to find authentication keys, and how to use them.
Recommended: Yes
Good Example
openapi: 3.0.0
info:
version: "1.0.0"
title: Descriptive API
description: >+
Some description about the general point of this API, and why it exists when another similar but different API also exists.## AuthenticationThis API uses OAuth2 and tokens can be requested from [Dev Portal: Tokens](https://example.org/developers/tokens).
The info
object should have a license
key.
It can be hard to pick a license, so if you don't have a lawyer around you can use TLDRLegal and Choose a License to help give you an idea.
How useful this is in court is not entirely known, but having a license is better than not having a license.
Recommended: Yes
Good Example
openapi: "3.0.2"
info:
license:
name: MIT
Mentioning a license is only useful if people know what the license means, so add a link to the full text for those who need it.
Recommended: Yes
Good Example
openapi: "3.0.2"
info:
license:
name: MIT
url: https://www.tldrlegal.com/l/mit
An object exposing a $ref
property cannot be further extended with additional properties.
Recommended: Yes
Bad Example
TheBadModel:
$ref: "#/components/TheBadModelProperties"
examples: # <= This property will be ignored
an_example:
name: something
This rule protects against an edge case, for anyone bringing in description documents from third parties and using the parsed content rendered in HTML/JS. If one of those third parties does something shady like inject eval()
JavaScript statements, it could lead to an XSS attack.
Recommended: Yes
Bad Example
openapi: "3.0.2"
info:
title: 'some title with eval(',
This rule protects against a potential hack, for anyone bringing in description documents from third parties then generating HTML documentation. If one of those third parties does something shady like inject <script>
tags, they could easily execute arbitrary code on your domain, which if it's the same as your main application could be all sorts of terrible.
Recommended: Yes
Bad Example
openapi: "3.0.2"
info:
title: 'some title with <script>alert("You are Hacked");</script>',
OpenAPI object should have alphabetical tags
. This will be sorted by the name
property.
Recommended: No
Bad Example
tags:
- name: "Badger"
- name: "Aardvark"
Good Example
tags:
- name: "Aardvark"
- name: "Badger"
OpenAPI object must not have duplicated tag names (identifiers).
Recommended: Yes
Bad Example
tags:
- name: "Badger"
- name: "Badger"
Good Example
tags:
- name: "Aardvark"
- name: "Badger"
OpenAPI object should have non-empty tags
array.
Why? Well, you can reference tags arbitrarily in operations, and definition is optional...
/invoices/{id}/items:
get:
tags:
- Invoice Items
Defining tags allows you to add more information like a description
. For more information see tag-description.
Recommended: No
Recommended: Yes
This operation ID is essentially a reference for the operation, which can be used to visually suggest a connection to other operations. This is like some theoretical static HATEOAS-style referencing, but it's also used for the URL in some documentation systems.
Make the value lower-hyphen-case
, and try and think of a name for the action which does not relate to the HTTP message. Base it off the actual action being performed. create-polygon
? search-by-polygon
? filter-companies
?
Recommended: Yes
Seeing as operationId is often used for unique URLs in documentation systems, it's a good idea to avoid non-URL safe characters.
Recommended: Yes
Bad Example
paths:
/pets:
get:
operationId: get cats
Use just one tag for an operation, which is helpful for some documentation systems which use tags to avoid duplicate content.
Recommended: No
Operation should have non-empty tags
array.
Recommended: Yes
Operation tags should be defined in global tags.
Recommended: Yes
Path parameter declarations cannot be empty, ex./given/{}
is invalid.
Recommended: Yes
Keep trailing slashes off of paths, as it can cause some confusion. Some web tooling (like mock servers, real servers, code generators, application frameworks, etc.) will treat example.com/foo
and example.com/foo/
as the same thing, but other tooling will not. Avoid any confusion by just documenting them without the slash, and maybe some tooling will let people shove a / on there when they're using it or maybe not, but at least the docs are suggesting how it should be done properly.
Recommended: Yes
Don't put query string items in the path, they belong in parameters with in: query
.
Recommended: Yes
Tags alone are not very descriptive. Give folks a bit more information to work with.
tags:
- name: "Aardvark"
description: Funny nosed pig-head racoon.
- name: "Badger"
description: Angry short-legged omnivores.
If your tags are business objects then you can use the term to explain them a bit. An 'Account' could be a user account, company information, bank account, potential sales lead, anything. What is clear to the folks writing the document is probably not as clear to others.
tags:
- name: Invoice Items
description: |+
Giant long explanation about what this business concept is, because other people _might_ not have a clue!
Recommended: No
Enum values should respect the type
specifier.
Recommended: Yes
Good Example
TheGoodModel:
type: object
properties:
number_of_connectors:
type: integer
description: The number of extension points.
enum:
- 1
- 2
- 4
- 8
Bad Example
TheBadModel:
type: object
properties:
number_of_connectors:
type: integer
description: The number of extension points.
enum:
- 1
- 2
- "a string!"
- 8
Each value of an enum
must be different from one another.
Recommended: Yes
Good Example
TheGoodModel:
type: object
properties:
number_of_connectors:
type: integer
description: The number of extension points.
enum:
- 1
- 2
- 4
- 8
Bad Example
TheBadModel:
type: object
properties:
number_of_connectors:
type: integer
description: The number of extension points.
enum:
- 1
- 2
- 3
- 2
These rules will only apply to OpenAPI v2.0 documents.
Operations with an in: formData
parameter must include application/x-www-form-urlencoded
or multipart/form-data
in their consumes
property.
Recommended: Yes
OpenAPI host
must be present and non-empty string.
Recommended: Yes
OpenAPI host schemes
must be present and non-empty array.
Recommended: Yes
The discriminator property MUST be defined at this schema and it MUST be in the required property list.
Recommended: Yes
Server URL should not point at example.com.
Recommended: No
Server URL should not have a trailing slash.
Recommended: Yes
Operation security
values must match a scheme defined in the securityDefinitions
object.
Ignores empty security
values for cases where authentication is explicitly not required or optional.
Recommended: Yes
Potential unused reusable definition
entry has been detected.
Warning: This rule may identify false positives when linting a specification that acts as a library (a container storing reusable objects, leveraged by other specifications that reference those objects).
Recommended: Yes
Examples must be valid against their defined schema.
Recommended: Yes
OpenAPI v3 keyword anyOf
detected in OpenAPI v2 document.
Recommended: Yes
OpenAPI v3 keyword oneOf
detected in OpenAPI v2 document.
Recommended: Yes
Validate structure of OpenAPI v2 specification.
Recommended: Yes
Parameter objects should have a description
.
Recommended: No
These rules will only be applied to OpenAPI v3.0 documents.
OpenAPI servers
must be present and non-empty array.
Recommended: Yes
Share links to any and all servers that people might care about. If this is going to be given to internal people then usually that is localhost (so they know the right port number), staging, and production.
servers:
- url: https://example.com/api
description: Production server
- url: https://staging.example.com/api
description: Staging server
- url: http://localhost:3001
description: Development server
If this is going out to the world, maybe have production and a general sandbox people can play with.
Examples for requestBody
or response examples can have an externalValue
or a value
, but they cannot have both.
Recommended: Yes
Bad Example
paths:
/pet:
put:
operationId: "replace-pet"
requestBody:
content:
"application/json":
examples:
foo:
summary: A foo example
value: { "foo": "bar" }
externalValue: "http://example.org/foo.json"
# marp! no, can only have one or the other
Operation security
values must match a scheme defined in the components.securitySchemes
object.
Recommended: Yes
Server URL should not point at example.com.
Recommended: No
Bad Example
servers:
- url: https://example.com/api
description: Production server
- url: https://staging.example.com/api
description: Staging server
- url: http://localhost:3001
description: Development server
We have example.com for documentation purposes here, but you should put in actual domains.
Server URL should not have a trailing slash.
Some tooling forgets to strip trailing slashes off when it's joining the servers.url
with paths
, and you can get awkward URLs like https://example.com/api//pets
. Best to just strip them off yourself.
Recommended: Yes
Good Example
servers:
- url: https://example.com
- url: https://example.com/api
Bad Example
servers:
- url: https://example.com/
- url: https://example.com/api/
Potential unused reusable components
entry has been detected.
Warning: This rule may identify false positives when linting a specification that acts as a library (a container storing reusable objects, leveraged by other specifications that reference those objects).
Recommended: Yes
Examples must be valid against their defined schema.
Recommended: Yes
Validate structure of OpenAPI v3 specification.
Recommended: Yes
Parameter objects should have a description
.
Recommended: No