SpotOn · API Governance Rules

SpotOn API Rules

Spectral linting rules defining API design standards and conventions for SpotOn.

35 Rules error 10 warn 20 info 5
View Rules File View on GitHub

Rule Categories

error get info microcks openapi operation parameter paths post request response schema security servers tag

Rules

warn
info-title-spoton-prefix
API title should start with "SpotOn".
$.info
warn
info-description-required
Info object must have a description of at least 40 characters.
$.info
error
info-version-required
Info object must declare a version.
$.info
info
info-contact-required
Info object should include contact information.
$.info
warn
openapi-version-3
Specs must be OpenAPI 3.0.x.
$
error
servers-defined
A servers array must be defined.
$
error
servers-https-only
Server URLs must use HTTPS.
$.servers[*]
warn
servers-have-description
Each server should have a description (for example Production or Sandbox).
$.servers[*]
warn
paths-kebab-case
Path segments must be lowercase kebab-case (path parameters in camelCase braces allowed).
$.paths[*]~
error
paths-no-trailing-slash
Paths must not end with a trailing slash.
$.paths[*]~
error
operation-operationid-required
Every operation must declare an operationId.
$.paths[*][get,post,put,patch,delete]
warn
operation-operationid-camelcase
operationId should be camelCase.
$.paths[*][get,post,put,patch,delete]
error
operation-summary-required
Every operation must have a summary.
$.paths[*][get,post,put,patch,delete]
warn
operation-summary-spoton-prefix
Operation summaries should start with "SpotOn".
$.paths[*][get,post,put,patch,delete]
warn
operation-description-required
Every operation must have a description.
$.paths[*][get,post,put,patch,delete]
warn
operation-tags-required
Every operation must be tagged.
$.paths[*][get,post,put,patch,delete]
info
tag-has-description
Global tags should have descriptions.
$.tags[*]
warn
tag-title-case
Tag names should be Title Case.
$.tags[*]
warn
parameter-description-required
Parameters must have a description.
$.paths[*][get,post,put,patch,delete].parameters[*]
warn
parameter-camelcase
Parameter names should be camelCase.
$.paths[*][get,post,put,patch,delete].parameters[?(@.name && @.in != 'header')]
error
parameter-no-apikey-in-query
API keys must be passed in the x-api-key header, never in query parameters.
$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')]
warn
request-body-json
Request bodies should offer an application/json representation.
$.paths[*][post,put,patch].requestBody.content
error
response-success-defined
Operations must define a 200 success response.
$.paths[*][get,post,put,patch,delete].responses
warn
response-unauthorized-defined
Operations should define a 401 Unauthorized response.
$.paths[*][get,post,put,patch,delete].responses
warn
response-forbidden-defined
Operations should define a 403 Forbidden response for per-location and per-restaurant access.
$.paths[*][get,post,put,patch,delete].responses
info
response-server-error-defined
Operations should define a 500 server error response.
$.paths[*][get,post,put,patch,delete].responses
warn
error-schema-has-message
The Error schema must include a message property.
$.components.schemas.Error.properties
warn
schema-property-camelcase
Schema property names should be camelCase.
$.components.schemas[*].properties[*]~
warn
schema-property-has-type-or-ref
Schema properties must declare a type or a $ref.
$.components.schemas[*].properties[*]
info
schema-top-level-description
Top-level component schemas should have a description.
$.components.schemas[*]
warn
security-global-defined
A global security requirement must be declared.
$
error
security-apikey-scheme-defined
An apiKeyAuth security scheme using the x-api-key header must be defined.
$.components.securitySchemes.apiKeyAuth
error
get-no-request-body
GET operations must not declare a request body.
$.paths[*].get
warn
post-has-request-body
POST operations should declare a request body.
$.paths[*].post
info
microcks-operation-present
Operations should carry an x-microcks-operation extension for mock-server compatibility.
$.paths[*][get,post,put,patch,delete]

Spectral Ruleset

Raw ↑
# Spectral ruleset for SpotOn APIs
# Enforces the conventions observed across the SpotOn Restaurant POS Export API
# and the SpotOn Reserve API: kebab-case paths, camelCase parameters and schema
# properties, x-api-key header authentication, Title Case tags, and complete
# operation metadata.
extends: [[spectral:oas, off]]

