Wordnik · API Governance Rules

Wordnik API Rules

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

45 Rules error 9 warn 30 info 6
View Rules File View on GitHub

Rule Categories

external http info no openapi operation parameter paths request response schema security servers tag tags

Rules

error
info-title-required
Info block must define a title.
$
warn
info-title-wordnik-prefix
API title should start with "Wordnik".
$.info.title
warn
info-description-required
Info block must include a description of at least 40 characters.
$.info
error
info-version-required
API version must be declared.
$.info
warn
info-contact-required
Info block should expose contact details (Wordnik publishes [email protected]).
$.info
info
info-external-docs-required
An externalDocs link to the Wordnik developer portal should be present.
$
warn
openapi-version-3
Wordnik specs should be OpenAPI 3.x.
$.openapi
error
servers-required
At least one server entry must be defined.
$
error
servers-https-only
Server URLs must use HTTPS.
$.servers[*].url
warn
servers-wordnik-host
Servers should point at api.wordnik.com.
$.servers[*].url
warn
paths-lower-camel-json-suffix
Wordnik resource segments follow `lowerCamel.json` (e.g. /word.json, /words.json, /wordList.json).
$.paths.*~
error
paths-no-trailing-slash
Paths must not end with a trailing slash.
$.paths.*~
error
paths-no-query-string
Paths must not embed query strings.
$.paths.*~
error
operation-operation-id-required
Every operation must declare an operationId.
$.paths[*][get,post,put,delete,patch]
warn
operation-operation-id-camel-case
operationId must be camelCase (e.g. getDefinitions, getRandomWord, authenticatePost).
$.paths[*][get,post,put,delete,patch].operationId
warn
operation-operation-id-verb-prefix
operationId should start with a recognised verb prefix.
$.paths[*][get,post,put,delete,patch].operationId
warn
operation-summary-required
Every operation must include a summary.
$.paths[*][get,post,put,delete,patch]
warn
operation-summary-title-case
Operation summaries must be Title Case.
$.paths[*][get,post,put,delete,patch].summary
warn
operation-description-required
Every operation must include a description.
$.paths[*][get,post,put,delete,patch]
warn
operation-tags-required
Every operation must declare at least one tag.
$.paths[*][get,post,put,delete,patch]
info
operation-microcks-extension
Operations should expose an x-microcks-operation block so Microcks can mock them.
$.paths[*][get,post,put,delete,patch]
warn
tags-global-required
A global tags array must be defined.
$
warn
tag-title-case
Tag names must be Title Case (Word, Words, Word List, Word Lists, Account).
$.tags[*].name
warn
tag-description-required
Each global tag must have a description.
$.tags[*]
warn
parameter-description-required
Every parameter must include a description.
$.paths[*][*].parameters[*]
warn
parameter-name-camel-case
Parameter names must be camelCase (api_key and auth_token are the only documented exceptions).
$.paths[*][*].parameters[*].name
warn
parameter-schema-type-required
Every parameter must declare a schema type.
$.paths[*][*].parameters[*].schema
warn
parameter-api-key-in-query
Wordnik's api_key parameter must remain in the query string.
$.paths[*][*].parameters[?(@.name == "api_key")]
info
parameter-pagination-skip-limit
Pagination parameters should use skip + limit (the Wordnik convention).
$.paths[*][*].parameters[*].name
warn
request-body-content-required
Request bodies must declare a content map.
$.paths[*][post,put,patch].requestBody
error
response-success-required
Every operation must define at least one 2xx response.
$.paths[*][get,post,put,delete,patch].responses
warn
response-description-required
Each response must include a description.
$.paths[*][*].responses[*]
warn
response-json-content
Successful 2xx responses should declare an application/json content type.
$.paths[*][*].responses[?(@property.match(/^2/))].content
warn
schema-name-pascal-case
Component schema names must be PascalCase (WordObject, FrequencySummary, AuthenticationToken).
$.components.schemas.*~
warn
schema-property-camel-case
Schema property names must be camelCase.
$.components.schemas[*].properties.*~
warn
schema-type-required
Every schema must declare a type.
$.components.schemas[*]
info
schema-property-id-int64
id properties on Wordnik domain objects are int64.
$.components.schemas[*].properties.id
warn
security-global-required
A global security requirement should be declared.
$
warn
security-schemes-required
components.securitySchemes must declare both api_key and auth_token.
$.components.securitySchemes
warn
security-scheme-api-key-shape
api_key security scheme must be apiKey-in-query.
$.components.securitySchemes.api_key
error
http-get-no-request-body
GET operations must not declare a request body.
$.paths[*].get
warn
http-delete-no-request-body
DELETE operations must not declare a request body.
$.paths[*].delete
info
http-write-204-or-200
PUT / DELETE writes should return 200 or 204.
$.paths[*][put,delete].responses
warn
no-empty-descriptions
Description fields must not be empty.
$..description
info
external-docs-encouraged
An externalDocs link helps consumers find Wordnik's developer portal.
$

