Skip to main content
All Tutorials
2026Spectral API Linting: Custom Rules & CI Enforcement GuideUsing Amazon Bedrock as an LLM Provider and Bedrock Guardrails with WSO2 AI GatewayAI Agent Evaluation: Task-Based Evals & Regression TestingBuilding and Managing an API CatalogOpenAPI for AI Agents: Write Specs Agents Can UseMulti-Step MCP Tools: How to Order API Calls with ArazzoWebSocket APIs: How to Build a Real-Time Notification SystemAI Gateway Guardrails for LLMs: Block Prompt Injection and Unsafe RequestsMCP Registry: How to Build a Governed Catalog for MCP ServersManaging API Breaking Changes: Detect, Version, DeprecateSelf-Hosted LLM Gateway: Open-source options and how to deploy oneMCP Server Authentication: OAuth 2.1 GuidePII Redaction for LLMs: How to Do It RightMCP Implementations: How to Implement MCPSemantic Caching for LLMs: Cut Cost & LatencyGovern write-capable MCP tools at the gateway in WSO2 API PlatformControlling Claude Code AI Costs Across a Large Engineering Team with the AI Gateway and AI Workspace

Spectral API Linting: Custom Rules & CI Enforcement Guide

· 25 min read
Senior Software Engineer, WSO2

An OpenAPI description is a contract. Consumers, SDK generators, documentation, and gateways all build on it, so a snake_case path, a missing operationId, or an undocumented error response doesn't stay small for long. Stoplight Spectral turns your API design guidelines into executable rules, so these issues fail a check instead of waiting for someone to spot them in review.

In this guide, you'll install the Spectral CLI, write custom rules, and assemble them into a ruleset. Then you'll run that ruleset in three places: in the editor with WSO2's API Designer, in CI with GitHub Actions, and across an organization with WSO2 API Platform.

What Is Spectral, and Why Lint an OpenAPI Spec at All?​

Spectral is an open source linter for JSON and YAML, maintained by Stoplight and built for API description documents such as OpenAPI and AsyncAPI. Think of it as ESLint for your API contract: it checks the spec itself, before anyone writes code against it, and reports problems such as inconsistent naming and missing metadata.

Those problems have real costs. A missing operationId changes the method names an SDK generator produces. An inconsistent error format forces consumers to write API-specific error handling. A mix of snake_case and kebab-case paths makes an API harder to learn. Spectral lets you encode each expectation as a rule and catch violations automatically.

Spectral is licensed under Apache 2.0. The source is on GitHub, and the Spectral documentation is the reference for the CLI and ruleset syntax.

Four related practices are easy to confuse. Each answers a different question:

PracticeQuestion it answers
ValidationIs the document structurally valid?
LintingDoes a valid document follow our design and style rules? Spectral does this, although its built-in rulesets include some structural checks too.
Contract testingDoes the running API match its spec? (It comes up again in the CI section.)
GovernanceAre those rules defined and applied consistently across the APIs they're meant to cover?

Installing Spectral and Running Your First Lint​

Install the Spectral CLI with npm. Pin the version so your output matches this guide:

npm install -g @stoplight/[email protected]
Versions used in this guide

The examples use Spectral CLI 6.16.3 and Node.js 22. Built-in rules, default severities, and messages can change between versions.

On a team, install Spectral as a pinned dev dependency instead, so everyone runs the same version:

npm install --save-dev --save-exact @stoplight/[email protected]

Then run it with npx spectral lint. The CI workflow later in this guide uses this setup.

Create a .spectral.yaml file that extends Spectral's built-in OpenAPI ruleset:

extends: spectral:oas

spectral:oas gives you a baseline before you write any rules of your own, including checks for schema validity, unused components, and duplicate operation IDs. The exact list varies by version.

Now lint a spec:

spectral lint openapi.yaml

Each finding shows the line and column, severity, rule name, message, and the JSON path of the affected node. For a small spec with a snake_case path and no operationId, Spectral 6.16.3 prints the following (trimmed to the first few findings):

openapi.yaml
1:1 warning oas3-api-servers OpenAPI "servers" must be present and non-empty array.
2:6 warning info-contact Info object must have "contact" object. info
8:9 warning operation-description Operation "description" must be present and non-empty string. paths./order_items.get
8:9 warning operation-operationId Operation must have "operationId". paths./order_items.get
...
✖ 8 problems (0 errors, 8 warnings, 0 infos, 0 hints)

