TheTVDB · API Governance Rules

TheTVDB API Rules

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

36 Rules error 12 warn 20
View Rules File View on GitHub

Rule Categories

tvdb

Rules

warn
tvdb-info-title-prefix
API title should reference TVDB
$.info.title
warn
tvdb-info-description-required
API info must include a description
$.info
error
tvdb-info-version-required
API info must include a version
$.info
warn
tvdb-openapi-version
Specs must declare OpenAPI 3.0.x
$.openapi
error
tvdb-servers-defined
At least one server must be defined
$
error
tvdb-server-https
All servers must use HTTPS
$.servers[*].url
warn
tvdb-server-base-url
Production server should be api4.thetvdb.com
$.servers[*].url
warn
tvdb-path-snake-or-lowercase
Paths must use lowercase with optional snake_case segments (no camelCase or PascalCase resource names)
$.paths.*~
error
tvdb-path-no-trailing-slash
Paths must not end with a trailing slash
$.paths.*~
error
tvdb-path-no-query-string
Paths must not include query strings (use parameters instead)
$.paths.*~
error
tvdb-operation-id-required
All operations must have an operationId
$.paths[*][get,post,put,patch,delete].operationId
warn
tvdb-operation-id-camel-case
operationId values must use camelCase
$.paths[*][get,post,put,patch,delete].operationId
warn
tvdb-operation-summary-required
All operations must have a summary
$.paths[*][get,post,put,patch,delete]
warn
tvdb-summary-prefix
Operation summaries should begin with 'TheTVDB'
$.paths[*][get,post,put,patch,delete].summary
warn
tvdb-summary-title-case
Operation summaries must start with an uppercase letter (Title Case)
$.paths[*][get,post,put,patch,delete].summary
warn
tvdb-operation-tags-required
All operations must declare at least one tag
$.paths[*][get,post,put,patch,delete]
warn
tvdb-tag-title-case
Operation tag names should use Title Case
$.paths[*][get,post,put,patch,delete].tags[*]
warn
tvdb-parameter-description-required
All parameters should have a description
$.paths[*][get,post,put,patch,delete].parameters[*]
error
tvdb-parameter-schema-required
All parameters must declare a schema with a type
$.paths[*][get,post,put,patch,delete].parameters[*]
hint
tvdb-pagination-page-parameter
Use the 'page' query parameter for paginated list endpoints (snake_case lowercase)
$.paths[*][get].parameters[?(@.in == 'query' && (@.name == 'pageNum' || @.name == 'pagenum'))]
warn
tvdb-request-body-json
Request bodies must use application/json
$.paths[*][post,put,patch].requestBody.content
error
tvdb-response-2xx-required
Every operation must define a successful 2xx response
$.paths[*][get,post,put,patch,delete].responses
warn
tvdb-response-401-defined
Authenticated endpoints should document a 401 Unauthorized response
$.paths[*][get,post,put,patch,delete].responses
warn
tvdb-response-json-content
2xx responses must return application/json
$.paths[*][get,post,put,patch,delete].responses['200','201','202'].content
error
tvdb-response-description-required
All responses must have a description
$.paths[*][get,post,put,patch,delete].responses[*]
hint
tvdb-schema-property-snake-or-camel
Schema property names should be lowercase, snake_case, or camelCase
$.components.schemas[*].properties.*~
hint
tvdb-schema-id-int64
Identifier properties named 'id' should use integer format int64
$.components.schemas[*].properties.id
warn
tvdb-schema-score-numeric
'score' properties must be numeric (used for relative popularity sorting)
$.components.schemas[*].properties.score
error
tvdb-global-security-defined
Global security must be defined (TheTVDB uses JWT bearer)
$
error
tvdb-bearer-auth-scheme
A 'bearerAuth' security scheme must be defined under components.securitySchemes
$.components.securitySchemes
warn
tvdb-bearer-jwt-format
The bearerAuth security scheme must specify type 'http', scheme 'bearer', bearerFormat 'JWT'
$.components.securitySchemes.bearerAuth
warn
tvdb-login-unsecured
The /login endpoint must override global security with [] (no auth required to obtain a token)
$.paths['/login'].post
error
tvdb-get-no-request-body
GET operations must not have a request body
$.paths[*].get
warn
tvdb-delete-no-request-body
DELETE operations should not have a request body
$.paths[*].delete
warn
tvdb-no-empty-descriptions
Descriptions must not be empty
$..description
hint
tvdb-microcks-operation-defined
Operations should define x-microcks-operation for mock server compatibility
$.paths[*][get,post,put,patch,delete]

