ReqRes · API Governance Rules

ReqRes API Rules

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

43 Rules error 15 warn 18 info 10
View Rules File View on GitHub

Rule Categories

delete get info no openapi operation parameter paths post request response schema security servers tag

Rules

warn
info-title-reqres-prefix
Spec title should begin with "ReqRes".
$.info
error
info-description-required
Spec must include a non-empty description.
$.info
error
info-version-required
Spec must declare a version.
$.info
warn
info-contact-required
Spec should declare a contact block.
$.info
warn
info-license-required
Spec must include license info (ReqRes is MIT).
$.info
warn
openapi-version-3-0-x
Specs must target OpenAPI 3.0.x.
$.openapi
error
servers-defined
At least one server URL must be defined.
$
error
servers-https-required
All production server URLs must use HTTPS.
$.servers[?(@.url =~ /^https?:\/\/(?!localhost)/)].url
warn
servers-reqres-host
Production server URL should point at reqres.in.
$.servers[?([email protected]("localhost"))].url
error
paths-lowercase
Paths must be lowercase kebab-case.
$.paths.*~
error
paths-no-trailing-slash
Paths must not end with a trailing slash.
$.paths.*~
warn
paths-prefix-known
Top-level path segments must be one of /api, /app, /agent.
$.paths.*~
info
paths-plural-resources
Resource collections should use plural nouns (users, collections, app-users, orders).
$.paths.*~
error
operation-summary-required
Every operation must have a summary.
$.paths.*[get,post,put,patch,delete]
warn
operation-description-required
Every operation must have a description.
$.paths.*[get,post,put,patch,delete]
warn
operation-summary-reqres-prefix
Every operation summary must start with "ReqRes".
$.paths.*[get,post,put,patch,delete].summary
error
operation-operationid-required
Every operation must declare an operationId.
$.paths.*[get,post,put,patch,delete]
warn
operation-operationid-camelcase
operationId must be camelCase.
$.paths.*[get,post,put,patch,delete].operationId
info
operation-operationid-verb-prefix
operationId should begin with a known verb (list/get/create/update/delete/login/register/logout/verify/simulate).
$.paths.*[get,post,put,patch,delete].operationId
error
operation-tags-required
Every operation must declare at least one tag.
$.paths.*[get,post,put,patch,delete]
warn
operation-security-required
Every /api/* and /app/* operation must declare security; /agent/v1/* may be public.
$.paths[?(@property.match(/^\/(api|app)\//))][get,post,put,patch,delete]
info
operation-microcks-extension
Every operation should declare x-microcks-operation for mock-server compatibility.
$.paths.*[get,post,put,patch,delete]
warn
tag-title-case
Global tag names must use Title Case (Legacy, Authentication, Collections, App Users, Custom Endpoints, Agent Sandbox).
$.tags[*].name
info
tag-description-recommended
Each global tag should include a description.
$.tags[*]
warn
parameter-description-required
Every parameter must have a description.
$.paths.*[get,post,put,patch,delete].parameters[*]
warn
parameter-snake-or-camel
Parameter names must be snake_case or camelCase (page, per_page, recordId).
$.paths.*[get,post,put,patch,delete].parameters[*].name
info
parameter-pagination-page-per-page
Pagination parameters should be named page and per_page (ReqRes convention).
$.paths.*[get,post,put,patch,delete].parameters[?(@.in=="query" && (@.name=="limit" || @.name=="offset"))]
error
request-body-json-content
Request bodies must accept application/json.
$.paths.*[post,put,patch].requestBody.content
info
request-body-description-recommended
Request bodies should include a description.
$.paths.*[post,put,patch].requestBody
error
response-success-required
Every operation must define a 2xx success response.
$.paths.*[get,post,put,patch,delete].responses
warn
response-description-required
Every response must have a description.
$.paths.*[get,post,put,patch,delete].responses.*
warn
response-json-content
Success responses must return application/json.
$.paths.*[get,post,put,patch,delete].responses[?(@property.match(/^2\d\d$/))].content
info
response-401-on-secured
Secured operations should declare a 401 response.
$.paths.*[get,post,put,patch,delete][?(@.security)]
info
schema-property-snake-or-camel
Schema property names should be snake_case or camelCase.
$.components.schemas.*.properties.*~
info
schema-description-recommended
Top-level schemas should include a description.
$.components.schemas.*
error
schema-type-required
Top-level schemas must declare a type.
$.components.schemas.*
error
security-schemes-defined
components.securitySchemes must define ApiKeyAuth and BearerAuth.
$.components.securitySchemes
warn
security-apikey-header
ApiKeyAuth must use the x-api-key header.
$.components.securitySchemes.ApiKeyAuth
warn
security-bearer-format
BearerAuth must be an HTTP bearer scheme.
$.components.securitySchemes.BearerAuth
error
get-no-request-body
GET operations must not declare a request body.
$.paths.*.get
error
delete-no-request-body
DELETE operations must not declare a request body.
$.paths.*.delete
info
post-put-patch-require-body
POST, PUT, and PATCH operations should declare a request body (login/register/logout exempt).
$.paths.*[put,patch]
warn
no-empty-descriptions
Descriptions must be non-empty when present.
$..description

Spectral Ruleset

Raw ↑
extends: spectral:oas

rules:

  # ── INFO / METADATA ──────────────────────────────────────────────
  info-title-reqres-prefix:
    description: Spec title should begin with "ReqRes".
    severity: warn
    given: $.info
    then:
      field: title
      function: pattern
      functionOptions:
        match: '^ReqRes'

  info-description-required:
    description: Spec must include a non-empty description.
    severity: error
    given: $.info
    then:
      field: description
      function: truthy

  info-version-required:
    description: Spec must declare a version.
    severity: error
    given: $.info
    then:
      field: version
      function: truthy

  info-contact-required:
    description: Spec should declare a contact block.
    severity: warn
    given: $.info
    then:
      field: contact
      function: truthy

  info-license-required:
    description: Spec must include license info (ReqRes is MIT).
    severity: warn
    given: $.info
    then:
      field: license
      function: truthy

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

  # ── SERVERS ──────────────────────────────────────────────────────
  servers-defined:
    description: At least one server URL must be defined.
    severity: error
    given: $
    then:
      field: servers
      function: truthy

  servers-https-required:
    description: All production server URLs must use HTTPS.
    severity: error
    given: $.servers[?(@.url =~ /^https?:\/\/(?!localhost)/)].url
    then:
      function: pattern
      functionOptions:
        match: '^https://'

  servers-reqres-host:
    description: Production server URL should point at reqres.in.
    severity: warn
    given: $.servers[?([email protected]("localhost"))].url
    then:
      function: pattern
      functionOptions:
        match: 'reqres\.in'

  # ── PATHS — NAMING CONVENTIONS ───────────────────────────────────
  paths-lowercase:
    description: Paths must be lowercase kebab-case.
    severity: error
    given: $.paths.*~
    then:
      function: pattern
      functionOptions:
        match: '^/[a-z0-9/{}_\-]*$'

  paths-no-trailing-slash:
    description: Paths must not end with a trailing slash.
    severity: error
    given: $.paths.*~
    then:
      function: pattern
      functionOptions:
        notMatch: '.+/$'

  paths-prefix-known:
    description: Top-level path segments must be one of /api, /app, /agent.
    severity: warn
    given: $.paths.*~
    then:
      function: pattern
      functionOptions:
        match: '^/(api|app|agent)(/.*)?$'

  paths-plural-resources:
    description: Resource collections should use plural nouns (users, collections, app-users, orders).
    severity: info
    given: $.paths.*~
    then:
      function: pattern
      functionOptions:
        notMatch: '^/(api|app|agent/v\d+)/(user|collection|order|scenario)(/|$)'

  # ── OPERATIONS ───────────────────────────────────────────────────
  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-description-required:
    description: Every operation must have a description.
    severity: warn
    given: $.paths.*[get,post,put,patch,delete]
    then:
      field: description
      function: truthy

  operation-summary-reqres-prefix:
    description: Every operation summary must start with "ReqRes".
    severity: warn
    given: $.paths.*[get,post,put,patch,delete].summary
    then:
      function: pattern
      functionOptions:
        match: '^ReqRes'

  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 must be camelCase.
    severity: warn
    given: $.paths.*[get,post,put,patch,delete].operationId
    then:
      function: pattern
      functionOptions:
        match: '^[a-z][a-zA-Z0-9]*$'

  operation-operationid-verb-prefix:
    description: operationId should begin with a known verb (list/get/create/update/delete/login/register/logout/verify/simulate).
    severity: info
    given: $.paths.*[get,post,put,patch,delete].operationId
    then:
      function: pattern
      functionOptions:
        match: '^(list|get|create|update|replace|delete|login|register|logout|verify|simulate|fetch|run|execute|invoke|trigger)[A-Z]'

  operation-tags-required:
    description: Every operation must declare at least one tag.
    severity: error
    given: $.paths.*[get,post,put,patch,delete]
    then:
      field: tags
      function: truthy

  operation-security-required:
    description: Every /api/* and /app/* operation must declare security; /agent/v1/* may be public.
    severity: warn
    given: $.paths[?(@property.match(/^\/(api|app)\//))][get,post,put,patch,delete]
    then:
      field: security
      function: truthy

  operation-microcks-extension:
    description: Every operation should declare x-microcks-operation for mock-server compatibility.
    severity: info
    given: $.paths.*[get,post,put,patch,delete]
    then:
      field: x-microcks-operation
      function: truthy

  # ── TAGS ─────────────────────────────────────────────────────────
  tag-title-case:
    description: Global tag names must use Title Case (Legacy, Authentication, Collections, App Users, Custom Endpoints, Agent Sandbox).
    severity: warn
    given: $.tags[*].name
    then:
      function: pattern
      functionOptions:
        match: '^[A-Z][A-Za-z]+( [A-Z][A-Za-z]+)*$'

  tag-description-recommended:
    description: Each global tag should include a description.
    severity: info
    given: $.tags[*]
    then:
      field: description
      function: truthy

  # ── PARAMETERS ───────────────────────────────────────────────────
  parameter-description-required:
    description: Every parameter must have a description.
    severity: warn
    given: $.paths.*[get,post,put,patch,delete].parameters[*]
    then:
      field: description
      function: truthy

  parameter-snake-or-camel:
    description: Parameter names must be snake_case or camelCase (page, per_page, recordId).
    severity: warn
    given: $.paths.*[get,post,put,patch,delete].parameters[*].name
    then:
      function: pattern
      functionOptions:
        match: '^[a-z][a-z0-9_]*$|^[a-z][a-zA-Z0-9]*$'

  parameter-pagination-page-per-page:
    description: Pagination parameters should be named page and per_page (ReqRes convention).
    severity: info
    given: $.paths.*[get,post,put,patch,delete].parameters[?(@.in=="query" && (@.name=="limit" || @.name=="offset"))]
    then:
      field: name
      function: pattern
      functionOptions:
        notMatch: '^(limit|offset)$'

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

  request-body-description-recommended:
    description: Request bodies should include a description.
    severity: info
    given: $.paths.*[post,put,patch].requestBody
    then:
      field: description
      function: truthy

  # ── RESPONSES ────────────────────────────────────────────────────
  response-success-required:
    description: Every operation must define a 2xx success response.
    severity: error
    given: $.paths.*[get,post,put,patch,delete].responses
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          patternProperties:
            '^2\d\d$': {}
          minProperties: 1

  response-description-required:
    description: Every response must have a description.
    severity: warn
    given: $.paths.*[get,post,put,patch,delete].responses.*
    then:
      field: description
      function: truthy

  response-json-content:
    description: Success responses must return application/json.
    severity: warn
    given: $.paths.*[get,post,put,patch,delete].responses[?(@property.match(/^2\d\d$/))].content
    then:
      field: application/json
      function: truthy

  response-401-on-secured:
    description: Secured operations should declare a 401 response.
    severity: info
    given: $.paths.*[get,post,put,patch,delete][?(@.security)]
    then:
      field: responses.401
      function: truthy

  # ── SCHEMAS — PROPERTY NAMING ────────────────────────────────────
  schema-property-snake-or-camel:
    description: Schema property names should be snake_case or camelCase.
    severity: info
    given: $.components.schemas.*.properties.*~
    then:
      function: pattern
      functionOptions:
        match: '^[a-z][a-z0-9_]*$|^[a-z][a-zA-Z0-9]*$|^\$[a-z]+$|^@.+$'

  schema-description-recommended:
    description: Top-level schemas should include a description.
    severity: info
    given: $.components.schemas.*
    then:
      field: description
      function: truthy

  schema-type-required:
    description: Top-level schemas must declare a type.
    severity: error
    given: $.components.schemas.*
    then:
      field: type
      function: truthy

  # ── SECURITY ─────────────────────────────────────────────────────
  security-schemes-defined:
    description: components.securitySchemes must define ApiKeyAuth and BearerAuth.
    severity: error
    given: $.components.securitySchemes
    then:
      function: truthy

  security-apikey-header:
    description: ApiKeyAuth must use the x-api-key header.
    severity: warn
    given: $.components.securitySchemes.ApiKeyAuth
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          properties:
            type: { const: apiKey }
            in: { const: header }
            name: { const: x-api-key }
          required: [type, in, name]

  security-bearer-format:
    description: BearerAuth must be an HTTP bearer scheme.
    severity: warn
    given: $.components.securitySchemes.BearerAuth
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          properties:
            type: { const: http }
            scheme: { const: bearer }
          required: [type, scheme]

  # ── 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

  delete-no-request-body:
    description: DELETE operations must not declare a request body.
    severity: error
    given: $.paths.*.delete
    then:
      field: requestBody
      function: falsy

  post-put-patch-require-body:
    description: POST, PUT, and PATCH operations should declare a request body (login/register/logout exempt).
    severity: info
    given: $.paths.*[put,patch]
    then:
      field: requestBody
      function: truthy

  # ── GENERAL QUALITY ──────────────────────────────────────────────
  no-empty-descriptions:
    description: Descriptions must be non-empty when present.
    severity: warn
    given: '$..description'
    then:
      function: truthy