Custom Rules for API Standardization

Last modified on October 06, 2023

Available in SwaggerHub SaaS for organizations on the Enterprise plan and in SwaggerHub On-Premise 1.23 and later.

Organizations can add custom rules for API standardization to validate OpenAPI definitions for compliance with API design guidelines. Among other things, these rules can help you verify if:

  • a specific node exists in YAML, regardless of the value,

  • the node name or value matches (or does not match) a regular expression.

  • length of a given field

Each rule consists of a node path (such as $.info.version) and, optionally, a regular expression that defines valid values for this node. You can customize the rule severity and applicable OpenAPI versions.

Considerations

Custom standardization rules have the same limitations as the built-in rules:

  • They apply only to APIs, not to domains.

  • They check the YAML structure as it is and do not resolve $refs.

Create a custom rule

You must be an organization owner to create rules.

  1. Go to My Hub and click next to the organization name in the sidebar.

  2. Switch to the Standardization tab.

  3. Scroll to the bottom and click Add Custom Rule.

    Add Custom Rule
  4. Configure the rule (see the parameters below) and click Save.

    Tip: You can also test the rule directly in the rule editor.

After you create or edit a rule, click Save at the top of the Standardization page to re-scan your organization’s APIs.

Rule parameters

Parameter Description
Name Required. A unique name for this rule, up to 35 characters. The name is also used as a prefix for the rule’s error message.
Specification Select if the rule applies to All API definitions. Different API types use a different structure and keywords, so some validations may need separate rules for different OpenAPI versions.
Rule Severity Error or Warning. Errors will prevent the API from being published if the Require API to pass Standardization to be publishable option is selected in the Standardization settings.
Error Message An optional additional error message displayed in the SwaggerHub editor, up to 130 chars. If omitted, the rule name is used as the error message. If both the name and the error message are specified, the name will prefix the error message. For example, given:
  • Rule name: Version

  • Error message: `info.version` must be major.minor.patch

the full error message in the editor is be:

Version -> `info.version` must be major.minor.patch

Path Required A JSONPath expression that specifies the target node or nodes to check. For example, $.info.version. Case-sensitive. We use the jsonpath-plus library that supports some extra selectors in addition to the standard JSONPath syntax. See the jsonpath-plus documentation for the supported syntax.
Test For Specify pattern to search for the regular expression specified in the Pattern field (below). Alternatively, you can choose defined to to check that the node is present, regardless of the value. For example, check that tag objects have a description specified. See also How "defined" rules work below.
Field Field to be tested. Set this to @key if you want to test against a field name rather than a value. Also, you can select alphabetical, truthy, or any other available rule.
Pattern A regular expression to test against the result of the specified JSONPath. For example, ^\d+\.\d+\.\d+$. Note that:
  • Pattern field appears only if in Test for you select pattern.

  • If the path expression returns an array, each array item is tested against this regular expression.

  • Patterns look for a partial match unless the pattern contains the ^ (beginning of value) and $ (end of value) anchors. For example, a matches any string that contains this character, but ^a$ matches the exact string "a".

Must Match Regular expression match type: "must match" (check box is selected) or "must not match" (unselected). Appears only if you select Test for patterns.
Alphabetical Passing a key enforces alphabetical content for simple arrays or for objects.
Try It Out Use this section to test the rule against an existing API. You can either paste the API definition into the Try It Out field or use the IMPORT API button to import an API into the Try It Out field for testing purposes.
Save Save the rule.

Examples

PATTERN custom rule

Version must be major.minor.patch (digits only)

Patterns are case-sensitive by default. For a case-insensitive match, use the format /pattern/i, for example, /https/i.

Path Required: $.info.version

Test For: pattern

Pattern: ^\d+\.\d+\.\d+$

Must Match: selected

Paths should not end with a slash

Path Required: $.paths.*~

Test For: pattern

Pattern: ^\/.+\/$

Must Match: unselected

Path names like /pets and /pets/{id} are considered valid, but /pets/ and /pets/{id}/ will be flagged.

Response content type must match application/json

Path Required:$.paths.*.*.responses.*.content

Test for: pattern

Field:@key

Pattern:application/json

Must Match: selected

