Rules are at the core of how rulesets work, so let’s look at how to create a rule and its properties.
Rules Properties
Rules can be added under the rules property in your ruleset file.
rules: my-rule-name: description: Tags must have a description. given: $.tags[*] severity: error then: field: description function: truthyThe example above is a valid ruleset with a single rule that can be used to lint an OpenAPI description, and validate that all tags have a description field.
Rules can have the following properties:
given(required): The part of the document the rule should be applied to. Uses the JSONPath syntax.then(required): Describes which function should be applied to thegivenpart of the document. Can be used with a core function or custom function.description(optional): A short description of the rule.message(optional): A message that’s displayed in thespectral lintoutput. Can be customized to use placeholder values that are evaluated at runtime, such as{{description}}or{{error}}.severity(optional): The severity of the rule. Used to differentiate between rules that must be followed (error) and warnings or hints. Default value iswarn.formats(optional): The format that the rule should apply to. For exampleoas3for any OpenAPI v3.x descriptions. Can be applied at the ruleset and/or rule level. See Formats for more details.recommended(optional): Userecommendedwhen extending a ruleset so users can enforce all rules (recommendedset tofalse) or only recommended rules (recommendedset totrue). Recommended can be used to slowly roll out a ruleset across API landscapes with a lot of legacy APIs. Default value istrue. See Recommended for more details.resolved(optional): Used to apply a rule to a document that’s not “resolved,” where$refJSON Schema references haven’t been replaced with the objects they point to.
Let’s look at all the properties that can be used for a rule.
Given
The given property is conceptually similar to a selector in CSS, in that it indicates the part of the document to apply rules to.
given has a specific syntax known as JSONPath, which is similar to XPath. JSONPath has a few competing implementations. Spectral uses nimma as its main implementation, and sometimes resorts to jsonpath-plus to ensure backwards-compatibility. Both support all the main JSONPath functionality and a bit more, but this syntax may differ slightly from other JSONPath implementations. Currently the implementation that Spectral uses is not fully aligned with IETF RFC 9535 (published in February 2024) which also is titled “JSONPath”. Once supported by the underlying implementations, we will look to make available within Spectral.
Your given value can be a string containing any valid JSONPath expression, or an array of expressions to apply a rule to multiple parts of a document.
You can also consume your aliases here if you have some defined.
Use the JSONPath Online Evaluator to determine what given path you want.
Then
The then part of the rule explains which function to apply to the given JSONPath. The function you apply may be one of the core functions or it may be a custom function.
then has two main keywords:
then: field: description function: truthyThe field keyword is optional and is used to apply the function to a specific property in an object. If omitted, the function is applied to the entire target of the given JSONPath. The value can also be @key to apply the rule to the keys of an object.
given: "$.responses"then: field: "@key" function: pattern functionOptions: match: "^[0-9]+$"The above pattern based rule would error on 456avbas as it’s not numeric.
responses: 123: foo: bar 456avbas: foo: barYou can also have multiple thens to target different properties in the same object, or to use different functions. For example, you can have one rule that checks if an object has multiple properties:
contact-properties: description: Contact object must have "name", "url", and "email". given: $.info.contact severity: warn then: - field: name function: truthy - field: url function: truthy - field: email function: truthyMessage
To help you create meaningful messages for results, Spectral comes with placeholders that are evaluated at runtime.
{{error}}- the error returned by function{{description}}- the description set on the rule{{path}}- the whole error path{{property}}- the last segment of error path{{value}}- the linted value
message: "{{error}}" # will output the message generated by then.functionmessage: "The value of '{{property}}' property must equal 'foo'"message: "{{value}} is greater than 0"message: "{{path}} cannot point at remote reference"Severity
The severity keyword is optional and can be error, warn, info, hint, or off.
The default value is warn.
Resolved
By default, Spectral processes each rule on a “resolved” document (a file where all $ref JSON Schema references have been replaced with the objects they point to). While this is typically the desired behavior, there are some use cases where you may need to run a rule on the “raw” un-resolved document (for example, to enforce conventions on the folder structure used for splitting up documents).
If your rule needs to access the raw $ref reference values, you can set resolved: false to allow the rule to receive the raw un-resolved version of the document. Otherwise resolved: true is the default.
Here’s an example of a rule that can access $ref values:
rules: my-rule-name: description: Parameters must be references given: $.paths[*][get,post,put,delete,options] severity: error resolved: false then: field: parameters function: schema functionOptions: schema: type: array items: type: object properties: $ref: type: string required: - $refIn most cases, you will want to operate on a resolved document.
Last updated Oct 24, 2026