rules:

  # ── INFO / METADATA ─────────────────────────────────────────────
  info-title-spoton-prefix:
    description: API title should start with "SpotOn".
    severity: warn
    given: $.info
    then:
      field: title
      function: pattern
      functionOptions:
        match: "^SpotOn"
  info-description-required:
    description: Info object must have a description of at least 40 characters.
    severity: warn
    given: $.info
    then:
      field: description
      function: length
      functionOptions:
        min: 40
  info-version-required:
    description: Info object must declare a version.
    severity: error
    given: $.info
    then:
      field: version
      function: truthy
  info-contact-required:
    description: Info object should include contact information.
    severity: info
    given: $.info
    then:
      field: contact
      function: truthy

  # ── OPENAPI VERSION ─────────────────────────────────────────────
  openapi-version-3:
    description: Specs must be OpenAPI 3.0.x.
    severity: warn
    given: $
    then:
      field: openapi
      function: pattern
      functionOptions:
        match: "^3\\.0\\."

  # ── SERVERS ─────────────────────────────────────────────────────
  servers-defined:
    description: A servers array must be defined.
    severity: error
    given: $
    then:
      field: servers
      function: truthy
  servers-https-only:
    description: Server URLs must use HTTPS.
    severity: error
    given: $.servers[*]
    then:
      field: url
      function: pattern
      functionOptions:
        match: "^https://"
  servers-have-description:
    description: Each server should have a description (for example Production or Sandbox).
    severity: warn
    given: $.servers[*]
    then:
      field: description
      function: truthy

  # ── PATHS — NAMING CONVENTIONS ─────────────────────────────────
  paths-kebab-case:
    description: Path segments must be lowercase kebab-case (path parameters in camelCase braces allowed).
    severity: warn
    given: $.paths[*]~
    then:
      function: pattern
      functionOptions:
        match: "^(/([a-z0-9-]+|\\{[a-zA-Z0-9]+\\}))+$"
  paths-no-trailing-slash:
    description: Paths must not end with a trailing slash.
    severity: error
    given: $.paths[*]~
    then:
      function: pattern
      functionOptions:
        notMatch: ".+/$"

  # ── OPERATIONS ─────────────────────────────────────────────────
  operation-operationid-required:
    description: Every operation must declare an operationId.
    severity: error
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: operationId
      function: truthy
  operation-operationid-camelcase:
    description: operationId should be camelCase.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: operationId
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"
  operation-summary-required:
    description: Every operation must have a summary.
    severity: error
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: summary
      function: truthy
  operation-summary-spoton-prefix:
    description: Operation summaries should start with "SpotOn".
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: summary
      function: pattern
      functionOptions:
        match: "^SpotOn "
  operation-description-required:
    description: Every operation must have a description.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: description
      function: truthy
  operation-tags-required:
    description: Every operation must be tagged.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: tags
      function: truthy

  # ── TAGS ────────────────────────────────────────────────────────
  tag-has-description:
    description: Global tags should have descriptions.
    severity: info
    given: $.tags[*]
    then:
      field: description
      function: truthy
  tag-title-case:
    description: Tag names should be Title Case.
    severity: warn
    given: $.tags[*]
    then:
      field: name
      function: pattern
      functionOptions:
        match: "^[A-Z][A-Za-z0-9]*( [A-Z][A-Za-z0-9]*)*$"

  # ── PARAMETERS ─────────────────────────────────────────────────
  parameter-description-required:
    description: Parameters must have a description.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].parameters[*]
    then:
      field: description
      function: truthy
  parameter-camelcase:
    description: Parameter names should be camelCase.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.name && @.in != 'header')]
    then:
      field: name
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"
  parameter-no-apikey-in-query:
    description: API keys must be passed in the x-api-key header, never in query parameters.
    severity: error
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')]
    then:
      field: name
      function: pattern
      functionOptions:
        notMatch: "(?i)(api[-_]?key|apikey|x-api-key)"

  # ── REQUEST BODIES ─────────────────────────────────────────────
  request-body-json:
    description: Request bodies should offer an application/json representation.
    severity: warn
    given: $.paths[*][post,put,patch].requestBody.content
    then:
      field: application/json
      function: truthy

  # ── RESPONSES ──────────────────────────────────────────────────
  response-success-defined:
    description: Operations must define a 200 success response.
    severity: error
    given: $.paths[*][get,post,put,patch,delete].responses
    then:
      field: "200"
      function: truthy
  response-unauthorized-defined:
    description: Operations should define a 401 Unauthorized response.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].responses
    then:
      field: "401"
      function: truthy
  response-forbidden-defined:
    description: Operations should define a 403 Forbidden response for per-location and per-restaurant access.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].responses
    then:
      field: "403"
      function: truthy
  response-server-error-defined:
    description: Operations should define a 500 server error response.
    severity: info
    given: $.paths[*][get,post,put,patch,delete].responses
    then:
      field: "500"
      function: truthy
  error-schema-has-message:
    description: The Error schema must include a message property.
    severity: warn
    given: $.components.schemas.Error.properties
    then:
      field: message
      function: truthy

  # ── SCHEMAS — PROPERTY NAMING ──────────────────────────────────
  schema-property-camelcase:
    description: Schema property names should be camelCase.
    severity: warn
    given: $.components.schemas[*].properties[*]~
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"
  schema-property-has-type-or-ref:
    description: Schema properties must declare a type or a $ref.
    severity: warn
    given: $.components.schemas[*].properties[*]
    then:
      function: schema
      functionOptions:
        schema:
          anyOf:
            - required: [type]
            - required: ["$ref"]
  schema-top-level-description:
    description: Top-level component schemas should have a description.
    severity: info
    given: $.components.schemas[*]
    then:
      field: description
      function: truthy

  # ── SECURITY ───────────────────────────────────────────────────
  security-global-defined:
    description: A global security requirement must be declared.
    severity: warn
    given: $
    then:
      field: security
      function: truthy
  security-apikey-scheme-defined:
    description: An apiKeyAuth security scheme using the x-api-key header must be defined.
    severity: error
    given: $.components.securitySchemes.apiKeyAuth
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          required: [type, in, name]
          properties:
            type:
              const: apiKey
            in:
              const: header
            name:
              const: x-api-key

  # ── HTTP METHOD CONVENTIONS ────────────────────────────────────
  get-no-request-body:
    description: GET operations must not declare a request body.
    severity: error
    given: $.paths[*].get
    then:
      field: requestBody
      function: falsy
  post-has-request-body:
    description: POST operations should declare a request body.
    severity: warn
    given: $.paths[*].post
    then:
      field: requestBody
      function: truthy

  # ── GENERAL QUALITY ────────────────────────────────────────────
  microcks-operation-present:
    description: Operations should carry an x-microcks-operation extension for mock-server compatibility.
    severity: info
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: x-microcks-operation
      function: truthy