The content field within the responses node can only contain a field that is application/json. Any other field within the content field causes the API definition to fail validation.

DEFINED custom rule

If you specify "defined" in the Test For field, then your custom rule verifies the presence of a specific node or nodes in YAML. The specified JSONPath expression is first split into two components: the last component (the target key name) and everything that precedes it (let's call this "base path"). SwaggerHub then finds all the nodes with the "base path" and checks whether each of them contains the target key. The nodes that do not contain this key fail the validation.

Sample rule: "201 responses to POST requests must include the Location header"

$.paths.*.post.responses.201.headers.Location
\__________________________________/ \______/
 find all the nodes at this path     and check whether
                                     they have this key

Note that the presence of intermediate nodes is not enforced. For example, the rule above doesn't flag 201 responses without headers – because these responses aren't found by the "base path" expression ….201.headers.

# Rule flags this response
responses:
  201:
    description: Created
    headers:
      X-RateLimit-Remaining:
        type: string

# but not this response
responses:
  201:
    description: Created

In this example, implement the "Location header exists" rule as two "defined" rules to verify if

  1. 201 responses have headers
  2. headers include the Location header:
Defined:  $.paths.*.post.responses.201.headers

Defined:  $.paths.*.post.responses.201.headers.Location

Example

POST responses must contain 200 response

Path Required:$.paths.*.post.responses

Test For: defined

Field:200

All POST responses in the document must contain the 200 response field.

ALPHABETICAL Custom rule

POST responses must contain 200 response

Examples

Path Required:$.paths.[*]

Test For: alphabetical

Field:tags

All POST responses in the document must contain the 200 response field.

The following alphabetical tags are considered valid:

paths:
 /devices:
 get:
  tags:
   - Atag
   - Btag

The following non-alphabetical tags are flagged:

paths:
 /devices:
 get:
  tags:
   - Btag
   - Atag

 

Path Required: $.paths.[*]

Test For: alphabetical

Field: tags

Alphabetical: greendot

kit:
  - object1:
   bluedot: 'color'
   greendot: 'b'
  - object2:
   bluedot: 'color'
   greendot: 'a'

Object2 is the first because it is sorted by "greendot" keyword.

TRUTHY Custom rule

Path Required:$.paths.[post].parameters.*.

Test For: truthy

Field:required

Required should have value: “”, 0, false, null or undefined.

FALSY custom rule

Path Required:$.paths.[post].parameters.*.

Test For: falsy

Field:required

Required. Should have value different than: “”, 0, false, null, or undefined.

LENGTH custom rule

Choosing this function reveals two additional fields:

  • Minimum length
  • Maximum length

They are not required but you should provide at least one of them.

Examples

Title must be between 0 and 12 characters.

Path Required:$.info

Test For: length

Field:title

Minimum length: 0

Maximum length: 12

Text must be maximum 12 characters.

Path Required:$.info

Test For: length

Field:title

Minimum length: not specified

Maximum length: 12

The number of elements in an array must be minimum 1.

Path Required:$.

Test For: length

Field:tags

Minimum length: 1

Maximum length: not specified

The number of elements in an array must be between 1 and 6.

Path Required:$.

Test For: length

Field:tags

Minimum length: 1

Maximum length: 6

XOR custom rule

Path $.info must contain either description or summary.

This shows error if none or both are found at path $.info.

Path Required:$.

Test For: xor

Field:title

Xor – first value: description.

Xor – second value: summary.

ENUMERATION custom rule

Name of the parameters should be either ‘status’ or ‘tags’.

This shows error if name will not be ‘status’ or ‘tags’.

Path Required:$.paths...parameters.*

Test For: enumeration

Field:name

Enumeration:status, tags

Each entry for enumeration should be followed by Enter or Tab.

 

OAS 3.1 Pet Store example for many fields:

paths:
  /pet/findByStatus:
    get:
      parameters:
        '0':
          name: status
  /pet/findByTags:
    get:
      parameters:
        '0':
          name: tags
  /pet/{petId}:
    get:
      parameters:
        '0':
          name: petId <---- will show error
    post:
      parameters:
        '0':
          name: petId <---- will show error
        '1':
          name: name <---- will show error
        '2':
          name: status
    delete:
      parameters:
        '0':
          name: api_key <---- will show error
        '1':
          name: petId <---- will show error
  /pet/{petId}/uploadImage:
    post:
      parameters:
        '0':
          name: petId <---- will show error
        '1':
          name: additionalMetadata <---- will show error
  /store/order/{orderId}:
    get:
      parameters:
        '0':
          name: orderId <---- will show error
    delete:
      parameters:
        '0':
          name: orderId <---- will show error
  /user/login:
    get:
      parameters:
        '0':
          name: username <---- will show error
        '1':
          name: password <---- will show error
  /user/{username}:
    get:
      parameters:
        '0':
          name: username <---- will show error
    put:
      parameters:
        '0':
          name: username <---- will show error
    delete:
      parameters:
        '0':
          name: username <---- will show error

 

Example for many fields:

The title should be either ‘Very Long Title’ or ‘Long Title’.

Path Required:$.info

Test For: enumeration

Field:title

Enumeration:Very Long Title, Long Title

Each entry for enumeration should be followed by Enter or Tab.

CASING custom rule

Text must be of flat/camel/pascal/kebab/cobol/snake/macro style casing.

This shows error if none or both are found at path $.info.

Path Required:$.info

Test For: casing

Field:title

Disallow digits: unchecked

Casing: flat/camel/pascal/kebab/cobol/snake/macro

Separator character: none

Allow leading separator: unchecked

flat verylongtitle
camel veryLongTitle
pascal VeryLongTitle
kebab very-long-title
cobol VERY-LONG-TITLE
snake very_long_title
macro VERY_LONG_TITLE

Text must be separated by '-' character while enforcing pascal casing.

 

Very-Long-Title

Path Required:$.info

Test For: casing

Field:title

Disallow digits: unchecked

Casing: pascal

Separator character: '-'

Allow leading separator: unchecked

 

-Very-Long-Title

Text can start with chosen separator.

Path Required:$.info

Test For: casing

Field:title

Disallow digits: unchecked

Casing: pascal

Separator character: '-'

Allow leading separator: unchecked

 

verylongtitle

Text can't contain numbers.

Path Required:$.info

Test For: casing

Field:title

Disallow digits: checked

Casing: flat

Separator character: none

Allow leading separator: unchecked

 

+flat+title123

Text can:

  • contain numbers
  • be separated by '+' character
  • start with '+' character

Path Required:$.info

Test For: casing

Field:title

Disallow digits: unchecked

Casing: flat

Separator character: '+'

Allow leading separator: checked

 

+very-long+kebab-title

You can separate a text with a kebab-style casing by '+' character and start it with this character.

Path Required:$.info

Test For: casing

Field:title

Disallow digits: unchecked

Casing: kebab

Separator character: '+'

Allow leading separator: checked

Test a rule

You can quickly test custom rules against existing APIs directly in the rule editor. To do that:

  1. Edit a rule or start to create a new one.

  2. Paste the YAML to test against, or click Import API and load an existing API.

    Note: Pasting works only if the path is not yet specified.
  3. Enter the JSONPath and, optionally, a regular expression to test the value.

  4. The validation results appears in the Try It Out section.

The Try It Out section displays YAML nodes found by the specified JSONPath. Leading dashes (-) indicate individual matches.

Note that a match can be:

  • a standalone value
  • a simple key: value node
  • an array
  • multi-property object (including nested objects)

The error and warning icons in the gutter indicate the nodes that failed the validation.

The results may look different. That depends on whether you test a "defined" rule or a pattern-based rule. For example, when you test the existence of tag descriptions ($.tags[*].description), the results show all the tag objects ("base" nodes) and indicate those without the description property. However, when you test the values of tag descriptions against a regular expression, the results show the descriptions themselves.

Delete a custom rule

Note: In SwaggerHub On-Premise, this is supported since v. 1.27.

  1. In the Custom Rules list, click next to the rule you want to delete and confirm the deletion.

  2. Click Save at the top of the Standardization page to save the changes.

    The 'Save' button

Enable or disable a rule

  1. Select or clear the check box next to the rule.

  2. Click Save at the top of the page to save the changes.

See Also

API Standardization

Highlight search results