Every finding here is a warning, so the command exits 0, and a CI job running it would pass. That's why exit codes matter.

Understanding Severity Levels and CI Exit Codes​

Every rule has a severity: error, warn, info, hint, or off. Severity controls how a finding is reported. The --fail-severity option controls which findings make spectral lint exit with a non-zero status.

The default threshold is error. Lower-severity findings still print, but they don't fail the build. To fail on warnings too:

spectral lint openapi.yaml --fail-severity=warn

Setting a rule to off silences it without removing it from the ruleset.

Together, these support an incremental rollout: introduce a rule as warn, see how much it flags, and promote it to error once your existing specs are clean.

Writing Custom Rules​

A Spectral rule has two required parts:

  • given: where the rule runs, as a JSONPath expression.
  • then: what it checks, as a function applied to the selected nodes.

Optional properties include severity, message, and description. Without a severity, a rule defaults to warn.

The following rule enforces kebab-case paths, one of the naming conventions in WSO2's REST API design guidelines. The guidelines give a practical reason: when a URL is shown as an underlined link, the underline makes underscores hard to read.

rules:
path-kebab-case:
description: Path segments must use kebab-case.
message: "{{property}} should be kebab-case (e.g. /order-items, not /order_items)"
given: "$.paths[*]~"
severity: error
then:
function: pattern
functionOptions:
match: "^/$|^(/([a-z0-9]+(-[a-z0-9]+)*|\\{[^}]+\\}))+$"

The ~ suffix in given selects property keys instead of values, so the rule checks the path strings themselves.

The then block uses the built-in pattern function. The regex allows lowercase segments joined by hyphens and {parameter} placeholders, and rejects trailing slashes.

Why not the casing function? With its separator option (char: "/", allowLeading: true), casing accepts /order-items. But in Spectral 6.16.3 it still treats {orderId} as part of the value, so it rejects a valid path such as /orders/{orderId}. A regex handles mixed literal and placeholder segments exactly. WSO2's own path-casing rule takes the same approach.

Adapt the regex to your own conventions. As written:

PathResult
/orders, /order-items, /orders/{orderId}, /customer-orders/{customerId}/items, /Passes
/order_items, /orderItems, /OrderItems, /order-items/, /order_items/{order_id}Flagged

The rule checks literal segments only. Parameter names are left alone, so /{OrderID} and /orders/{order_id} pass, and /order_items/{order_id} fails only because of order_items. Add a separate rule if you want to enforce parameter naming.

Renaming a path is a breaking change

Before you enforce this rule on existing APIs, remember that fixing a finding means renaming a path, which breaks consumers. Treat those fixes as versioning decisions, and start the rule at warn for APIs that are already published.

The second rule requires an operationId on every operation:

rules:
operation-operationId-required:
description: Every operation must define an operationId.
given: "$.paths[*][get,put,post,delete,options,head,patch,trace]"
severity: error
then:
field: operationId
function: truthy

given lists the HTTP methods explicitly. A path item can also contain summary, parameters, and servers, and a broader $.paths[*][*] would select those and report false positives. then.field points the check at operationId, and truthy fails if it's missing or falsy (null, false, or an empty string).

Spectral's core functions cover most rules without custom code:

FunctionChecks
patternValue matches a regex
casingValue follows a case convention (kebab, camel, snake, pascal, etc.)
truthyValue exists and isn't falsy
schemaValue validates against a JSON Schema
enumerationValue is one of a fixed set
lengthString, array, or number length falls in a range

For anything these can't express, Spectral supports custom JavaScript functions. None of the rules in this guide need one.

A Practical Governance Ruleset: Beyond the Defaults​

spectral:oas is a baseline. Your organization's design standards are what make linting worth enforcing. This ruleset adds five rules on top of the built-ins:

  • Enforce kebab-case for API paths
  • Require an operationId for every operation
  • Require an explicit security requirement for every operation
  • Require a description for every operation
  • Require a JSON schema for every 4xx and 5xx response
extends: spectral:oas
rules:
path-kebab-case:
description: Path segments must use kebab-case, not snake_case or camelCase.
message: "{{property}} should be kebab-case (e.g. /order-items, not /order_items)"
given: "$.paths[*]~"
severity: error
then:
function: pattern
functionOptions:
match: "^/$|^(/([a-z0-9]+(-[a-z0-9]+)*|\\{[^}]+\\}))+$"

operation-operationId-required:
description: Every operation must define an operationId.
message: "Operation is missing an operationId"
given: "$.paths[*][get,put,post,delete,options,head,patch,trace]"
severity: error
then:
field: operationId
function: truthy

