Workday Payroll · API Governance Rules

Workday Payroll API Rules

Spectral linting rules defining API design standards and conventions for Workday Payroll.

63 Rules error 21 warn 38 info 4
View Rules File View on GitHub

Rule Categories

collection delete examples external get global info no openapi operation parameter patch paths pay post ref request response schema security servers tags worker

Rules

warn
info-title-format
API title must follow the Workday Payroll naming pattern
$.info.title
error
info-description-required
API info must have a description
$.info
warn
info-description-min-length
API description should be at least 50 characters
$.info.description
error
info-version-required
API info must specify a version
$.info
warn
info-version-format
Version should follow the v{n} pattern (e.g. v1)
$.info.version
warn
info-contact-required
API info must include contact information
$.info
warn
info-contact-email
Contact must include an email address
$.info.contact
info
info-terms-of-service
API info should reference Workday terms of service
$.info
info
external-docs-required
APIs should provide external documentation links
$
error
openapi-version
APIs must use OpenAPI 3.1.x
$.openapi
error
servers-defined
At least one server must be defined
$
error
servers-https
All server URLs must use HTTPS
$.servers[*].url
warn
servers-description-required
All servers should include a description
$.servers[*]
warn
servers-versioned-path
Server URLs should include a version segment (e.g. /v1)
$.servers[*].url
warn
paths-camel-case
Path segments must use camelCase resource names (Workday convention)
$.paths[*]~
error
paths-no-trailing-slash
Paths must not have trailing slashes
$.paths[*]~
error
paths-no-query-strings
Paths must not contain query strings
$.paths[*]~
error
operation-summary-required
All operations must have a summary
$.paths[*][get,post,put,patch,delete]
warn
operation-summary-prefix
Operation summaries should start with "Workday Payroll"
$.paths[*][get,post,put,patch,delete].summary
warn
operation-description-required
All operations must have a description
$.paths[*][get,post,put,patch,delete]
error
operation-id-required
All operations must have an operationId
$.paths[*][get,post,put,patch,delete]
warn
operation-id-camel-case
operationId must use camelCase
$.paths[*][get,post,put,patch,delete].operationId
warn
operation-id-verb-prefix
operationId should start with a recognized verb (list, get, create, update, delete, calculate, complete, submit)
$.paths[*][get,post,put,patch,delete].operationId
error
operation-tags-required
All operations must have at least one tag
$.paths[*][get,post,put,patch,delete]
warn
global-tags-defined
Top-level tags array should be defined for documentation grouping
$
warn
tags-title-case
Global tag names should use Title Case (hyphenated words allowed)
$.tags[*].name
warn
tags-description-required
All global tags must have descriptions
$.tags[*]
error
parameter-description-required
All parameters must have descriptions
#Parameter
warn
parameter-camel-case
Parameter names should use camelCase (Workday convention)
#Parameter
error
parameter-schema-required
All parameters must define a schema
#Parameter
warn
parameter-pagination-limit
Pagination should use a "limit" parameter, not page-size or perPage
$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')].name
warn
parameter-pagination-offset
Pagination should use an "offset" parameter, not page or pageNumber
$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')].name
error
parameter-no-api-key-in-query
API keys must not be passed as query parameters
$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')].name
error
request-body-json-content
Request bodies must support application/json content type
$.paths[*][post,put,patch].requestBody.content
warn
request-body-schema-required
Request body content must reference a schema
$.paths[*][post,put,patch].requestBody.content[*]
error
response-success-required
All operations must define at least one 2xx response
$.paths[*][get,post,put,patch,delete].responses
warn
response-401-required
Operations should define a 401 Unauthorized response
$.paths[*][get,post,put,patch,delete].responses
warn
response-404-on-resource-get
GET operations on a single resource should define a 404 Not Found response
$.paths[?(@property.match(/\\{[a-zA-Z]+\\}$/))].get.responses
warn
response-400-on-mutations
POST/PUT/PATCH operations should define a 400 Bad Request response
$.paths[*][post,put,patch].responses
error
response-description-required
All responses must have a description
$.paths[*][get,post,put,patch,delete].responses[*]
warn
response-json-content
Success responses must use application/json content type
$.paths[*][get,post,put,patch,delete].responses['200','201','202'].content
warn
response-error-schema-fields
Reusable error responses should reference a schema with message/error fields
$.components.responses[*].content.application/json
warn
schema-property-camel-case
Schema property names must use camelCase (Workday convention)
$.components.schemas[*].properties[*]~
warn
schema-type-defined
Top-level schemas must define a type
$.components.schemas[*]
warn
schema-id-property-string
Resource id properties must be strings
$.components.schemas[*].properties.id
warn
schema-timestamps-date-time
createdOn, completedOn, startedAt, completedAt, submittedOn properties should use date-time format
$.components.schemas[*].properties[?(@property.match(/^(createdOn|completedOn|startedAt|completedAt|submittedOn|updatedOn|approvedOn|processedOn)$/))]
warn
schema-effective-date-format
effectiveDate, paymentDate, fromDate, toDate, startDate, endDate properties should use date format
$.components.schemas[*].properties[?(@property.match(/^(effectiveDate|paymentDate|fromDate|toDate|startDate|endDate)$/))]
warn
collection-schema-data-array
Collection schemas (named *Collection) must have a data property
$.components.schemas[?(@property.match(/Collection$/))]
warn
collection-schema-total
Collection schemas (named *Collection) must have a total property indicating full result count
$.components.schemas[?(@property.match(/Collection$/))]
info
ref-schema-naming
Lightweight reference schemas should be named with a Ref suffix (e.g. WorkerRef)
$.components.schemas[?(@property.match(/Ref$/))].properties
error
global-security-defined
Global security must be declared
$
error
security-schemes-defined
Security schemes must be defined under components
$
warn
security-bearer-auth
A bearerAuth security scheme is required for Workday APIs
$.components.securitySchemes
warn
security-bearer-jwt-format
Bearer security scheme should declare bearerFormat (e.g. JWT)
$.components.securitySchemes[?(@.scheme == 'bearer')]
warn
security-scheme-description
Security schemes must include a description
$.components.securitySchemes[*]
error
get-no-request-body
GET operations must not have a request body
$.paths[*].get
warn
delete-no-request-body
DELETE operations should not have a request body
$.paths[*].delete
warn
post-has-request-body
POST operations should have a request body
$.paths[*].post
error
patch-has-request-body
PATCH operations must have a request body
$.paths[*].patch
error
no-empty-descriptions
Descriptions must not be empty strings
$..description
info
examples-encouraged
Response and request examples improve developer experience
$.paths[*][get,post,put,patch,delete].responses['200','201'].content.application/json
warn
worker-id-path-param-naming
Worker ID path parameter must be named workerId
$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'path' && @.name =~ /^worker/i)].name
warn
pay-run-id-path-param-naming
Pay run ID path parameter must be named payRunId
$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'path' && @.name =~ /^payRun/i)].name

