# harvested from https://github.com/apiaddicts/apiaddicts-style-guide-spectral/blob/fba927d25373406a42f384c3905b28dc9d9ad758/apq-spectral.yaml on 2026-10-09 — a Spectral ruleset published in the provider's own GitHub repository (apiaddicts/apiaddicts-style-guide-spectral); found by GitHub code search, fetched verbatim functionsDir: './functions' functions: - apq-alternate-paths - apq-custom-schema - apq-compare-insensitive - apq-has-filter-query-param - apq-parameter-naming-convention - apq-resources-by-verb - apq-at-most-one-body-parameter - apq-standard-response-codes - apq-response-headers - apq-require-response-on-path-params - apq-required-fields-exist - apq-response-media-type - apq-security-check - apq-custom-field - apq-check-examples-coverage - apq-path-depth - apq-forbidden-characters - apq-valid-response-schema - apq-post-201-location-header - apq-response-no-content - apq-valid-openapi-version - apq-collection-query-param-required - apq-total-param-default-value - apq-path-param-query-conflict - apq-schema-format - apq-security-required-response - apq-check-ambiguous-path - apq-password-format - apq-binary-format-check - apq-paged-response-check - apq-status-endpoint-check - apq-validate-structure - apq-numeric-parameter-integrity - apq-path-pattern - apq-query-params-optional - apq-wso2-scopes-valid - apq-numeric-path-param - apq-numeric-invalid-format - apq-numeric-missing-format - apq-numeric-well-defined-format - apq-string-parameter-integrity - apq-example-schema-types - apq-standard-response-schema - apq-allowed-http-verbs - apq-url-naming-convention - apq-mandatory-response-codes - apq-rate-limit-response - apq-forbidden-query-format - apq-wso2-scope-defined - apq-undefined-response-media-type - apq-wso2-auth-type-required - apq-response-content-required - apq-tags-consistency - apq-forbidden-title-pattern rules: apiq:OAR001: description: "For security reasons and as a REST best practice, the HTTPS protocol is mandatory." message: "OAR001: HTTPS protocol is mandatory." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR001.md" severity: "error" given: "$.servers[*].url" then: function: pattern functionOptions: match: "^https://" apiq:OAR002: description: "A wrong scope definition may cause problems to import the API definition into WSO2." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR002.md" severity: "error" given: "$.x-wso2-security.apim.x-wso2-scopes" then: function: apq-wso2-scopes-valid apiq:OAR003: description: "A description can help other developers to understand the correct use of the scope." message: "OAR003: Scope must define a 'description' attribute." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR003.md" severity: "error" given: "$.x-wso2-security.apim.x-wso2-scopes[*]" then: - function: "truthy" field: "description" message: "Scope must define a 'description' attribute." apiq:OAR004: description: "A role with forbidden characters may cause problems in some applications." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR004.md" severity: "error" given: "$.x-wso2-security.apim.x-wso2-scopes[*].roles" then: function: apq-forbidden-characters functionOptions: pattern: "^[a-zA-Z0-9_\\-., ]+$" apiq:OAR005: description: "A wrong scope may cause problems to import the API definition into WSO2 or allow all users to call the endpoint." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR005.md" severity: "error" resolved: false given: "$" then: function: apq-wso2-scope-defined apiq:OAR006: description: "Routes must define request media types supported by the API." message: "OAR006: Specify at least one Media Type in the content of the request body." severity: "error" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR006.md" given: "$.paths[*][post,put,patch]" then: - field: "requestBody" function: truthy - field: "requestBody.content" function: truthy apiq:OAR007: description: "Routes must define response media types supported by the API" message: "OAR007: Specify at least one Media Type in the content of the response body." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR007.md" severity: "error" given: - "$.paths[*][post,put,patch]" - "$.webhooks[*][post,put,patch]" - "$.paths[*][get,post,put,patch,delete].responses[?(@property != '204')]" - "$.webhooks[*][get,post,put,patch,delete].responses[?(@property != '204')]" then: function: apq-undefined-response-media-type apiq:OAR008: description: "HTTP verbs not encouraged." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR008.md" severity: error given: "$.paths[*]" then: function: apq-allowed-http-verbs functionOptions: allowed-verbs: "get,post,put,delete,patch" apiq:OAR009: description: "Default request media type should be defined for operations." message: "OAR009: Default request media type is mandatory." severity: "error" given: "$..content" then: field: "application/json" function: truthy apiq:OAR010: description: "Default response media type should be defined for responses." message: "OAR010: Default response media type is mandatory." severity: warn given: - "$.paths[*][post,put,patch]" - "$.webhooks[*][post,put,patch]" - "$.paths[*][get,post,put,patch,delete].responses[?(@property != '204')]" - "$.webhooks[*][get,post,put,patch,delete].responses[?(@property != '204')]" - "$.paths[*][get,post,put,patch,delete].responses[?(@property != '204')].content" - "$.webhooks[*][get,post,put,patch,delete].responses[?(@property != '204')].content" then: function: apq-response-media-type functionOptions: default-media-type: "application/json" media-type-exceptions: "-" apiq:OAR011: description: "URLs should follow the configured naming convention (default kebab-case): all literal path segments must comply." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR011.md" severity: error given: - "$.paths[*]~" - "$.servers[*].url" then: function: apq-url-naming-convention functionOptions: naming-convention: "kebab-case" apiq:OAR012: description: "Path params, query params, object names and property names should follow the configured naming convention. You can configure snake_case (default), kebab-case, camelCase or UpperCamelCase" message: "OAR012: Path params, query params, object names and property names must follow the configured naming convention." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR012.md" severity: warn given: - "$.paths[*][*].parameters[?(@.in == 'path' || @.in == 'query')].name" - "$.paths[*][*].parameters[*].schema.properties.*~" - "$.paths[*][*].requestBody..schema.properties.*~" - "$.paths[*][*].responses..schema.properties.*~" - "$.components.schemas.*~" then: function: apq-parameter-naming-convention functionOptions: namingConvention: "snake_case" apiq:OAR013: description: "Default response is required for all operations." message: "OAR013: Default response is required." severity: error given: "$.paths[*][get,post,put,patch,delete].responses" then: field: "default" function: truthy apiq:OAR014: description: "Resources depth level should be below the non-suggested range." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR014.md" severity: warn given: "$.paths.*~" then: function: apq-path-depth functionOptions: min-level: 4 max-level: 5 ignoreSegments: - me apiq:OAR015: description: "Resources depth level should be smaller than 5." message: "{{error}}" severity: error given: "$.paths.*~" then: function: apq-path-depth functionOptions: max-level-allowed: 5 ignoreSegments: - me apiq:OAR016: description: "Numeric types requires a valid format." message: "OAR016: Numeric types must use a valid format for their type." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR016.md" severity: error resolved: false given: "$..[?(@ && @.type)]" then: function: apq-numeric-invalid-format apiq:OAR017: description: "Resource path should alternate static and parametrized parts." message: "OAR017: Resource path should alternate static and parametrized parts" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR017.md" severity: error given: "$.paths.*~" then: function: apq-alternate-paths functionOptions: exclude_patterns: "get,me,search,delete" apiq:OAR018: description: Operation not recommended for resource path depending on HTTP verb message: "OAR018: Operation not recommended for resource path: {{path}} ({{verb}})" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR018.md" severity: warn given: "$.paths" then: function: apq-resources-by-verb functionOptions: allowed-resources-paths: | ;get:^/[^/{}]+$ ;get:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+$ ;get:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+$ ;get:^/[^/{}]+/(\{[^/{}]+\}|me)$ ;get:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;get:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;post:^/[^/{}]+$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+$ ;post:^/[^/{}]+/get$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/get$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/get$ ;post:^/[^/{}]+/delete$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/delete$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/delete$ ;put:^/[^/{}]+/(\{[^/{}]+\}|me)$ ;put:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;put:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;patch:^/[^/{}]+/(\{[^/{}]+\}|me)$ ;patch:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;patch:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;delete:^/[^/{}]+/(\{[^/{}]+\}|me)$ ;delete:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;delete:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)$ ;post:^/[^/{}]+/archive$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/archive$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/archive$ ;post:^/[^/{}]+/clone$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/clone$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/clone$ ;post:^/[^/{}]+/restore$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/restore$ ;post:^/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/(\{[^/{}]+\}|me)/[^/{}]+/restore$ ;head:.* ;options:.* apiq:OAR019: description: "$select must be defined as a query parameter in collection operations (excluding detail endpoints and health checks)." message: "{{error}}" severity: warn given: "$.paths" then: function: apq-collection-query-param-required functionOptions: parameter-name: "$select" apiq:OAR020: description: "$expand must be defined as a query parameter in collection operations (excluding detail endpoints and health checks)." message: "{{error}}" severity: warn given: "$.paths" then: function: apq-collection-query-param-required functionOptions: parameterName: "$expand" paths: "/me,/health,/ping,/status" pathValidationStrategy: "/exclude" apiq:OAR021: description: "$exclude must be defined as a query parameter in collection operations (excluding detail endpoints and health checks)." message: "{{error}}" severity: warn given: "$.paths" then: function: apq-collection-query-param-required functionOptions: parameterName: "$exclude" paths: "/me,/health,/ping,/status" pathValidationStrategy: "/exclude" apiq:OAR022: description: "$orderby must be defined as a query parameter in the collection GET operations selected by the configured paths." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR022.md" severity: warn given: "$.paths" then: function: apq-collection-query-param-required functionOptions: parameterName: "$orderby" paths: "/examples" pathValidationStrategy: "/include" apiq:OAR023: description: "$total must be defined as a query parameter in all collection operations (excluding detail endpoints and health checks)." message: "OAR023: $total must be defined as a query parameter in this operation." severity: error given: "$.paths[?(!@property.match(/\\/me(\\/|$)/) && !@property.match(/\\/\\{[^}]+\\}$/) && !@property.match(/status|health|ping/))].get.parameters" then: field: "$[?(@.name == '$total' && @.in == 'query')]" function: truthy apiq:OAR024: description: "$start must be defined as a query parameter in all collection operations (excluding detail endpoints and health checks)." message: "OAR024: $start must be defined as a query parameter in this operation." severity: error given: "$.paths[?(!@property.match(/\\/me(\\/|$)/) && !@property.match(/\\/\\{[^}]+\\}$/) && !@property.match(/status|health|ping/))].get.parameters" then: field: "$[?(@.name == '$start' && @.in == 'query')]" function: truthy apiq:OAR025: description: "$limit must be defined as an integer query parameter in the collection GET operations selected by the configured paths." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR025.md" severity: error given: "$.paths" then: function: apq-collection-query-param-required functionOptions: parameterName: "$limit" paths: "/examples" pathValidationStrategy: "/include" apiq:OAR026: description: "The $total parameter default value should be false." message: "{{error}}" severity: error given: "$.paths[*].get.parameters[?(@.name == '$total' && @.in == 'query')]" then: function: apq-total-param-default-value apiq:OAR027: description: "Location header is required in responses with code 201 from POST operations." message: "{{error}}" severity: error given: "$.paths.*.post.responses['201']" then: function: apq-post-201-location-header apiq:OAR028: description: "$filter must be defined as a query parameter in the collection GET operations selected by the configured paths." message: "{{error}}" severity: warn given: "$.paths" then: function: apq-collection-query-param-required functionOptions: parameterName: "$filter" paths: "/examples" pathValidationStrategy: "/include" apiq:OAR029: description: "A response not compliant with the standard may cause application issues." message: "{{error}}" severity: error given: "$.paths" then: function: apq-standard-response-schema functionOptions: response-schema: '{"type":"object","properties":{"status":{"type":"object","properties":{"code":{"type":"integer"},"description":{"type":"string"},"internal_code":{"type":"string"},"errors":{"type":"array","nullable":true,"items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}}}}},"required":["code"]},"payload":{"type":"any"}},"required":["status","payload"]}' path-exclusions: "/status" apiq:OAR030: description: "The configured status endpoint must be declared with the configured HTTP method." message: "OAR030: The required status endpoint is not declared or does not have the required method." severity: error given: "$.paths" then: function: apq-status-endpoint-check functionOptions: status-endpoint: "/status" method: "get" apiq:OAR031: description: "The examples can help developers to understand the response data structure and representation." message: "{{error}}" severity: error given: - $.paths.*.*.parameters.* - $.paths.*.*.requestBody - $.paths.*.*.responses[?(@property !== "204")] then: function: apq-check-examples-coverage functionOptions: validateResponse: true validateRequestBody: true validateParameter: true validateProperty: true apiq:OAR032: description: "Ambiguous path parts not encouraged." message: "{{error}}" severity: error given: "$.paths.*~" then: function: apq-check-ambiguous-path functionOptions: ambiguous-names: "elementos,instancias,recursos,valores,terminos,objetos,articulos,elements,instances,resources,values,terms,objects,items" apiq:OAR033: description: "Request operation parameters must not include forbidden headers (Accept, Content-Type, Authorization). Note: This validates REQUEST headers, not response headers (see OAR053/114 for response header validation)." message: "OAR033: The request header parameter '{{value}}' is not allowed in operations." severity: error given: "$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'header')]" then: field: "name" function: pattern functionOptions: notMatch: "^(Accept|Content-Type|Authorization)$" apiq:OAR034: description: "GET collection responses must include a paging block that complies with the standard paging schema (required start, limit and links with self/previous/next; optional numPages and total as integers)." message: "{{error}}" severity: error given: "$.paths[*].get.responses[*]" then: function: apq-paged-response-check functionOptions: paging-schema: '{"type":"object","properties":{"numPages":{"type":"integer"},"total":{"type":"integer"},"start":{"type":"integer"},"limit":{"type":"integer"},"links":{"type":"object","properties":{"next":{"type":"object","properties":{"href":{"type":"string"}}},"previous":{"type":"object","properties":{"href":{"type":"string"}}},"last":{"type":"object","properties":{"href":{"type":"string"}}},"self":{"type":"object","properties":{"href":{"type":"string"}}},"first":{"type":"object","properties":{"href":{"type":"string"}}}},"required":["self","previous","next"]}},"required":["start","limit","links"],"pagingPropertyName":"paging"}' apiq:OAR035: description: "Response code 401 must be defined for operations with security schemes defined." message: "{{error}}" severity: "error" given: "$.paths[*][*]" then: function: apq-security-required-response functionOptions: expected-codes: "401" apiq:OAR036: description: "Cookie use is forbidden as a session mechanism." message: "OAR036: Cookie use is forbidden as a session mechanism." severity: error given: - "$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'header')]" - "$.paths[*][get,post,put,patch,delete].responses[*].headers.*~" then: field: "name" function: pattern functionOptions: notMatch: "^(Cookie|Set-Cookie)$" apiq:OAR037: description: "String schemas must specify a valid format, or a valid pattern when no format is defined." message: "OAR037: String schemas must specify a valid format (date, date-time, password, byte, binary, email, uuid, uri, hostname, ipv4, ipv6, HEX, HEX(16), json, xml, or base64), or a valid pattern when no format is defined." severity: error resolved: false given: "$..[?(@ && @.type)]" then: function: apq-schema-format apiq:OAR038: description: "The 201 response schema of a POST operation must have properties named 'data' or 'error' with at least one sub-property." message: "{{error}}" severity: error given: "$.paths.*.post.responses['201']" then: function: apq-valid-response-schema functionOptions: data-property: data apiq:OAR039: description: "Response codes must be defined according to the standard depending on the HTTP verb and resource path." message: "{{error}}" documentationUrl: https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR039.md severity: error given: "$.paths[*][*]" then: function: apq-standard-response-codes functionOptions: resources-exclusions: - "get:/status" required-codes-by-resources-paths: > ;get:^/[^/{}]+$:200|206,400,500,503 ;get:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+$:200|206,400,500,503,404 ;get:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+$:200|206,400,500,503,404 ;get:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,400,404,500,503 ;get:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,400,404,500,503 ;get:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,400,404,500,503 ;post:^/[^/{}]+$:200|201|202,400,415,500,503 ;post:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+$:200|201|202,400,415,500,503,404 ;post:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+$:200|201|202,400,415,500,503,404 ;post:^/[^/{}]+/get$:200,404,400,415,500,503 ;post:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/get$:200,404,400,415,500,503 ;post:^/[^/{}]+/delete$:200,404,400,415,500,503 ;post:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/delete$:200,404,400,415,500,503 ;post:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/get$:200,404,400,415,500,503 ;post:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/delete$:200,404,400,415,500,503 ;put:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,404,400,415,500,503 ;put:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,404,400,415,500,503 ;put:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,404,400,415,500,503 ;delete:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,400,404,500,503 ;delete:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,400,404,500,503 ;delete:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,400,404,500,503 ;patch:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,404,400,415,500,503 ;patch:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,404,400,415,500,503 ;patch:^/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)/[^/{}]+/(\{[^/{}]+\}|\bme\b)$:200,404,400,415,500,503 apiq:OAR040: description: "A scope name non-compliant with the standard may cause problems at application level." message: "{{error}}" severity: "error" given: "$.x-wso2-security.apim.x-wso2-scopes[*].name" then: function: apq-forbidden-characters functionOptions: pattern: "^[a-zA-Z]{4,}_(SC|sc)_[a-zA-Z0-9]{1,}$" apiq:OAR041: description: "A WSO2 x-scope on an operation always requires an x-auth-type definition." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR041.md" severity: "error" resolved: false given: "$" then: function: apq-wso2-auth-type-required apiq:OAR042: description: "Base path must be compliant with the standard." message: "OAR042: Base path must follow the '/api-/v' standard." severity: "error" given: - "$.basePath" - "$.servers[*].url" then: function: pattern functionOptions: match: "^(/api-[^/]+/v[0-9]+|https?:\\/\\/[^/]+\\/api-[^/]+\\/v[0-9]+)$" apiq:OAR043: description: "OpenAPI definition contains structural errors that would be detected by a strict parser or validator." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR043.md" severity: error given: - $.paths.*.*.parameters.*.in - $.components.parameters.*.in - $.paths.*.*.parameters.*.type - $.components.parameters.*.type - $.paths.*.*.parameters.*.schema.type - $.components.parameters.*.schema.type - $.webhooks.*.*.parameters.*.in - $.webhooks.*.*.parameters.*.schema.type - $.components.pathItems.*.*.parameters.*.in - $.components.pathItems.*.*.parameters.*.schema.type then: function: apq-validate-structure apiq:OAR044: description: "Declared media type should conform to RFC6838 and RFC7231." message: "OAR044: Declared media type range should conform to RFC7231." severity: "error" given: - "$.paths.*.*.responses[?(@property !== '204')].content.*~" - "$.paths.*[post,put,patch].requestBody.content.*~" - "$.paths.*.*.parameters[*].content.*~" - "$.paths.*.parameters[*].content.*~" - "$.components.responses.*.content.*~" - "$.components.requestBodies.*.content.*~" - "$.components.parameters.*.content.*~" then: function: pattern functionOptions: match: '^(\*|[a-zA-Z0-9][a-zA-Z0-9.!#$&^_+\-]*)/(\*|[a-zA-Z0-9][a-zA-Z0-9.!#$&^_+\-]*)(?:[ \t]*;[ \t]*[a-zA-Z0-9!#$%&''*+\-.^_`|~]+=(?:[a-zA-Z0-9!#$%&''*+\-.^_`|~]+|"(?:[^"\\]|\\.)*"))*$' apiq:OAR045: description: "Response schema is required for responses with status codes 201 and others that return content." message: "OAR045: Response schema is required for status code '{{property}}'." severity: error given: "$.paths[*][get,post,put,patch,delete].responses[?(@property !== '204')]" then: function: apq-response-content-required apiq:OAR046: description: "Each operation SHOULD have a tag." message: "OAR046: You should categorize the operations of your contract with tags." severity: error given: - "$.paths[*].get" - "$.paths[*].post" - "$.paths[*].put" - "$.paths[*].patch" - "$.paths[*].delete" then: function: schema functionOptions: schema: type: object required: ["tags"] properties: tags: type: array minItems: 1 apiq:OAR047: description: "Tags required and each tag must have a short description, must not be duplicated, and every tag used by an operation must be declared at the top level." message: "{{error}}" severity: error given: "$" then: function: apq-tags-consistency apiq:OAR048: description: APIs must define at most one body parameter. message: "OAR048: An operation can have at most one body parameter" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR048.md" severity: error given: "$.paths[*][*]" then: field: parameters function: apq-at-most-one-body-parameter apiq:OAR049: description: "204 No Content MUST NOT return any content." message: "{{error}}" severity: error given: "$.paths[*][get,post,put,patch,delete].responses['204']" then: function: apq-response-no-content apiq:OAR050: description: "Provide a summary for each operation." message: "OAR050: Provide a summary for each operation." severity: "error" given: "$.paths[*][get,post,put,patch,delete]" then: field: "summary" function: truthy apiq:OAR051: description: "Summary and description must be different - not just case variations or semantic duplicates." message: "{{error}}" severity: "error" given: "$.paths[*][get,post,put,patch,delete]" then: function: apq-compare-insensitive functionOptions: property: summary equalTo: description result: falsy threshold: 0.55 apiq:OAR052: description: "Numeric schema types must define a format." message: "OAR052: Numeric types requires a format" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR052.md" severity: warn resolved: false given: "$..[?(@ && @.type)]" then: function: apq-numeric-missing-format apiq:OAR053: description: "Response headers for API observability and tracing must be defined (excluding 204 responses and health endpoints)." message: "OAR053: Response must include mandatory headers and exclude forbidden headers." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR053.md" severity: error given: "$.paths[*][*].responses[*]" then: - function: apq-response-headers functionOptions: mandatory-headers: "x-trace-id" allowed-headers: "idcorrelacion,x-correlacionid,x-global-trasaction-id,x-power-by,x-trace-id,x-request-id" included-response-codes: "*" excluded-response-codes: "204" path-exclusions: "/status" apiq:OAR054: description: "Ensure the host matches the specified format" message: "OAR054: Hostname must be a subdomain of the organization's domain name." severity: error given: "$.servers[*]" then: field: url function: pattern functionOptions: match: ^(http(s)?:\/\/.)[-a-zA-Z0-9@:%._\+~#=]{2,256}\.apiquality.io\b([-a-zA-Z0-9@:%_\+.~#?&\/=]*)$ apiq:OAR060: description: "All query parameters must be defined as optional." message: "{{error}}" severity: error given: - "$.paths[*][get,put,post,delete,options,head,patch,trace].parameters[?(@.in == 'query')]" - "$.paths[*].parameters[?(@.in == 'query')]" - "$.components.parameters[?(@.in == 'query')]" - "$.parameters[?(@.in == 'query')]" then: field: "required" function: apq-query-params-optional functionOptions: path-exclusions: "/status" apiq:OAR061: description: "Ensure get have mandatory response codes" message: "{{error}}" severity: error given: "$.paths[*][get]" then: function: apq-mandatory-response-codes functionOptions: mandatory-response-codes: "200, 202, 206" paths: "/status, /another" pathValidationStrategy: "/exclude" apiq:OAR062: description: "Ensure post have mandatory response codes" message: "{{error}}" severity: error given: "$.paths[*][post]" then: function: apq-mandatory-response-codes functionOptions: mandatory-response-codes: "200, 201, 202, 204, 206" paths: "/status, /another" pathValidationStrategy: "/exclude" apiq:OAR063: description: "Ensure put have mandatory response codes" message: "{{error}}" severity: error given: "$.paths[*][put]" then: function: apq-mandatory-response-codes functionOptions: mandatory-response-codes: "200, 202, 204, 206" paths: "/status, /another" pathValidationStrategy: "/exclude" apiq:OAR064: description: "Ensure patch have mandatory response codes" message: "{{error}}" severity: error given: "$.paths[*][patch]" then: function: apq-mandatory-response-codes functionOptions: mandatory-response-codes: "200, 202, 204, 206" paths: "/status, /another" pathValidationStrategy: "/exclude" apiq:OAR065: description: "Ensure delete have mandatory response codes" message: "{{error}}" severity: error given: "$.paths[*][delete]" then: function: apq-mandatory-response-codes functionOptions: mandatory-response-codes: "200, 202, 204" paths: "/status, /another" pathValidationStrategy: "/exclude" apiq:OAR066: description: "RequestBody and Responses schema property names must be compliant with the snake_case naming convention." message: "OAR066: RequestBody and Responses schema property names must be compliant with the snake_case naming convention." severity: "warn" given: - "$.paths.*.*[responses,requestBody]..content..schema..properties.*~" - "$.paths.*.*.parameters[?(@.in=='body')].schema..properties.*~" - "$.paths.*.*.responses[*].schema..properties.*~" then: function: pattern functionOptions: match: "^([a-z$][a-z0-9_$]*|_[a-z0-9_]+|@[a-zA-Z][a-zA-Z0-9_]*|x-[a-zA-Z][a-zA-Z0-9_-]*)$" apiq:OAR067: description: "RequestBody and Responses schema property names must be compliant with the camelCase naming convention." message: "OAR067: RequestBody and Responses schema property names must be compliant with the camelCase naming convention." severity: "warn" given: "$.paths.*.*[responses,requestBody]..content..schema..properties.*~" then: function: casing functionOptions: type: camel apiq:OAR068: description: "RequestBody and Responses schema property names must be compliant with the PascalCase naming convention." message: "OAR068: RequestBody and Responses schema property names must be compliant with the PascalCase naming convention." severity: "warn" given: "$.paths.*.*[responses,requestBody]..content..schema..properties.*~" then: function: casing functionOptions: type: pascal apiq:OAR069: description: "Any param in PATH or QUERY should have a Bad Request (400) response." message: "OAR069: Any param in PATH or QUERY should have a Bad Request (400) response." severity: "error" given: "$.paths" then: function: apq-path-param-query-conflict apiq:OAR070: description: "Parameters in path should not be numeric." message: "OAR070: Parameters in path should not be numeric." severity: error given: "$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'path')]" then: function: apq-numeric-path-param apiq:OAR071: description: "Query parameters 'param1', 'param2', and 'param3' must be defined in the operation." message: "OAR071: Query parameters 'param1', 'param2', and 'param3' must be defined." severity: error given: "$.paths[*].get.parameters" then: - field: "$[?(@.name == 'param1')]" function: truthy - field: "$[?(@.name == 'param2')]" function: truthy - field: "$[?(@.name == 'param3')]" function: truthy apiq:OAR072: description: "Responses with status codes other than 200 must not include 'stacktrace'." message: "The response with status code {{property}} must not include 'stacktrace'." severity: error given: "$.paths[*][get,post,put,patch,delete].responses[?(@property != '200')]" then: field: "content.application/json.schema.properties" function: pattern functionOptions: notMatch: "stacktrace" apiq:OAR073: description: "API should include a 429 response to indicate rate limiting, except for health check paths like /status, /health, /health-check, /ping, /liveness, /readiness." message: "OAR073: API should include a 429 response to indicate rate limiting." severity: error given: "$.paths[*][get,post,put,patch,delete]" then: function: apq-rate-limit-response functionOptions: paths: "/status, /health, /health-check, /ping, /liveness, /readiness" pathValidationStrategy: "/exclude" apiq:OAR074: description: "Numeric parameters should define minimum and maximum, or a format restriction." message: "OAR074: Numeric parameter should define both 'minimum' and 'maximum', or a 'format' restriction." severity: error resolved: false given: - "$..[?(@ && @.in && @.schema && (@.schema.type == 'integer' || @.schema.type == 'number' || (@.schema.type && @.schema.type.indexOf && (@.schema.type.indexOf('integer') > -1 || @.schema.type.indexOf('number') > -1))))].schema" - "$..[?(@ && @.in && (@.type == 'integer' || @.type == 'number' || (@.type && @.type.indexOf && (@.type.indexOf('integer') > -1 || @.type.indexOf('number') > -1))))]" then: function: apq-numeric-parameter-integrity apiq:OAR075: description: "String parameters should have minLength, maxLength, pattern (regular expression), or enum restriction." message: "OAR075: String parameters should have minLength, maxLength, pattern, or enum restriction." severity: error resolved: false given: - "$.paths[*][*].parameters[*]" - "$.paths[*].parameters[*]" - "$.paths[*].additionalOperations[*].parameters[*]" - "$.webhooks[*][*].parameters[*]" - "$.webhooks[*].parameters[*]" - "$.webhooks[*].additionalOperations[*].parameters[*]" - "$.components.parameters[*]" - "$.parameters[*]" then: function: apq-string-parameter-integrity functionOptions: parameter_integrity: "minLength,maxLength,pattern,enum" apiq:OAR076: description: "Schema should use well-defined type and format." message: "OAR076: Schema should use well-defined type and format." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR076.md" severity: error resolved: false given: "$..[?(@ && @.type)]" then: function: apq-numeric-well-defined-format apiq:OAR077: description: "All parameters in query must be snake_case." message: "OAR077: All parameters in query must be snake_case." severity: warn given: - "$.paths[*][*].parameters[?(@.in == 'query')]" - "$.paths[*].parameters[?(@.in == 'query')]" then: field: "name" function: pattern functionOptions: match: ^\$?_?[a-z]+(_[a-z]+)*$ apiq:OAR078: description: "All API methods must have security defined." message: "OAR078: Operation must have security defined." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR078.md" severity: error given: "$" then: function: apq-security-check apiq:OAR079: description: "Operations with path parameters should include a 404 Not Found response." message: "OAR079: Path parameter present, but missing 404 Not Found response." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR079.md" severity: "warn" given: "$.paths[*][get,post,put,patch,delete]" then: function: apq-require-response-on-path-params functionOptions: paths: "/status" pathValidationStrategy: "/exclude" apiq:OAR080: description: "The security scheme must be among those allowed by the organization and must be complete." message: "OAR080: The security scheme '{{property}}' must be among those allowed by the organization and must be complete." severity: error given: "$.paths[*][get,post,put,patch,delete].security[*]" then: field: "@key" function: pattern functionOptions: match: "^(apiKey|oauth2)$" apiq:OAR081: description: "Fields of type password should be string with format password." message: "OAR081: Fields of type password should be string with format password." severity: error given: "$..properties" then: function: apq-password-format apiq:OAR082: description: "The string properties 'product', 'line', and 'price' must define a byte or binary format." message: "{{error}}" severity: error given: "$..[?(@ && @.properties)]" then: function: apq-binary-format-check functionOptions: fields-to-apply: "product,line,price" apiq:OAR083: description: "Certain parameters (e.g., email, password) should not pass through the querystring." message: "OAR083: The parameter '{{value}}' should not pass through the querystring." severity: error given: "$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')]" then: field: "name" function: pattern functionOptions: notMatch: "^(email|password)$" apiq:OAR084: description: "Some formats should not pass through this querystring." message: "{{error}}" severity: error given: - "$.paths[*][get,post,put,patch,delete].parameters[?(@.in == 'query')]" - "$.paths[*].parameters[?(@.in == 'query')]" then: function: apq-forbidden-query-format functionOptions: forbidden-query-formats: "password" paths: "/examples" pathValidationStrategy: "/include" apiq:OAR085: description: "The OpenAPI version must be one of: 2.0, 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.1.0, 3.1.1, 3.1.2, 3.2.0." message: "{{error}}" severity: warn given: - "$.openapi" - "$.swagger" then: function: apq-valid-openapi-version functionOptions: valid-versions: "2.0,3.0.0,3.0.1,3.0.2,3.0.3,3.0.4,3.1.0,3.1.1,3.1.2,3.2.0" apiq:OAR086: description: "Descriptions must begin with a capital letter, end with a period, and not be empty." message: "OAR086: Descriptions must begin with a capital letter, end with a period, and not be empty." severity: "warn" given: "$..description" then: function: pattern functionOptions: match: "^[A-Z][\\s\\S]*\\.$" apiq:OAR087: description: "Summaries must begin with a capital letter, end with a period, and not be empty." message: "OAR087: Summaries must begin with a capital letter, end with a period, and not be empty." severity: "warn" given: "$..summary" then: function: pattern functionOptions: match: "^[A-Z][\\s\\S]*\\.$" apiq:OAR088: description: "The $ref of a parameter must end with the suffix Param." message: "OAR088: The $ref of a parameter must end with the suffix Param." severity: "warn" given: "$..parameters[*].$ref" then: function: pattern functionOptions: match: "Param$" apiq:OAR089: description: "The $ref of a request body must end with the suffix Body." message: "OAR089: The $ref of a request body must end with the suffix Body." severity: "warn" resolved: false given: "$..requestBody.$ref" then: function: pattern functionOptions: match: "Body$" apiq:OAR090: description: "The $ref of a response must end with the suffix Response." message: "OAR090: The $ref of a response must end with the suffix Response" severity: error given: "$.paths[*][*].responses[*].$ref" then: function: pattern functionOptions: match: ".*Response$" resolved: false apiq:OAR091: description: "Parameters must contain only $ref references." message: "OAR091: Parameters must contain only $ref references." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR091.md" severity: error resolved: false given: "$.paths[*][get,post,put,patch,delete].parameters[*]" then: field: $ref function: truthy apiq:OAR092: description: "RequestBody must contain a $ref." message: "OAR092: RequestBody must contain a $ref reference." severity: error given: "$.paths[*][get,post,put,patch,delete].requestBody[*].$ref" then: function: truthy apiq:OAR093: description: "RequestBody must contain only references ($ref)." message: "OAR093: RequestBody must contain only references ($ref)." severity: error given: "$.paths[*][get,post,put,patch,delete].responses[*].$ref" then: function: truthy apiq:OAR094: description: "Examples must be used instead of example in the content definition for better tool compatibility." message: "OAR094: Examples must be used instead of example in the content definition for better tool compatibility." severity: warn given: "$..content[*].example" then: function: falsy apiq:OAR096: description: "Response code 403 must be defined for operations with security schemes defined." message: "{{error}}" severity: "error" given: "$.paths[*][*]" then: function: apq-security-required-response functionOptions: expected-codes: "403" apiq:OAR097: description: "The base path must contain at least two parts." message: "OAR097: Path has too few parts." severity: "error" given: "$.servers[*].url" then: function: pattern functionOptions: match: "^https?://[^/]+/[^/]+/[^/]+" apiq:OAR098: description: "The base path must not contain more than two parts." message: "OAR098: Path has too many parts." severity: "error" given: "$.servers[*].url" then: function: pattern functionOptions: notMatch: "^https?://[^/]+/([^/]+/){2,}[^/]+" apiq:OAR099: description: "API name must start with prefix 'api-'." message: "OAR099: API name must start with prefix 'api-'." severity: "error" given: - "$.servers[*].url" - "$.paths[*]~" - "$.basePath" then: function: pattern functionOptions: match: ".*?/api-[^/]+/v[0-9]+" apiq:OAR100: description: "Last path part must be the API version, indicated with the prefix 'v' and the version number as integer." message: "OAR100: Last path part must be the API version, indicated with the prefix 'v' and the version number as integer." severity: "error" given: - "$.servers[*].url" - "$.basePath" then: function: pattern functionOptions: match: "^(https?://[^/]+)?(?:/[^/]+)*/v[0-9]+$" apiq:OAR101: description: "The first part of the path should be one of the allowed paths (e.g., '/hello')." message: "OAR101: The first part of the path should be one of the allowed paths." severity: "error" given: "$.servers[*].url" then: function: pattern functionOptions: match: "^https?://[^/]+/hello/.*$" apiq:OAR102: description: "The second part of the path should be one of the allowed values." message: "OAR102: The second part of the path should be one of the allowed values." severity: "error" given: "$.servers[*].url" then: function: pattern functionOptions: match: "^https?://[^/]+/hola/hello$" apiq:OAR103: description: "GET requests are not recommended for resource paths containing 'get' or 'delete', as this may indicate a design flaw." message: "OAR103: GET request should not be used on paths containing 'get' or 'delete'." severity: error given: "$.paths[?(@property.match(/(get|delete)/))].get" then: function: falsy apiq:OAR104: description: "POST requests should not be used on paths ending with 'me' or a templated parameter." message: "OAR104: POST requests should not target paths ending in 'me' or a path parameter like '{id}'." severity: error given: "$.paths[?(/\\/(me|{[^}]+})$/.test(@property))].post" then: function: falsy apiq:OAR105: description: "PUT requests are not recommended for resource paths containing 'get' or 'delete', as this may indicate a design flaw." message: "OAR105: PUT request should not be used on paths containing 'get' or 'delete'." severity: error given: "$.paths[?(@property.match(/(get|delete)/))].put" then: function: falsy apiq:OAR106: description: "PATCH requests are not recommended for resource paths containing 'get' or 'delete', as this may indicate a design flaw." message: "OAR106: PATCH request should not be used on paths containing 'get' or 'delete'." severity: error given: "$.paths[?(@property.match(/(get|delete)/))].patch" then: function: falsy apiq:OAR107: description: "DELETE requests are not recommended for resource paths containing 'get' or 'delete', as this may indicate a design flaw." message: "OAR107: DELETE request should not be used on paths containing 'get' or 'delete'." severity: error given: "$.paths[?(@property.match(/(get|delete)/))].delete" then: function: falsy apiq:OAR108: description: "The schemas should match the provided examples." message: "OAR108: Schema does not match the provided example." severity: "error" resolved: false given: "$.paths[*][*].responses[*]" then: function: apq-example-schema-types apiq:OAR109: description: "Use default response instead of directly specifying 5XX codes." message: "OAR109: Use default response instead of specifying 5XX codes directly." severity: error given: "$.paths[*][get,post,put,patch,delete].responses" then: field: "$[?(@property.match(/^5[0-9][0-9]$/))]" function: falsy apiq:OAR110: description: "License information cannot be empty." message: "OAR110: License information cannot be empty." severity: "error" given: "$.info" then: field: "license" function: truthy apiq:OAR111: description: "Contact information cannot be empty." message: "OAR111: Contact information cannot be empty." severity: "error" given: "$.info" then: field: "contact" function: truthy apiq:OAR113: description: "Field or extension must be at the assigned location" message: "OAR113: Field or extension x-custom-example must be at the assigned location" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR113.md" severity: warn given: "$" then: function: apq-custom-field functionOptions: fieldName: "x-custom-example" fieldLocation: "path,operation_get,response_200" apiq:OAR114: description: "Response headers for API security and key management must be defined (excluding 204 responses)." message: "OAR114: Response must include mandatory headers and exclude forbidden headers." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR114.md" severity: "error" given: "$.paths[*][*].responses[*]" then: - function: apq-response-headers functionOptions: mandatory-headers: "x-api-key" allowed-headers: "x-api-key,traceId,dateTime" excluded-response-codes: "204" path-exclusions: "/status" apiq:OAR115: description: "All fields listed in the required array must be defined in the schema properties." message: "OAR115: All fields in the required array must be defined in schema properties." documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR115.md" severity: warn resolved: false given: "$..[?(@ && @.required)]" then: function: apq-required-fields-exist apiq:OAR116: description: "Every API path must match the configured regular expression." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR116.md" severity: error given: "$.paths.*~" then: function: apq-path-pattern functionOptions: pattern: "^/" apiq:OAR117: description: "The API title must not match the configured forbidden regular expression." message: "{{error}}" documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR117.md" severity: error given: "$.info.title" then: function: apq-forbidden-title-pattern functionOptions: forbidden-pattern: "(?!)"