*** title: Define custom governance rules using Spectral updated: 2025-02-06T00:00:00.000Z slug: docs/api-governance/configurable-rules/spectral max-toc-depth: 2 ---------------- Spectral is a linting engine that helps you define custom rules and enforce them on JSON and YAML files. Postman supports Spectral v6 rules for the configurable [API Governance and Security](/docs/api-governance/configurable-rules/configuring-api-governance-rules/#add-custom-rules) rules for your team. Postman also supports ES6 syntax and CommonJS syntax for custom functions configurable in custom governance rules. ## How Spectral works Spectral checks that the APIs defined in OpenAPI documents conform to API design guidelines using a specific set of rules. For example, you can use Spectral to check that all properties of all data models are in camel case, or that all operations have a summary. A Spectral rule targets a given location using a [JSON Path Plus expression](#json-path-and-json-path-plus), then tests the values it finds with a `function`. It returns an error if the values don't conform to the rule. {/* vale Vale.Terms = NO */} {/* The incorrect spelling of "API" is for illustrative purposes, and is ok. */} This example shows how to check that the name of an API doesn't contain the word "API," regardless of case (for instance, "api" or "Api"): {/* vale Vale.Terms = YES */} ```json rules: api-name-doesnt-contain-api: given: $.info.title then: function: pattern functionOptions: notMatch: /\b(api)\b/i ``` First, the rule targets the `title` property of the `info` object located at the root (`$`) of the document with the [JSON Path Plus expression](#json-path-and-json-path-plus) `$.info.title`. In `then`, the `function` named `pattern` checks whether the value of the `title` property doesn't match (`functionOptions.notMatch`) the regular expression looking for the word `api` in any case (`/\b(api)\b/i`). {/* vale Vale.Terms = NO */} {/* vale postman-style-guide.Headings = NO */} {/* It should be ok to sentence-case "rulesets". */} ### Rulesets in Spectral documents {/* vale postman-style-guide.Headings = YES */} {/* vale Vale.Terms = YES */} A Spectral document (often called a ruleset) has a `rules` property that can have one or more rules. Spectral identifies each rule with a key, which can be any JSON-compatible string. ```json rules: api-name-doesnt-contain-api: # ... api-name-length: # ... ``` ## Spectral support in Postman Postman supports many of Spectral's features, though not all. Whether it's created within Postman or imported from another source, a Spectral document needs to contain the properties shown in this example: ```json rules: api-name-doesnt-contain-api: description: The API name must not contain the word API message: The info.title value "{{value}}" contains the forbidden word API severity: error formats: - oas2 - oas3 given: - $.info then: - field: title function: pattern functionOptions: notMatch: /\b(api)\b/i ``` To be valid in Postman, your Spectral document can't contain any properties beyond those listed here. For the full list of rules and their descriptions, see [Spectral rule properties](#spectral-rule-properties). You'll find each rule defined in `rules` in the **Custom Rules** section in the configurable [API Governance](/docs/api-governance/configurable-rules/configuring-api-governance-rules/) page. Remember to turn on your custom rules after you create or import them. ## Spectral rule properties |
Property
| Description | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `description` | An optional description of the rule. If you provide one, it will be shown in the configurable rules page for either API Governance or API Security. | | `message` |

If the rule is triggered, the list of rule violations will contain the `message`, used in Postman as the name of the rule. This message aims to help users solve the problem. Keep it as short and meaningful as possible. It can contain optional placeholders:


If `message` isn't provided, the `description` is used instead. And if `description` isn't available, the rule's key (in `rules`) is used. | | `severity` |

The severity of the problem detected by the rule. The possible values are `error`, `warn` (default), `info`, and `hint`. These values can be used as follows:

| | `resolved` |

Determines whether your OpenAPI document is a resolved or unresolved document when Spectral runs your rule. This affects whether Spectral resolves `$ref` properties when running your rule.

A `$ref` property is a reference in the form of a URI that references other components, which can be in your OpenAPI document. In a resolved document, references are replaced with the components each URI points to. In an unresolved document, references aren't replaced. The possible values are `true` (default) and `false`. These values can be used as follows:

| | `formats` |

The list of document formats to which the rule will be applied. The accepted values are:


By default, a rule will target all versions 2 and 3.x (the default value is `[oas2,oas3]`). | | `given` |

**Required**. This can be a list with at least one element or a single element. Each value is a [JSON Path Plus expression](#json-path-and-json-path-plus) that may return zero, one, or more elements.

If `given` paths don't find any value, the `then` controls won't run.

| | `then` | **Required**. This can be a list that contains one or more elements. If the given [JSON Path Plus expressions](#json-path-and-json-path-plus) return multiple values, the function makes a call for each item found. For example, for 10 values, there are 10 calls. | | `then.field` |

This optional name can be used if the value returned by the `given` paths is an object to target a specific field inside it. This value must be a name and can't hold a [JSON Path Plus expression](#json-path-and-json-path-plus).

The keyword `@key` can be used to check all keys of an object returned by the `given` paths.

| | `then.function` | **Required**. The name of the function to use. You can use all Spectral core functions in Postman. For more information about Spectral core functions, see the [Spectral documentation](https://github.com/stoplightio/spectral/blob/develop/docs/reference/functions.md). [Custom functions](#spectral-custom-functions) are supported in custom API Governance rules. | | `then.functionOptions` | **May be required depending on the function**. The options of the function. You can use all Spectral core functions in Postman. For more information about Spectral core functions, see the [Spectral documentation](https://github.com/stoplightio/spectral/blob/develop/docs/reference/functions.md). [Custom functions](#spectral-custom-functions) are supported in custom API Governance rules. | {/* vale postman-style-guide.Headings = NO */} ## JSON Path and JSON Path Plus {/* vale postman-style-guide.Headings = YES */} A JSON Path (or JSON Path Plus) expression aims to represent the path to some elements in a JSON or YAML document. For example, `$.info.title` represents the `title` property of the `info` object located at the document's root (`$`). Initially, JSON Path was created to be [XPath for JSON](https://goessner.net/articles/JsonPath/) and aimed to represent the path to some element in an XML document. [JSON Path Plus](https://jsonpath-plus.github.io/JSONPath/docs/ts/) is an extension of JSON Path. It adds more operators and makes some behaviors of the original specification explicit. {/* vale postman-style-guide.Headings = NO */} ### Building and testing JSON Path Plus expressions {/* vale postman-style-guide.Headings = YES */} You can use the official JSON Path Plus [documentation](https://jsonpath-plus.github.io/JSONPath/docs/ts/) to build and test your rules' given paths. [Syntax Through Examples](https://jsonpath-plus.github.io/JSONPath/docs/ts/#syntax-through-examples) and the [JSON Path Plus demo](https://jsonpath-plus.github.io/JSONPath/demo/) are both useful. {/* vale postman-style-guide.Headings = NO */} ### JSON Path Plus examples {/* vale postman-style-guide.Headings = YES */} These examples show the typical JSON Path Plus features you'll need to create rules in Postman: * `$.info.title` - The `title` property inside the `info` object, which is located at the document's root (`$`). * `$.paths.*.*.responses` - All responses of all operations of all `paths`. `*` gets all elements inside an object or an array. * `$.paths.*[post,patch,put]` - All `POST`, `PATCH`, and `PUT` operations across all `paths`. `[ ]` can be used to filter elements. * `$..properties` - All `properties` of all schema objects wherever they're located (for example, in parameters, responses, or reusable components). `..` gets all elements in the path tree. ## Check for the presence of a property In the following example, the rule is supposed to check that there's a description of the API. The way it's written, though, it will never return a rule violation when the `description` isn't present in the `info` object. ```json # this approach won't work! rules: info-description: given: $.info.description then: function: truthy ``` If the `given` path doesn't find any value, the `then` checks won't run. This means you can't use the path `$.info.description` to check that the API description is defined in the OpenAPI document. This verification must be done using the path `$.info`, which will return the `info` object and the `field` value set with the name of the field you're looking for (in this example, `description`). ```json # this approach will work rules: info-description: given: $.info then: field: description function: truthy ``` ## Spectral custom functions You can [add custom governance functions](/docs/api-governance/configurable-rules/configuring-custom-governance-functions/) to your custom governance rules that Postman applies to your API specifications in the API Builder and Spec Hub. You can use these guidelines to write custom functions in JavaScript and add them to your custom governance rules. Postman supports ES6 syntax and CommonJS syntax for custom functions. Postman recommends using ES6 syntax for your custom functions. Your custom function must have the [`targetVal` parameter](#spectral-function-parameters), the [`message` property](#spectral-function-return-statement-properties) in your return statement, and either the [`export default` declaration (ES6) or `module.exports` object property (CommonJS)](#export-your-custom-function) exporting your function. To add a custom function to a rule, your rule must have the [`then.function` property](#spectral-rule-properties) whose value is the name of the file containing the custom function. The filename is defined using the **Name** field when you [create a custom function](/docs/api-governance/configurable-rules/configuring-custom-governance-functions/#add-a-custom-function). ### Spectral function parameters Use the following parameters in your custom functions depending on your use case. You must add parameters to your custom function in the following order: `targetVal`, `options`, then `context`. You can use any parameter names you want. Postman expects the parameters to be in a specific order. |
Parameter
| Description | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `targetVal` |

**Required**. The first parameter you must add to your function. This can be any data type, such as a string or array. This is the value that the [`given` property](#spectral-rule-properties) returns. The rule tests the value of `targetVal` using your custom function.

If you also define a value for the [`then.field` property](#spectral-rule-properties) in your rule, `targetVal` is the value returned by the `given` path appended with `then.field`.

| | `options` |

The second parameter you can add to your function. This is the optional value of the [`then.functionOptions` property](#spectral-rule-properties). Add this parameter to your function if your function expects options.

If your custom function accepts options, Postman recommends adding a [JSON Schema](#json-schema) to your custom function. A JSON Schema enables you to define and validate your custom function's options when editing your rule. This requires you to export your custom function using the [`createRulesetFunction` Spectral function](#createrulesetfunction).

| | `context` |

The third parameter you can add to your function. You can use this optional parameter to access properties about the context in which the custom function is called. For example, you can access the `targetVal` path or other locations in the document. These properties are as follows:

| ```js function myCustomFunction(targetVal, options, context) { ... } ``` ### Spectral function return statement properties Use the following properties to write the return statement in your custom functions depending on your use case. {/* vale Vale.Spelling = NO */} {/* Turned off vale here because "subelements" below was erroneously triggering a vale error. TW-2358 */} |
Property
| Description | | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` | **Required**. The message describing the rule violation. | | `path` |

An optional path to an element in the document that triggers the rule violation. If you use the `path` property, you must add the [`context` parameter](#spectral-function-parameters) to your function. If you don't add the `path` property, the default path is the `targetVal` path.

You can add the `path` property when investigating other locations in the document. The path must be an array of strings, such as `["paths", "/resources", "get", "responses", "306"]`.

You can also add the `path` property when investigating subelements of the `targetVal` path. Add `...context.path` to the beginning of the path, enabling you to append a path to the `targetVal` path. For example, `[...context.path, "a", "custom", "path"]`.

| {/* vale Vale.Spelling = YES */} ```js return [ // Rule violation with the default targetVal path { message: `Value must be different from "${values.join(',')}".`, }, // Rule violation with a custom path leveraging the default targetVal path { message: `Value must be different from "${values.join(',')}".`, path: [...context.path, "a", "custom", "path"] }, ]; ``` ### Export your custom function **Required**. Export your custom function. This enables you to add the custom function's filename to your custom rule using the [`then.function` property](#spectral-rule-properties). The custom function name you export must match the name in the function declaration. If your custom function accepts options, Postman recommends adding a [JSON Schema](#json-schema) to your custom function. A JSON Schema enables you to define and validate your custom function's options when editing your rule. This requires you to export your custom function using the [`createRulesetFunction` Spectral function](#createrulesetfunction). * For ES6 format, use the following syntax: `export default function-name`. * For CommonJS format, use the following syntax: `module.exports = function-name`. ```js function myCustomFunction(targetVal, options, context) { ... } // ES6 syntax export default myCustomFunction; // CommonJS syntax // module.exports = myCustomFunction; ``` ### Supported Spectral functions You can import the following Spectral functions into your custom function file in Postman. {/* vale postman-style-guide.Headings = NO */} #### createRulesetFunction {/* vale postman-style-guide.Headings = YES */} The `createRulesetFunction` function is an optional Spectral function you can import from the `@stoplight/spectral-core` module. Use a [JSON Schema](#json-schema) to define your custom function's options, enabling you to validate whether the [options provided in your rule](/docs/api-governance/configurable-rules/configuring-api-governance-rules/#add-custom-rules) using `then.functionOptions` match specific criteria. The JSON Schema must be nested inside of a JSON object. If the provided options don't match the JSON Schema, an error message will explain the issue when editing your rule. If you use ES6 syntax, error messages refer to your custom function as `"" function`. Add a JSON Schema for each of the following to your JSON object: |
Key
| Description | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `input` |

**Required**. Postman expects a key named `input` in the JSON object. This is the JSON Schema that defines the [`targetVal` parameter](#spectral-function-parameters) in your custom function. This JSON Schema enables you to define and validate whether the value of `targetVal` matches specific criteria.

If the `targetVal` value doesn't match the `input` JSON Schema, your rule won't call the function. You won't receive an error if the `targetVal` value doesn't match the `input` JSON Schema.

Enter the following to skip validation for the `input` JSON Schema: `input: null,`.

| | `options` | **Required**. Postman expects a key named `options` in the JSON object. This is the JSON Schema that defines the [`options` parameter](#spectral-function-parameters) in your custom function. Options are provided in your rule using the [`then.functionOptions` property](#spectral-rule-properties). This JSON Schema enables you to define and validate whether the values of `options` matches specific criteria. | ```json { // JSON Schema of the targetVal parameter input: { type: "string" }, // JSON Schema of the options parameter options: { type: "object", additionalProperties: false, properties: { values: { type: "array" } }, required: ["values"], }, }, ``` When you [export your custom function](#export-your-custom-function), call the `createRulesetFunction` Spectral function and include a JSON object containing JSON Schemas and the custom function's name as arguments. For a complete example of using a JSON Schema with a custom function, see [Check that a value isn't in a list (JSON Schema)](#check-that-a-value-isnt-in-a-list-json-schema). * ES6 format: * To import, use the following syntax: `import { createRulesetFunction } from "@stoplight/spectral-core";`. * To export, use the following syntax: `export default createRulesetFunction(json-object, function-name);`. * CommonJS format: * To import, use the following syntax: `const { createRulesetFunction } = require("@stoplight/spectral-core");`. * To export, use the following syntax: `module.exports = createRulesetFunction(json-object, function-name);`. ```js // ES6 syntax import { createRulesetFunction } from "@stoplight/spectral-core"; // CommonJS syntax // const { createRulesetFunction } = require("@stoplight/spectral-core"); function myCustomFunction(targetVal, options, context) { ... } // ES6 Syntax export default createRulesetFunction( // CommonJS Syntax // module.exports = createRulesetFunction( { // JSON Schema of the targetVal parameter input: { type: "string" }, // JSON Schema of the options parameter options: { type: "object", additionalProperties: false, properties: { values: { type: "array" } }, required: ["values"], }, }, myCustomFunction, ); ``` {/* vale postman-style-guide.Headings = NO */} ### JSON Schema {/* vale postman-style-guide.Headings = YES */} JSON Schema specification enables you to describe a JSON document using a standard format. You can add a JSON Schema that defines and validates your custom function's options. To learn about adding a JSON Schema to your custom function, see the [`createRulesetFunction` Spectral function](#createrulesetfunction). You can use the [official JSON Schema documentation](https://json-schema.org/learn/getting-started-step-by-step.html) to learn more about describing a JSON document using this format. {/* vale postman-style-guide.Headings = NO */} #### JSON Schema examples {/* vale postman-style-guide.Headings = YES */} The following examples show JSON Schema key-value pairs you can use to validate your custom function's options: * `$.options` - The root object that contains the JSON Schema of the [`options` parameter](#spectral-function-parameters), which is your custom function's options. * `$.options.type` - A validation keyword that defines a constraint on the JSON data. In this example, the value is `object`, meaning the data must be a JSON object. * `$.options.properties` - An object whose values define the parameter used to pass options to your custom function. In this example, `values` is a variable that stores the value of the [`options` parameter](#spectral-function-parameters). * `$.options.required` - A validation keyword that's an array of strings containing keys from `$.options.properties`. Add properties to the array if they must be defined in the JSON Schema. In this example, `values` must be defined in the JSON Schema. ```json { input: { type: "string" }, options: { type: "object", additionalProperties: false, properties: { values: { type: "array" } }, required: ["values"], }, }, ``` ### Check that a value isn't in a list In the following example, the custom function named `notInEnumeration` is in a file named `not_in_enumeration`. The filename is defined using the **Name** field when you [create a custom function](/docs/api-governance/configurable-rules/configuring-custom-governance-functions/#add-a-custom-function). If your custom function accepts options, Postman recommends adding a [JSON Schema](#json-schema) to your custom function. A JSON Schema enables you to define and validate your custom function's options when editing your rule. This requires you to export your custom function using the [`createRulesetFunction` Spectral function](#createrulesetfunction). The custom function checks the value of the option `values`, which is defined in the [Spectral document](#rule-that-uses-a-custom-function) (or ruleset) using the [`then.functionOptions` property](#spectral-rule-properties). The value of `values` is a list of numeric strings. If `targetVal` is a value already in the list, the rule violation is triggered. After the custom function, `export default` or `module.exports` references the custom function's name. This exports the custom function, enabling you to add its filename to your rule using the [`then.function` property](#spectral-rule-properties). ```js // filename: not_in_enumeration function notInEnumeration(targetVal, options, context) { const { values } = options; if (values.includes(targetVal)) { return [ { message: `Value must be different from "${values.join(',')}".`, }, ]; } } // ES6 syntax export default notInEnumeration; // CommonJS syntax // module.exports = notInEnumeration; ``` ### Check that a value isn't in a list (JSON Schema) In the following example, the custom function named `notInEnumeration` is in a file named `not_in_enumeration`. The filename is defined using the **Name** field when you [create a custom function](/docs/api-governance/configurable-rules/configuring-custom-governance-functions/#add-a-custom-function). Before the custom function, the [`createRulesetFunction` Spectral function](#createrulesetfunction) is imported into the file. This enables you to define the expected options in a [JSON Schema](#json-schema) to validate whether the [provided options in your rule](/docs/api-governance/configurable-rules/configuring-api-governance-rules/#add-custom-rules) match specific criteria. The custom function checks the value of the option `values`, which is defined in the [Spectral document](#rule-that-uses-a-custom-function) (or ruleset) using the [`then.functionOptions` property](#spectral-rule-properties). The value of `values` is a list of numeric strings. If `targetVal` is a value already in the list, the rule violation is triggered. After the custom function, `export default` or `module.exports` calls the `createRulesetFunction` Spectral function and includes the following arguments: a JSON object containing JSON Schemas of the `targetVal` parameter and `options` parameter, and the custom function's name. This exports the custom function, enabling you to add its filename to your rule using the [`then.function` property](#spectral-rule-properties). Learn more about the [JSON Schemas used in this example](#json-schema-examples). ```js // filename: not_in_enumeration // ES6 Syntax import { createRulesetFunction } from "@stoplight/spectral-core"; // CommonJS Syntax // const { createRulesetFunction } = require("@stoplight/spectral-core"); function notInEnumeration(targetVal, options, context) { const { values } = options; if (values.includes(targetVal)) { return [ { message: `Value must be different from "${values.join(',')}".`, }, ]; } } // ES6 Syntax export default createRulesetFunction( // CommonJS Syntax // module.exports = createRulesetFunction( { // JSON Schema of the targetVal parameter input: { type: "string" }, // JSON Schema of the options parameter options: { type: "object", additionalProperties: false, properties: { values: { type: "array" } }, required: ["values"], }, }, notInEnumeration, ); ``` ### Rule that uses a custom function In the following example, the Spectral document has a rule named `http-status-obsolete` that uses a custom function file named `not_in_enumeration`, which is defined using the **Name** field when you [create a custom function](/docs/api-governance/configurable-rules/configuring-custom-governance-functions/#add-a-custom-function). The custom function file has a custom function named `notInEnumeration`. The custom function filename is added to the rule using the [`then.function` property](#spectral-rule-properties). The custom function accepts options using the [`then.functionOptions` property](#spectral-rule-properties), defining a property named `values` that's a list of numeric strings. The value of `then.functionOptions.values` is passed to the custom function `notInEnumeration`. The custom function then checks whether a rule violation occurred at the `given` path appended with the value of the [`then.field` property](#spectral-rule-properties). ```yaml rules: http-status-obsolete: formats: [oas2, oas3] severity: warn message: "{{property}} is an obsolete or unused HTTP status code" given: $.paths.*.*.responses then: field: "@key" function: not_in_enumeration functionOptions: values: ["306","418","510"] ```