operation-security-required:
description: Every operation must define a non-empty security requirement.
message: "Operation is missing a security requirement"
given: "$.paths[*][get,put,post,delete,options,head,patch,trace]"
severity: error
then:
field: security
function: schema
functionOptions:
schema:
type: array
minItems: 1
items:
type: object
minProperties: 1

operation-description-required:
description: Every operation must document what it does.
message: "Operation is missing a description"
given: "$.paths[*][get,put,post,delete,options,head,patch,trace]"
severity: warn
then:
field: description
function: truthy

error-response-schema:
description: Every 4xx/5xx response must define an application/json response schema.
message: "Error response is missing an application/json schema"
given: "$.paths[*][get,put,post,delete,options,head,patch,trace].responses[?(@property >= 400 && @property < 600)]"
severity: warn
then:
field: content.application/json.schema
function: truthy

The severities reflect what should block a merge. Naming and security are error because this example treats them as non-negotiable. operationId is error because SDK generators build method names from it. Descriptions and error schemas are warn: they matter, but they shouldn't block merges during the initial rollout.

If you've used spectral:oas before, you'll notice it already has operation-operationId and operation-description rules. For CLI-only use, the idiomatic approach is to override the built-in's severity (operation-operationId: error under rules) instead of adding a new rule, because with both, the CLI reports the same issue twice. This guide uses standalone rules on purpose: the built-ins don't show up in WSO2 API Platform's results (see Beyond the CLI), and a self-contained rule doesn't depend on which built-in rules an environment loads.

The Security Rule​

This rule has to catch two different cases. One is a missing security field. The other is security: [], which explicitly removes any requirement inherited from the top level.

truthy only catches the first, because an empty array is truthy in JavaScript. The schema function catches both, plus one more: minItems: 1 rejects an empty array, and items.minProperties: 1 rejects {}, an entry that names no scheme and which OpenAPI treats as "authentication optional."

security: []      # flagged by minItems: declares nothing
security:
- {} # flagged by minProperties: makes authentication optional
security:
- oauth2: [] # passes: names a scheme

Be clear about what this rule doesn't do. Requiring security is your policy, not an OpenAPI rule. The check confirms that security is present, non-empty, and names a scheme. It doesn't confirm that oauth2 exists under components.securitySchemes, that its scopes are valid, or that it fits your authentication model. Those need their own rules.

It also requires each operation to declare security itself, so on Spectral 6.16.3 it flags operations that inherit a root-level security. If your standard allows inheritance, replace it with a rule that evaluates the effective security.

The Error-Response Rule​

This rule checks only for an application/json schema on 4xx and 5xx responses. A response that uses application/problem+json is flagged even if it has a schema (on Spectral 6.16.3), so change field if your error media type differs.

The filter also compares response keys as numbers, so it skips 4XX, 5XX, and default. If your specs use range keys, extend it:

    given: "$.paths[*][get,put,post,delete,options,head,patch,trace].responses[?(@property >= 400 && @property < 600 || @property == '4XX' || @property == '5XX')]"

You can tighten this rule over time. WSO2's REST API design guidelines define an error model with required code and message fields, optional description and moreInfo fields, and an error array that lists each error separately when more than one occurs. Start by requiring a schema, then require the key fields, then validate the full model.

Running the Ruleset​

Here's a small spec that breaks all five rules:

openapi: 3.0.3
info:
title: Orders API
version: 1.0.0
paths:
/order_items:
get:
summary: List order items
responses:
"500":
description: Internal error

Linting it fires every custom rule and exits with status 1. The output below omits the seven spectral:oas findings for readability, including the duplicate operation-operationId and operation-description warnings:

6:16    error  path-kebab-case                 /order_items should be kebab-case (e.g. /order-items, not /order_items)
7:9 warning operation-description-required Operation is missing a description
7:9 error operation-operationId-required Operation is missing an operationId
7:9 error operation-security-required Operation is missing a security requirement
10:15 warning error-response-schema Error response is missing an application/json schema

To fix it, rename the path to /order-items, add an operationId and a description, add an apiKey security requirement, and point the 500 response at an Error schema with a $ref. Lint again: none of the five rules fire, and the command exits 0. Some spectral:oas warnings, such as the missing servers, still print.

Before you share the ruleset with your team, test it against both inline definitions and $refs. A $ref changes which node a rule evaluates and where the finding is reported. For an example, see "Does Spectral resolve $ref before linting?" in the FAQ.

