Spectral has a built-in “asyncapi” ruleset for the AsyncAPI Specification.
In your ruleset file you can add extends: "spectral:asyncapi" and you’ll get all of the following rules applied.
Recommended indicates whether a rule is enabled by default. Default severity when enabled is the severity the rule reports when active.
For simplicity, the rules are split up into v2 and v3 compliant rules to make it easier to know which apply when.
AsyncAPI v2 and v3
The following rules apply to both AsyncAPI v2 and v3 documents.
asyncapi-channel-parameters
All channel parameters should be defined in the parameters object of the channel. They should also not contain redundant parameters that do not exist in the channel address.
Recommended: Yes
Default severity when enabled: error
asyncapi-info-contact-properties
The asyncapi-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: Yes
Default severity when enabled: warn
Good Example
asyncapi: "2.0.0"info: title: Awesome API description: A very well-defined API version: "1.0" contact: name: A-Team email: a-team@goarmy.com url: https://goarmy.com/apis/supportasyncapi-info-contact
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
Default severity when enabled: warn
Good Example
asyncapi: "2.0.0"info: title: Awesome API version: "1.0" contact: name: A-Team email: a-team@goarmy.comasyncapi-info-description
AsyncAPI 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
Default severity when enabled: warn
Good Example
asyncapi: "2.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.asyncapi-info-license-url
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: No
Default severity when enabled: warn
Good Example
asyncapi: "2.0.0"info: license: name: MIT url: https://www.tldrlegal.com/l/mitasyncapi-info-license
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
Default severity when enabled: warn
Good Example
asyncapi: "2.0.0"info: license: name: MITasyncapi-latest-version
Checking if the AsyncAPI document is using the latest version.
Recommended: Yes
Default severity when enabled: info
asyncapi-parameter-description
Parameter objects should have a description.
Recommended: No
Default severity when enabled: warn
asyncapi-servers
A non-empty servers object is expected to be located at the root of the document.
Recommended: Yes
Default severity when enabled: warn
asyncapi-unused-components-schema
Potential unused reusable schema 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
Default severity when enabled: warn
asyncapi-unused-components-server
Potential unused reusable server 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
Default severity when enabled: warn
AsyncAPI v2
The following rules ONLY apply to AsyncAPI v2 documents.
asyncapi-schema
Validate structure of AsyncAPI specification.
Recommended: Yes
Default severity when enabled: error
asyncapi-server-security
Server security values must match a scheme defined in the components.securitySchemes object. It also checks if there are oauth2 scopes that have been defined for the given security.
Recommended: Yes
Default severity when enabled: error
Good Example
asyncapi: 2.0.0servers: production: url: test.mosquitto.org security: - petstore_auth: []components: securitySchemes: petstore_auth: ...Bad Example
asyncapi: 2.0.0servers: production: url: test.mosquitto.org security: - not_defined: []components: securitySchemes: petstore_auth: ...asyncapi-channel-no-empty-parameter
Channel parameter declarations cannot be empty, ex./given/{} is invalid.
Recommended: Yes
Default severity when enabled: warn
asyncapi-channel-no-query-nor-fragment
Query parameters and fragments shouldn’t be used in channel names. Instead, use bindings to define them.
Recommended: Yes
Default severity when enabled: warn
asyncapi-channel-no-trailing-slash
Keep trailing slashes off of channel names, as it can cause some confusion. Most messaging protocols will treat example/foo and example/foo/ as different things. Keep in mind that tooling may replace slashes (/) with protocol-specific notation (e.g.: . for AMQP), therefore, a trailing slash may result in an invalid channel name in some protocols.
Recommended: Yes
Default severity when enabled: warn
asyncapi-channel-servers
Channel servers must be defined in the servers object.
Bad Example
asyncapi: "2.0.0"info: title: Awesome API description: A very well-defined API version: "1.0"servers: production: url: "stoplight.io" protocol: "https"channels: hello: servers: - developmentGood Example
asyncapi: "2.0.0"info: title: Awesome API description: A very well-defined API version: "1.0"servers: production: url: "stoplight.io" protocol: "https"channels: hello: servers: - productionRecommended: Yes
Default severity when enabled: error
asyncapi-headers-schema-type-object
The schema definition of the application headers must be of type “object”.
Recommended: Yes
Default severity when enabled: error
asyncapi-message-examples
All examples in message object should follow payload and headers schemas.
Bad Example
asyncapi: "2.0.0"info: title: Bad API version: "1.0.0"components: messages: someMessage: payload: type: string headers: type: object examples: - payload: 2137 headers: someHeaderGood Example
asyncapi: "2.0.0"info: title: Good API version: "1.0.0"components: messages: someMessage: payload: type: string headers: type: object examples: - payload: foobar headers: someHeader: someValueRecommended: Yes
Default severity when enabled: error
asyncapi-message-messageId-uniqueness
messageId must be unique across all the messages (except those one defined in the components).
Recommended: Yes
Default severity when enabled: error
Bad Example
channels: smartylighting.streetlights.1.0.action.{streetlightId}.turn.on: publish: message: messageId: turnMessage smartylighting.streetlights.1.0.action.{streetlightId}.turn.off: publish: message: messageId: turnMessageGood Example
channels: smartylighting.streetlights.1.0.action.{streetlightId}.turn.on: publish: message: messageId: turnOnMessage smartylighting.streetlights.1.0.action.{streetlightId}.turn.off: publish: message: messageId: turnOffMessageasyncapi-operation-description
Operation objects should have a description.
Recommended: Yes
Default severity when enabled: warn
asyncapi-operation-operationId-uniqueness
operationId must be unique across all the operations (except the ones defined in the components).
Recommended: Yes
Default severity when enabled: error
Bad Example
channels: smartylighting.streetlights.1.0.action.{streetlightId}.turn.on: publish: operationId: turn smartylighting.streetlights.1.0.action.{streetlightId}.turn.off: publish: operationId: turnGood Example
channels: smartylighting.streetlights.1.0.action.{streetlightId}.turn.on: publish: operationId: turnOn smartylighting.streetlights.1.0.action.{streetlightId}.turn.off: publish: operationId: turnOffasyncapi-operation-operationId
This operation ID is essentially a reference for the operation. Tools may use it for defining function names, class method names, and even URL hashes in documentation systems.
Recommended: Yes
Default severity when enabled: error
asyncapi-operation-security
Operation security values must match a scheme defined in the components.securitySchemes object. It also checks if there are oauth2 scopes that have been defined for the given security.
Recommended: Yes
Default severity when enabled: error
Good Example
channels: "user/signup": publish: security: - petstore_auth: []components: securitySchemes: petstore_auth: ...Bad Example
channels: "user/signup": publish: security: - not_defined: []components: securitySchemes: petstore_auth: ...asyncapi-payload-default
default objects should be valid against the payload they decorate.
Recommended: Yes
Default severity when enabled: error
Good Example
payload: type: object properties: value: type: integer required: - value default: value: 17Bad Example
payload: type: object properties: value: type: integer required: - value default: value: nope!asyncapi-payload-examples
Values of the examples array should be valid against the payload they decorate.
Recommended: Yes
Default severity when enabled: error
Good Example
payload: type: object properties: value: type: integer required: - value examples: - value: 13 - value: 17Bad Example
payload: type: object properties: value: type: integer required: - value examples: - value: nope! # Wrong type - notGoodEither: 17 # Missing required propertyasyncapi-payload-unsupported-schemaFormat
AsyncAPI can support various schemaFormat values. When unspecified, one of the following will be assumed:
application/vnd.aai.asyncapi;version=2.0.0 application/vnd.aai.asyncapi+json;version=2.0.0 application/vnd.aai.asyncapi+yaml;version=2.0.0
At this point, explicitly setting schemaFormat is not supported by Spectral, so if you use it this rule will emit an info message and skip validating the payload.
Other formats such as OpenAPI Schema Object, JSON Schema Draft 07, and Avro will be added in various upcoming versions.
Recommended: Yes
Default severity when enabled: info
asyncapi-payload
When schemaFormat is undefined, the payload object should be valid against the AsyncAPI v2 Schema Object definition.
Recommended: Yes
Default severity when enabled: error
asyncapi-schema-default
default objects should be valid against the schema they decorate.
Recommended: Yes
Default severity when enabled: error
asyncapi-schema-examples
Values of the examples array should be valid against the schema they decorate.
Recommended: Yes
Default severity when enabled: error
asyncapi-server-no-empty-variable
Server URL variable declarations cannot be empty, ex.gigantic-server.com/{} is invalid.
Recommended: Yes
Default severity when enabled: warn
asyncapi-server-no-trailing-slash
Server URL should not have a trailing slash.
Some tooling forgets to strip trailing slashes off when it’s joining the servers.url with channels, and you can get awkward URLs like mqtt://example.com/broker//pets. Best to just strip them off yourself.
Recommended: Yes
Default severity when enabled: warn
Good Example
servers: - url: mqtt://example.com - url: mqtt://example.com/brokerBad Example
servers: - url: mqtt://example.com/ - url: mqtt://example.com/broker/asyncapi-server-not-example-com
Server URL should not point to example.com.
Recommended: No
Default severity when enabled: warn
asyncapi-server-variables
All server URL variables should be defined in the variables object of the server. They should also not contain redundant variables that do not exist in the server address.
Recommended: Yes
Default severity when enabled: error
asyncapi-tag-description
Tags alone are not very descriptive. Give folks a bit more information to work with.
tags: - name: "Aardvark" description: Funny-nosed pig-head raccoon. - 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, or 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
Default severity when enabled: warn
asyncapi-tags-alphabetical
AsyncAPI object should have alphabetical tags. This will be sorted by the name property.
Recommended: No
Default severity when enabled: warn
Bad Example
tags: - name: "Badger" - name: "Aardvark"Good Example
tags: - name: "Aardvark" - name: "Badger"Recommended: No
asyncapi-tags-uniqueness
Tags must not have duplicate names (identifiers).
Recommended: Yes
Default severity when enabled: error
Bad Example
tags: - name: "Badger" - name: "Badger"Good Example
tags: - name: "Aardvark" - name: "Badger"asyncapi-tags
AsyncAPI root object should have non-empty tags array.
Why? Well, you can reference tags arbitrarily in operations, and definition is optional…
/invoices/{id}/items: tags: - Invoice ItemsDefining tags allows you to add more information like a description. For more information see asyncapi-tag-description.
Recommended: Yes
Default severity when enabled: warn
AsyncAPI v3
The following rules ONLY apply to AsyncAPI v3 documents.
asyncapi-3-channel-no-empty-parameter
Channel address parameter declarations cannot be empty, ex./given/{} is invalid.
Recommended: Yes
Default severity when enabled: warn
asyncapi-3-channel-no-query-nor-fragment
Query parameters and fragments shouldn’t be used in channel address. Instead, use bindings to define them, ex./given?test is invalid.
Recommended: Yes
Default severity when enabled: warn
asyncapi-3-channel-no-trailing-slash
Keep trailing slashes off of channel address, as it can cause some confusion. Most messaging protocols will treat example/foo and example/foo/ as different things. Keep in mind that tooling may replace slashes (/) with protocol-specific notation (e.g.: . for AMQP), therefore, a trailing slash may result in an invalid channel address in some protocols.
Recommended: Yes
Default severity when enabled: warn
asyncapi-3-channel-servers
Channel servers must be defined in the servers object.
Bad Example
asyncapi: "3.1.0"info: title: Awesome API description: A very well-defined API version: "1.0"servers: production: url: "stoplight.io" protocol: "https"channels: hello: servers: - $ref: #/servers/developmentGood Example
asyncapi: "3.1.0"info: title: Awesome API description: A very well-defined API version: "1.0"servers: production: url: "stoplight.io" protocol: "https"channels: hello: servers: - $ref: #/servers/productionRecommended: Yes
Default severity when enabled: error
asyncapi-3-headers-schema-type-object
The schema definition of the application headers must be of type “object”.
Recommended: Yes
Default severity when enabled: error
asyncapi-3-operation-security
Operations must reference a defined security scheme.
Recommended: Yes
Default severity when enabled: error
asyncapi-3-operation-description
Operation objects should have a description.
Recommended: Yes
Default severity when enabled: warn
asyncapi-3-payload-unsupported-schemaFormat
AsyncAPI can support various schemaFormat values. When unspecified, one of the following will be assumed:
application/vnd.aai.asyncapi;version=2.0.0 application/vnd.aai.asyncapi+json;version=2.0.0 application/vnd.aai.asyncapi+yaml;version=2.0.0
At this point, explicitly setting schemaFormat is not supported by Spectral, so if you use it this rule will emit an info message and skip validating the payload.
Other formats such as OpenAPI Schema Object, JSON Schema Draft 07, and Avro will be added in various upcoming versions.
Recommended: Yes
Default severity when enabled: info
asyncapi-3-server-no-empty-variable
Server host and pathname variable declarations cannot be empty, ex.gigantic-server.com{} is invalid.
Recommended: Yes
Default severity when enabled: warn
asyncapi-3-server-no-trailing-slash
Server host should not have a trailing slash.
Some tooling forgets to strip trailing slashes off when it’s joining the servers.host with channels, and you can get awkward URLs like mqtt://example.com//pets. Best to just strip them off yourself.
Recommended: Yes
Default severity when enabled: warn
Good Example
servers: - host: mqtt://example.comBad Example
servers: - host: mqtt://example.com/ - host: mqtt://example.com/broker/asyncapi-3-server-not-example-com
Server host should not point to example.com.
Recommended: No
Default severity when enabled: warn
asyncapi-3-tag-description
Tags alone are not very descriptive. Give folks a bit more information to work with.
info: tags: - name: "Aardvark" description: Funny-nosed pig-head raccoon. - 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, or anything. What is clear to the folks writing the document is probably not as clear to others.
info: tags: - name: Invoice Items description: |+ Giant long explanation about what this business concept is, because other people _might_ not have a clue!Recommended: No
Default severity when enabled: warn
asyncapi-3-tags-alphabetical
AsyncAPI object should have alphabetical tags. This will be sorted by the name property.
Recommended: No
Default severity when enabled: warn
Bad Example
info: tags: - name: "Badger" - name: "Aardvark"Good Example
info: tags: - name: "Aardvark" - name: "Badger"Recommended: No
asyncapi-3-tags-uniqueness
Tags must not have duplicate names (identifiers).
Recommended: Yes
Default severity when enabled: error
Bad Example
info: tags: - name: "Badger" - name: "Badger"Good Example
info: tags: - name: "Aardvark" - name: "Badger"asyncapi-3-tags
AsyncAPI object should have non-empty tags array.
Why? Well, you can reference tags arbitrarily in operations, and definition is optional…
invoicedItems: address: /invoices/{id}/items tags: - Invoice ItemsDefining tags allows you to add more information like a description. For more information see asyncapi-3-tag-description.
Recommended: Yes
Default severity when enabled: warn
asyncapi-3-document-resolved
Validate structure of AsyncAPI specification when references have been resolved.
Recommended: Yes
Default severity when enabled: error
asyncapi-3-document-unresolved
Validate structure of AsyncAPI specification before references have been resolved.
Recommended: Yes
Default severity when enabled: error
Last updated Oct 24, 2026