Spectral Ruleset

Raw ↑
rules:

  # INFO / METADATA
  info-title-format:
    description: API title must follow the Workday Payroll naming pattern
    severity: warn
    given: $.info.title
    then:
      function: pattern
      functionOptions:
        match: "^Workday Payroll .+"

  info-description-required:
    description: API info must have a description
    severity: error
    given: $.info
    then:
      field: description
      function: truthy

  info-description-min-length:
    description: API description should be at least 50 characters
    severity: warn
    given: $.info.description
    then:
      function: length
      functionOptions:
        min: 50

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

  info-version-format:
    description: Version should follow the v{n} pattern (e.g. v1)
    severity: warn
    given: $.info.version
    then:
      function: pattern
      functionOptions:
        match: "^v[0-9]+$"

  info-contact-required:
    description: API info must include contact information
    severity: warn
    given: $.info
    then:
      field: contact
      function: truthy

  info-contact-email:
    description: Contact must include an email address
    severity: warn
    given: $.info.contact
    then:
      field: email
      function: truthy

  info-terms-of-service:
    description: API info should reference Workday terms of service
    severity: info
    given: $.info
    then:
      field: termsOfService
      function: truthy

  external-docs-required:
    description: APIs should provide external documentation links
    severity: info
    given: $
    then:
      field: externalDocs
      function: truthy

  # OPENAPI VERSION
  openapi-version:
    description: APIs must use OpenAPI 3.1.x
    severity: error
    given: $.openapi
    then:
      function: pattern
      functionOptions:
        match: "^3\\.1\\."

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

  servers-https:
    description: All server URLs must use HTTPS
    severity: error
    given: $.servers[*].url
    then:
      function: pattern
      functionOptions:
        match: "^https://"

  servers-description-required:
    description: All servers should include a description
    severity: warn
    given: $.servers[*]
    then:
      field: description
      function: truthy

  servers-versioned-path:
    description: Server URLs should include a version segment (e.g. /v1)
    severity: warn
    given: $.servers[*].url
    then:
      function: pattern
      functionOptions:
        match: "/v[0-9]+(/|$)"

  # PATHS — NAMING CONVENTIONS
  paths-camel-case:
    description: Path segments must use camelCase resource names (Workday convention)
    severity: warn
    given: $.paths[*]~
    then:
      function: pattern
      functionOptions:
        match: "^(/[a-z][a-zA-Z0-9]*(/\\{[a-zA-Z][a-zA-Z0-9]*\\})?)+$"

  paths-no-trailing-slash:
    description: Paths must not have trailing slashes
    severity: error
    given: $.paths[*]~
    then:
      function: pattern
      functionOptions:
        notMatch: "/$"

  paths-no-query-strings:
    description: Paths must not contain query strings
    severity: error
    given: $.paths[*]~
    then:
      function: pattern
      functionOptions:
        notMatch: "\\?"

  # OPERATIONS
  operation-summary-required:
    description: All operations must have a summary
    severity: error
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: summary
      function: truthy

  operation-summary-prefix:
    description: Operation summaries should start with "Workday Payroll"
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].summary
    then:
      function: pattern
      functionOptions:
        match: "^Workday Payroll "

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

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

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

  operation-id-verb-prefix:
    description: operationId should start with a recognized verb (list, get, create, update, delete, calculate, complete, submit)
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].operationId
    then:
      function: pattern
      functionOptions:
        match: "^(list|get|create|update|delete|calculate|complete|submit|cancel|approve|reject|process)[A-Z]"

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

  # TAGS
  global-tags-defined:
    description: Top-level tags array should be defined for documentation grouping
    severity: warn
    given: $
    then:
      field: tags
      function: truthy

  tags-title-case:
    description: Global tag names should use Title Case (hyphenated words allowed)
    severity: warn
    given: $.tags[*].name
    then:
      function: pattern
      functionOptions:
        match: "^[A-Z][A-Za-z]*((-|\\s)[A-Z][A-Za-z]*)*$"

  tags-description-required:
    description: All global tags must have descriptions
    severity: warn
    given: $.tags[*]
    then:
      field: description
      function: truthy

  # PARAMETERS
  parameter-description-required:
    description: All parameters must have descriptions
    severity: error
    given: "#Parameter"
    then:
      field: description
      function: truthy

  parameter-camel-case:
    description: Parameter names should use camelCase (Workday convention)
    severity: warn
    given: "#Parameter"
    then:
      field: name
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"

  parameter-schema-required:
    description: All parameters must define a schema
    severity: error
    given: "#Parameter"
    then:
      field: schema
      function: truthy

  parameter-pagination-limit:
    description: Pagination should use a "limit" parameter, not page-size or perPage
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')].name
    then:
      function: pattern
      functionOptions:
        notMatch: "^(pageSize|perPage|page_size|per_page|size)$"

  parameter-pagination-offset:
    description: Pagination should use an "offset" parameter, not page or pageNumber
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')].name
    then:
      function: pattern
      functionOptions:
        notMatch: "^(page|pageNumber|page_number|pageNo)$"

  parameter-no-api-key-in-query:
    description: API keys must not be passed as query parameters
    severity: error
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')].name
    then:
      function: pattern
      functionOptions:
        notMatch: "(?i)(api[_-]?key|apikey|access[_-]?token|token)"

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

  request-body-schema-required:
    description: Request body content must reference a schema
    severity: warn
    given: $.paths[*][post,put,patch].requestBody.content[*]
    then:
      field: schema
      function: truthy

  # RESPONSES
  response-success-required:
    description: All operations must define at least one 2xx response
    severity: error
    given: $.paths[*][get,post,put,patch,delete].responses
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          patternProperties:
            "^2[0-9][0-9]$": {}
          minProperties: 1

  response-401-required:
    description: Operations should define a 401 Unauthorized response
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].responses
    then:
      field: '401'
      function: truthy

  response-404-on-resource-get:
    description: GET operations on a single resource should define a 404 Not Found response
    severity: warn
    given: $.paths[?(@property.match(/\\{[a-zA-Z]+\\}$/))].get.responses
    then:
      field: '404'
      function: truthy

  response-400-on-mutations:
    description: POST/PUT/PATCH operations should define a 400 Bad Request response
    severity: warn
    given: $.paths[*][post,put,patch].responses
    then:
      field: '400'
      function: truthy

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

  response-json-content:
    description: Success responses must use application/json content type
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].responses['200','201','202'].content
    then:
      field: application/json
      function: truthy

  response-error-schema-fields:
    description: Reusable error responses should reference a schema with message/error fields
    severity: warn
    given: $.components.responses[*].content.application/json
    then:
      field: schema
      function: truthy

  # SCHEMAS — PROPERTY NAMING
  schema-property-camel-case:
    description: Schema property names must use camelCase (Workday convention)
    severity: warn
    given: $.components.schemas[*].properties[*]~
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"

  schema-type-defined:
    description: Top-level schemas must define a type
    severity: warn
    given: $.components.schemas[*]
    then:
      field: type
      function: truthy

  schema-id-property-string:
    description: Resource id properties must be strings
    severity: warn
    given: $.components.schemas[*].properties.id
    then:
      field: type
      function: enumeration
      functionOptions:
        values:
          - string

  schema-timestamps-date-time:
    description: createdOn, completedOn, startedAt, completedAt, submittedOn properties should use date-time format
    severity: warn
    given: $.components.schemas[*].properties[?(@property.match(/^(createdOn|completedOn|startedAt|completedAt|submittedOn|updatedOn|approvedOn|processedOn)$/))]
    then:
      field: format
      function: enumeration
      functionOptions:
        values:
          - date-time

  schema-effective-date-format:
    description: effectiveDate, paymentDate, fromDate, toDate, startDate, endDate properties should use date format
    severity: warn
    given: $.components.schemas[*].properties[?(@property.match(/^(effectiveDate|paymentDate|fromDate|toDate|startDate|endDate)$/))]
    then:
      field: format
      function: enumeration
      functionOptions:
        values:
          - date

  collection-schema-data-array:
    description: Collection schemas (named *Collection) must have a data property
    severity: warn
    given: $.components.schemas[?(@property.match(/Collection$/))]
    then:
      field: properties.data
      function: truthy

  collection-schema-total:
    description: Collection schemas (named *Collection) must have a total property indicating full result count
    severity: warn
    given: $.components.schemas[?(@property.match(/Collection$/))]
    then:
      field: properties.total
      function: truthy

  ref-schema-naming:
    description: Lightweight reference schemas should be named with a Ref suffix (e.g. WorkerRef)
    severity: info
    given: $.components.schemas[?(@property.match(/Ref$/))].properties
    then:
      field: descriptor
      function: truthy

  # SECURITY
  global-security-defined:
    description: Global security must be declared
    severity: error
    given: $
    then:
      field: security
      function: truthy

  security-schemes-defined:
    description: Security schemes must be defined under components
    severity: error
    given: $
    then:
      field: components.securitySchemes
      function: truthy

  security-bearer-auth:
    description: A bearerAuth security scheme is required for Workday APIs
    severity: warn
    given: $.components.securitySchemes
    then:
      field: bearerAuth
      function: truthy

  security-bearer-jwt-format:
    description: Bearer security scheme should declare bearerFormat (e.g. JWT)
    severity: warn
    given: $.components.securitySchemes[?(@.scheme == 'bearer')]
    then:
      field: bearerFormat
      function: truthy

  security-scheme-description:
    description: Security schemes must include a description
    severity: warn
    given: $.components.securitySchemes[*]
    then:
      field: description
      function: truthy

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

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

  post-has-request-body:
    description: POST operations should have a request body
    severity: warn
    given: $.paths[*].post
    then:
      field: requestBody
      function: truthy

  patch-has-request-body:
    description: PATCH operations must have a request body
    severity: error
    given: $.paths[*].patch
    then:
      field: requestBody
      function: truthy

  # GENERAL QUALITY
  no-empty-descriptions:
    description: Descriptions must not be empty strings
    severity: error
    given: $..description
    then:
      function: pattern
      functionOptions:
        match: ".+"

  examples-encouraged:
    description: Response and request examples improve developer experience
    severity: info
    given: $.paths[*][get,post,put,patch,delete].responses['200','201'].content.application/json
    then:
      field: examples
      function: truthy

  worker-id-path-param-naming:
    description: Worker ID path parameter must be named workerId
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'path' && @.name =~ /^worker/i)].name
    then:
      function: enumeration
      functionOptions:
        values:
          - workerId

  pay-run-id-path-param-naming:
    description: Pay run ID path parameter must be named payRunId
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'path' && @.name =~ /^payRun/i)].name
    then:
      function: enumeration
      functionOptions:
        values:
          - payRunId