Save the ruleset as .spectral.yaml, and spectral lint picks it up automatically. The rest of this guide runs this same file in CI and in WSO2 API Platform.

In the Editor: API Designer​

The editor is the earliest point to catch a violation. API Designer is WSO2's VS Code extension for designing OpenAPI specs. Its Design view shows errors and warnings from Spectral-based governance rulesets.

Three report cards sit at the top of the Design view: AI Readiness, Security (OWASP), and REST Compliance, which measures alignment with WSO2's REST API design guidelines. In the example below, GET /customers has no summary or description, the same kind of issue operation-description-required catches.

API Designer Design view in VS Code showing AI Readiness, Security (OWASP), and REST Compliance score cards above an operation with an undefined summary and description

See full report opens a detailed view with the overall score, passed checks, affected endpoints, and error and warning counts. It breaks results down by category and groups violations by rule, severity, or area of the spec.

The screenshot below shows the AI Readiness report for a sample Leave Management API. The score and the passed-check count are separate measures, so 78% doesn't mean 78% of checks passed. The extension bundles three Spectral rulesets: WSO2 REST API AI Readiness Guidelines, WSO2 REST API Design Guidelines, and OWASP API Security Top 10. You can fix findings with GitHub Copilot Chat or the form-based editor.

API Designer AI Readiness report with a 78% score, 33 of 64 passed checks, 19 affected endpoints, 20 errors, 293 warnings, and a breakdown by dimension

Because these are Spectral rulesets, you can supply your own. Point apiDesigner.spectral.rulesetFolder at a GitHub folder URL or a local directory:

{
"apiDesigner.spectral.rulesetFolder": "https://github.com/<org>/<repo>/tree/main/<path>"
}

API Designer matches a custom ruleset to a report by filename, so name each file after the report it replaces: ai-readiness.yaml, owasp_top_10.yaml, or wso2_rest_api_design_guidelines.yaml. If a file fails to parse, API Designer shows a warning and falls back to the bundled default.

What you can customize depends on the report. You can edit existing rules in all three. New OWASP rules should use the owasp:apiN:2023-<description> ID format, new REST design rules appear under Others, and the API Designer documentation advises against adding new AI Readiness rules. The easiest starting point is to copy WSO2's bundled rulesets and edit them.

Running Spectral in CI/CD​

Editor feedback is advisory, and a ruleset that only runs on laptops enforces nothing. Run spectral lint on every pull request and it becomes a gate. Here's a GitHub Actions workflow with a pinned CLI version:

name: Lint OpenAPI Spec

on:
pull_request:

permissions:
contents: read

jobs:
spectral-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
- run: npm ci
- run: npx spectral lint openapi.yaml --fail-severity=error --format github-actions

The workflow runs on every pull request. Don't add a paths filter if you make it a required check: when a filtered workflow is skipped, GitHub leaves the required check pending and blocks the merge.

The workflow installs Spectral with npm ci and runs it through npx, so it uses the exact version recorded in package-lock.json. Commit package.json and the lock file alongside the ruleset:

{
"private": true,
"devDependencies": {
"@stoplight/spectral-cli": "6.16.3"
}
}

--format github-actions turns findings into inline pull request annotations, so reviewers see each violation on the line that caused it. For GitHub code scanning, use --format sarif --output spectral.sarif and upload the file instead.

Pinning matters more once linting gates merges. A new Spectral release can add, remove, or change built-in rules and messages, and your builds would start failing (or passing) without any change to your ruleset.

An error finding makes Spectral exit with a non-zero status, which fails the step. Make the job a required status check in your branch protection rules, and a failing lint blocks the merge. warn findings still appear in the log and as annotations, but they don't fail the job at the default threshold.

Other CI platforms work the same way: run the command as a job step in GitLab CI or as a run step in CircleCI. The platform triggers the check, and Spectral's exit status decides the result.

Linting doesn't replace contract testing. Linting checks that the spec follows your rules before the API is built. Contract testing checks that the running API matches the spec. Tools such as Schemathesis generate requests from an OpenAPI schema and validate the responses. Use both: lint the contract, then test the implementation against it.

Beyond the CLI: Applying API Governance with WSO2​

CI only sees changes that go through the pipeline. Some APIs never do: they're created or edited directly in a platform console. For those, the question shifts from "did this commit pass?" to "is every API in the organization compliant?"