Spectral Ruleset

Raw ↑
extends:
  - spectral:oas

# Spectral ruleset for TheTVDB v4 API
# Codifies the conventions observed in https://github.com/thetvdb/v4-api/blob/main/docs/swagger.yml

rules:

  # ---------- INFO / METADATA ----------

  tvdb-info-title-prefix:
    description: API title should reference TVDB
    message: "Info title '{{value}}' should include 'TVDB'"
    severity: warn
    given: "$.info.title"
    then:
      function: pattern
      functionOptions:
        match: "TVDB"

  tvdb-info-description-required:
    description: API info must include a description
    severity: warn
    given: "$.info"
    then:
      field: description
      function: defined

  tvdb-info-version-required:
    description: API info must include a version
    severity: error
    given: "$.info"
    then:
      field: version
      function: defined

  # ---------- OPENAPI VERSION ----------

  tvdb-openapi-version:
    description: Specs must declare OpenAPI 3.0.x
    message: "OpenAPI version '{{value}}' should be 3.0.x"
    severity: warn
    given: "$.openapi"
    then:
      function: pattern
      functionOptions:
        match: "^3\\.0\\."

  # ---------- SERVERS ----------

  tvdb-servers-defined:
    description: At least one server must be defined
    severity: error
    given: "$"
    then:
      field: servers
      function: defined

  tvdb-server-https:
    description: All servers must use HTTPS
    message: "Server URL '{{value}}' must use HTTPS"
    severity: error
    given: "$.servers[*].url"
    then:
      function: pattern
      functionOptions:
        match: "^https://"

  tvdb-server-base-url:
    description: Production server should be api4.thetvdb.com
    message: "Server URL '{{value}}' should target api4.thetvdb.com"
    severity: warn
    given: "$.servers[*].url"
    then:
      function: pattern
      functionOptions:
        match: "thetvdb\\.com"

  # ---------- PATHS — NAMING CONVENTIONS ----------

  tvdb-path-snake-or-lowercase:
    description: Paths must use lowercase with optional snake_case segments (no camelCase or PascalCase resource names)
    message: "Path '{{property}}' must be lowercase (snake_case allowed)"
    severity: warn
    given: "$.paths.*~"
    then:
      function: pattern
      functionOptions:
        match: "^/[a-z0-9{}/_-]+$"

  tvdb-path-no-trailing-slash:
    description: Paths must not end with a trailing slash
    message: "Path '{{property}}' must not end with '/'"
    severity: error
    given: "$.paths.*~"
    then:
      function: pattern
      functionOptions:
        notMatch: ".+/$"

  tvdb-path-no-query-string:
    description: Paths must not include query strings (use parameters instead)
    message: "Path '{{property}}' must not contain '?'"
    severity: error
    given: "$.paths.*~"
    then:
      function: pattern
      functionOptions:
        notMatch: "\\?"

  # ---------- OPERATIONS ----------

  tvdb-operation-id-required:
    description: All operations must have an operationId
    message: "Operation must have an operationId"
    severity: error
    given: "$.paths[*][get,post,put,patch,delete].operationId"
    then:
      function: truthy

  tvdb-operation-id-camel-case:
    description: operationId values must use camelCase
    message: "operationId '{{value}}' must be camelCase"
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete].operationId"
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"

  tvdb-operation-summary-required:
    description: All operations must have a summary
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete]"
    then:
      field: summary
      function: defined

  tvdb-summary-prefix:
    description: Operation summaries should begin with 'TheTVDB'
    message: "Summary '{{value}}' should start with 'TheTVDB'"
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete].summary"
    then:
      function: pattern
      functionOptions:
        match: "^TheTVDB "

  tvdb-summary-title-case:
    description: Operation summaries must start with an uppercase letter (Title Case)
    message: "Summary '{{value}}' should use Title Case"
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete].summary"
    then:
      function: pattern
      functionOptions:
        match: "^[A-Z]"

  tvdb-operation-tags-required:
    description: All operations must declare at least one tag
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete]"
    then:
      field: tags
      function: defined

  # ---------- TAGS ----------

  tvdb-tag-title-case:
    description: Operation tag names should use Title Case
    message: "Tag '{{value}}' should start with an uppercase letter"
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete].tags[*]"
    then:
      function: pattern
      functionOptions:
        match: "^[A-Z]"

  # ---------- PARAMETERS ----------

  tvdb-parameter-description-required:
    description: All parameters should have a description
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete].parameters[*]"
    then:
      field: description
      function: defined

  tvdb-parameter-schema-required:
    description: All parameters must declare a schema with a type
    severity: error
    given: "$.paths[*][get,post,put,patch,delete].parameters[*]"
    then:
      field: schema
      function: defined

  tvdb-pagination-page-parameter:
    description: Use the 'page' query parameter for paginated list endpoints (snake_case lowercase)
    message: "Pagination parameters should be named 'page'"
    severity: hint
    given: "$.paths[*][get].parameters[?(@.in == 'query' && (@.name == 'pageNum' || @.name == 'pagenum'))]"
    then:
      function: falsy

  # ---------- REQUEST BODIES ----------

  tvdb-request-body-json:
    description: Request bodies must use application/json
    severity: warn
    given: "$.paths[*][post,put,patch].requestBody.content"
    then:
      field: "application/json"
      function: defined

  # ---------- RESPONSES ----------

  tvdb-response-2xx-required:
    description: Every operation must define a successful 2xx response
    severity: error
    given: "$.paths[*][get,post,put,patch,delete].responses"
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          anyOf:
            - required: ['200']
            - required: ['201']
            - required: ['202']
            - required: ['204']

  tvdb-response-401-defined:
    description: Authenticated endpoints should document a 401 Unauthorized response
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete].responses"
    then:
      field: '401'
      function: defined

  tvdb-response-json-content:
    description: 2xx responses must return application/json
    severity: warn
    given: "$.paths[*][get,post,put,patch,delete].responses['200','201','202'].content"
    then:
      field: "application/json"
      function: defined

  tvdb-response-description-required:
    description: All responses must have a description
    severity: error
    given: "$.paths[*][get,post,put,patch,delete].responses[*]"
    then:
      field: description
      function: defined

  # ---------- SCHEMAS — PROPERTY NAMING ----------

  tvdb-schema-property-snake-or-camel:
    description: Schema property names should be lowercase, snake_case, or camelCase
    message: "Property '{{property}}' should use snake_case or camelCase"
    severity: hint
    given: "$.components.schemas[*].properties.*~"
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9_]*$"

  tvdb-schema-id-int64:
    description: Identifier properties named 'id' should use integer format int64
    severity: hint
    given: "$.components.schemas[*].properties.id"
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          properties:
            type:
              const: integer

  tvdb-schema-score-numeric:
    description: "'score' properties must be numeric (used for relative popularity sorting)"
    severity: warn
    given: "$.components.schemas[*].properties.score"
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          properties:
            type:
              enum: [integer, number]

  # ---------- SECURITY ----------

  tvdb-global-security-defined:
    description: Global security must be defined (TheTVDB uses JWT bearer)
    severity: error
    given: "$"
    then:
      field: security
      function: defined

  tvdb-bearer-auth-scheme:
    description: A 'bearerAuth' security scheme must be defined under components.securitySchemes
    severity: error
    given: "$.components.securitySchemes"
    then:
      field: bearerAuth
      function: defined

  tvdb-bearer-jwt-format:
    description: The bearerAuth security scheme must specify type 'http', scheme 'bearer', bearerFormat 'JWT'
    severity: warn
    given: "$.components.securitySchemes.bearerAuth"
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          properties:
            type:
              const: http
            scheme:
              const: bearer
            bearerFormat:
              const: JWT
          required: [type, scheme, bearerFormat]

  tvdb-login-unsecured:
    description: The /login endpoint must override global security with [] (no auth required to obtain a token)
    severity: warn
    given: "$.paths['/login'].post"
    then:
      field: security
      function: defined

  # ---------- HTTP METHOD CONVENTIONS ----------

  tvdb-get-no-request-body:
    description: GET operations must not have a request body
    severity: error
    given: "$.paths[*].get"
    then:
      field: requestBody
      function: falsy

  tvdb-delete-no-request-body:
    description: DELETE operations should not have a request body
    severity: warn
    given: "$.paths[*].delete"
    then:
      field: requestBody
      function: falsy

  # ---------- GENERAL QUALITY ----------

  tvdb-no-empty-descriptions:
    description: Descriptions must not be empty
    severity: warn
    given: "$..description"
    then:
      function: truthy

  tvdb-microcks-operation-defined:
    description: Operations should define x-microcks-operation for mock server compatibility
    severity: hint
    given: "$.paths[*][get,post,put,patch,delete]"
    then:
      field: x-microcks-operation
      function: defined