Spectral Ruleset

Raw ↑
# Wordnik API Spectral Ruleset
#
# Conventions derived from the Wordnik v4 OpenAPI specification served at
# https://developer.wordnik.com/api-docs/swagger.json:
#   - REST surface rooted at https://api.wordnik.com/v4
#   - Resource paths are lowerCamelCase + `.json` suffix (e.g. /word.json/{word}/examples)
#   - Parameter names are camelCase (useCanonical, partOfSpeech, sortBy)
#   - Operation IDs are camelCase with verb prefix (getDefinitions, getRandomWord)
#   - Schema component names are PascalCase (WordObject, Definition, FrequencySummary)
#   - Schema property names are camelCase (sourceDictionary, scoredWords, attributionText)
#   - Authentication is a single apiKey query parameter (`api_key`) plus an `auth_token`
#     header for user-scoped endpoints
#   - Title Case OpenAPI operation summaries (`Return Definitions For A Word`)

rules:
  # ── INFO / METADATA ────────────────────────────────────────────────
  info-title-required:
    description: Info block must define a title.
    given: $
    severity: error
    then:
      field: info.title
      function: truthy
  info-title-wordnik-prefix:
    description: API title should start with "Wordnik".
    message: 'Info title should start with "Wordnik": {{value}}'
    given: $.info.title
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: '^Wordnik'
  info-description-required:
    description: Info block must include a description of at least 40 characters.
    given: $.info
    severity: warn
    then:
      field: description
      function: length
      functionOptions: { min: 40 }
  info-version-required:
    description: API version must be declared.
    given: $.info
    severity: error
    then: { field: version, function: truthy }
  info-contact-required:
    description: Info block should expose contact details (Wordnik publishes [email protected]).
    given: $.info
    severity: warn
    then: { field: contact, function: truthy }
  info-external-docs-required:
    description: An externalDocs link to the Wordnik developer portal should be present.
    given: $
    severity: info
    then: { field: externalDocs, function: truthy }

  # ── OPENAPI VERSION ────────────────────────────────────────────────
  openapi-version-3:
    description: Wordnik specs should be OpenAPI 3.x.
    given: $.openapi
    severity: warn
    then:
      function: pattern
      functionOptions: { match: '^3\.' }

  # ── SERVERS ────────────────────────────────────────────────────────
  servers-required:
    description: At least one server entry must be defined.
    given: $
    severity: error
    then: { field: servers, function: truthy }
  servers-https-only:
    description: Server URLs must use HTTPS.
    given: $.servers[*].url
    severity: error
    then:
      function: pattern
      functionOptions: { match: '^https://' }
  servers-wordnik-host:
    description: Servers should point at api.wordnik.com.
    message: 'Server URL should reference api.wordnik.com: {{value}}'
    given: $.servers[*].url
    severity: warn
    then:
      function: pattern
      functionOptions: { match: '^https://api\.wordnik\.com/' }

  # ── PATHS — NAMING CONVENTIONS ─────────────────────────────────────
  paths-lower-camel-json-suffix:
    description: Wordnik resource segments follow `lowerCamel.json` (e.g. /word.json, /words.json, /wordList.json).
    message: 'Path segment "{{value}}" deviates from the lowerCamel.json convention.'
    given: $.paths.*~
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: '^/[a-z][a-zA-Z]*\.json(/[a-zA-Z0-9_{}\-]+)*$'
  paths-no-trailing-slash:
    description: Paths must not end with a trailing slash.
    given: $.paths.*~
    severity: error
    then:
      function: pattern
      functionOptions: { notMatch: '.+/$' }
  paths-no-query-string:
    description: Paths must not embed query strings.
    given: $.paths.*~
    severity: error
    then:
      function: pattern
      functionOptions: { notMatch: '\?' }

  # ── OPERATIONS ─────────────────────────────────────────────────────
  operation-operation-id-required:
    description: Every operation must declare an operationId.
    given: $.paths[*][get,post,put,delete,patch]
    severity: error
    then: { field: operationId, function: truthy }
  operation-operation-id-camel-case:
    description: operationId must be camelCase (e.g. getDefinitions, getRandomWord, authenticatePost).
    given: $.paths[*][get,post,put,delete,patch].operationId
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: '^[a-z][a-zA-Z0-9]*$'
  operation-operation-id-verb-prefix:
    description: operationId should start with a recognised verb prefix.
    message: 'operationId "{{value}}" should start with one of get|list|create|update|delete|search|authenticate|reverse|add.'
    given: $.paths[*][get,post,put,delete,patch].operationId
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: '^(get|list|create|update|delete|search|authenticate|reverse|add)[A-Z]'
  operation-summary-required:
    description: Every operation must include a summary.
    given: $.paths[*][get,post,put,delete,patch]
    severity: warn
    then: { field: summary, function: truthy }
  operation-summary-title-case:
    description: Operation summaries must be Title Case.
    message: 'Operation summary "{{value}}" should be Title Case (capitalize Each Major Word).'
    given: $.paths[*][get,post,put,delete,patch].summary
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: '^([A-Z][a-zA-Z0-9]*)( ([A-Z][a-zA-Z0-9]*|For|A|An|The|And|Or|Of|In|On|To|By|With|From))*$'
  operation-description-required:
    description: Every operation must include a description.
    given: $.paths[*][get,post,put,delete,patch]
    severity: warn
    then: { field: description, function: truthy }
  operation-tags-required:
    description: Every operation must declare at least one tag.
    given: $.paths[*][get,post,put,delete,patch]
    severity: warn
    then:
      field: tags
      function: length
      functionOptions: { min: 1 }
  operation-microcks-extension:
    description: Operations should expose an x-microcks-operation block so Microcks can mock them.
    given: $.paths[*][get,post,put,delete,patch]
    severity: info
    then: { field: x-microcks-operation, function: truthy }

  # ── TAGS ───────────────────────────────────────────────────────────
  tags-global-required:
    description: A global tags array must be defined.
    given: $
    severity: warn
    then:
      field: tags
      function: length
      functionOptions: { min: 1 }
  tag-title-case:
    description: Tag names must be Title Case (Word, Words, Word List, Word Lists, Account).
    given: $.tags[*].name
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: '^[A-Z][a-zA-Z]*( [A-Z][a-zA-Z]*)*$'
  tag-description-required:
    description: Each global tag must have a description.
    given: $.tags[*]
    severity: warn
    then: { field: description, function: truthy }

  # ── PARAMETERS ─────────────────────────────────────────────────────
  parameter-description-required:
    description: Every parameter must include a description.
    given: $.paths[*][*].parameters[*]
    severity: warn
    then: { field: description, function: truthy }
  parameter-name-camel-case:
    description: Parameter names must be camelCase (api_key and auth_token are the only documented exceptions).
    message: 'Parameter name "{{value}}" should be camelCase or the documented api_key / auth_token exception.'
    given: $.paths[*][*].parameters[*].name
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: '^([a-z][a-zA-Z0-9]*|api_key|auth_token)$'
  parameter-schema-type-required:
    description: Every parameter must declare a schema type.
    given: $.paths[*][*].parameters[*].schema
    severity: warn
    then: { field: type, function: truthy }
  parameter-api-key-in-query:
    description: Wordnik's api_key parameter must remain in the query string.
    message: 'api_key must be sent as a query parameter, not in header/path/cookie.'
    given: '$.paths[*][*].parameters[?(@.name == "api_key")]'
    severity: warn
    then:
      field: in
      function: pattern
      functionOptions: { match: '^query$' }
  parameter-pagination-skip-limit:
    description: Pagination parameters should use skip + limit (the Wordnik convention).
    given: $.paths[*][*].parameters[*].name
    severity: info
    then:
      function: pattern
      functionOptions:
        notMatch: '^(page|page_size|offset|pageSize|perPage|cursor)$'

  # ── REQUEST BODIES ────────────────────────────────────────────────
  request-body-content-required:
    description: Request bodies must declare a content map.
    given: $.paths[*][post,put,patch].requestBody
    severity: warn
    then: { field: content, function: truthy }

  # ── RESPONSES ─────────────────────────────────────────────────────
  response-success-required:
    description: Every operation must define at least one 2xx response.
    given: $.paths[*][get,post,put,delete,patch].responses
    severity: error
    then:
      function: pattern
      functionOptions: { match: '^2' }
  response-description-required:
    description: Each response must include a description.
    given: $.paths[*][*].responses[*]
    severity: warn
    then: { field: description, function: truthy }
  response-json-content:
    description: Successful 2xx responses should declare an application/json content type.
    given: $.paths[*][*].responses[?(@property.match(/^2/))].content
    severity: warn
    then:
      field: application/json
      function: truthy

  # ── SCHEMAS — PROPERTY NAMING ─────────────────────────────────────
  schema-name-pascal-case:
    description: Component schema names must be PascalCase (WordObject, FrequencySummary, AuthenticationToken).
    given: $.components.schemas.*~
    severity: warn
    then:
      function: pattern
      functionOptions: { match: '^[A-Z][a-zA-Z0-9]*$' }
  schema-property-camel-case:
    description: Schema property names must be camelCase.
    given: $.components.schemas[*].properties.*~
    severity: warn
    then:
      function: pattern
      functionOptions: { match: '^[a-z][a-zA-Z0-9]*$' }
  schema-type-required:
    description: Every schema must declare a type.
    given: $.components.schemas[*]
    severity: warn
    then: { field: type, function: truthy }
  schema-property-id-int64:
    description: id properties on Wordnik domain objects are int64.
    given: $.components.schemas[*].properties.id
    severity: info
    then:
      field: format
      function: pattern
      functionOptions: { match: '^int64$' }

  # ── SECURITY ──────────────────────────────────────────────────────
  security-global-required:
    description: A global security requirement should be declared.
    given: $
    severity: warn
    then: { field: security, function: truthy }
  security-schemes-required:
    description: components.securitySchemes must declare both api_key and auth_token.
    given: $.components.securitySchemes
    severity: warn
    then: { field: api_key, function: truthy }
  security-scheme-api-key-shape:
    description: api_key security scheme must be apiKey-in-query.
    given: $.components.securitySchemes.api_key
    severity: warn
    then:
      field: type
      function: pattern
      functionOptions: { match: '^apiKey$' }

  # ── HTTP METHOD CONVENTIONS ───────────────────────────────────────
  http-get-no-request-body:
    description: GET operations must not declare a request body.
    given: $.paths[*].get
    severity: error
    then: { field: requestBody, function: falsy }
  http-delete-no-request-body:
    description: DELETE operations must not declare a request body.
    given: $.paths[*].delete
    severity: warn
    then: { field: requestBody, function: falsy }
  http-write-204-or-200:
    description: PUT / DELETE writes should return 200 or 204.
    given: $.paths[*][put,delete].responses
    severity: info
    then:
      function: pattern
      functionOptions: { match: '^(200|204)' }

  # ── GENERAL QUALITY ───────────────────────────────────────────────
  no-empty-descriptions:
    description: Description fields must not be empty.
    given: $..description
    severity: warn
    then:
      function: length
      functionOptions: { min: 1 }
  external-docs-encouraged:
    description: An externalDocs link helps consumers find Wordnik's developer portal.
    given: $
    severity: info
    then: { field: externalDocs, function: truthy }