WSO2 API Platform answers that with Spectral-based compliance validation. According to the WSO2 API Platform documentation, rulesets are Spectral YAML rule definitions used to validate API artifacts. You attach rulesets to a policy and apply the policy globally, and the platform evaluates existing and new API proxies automatically. No one has to run a linter or wire one into a pipeline.

What we found in testing

The platform uses the same given, then, and function rule model, but it evaluates rules in its own environment, so the results aren't identical to the CLI. We tested this guide's ruleset in the WSO2 API Platform Console and found two differences:

  • Built-in rules from extends: spectral:oas didn't appear in the results. Only the custom rules did.
  • Importing an API added a default security requirement before the rules ran.

Both are covered below, in What the Compliance Dashboard Shows and Same Rule Model, Different Execution Environments. Treat CLI and platform results as complementary, and check your rulesets in the compliance dashboard before you rely on them.

Rulesets and Policies in the Console​

In the WSO2 API Platform Console, governance lives under Admin > Governance, on the Policies tab, in the Rulesets section. Every organization starts with three locked default rulesets, each available as a Spectral ruleset file in JSON: WSO2 API Design Guidelines, WSO2 Style Guidelines, and OWASP Top 10. Custom rulesets you add can be edited.

The WSO2 API Design Guidelines ruleset has 11 rules, including path-casing (error) and resource-names-plural (warn). path-casing is the platform's equivalent of the kebab-case rule you wrote earlier.

WSO2 API Platform Console governance page showing default Spectral rulesets: WSO2 API Design Guidelines, WSO2 Style Guidelines, and OWASP Top 10

Add Ruleset opens a form that takes a name, an optional description, a Spectral Ruleset file (.yaml, .yml, or .json), an optional Document Link, and a required Provider Name. Applies To is fixed to API Definitions, and Artifact Type is set to HTTP API.

Upload the practical ruleset from earlier, the same file the CLI uses. The console accepts it as is.

Create Spectral Ruleset form in WSO2 API Platform Console with the practical governance ruleset YAML file uploaded

A ruleset takes effect only once it's attached to a Policy. The policy form sets an enforcement action for each severity: error, warn, and info. By default, the Enforcement Details table has an Update row with Notify selected for all three. Notify reports violations in the compliance dashboard without blocking the API from being created. Applicability is set to Global.

Create Policy form in WSO2 API Platform Console showing severity-based enforcement (Error, Warning, Info) and ruleset selection

What the Compliance Dashboard Shows​

To see the policy work, import a deliberately non-compliant definition as a new API proxy. We used a slightly larger spec than the CLI example: a /order_items path with both get and post operations, no operationId values or descriptions, and a 500 response with no schema. The platform evaluates the API as soon as the proxy is created, with no separate linting step.

The Insights > Compliance dashboard showed Errors (2), Warnings (2), Info (0), and Passed (1). These count rules, not individual violations, so they add up to the ruleset's five rules.

WSO2 API Platform Compliance Dashboard showing violations detected automatically: operation-operationId-required and path-kebab-case errors from the custom ruleset

Under Errors, operation-operationId-required flags $.paths['/order_items'].get and .post, and path-kebab-case flags $.paths['/order_items'], each with the message defined in the ruleset. Under Warnings, operation-description-required and error-response-schema appear, the latter at $.paths['/order_items'].get.responses['500'].

The fifth rule, operation-security-required, shows as Passed. That's the result to be careful with.

Why the security rule passed

The CLI evaluates the document exactly as written. On import, the console added a default security requirement to the API and to every operation, including operations that explicitly declared security: []. You can see it under View Source in the API proxy contract, where the API is marked Secured.

The rule runs against that enriched definition, so there's nothing to flag. The same source document fails this rule in the CLI and passes it in the platform. The schema function itself works in the console; what differs is the input.

As tested, operation-security-required can't fail in the platform, and a Passed result there doesn't mean the source spec declares security. Enforce this rule in CI, where it sees the document as written.

A compliant spec behaves as expected. With kebab-case paths (including an /inventory-items/{itemId} placeholder), an operationId and description on every operation, and a schema on the error response, the dashboard showed Errors (0), Warnings (0), and Passed (5).

The dashboard also rolls compliance up to the organization, project, and component levels, by policy and, at the component level, by ruleset. Platform teams can see where they stand without opening each API. For details, see the compliance documentation and WSO2's overview of the broader API governance program.

Same Rule Model, Different Execution Environments​

You can write a ruleset once and run it in three places, but each place evaluates something different, so don't expect identical findings:

EnvironmentWhat is evaluatedMain purpose
Spectral CLIThe API description you supplyLocal development and CI
API DesignerThe spec you're editing in VS CodeEarly design feedback
WSO2 API PlatformThe API definition after platform/import processingOrganization-wide compliance reporting

The differences come from three sources. The input: the console added a default security requirement on import. The ruleset: the spectral:oas built-ins didn't appear in the console. The outcome: a non-zero exit code in CI, a Notify result in the dashboard, and a score in API Designer. Reference handling, on the other hand, was consistent: an internal $ref to a response was evaluated at the referenced location in both the CLI and the console.

Test your rules in every environment you rely on.

Spectral vs. Other OpenAPI Linters​

Spectral fits this workflow well, but it isn't the only option:

ToolLanguage/RuntimeCustom RulesBest For
SpectralNode.js (JSONPath Plus)Full: built-in functions + custom JavaScriptGeneral-purpose OpenAPI/AsyncAPI linting
VacuumGo (single binary; also available via Homebrew, npm, and Docker)Reads Spectral rulesets, plus custom functions in JavaScript or GoPerformance-focused linting that reuses existing Spectral rulesets
Speakeasy's linterGo, built on Speakeasy's open source OpenAPI libraryCustom rules in TypeScript/JavaScript, configured in Speakeasy's own lint.yaml formatTeams generating SDKs, where a spec has to be "generation-safe," not just spec-valid

Vacuum is a Go-based linter focused on speed that reads Spectral rulesets, so it's worth benchmarking if you have very large specs or slow CI. Speakeasy's linter is built around SDK-generation readiness, with 90+ built-in rules according to its documentation. It uses its own rule format, so Spectral rulesets don't carry over. To evaluate them, see the Vacuum repository and the Speakeasy linter documentation.

Conclusion​

A Spectral ruleset is your API design guidelines in executable form. Write it once and you can run it at three points: in the editor for early feedback, in CI to block non-compliant changes, and in a governance platform to monitor every API in the organization, including the ones that never pass through your pipeline.

Each environment evaluates rules a little differently, so test your rules where you use them. Start small: take the five rules from this guide, run them as warn against your existing specs, and promote them to error as the findings get fixed.

If you already lint in CI, WSO2 API Platform accepts the same ruleset file and reports compliance across your organization. Keep CI as the gate for rules such as operation-security-required that depend on the source document as written.

Frequently Asked Questions​

What's the difference between Spectral and a validator?

A validator checks that a document conforms to a specification: required fields are present, types are correct, and references resolve. Spectral can run structural checks too, but its value here is enforcing design rules on top of a valid document, such as naming conventions, required metadata, and organizational standards.

Can Spectral lint AsyncAPI?

Yes. Spectral ships a spectral:asyncapi ruleset alongside spectral:oas, and custom rules use the same given, then, and function syntax, targeting AsyncAPI's document structure.

Does Spectral resolve $ref before linting?

Yes, including references to external files. What a rule evaluates, and where a finding is reported, depends on how the rule targets the document.

For example, in Spectral 6.16.3 the error-response-schema rule follows a 500 response declared as $ref: '#/components/responses/InternalError'. If InternalError has an application/json schema, the rule passes. If it doesn't, Spectral reports the finding where InternalError is defined, not on the line with the $ref. External references such as ./responses.yaml#/InternalError behave the same way, and so did an internal response $ref in WSO2 API Platform.

Results can depend on document structure and Spectral version, so test your rules against the file layouts in your own repositories.

Will the same ruleset give the same results everywhere?

Not necessarily. The input, the available built-in rules, and the enforcement behavior differ between the Spectral CLI, API Designer, and WSO2 API Platform. See Same Rule Model, Different Execution Environments.

Is Spectral free to use?

Yes. Spectral is open source under the Apache 2.0 license, and the CLI has no paid tier.

Can I lint from an editor instead of the terminal?

Yes. Stoplight's Spectral extension for VS Code lints as you type or on save, depending on its configuration. WSO2's API Designer extension also runs governance checks using Spectral rulesets and AI, with reports for the WSO2 REST API AI Readiness Guidelines, WSO2 REST API Design Guidelines, and OWASP API Security Top 10.

WSO2 API PlatformWSO2 API Platform

The open, universal platform for managing every API and AI service at scale. 100% open source.

Explore

BlogTutorialsTopics
© WSO2 LLC. All rights reserved.
WSO2 LegalDo Not Sell My Personal InformationModern Slavery Statement